typedef struct
{
- u8 *rx_buf;
+ u8 **rx_buf;
unix_shared_memory_queue_t **vpp_queue;
u64 byte_index;
/* process node index for evnt scheduling */
u32 node_index;
+
+ u32 prealloc_fifos;
+ u32 private_segment_size;
+ u32 fifo_size;
vlib_main_t *vlib_main;
} http_server_main_t;
static const char *html_footer = "</pre></body></html>\r\n";
+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";
+
+static u8 *static_http;
+
static void
http_cli_output (uword arg, u8 * buffer, uword buffer_bytes)
{
}
void
-send_data (builtin_http_server_args * args, u8 * data)
+send_data (stream_session_t * s, u8 * data)
{
session_fifo_event_t evt;
u32 offset, bytes_to_send;
http_server_main_t *hsm = &http_server_main;
vlib_main_t *vm = hsm->vlib_main;
f64 last_sent_timer = vlib_time_now (vm);
- stream_session_t *s;
- s = session_get_from_handle (args->session_handle);
- ASSERT (s);
bytes_to_send = vec_len (data);
offset = 0;
}
static void
-send_error (builtin_http_server_args * args, char *str)
+send_error (stream_session_t * s, char *str)
{
u8 *data;
data = format (0, http_error_template, str);
- send_data (args, data);
+ send_data (s, data);
vec_free (data);
}
u8 *request = 0, *reply = 0;
builtin_http_server_args **save_args;
builtin_http_server_args *args;
+ stream_session_t *s;
unformat_input_t input;
int i;
u8 *http = 0, *html = 0;
save_args = vlib_node_get_runtime_data (hsm->vlib_main, rt->node_index);
args = *save_args;
+ s = session_get_from_handle (args->session_handle);
+ ASSERT (s);
request = (u8 *) (void *) (args->data);
if (vec_len (request) < 7)
{
- send_error (args, "400 Bad Request");
+ send_error (s, "400 Bad Request");
goto out;
}
goto found;
}
bad_request:
- send_error (args, "400 Bad Request");
+ send_error (s, "400 Bad Request");
goto out;
found:
http = format (0, http_response, vec_len (html), html);
/* Send it */
- send_data (args, http);
+ send_data (s, http);
out:
/* Cleanup */
}
static int
-http_server_rx_callback (stream_session_t * s)
+session_rx_request (stream_session_t * s)
{
- u32 max_dequeue;
- int actual_transfer;
http_server_main_t *hsm = &http_server_main;
svm_fifo_t *rx_fifo;
- builtin_http_server_args *args;
+ u32 max_dequeue;
+ int actual_transfer;
rx_fifo = s->server_rx_fifo;
max_dequeue = svm_fifo_max_dequeue (rx_fifo);
svm_fifo_unset_event (rx_fifo);
if (PREDICT_FALSE (max_dequeue == 0))
- return 0;
+ return -1;
- vec_validate (hsm->rx_buf, max_dequeue - 1);
- _vec_len (hsm->rx_buf) = max_dequeue;
+ vec_validate (hsm->rx_buf[s->thread_index], max_dequeue - 1);
+ _vec_len (hsm->rx_buf[s->thread_index]) = max_dequeue;
actual_transfer = svm_fifo_dequeue_nowait (rx_fifo, max_dequeue,
- hsm->rx_buf);
+ hsm->rx_buf[s->thread_index]);
ASSERT (actual_transfer > 0);
- _vec_len (hsm->rx_buf) = actual_transfer;
+ _vec_len (hsm->rx_buf[s->thread_index]) = actual_transfer;
+ return 0;
+}
+
+static int
+http_server_rx_callback (stream_session_t * s)
+{
+ http_server_main_t *hsm = &http_server_main;
+ builtin_http_server_args *args;
+ int rv;
+
+ rv = session_rx_request (s);
+ if (rv)
+ return rv;
/* send the command to a new/recycled vlib process */
args = clib_mem_alloc (sizeof (*args));
- args->data = vec_dup (hsm->rx_buf);
+ args->data = vec_dup (hsm->rx_buf[s->thread_index]);
args->session_handle = session_handle (s);
/* Send an RPC request via the thread-0 input node */
return 0;
}
+static int
+http_server_rx_callback_static (stream_session_t * s)
+{
+ http_server_main_t *hsm = &http_server_main;
+ u8 *request = 0;
+ int i;
+ int rv;
+
+ rv = session_rx_request (s);
+ if (rv)
+ return rv;
+
+ request = hsm->rx_buf[s->thread_index];
+ if (vec_len (request) < 7)
+ {
+ send_error (s, "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;
+ }
+ send_error (s, "400 Bad Request");
+ goto out;
+
+found:
+
+ /* Send it */
+ send_data (s, static_http);
+
+out:
+ /* Cleanup */
+ vec_free (request);
+ hsm->rx_buf[s->thread_index] = request;
+ return 0;
+}
+
static int
builtin_session_accept_callback (stream_session_t * s)
{
shmem_hdr = am->shmem_hdr;
hsm->vl_input_queue = shmem_hdr->vl_input_queue;
hsm->my_client_index =
- vl_api_memclnt_create_internal ("tcp_test_client", hsm->vl_input_queue);
+ vl_api_memclnt_create_internal ("test_http_server", hsm->vl_input_queue);
return 0;
}
{
http_server_main_t *hsm = &http_server_main;
u8 segment_name[128];
- u64 options[SESSION_OPTIONS_N_OPTIONS];
+ u64 options[APP_OPTIONS_N_OPTIONS];
vnet_app_attach_args_t _a, *a = &_a;
+ u32 segment_size = 128 << 20;
memset (a, 0, sizeof (*a));
memset (options, 0, sizeof (options));
+ if (hsm->private_segment_size)
+ segment_size = hsm->private_segment_size;
+
a->api_client_index = hsm->my_client_index;
a->session_cb_vft = &builtin_session_cb_vft;
a->options = options;
- a->options[SESSION_OPTIONS_SEGMENT_SIZE] = 128 << 20;
- a->options[SESSION_OPTIONS_RX_FIFO_SIZE] = 8 << 10;
- a->options[SESSION_OPTIONS_TX_FIFO_SIZE] = 32 << 10;
+ a->options[APP_OPTIONS_SEGMENT_SIZE] = segment_size;
+ a->options[APP_OPTIONS_RX_FIFO_SIZE] =
+ hsm->fifo_size ? hsm->fifo_size : 8 << 10;
+ a->options[APP_OPTIONS_TX_FIFO_SIZE] =
+ hsm->fifo_size ? hsm->fifo_size : 32 << 10;
a->options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
- a->options[APP_OPTIONS_PREALLOC_FIFO_PAIRS] = 16;
+ a->options[APP_OPTIONS_PREALLOC_FIFO_PAIRS] = hsm->prealloc_fifos;
a->segment_name = segment_name;
a->segment_name_length = ARRAY_LEN (segment_name);
unformat_input_t * input, vlib_cli_command_t * cmd)
{
http_server_main_t *hsm = &http_server_main;
- int rv;
-
+ int rv, is_static = 0;
+ u64 seg_size;
+ u8 *html;
+
+ hsm->prealloc_fifos = 0;
+ hsm->private_segment_size = 0;
+ hsm->fifo_size = 0;
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "static"))
+ is_static = 1;
+ else if (unformat (input, "prealloc-fifos %d", &hsm->prealloc_fifos))
+ ;
+ else if (unformat (input, "private-segment-size %U",
+ unformat_memory_size, &seg_size))
+ {
+ if (seg_size >= 0x100000000ULL)
+ {
+ vlib_cli_output (vm, "private segment size %llu, too large",
+ seg_size);
+ return 0;
+ }
+ hsm->private_segment_size = seg_size;
+ }
+ else if (unformat (input, "fifo-size %d", &hsm->fifo_size))
+ hsm->fifo_size <<= 10;
+ else
+ return clib_error_return (0, "unknown input `%U'",
+ format_unformat_error, input);
+ }
if (hsm->my_client_index != (u32) ~ 0)
return clib_error_return (0, "test http server is already running");
vnet_session_enable_disable (vm, 1 /* turn on TCP, etc. */ );
+
+ if (is_static)
+ {
+ builtin_session_cb_vft.builtin_server_rx_callback =
+ http_server_rx_callback_static;
+ html = format (0, html_header_static);
+ static_http = format (0, http_response, vec_len (html), html);
+ }
rv = server_create (vm);
switch (rv)
{
builtin_http_server_main_init (vlib_main_t * vm)
{
http_server_main_t *hsm = &http_server_main;
+ vlib_thread_main_t *vtm = vlib_get_thread_main ();
+ u32 num_threads;
+
hsm->my_client_index = ~0;
hsm->vlib_main = vm;
-
+ num_threads = 1 /* main thread */ + vtm->n_threads;
+ vec_validate (hsm->rx_buf, num_threads - 1);
return 0;
}