LCOV - code coverage report
Current view: top level - plugins/hs_apps - http_cli.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 80 303 26.4 %
Date: 2023-07-05 22:20:52 Functions: 10 30 33.3 %

          Line data    Source code
       1             : /*
       2             : * Copyright (c) 2017-2019 Cisco and/or its affiliates.
       3             : * Licensed under the Apache License, Version 2.0 (the "License");
       4             : * you may not use this file except in compliance with the License.
       5             : * You may obtain a copy of the License at:
       6             : *
       7             : *     http://www.apache.org/licenses/LICENSE-2.0
       8             : *
       9             : * Unless required by applicable law or agreed to in writing, software
      10             : * distributed under the License is distributed on an "AS IS" BASIS,
      11             : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             : * See the License for the specific language governing permissions and
      13             : * limitations under the License.
      14             : */
      15             : 
      16             : #include <vnet/session/application.h>
      17             : #include <vnet/session/application_interface.h>
      18             : #include <vnet/session/session.h>
      19             : #include <http/http.h>
      20             : 
      21             : typedef struct
      22             : {
      23             :   u32 hs_index;
      24             :   u32 thread_index;
      25             :   u64 node_index;
      26             :   u8 *buf;
      27             : } hcs_cli_args_t;
      28             : 
      29             : typedef struct
      30             : {
      31             :   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
      32             :   u32 session_index;
      33             :   u32 thread_index;
      34             :   u8 *tx_buf;
      35             :   u32 tx_offset;
      36             :   u32 vpp_session_index;
      37             : } hcs_session_t;
      38             : 
      39             : typedef struct
      40             : {
      41             :   hcs_session_t **sessions;
      42             :   u32 *free_http_cli_process_node_indices;
      43             :   u32 app_index;
      44             : 
      45             :   /* Cert key pair for tls */
      46             :   u32 ckpair_index;
      47             : 
      48             :   u32 prealloc_fifos;
      49             :   u32 private_segment_size;
      50             :   u32 fifo_size;
      51             :   u8 *uri;
      52             :   vlib_main_t *vlib_main;
      53             : } hcs_main_t;
      54             : 
      55             : static hcs_main_t hcs_main;
      56             : 
      57             : static hcs_session_t *
      58           0 : hcs_session_alloc (u32 thread_index)
      59             : {
      60           0 :   hcs_main_t *hcm = &hcs_main;
      61             :   hcs_session_t *hs;
      62           0 :   pool_get (hcm->sessions[thread_index], hs);
      63           0 :   memset (hs, 0, sizeof (*hs));
      64           0 :   hs->session_index = hs - hcm->sessions[thread_index];
      65           0 :   hs->thread_index = thread_index;
      66           0 :   return hs;
      67             : }
      68             : 
      69             : static hcs_session_t *
      70           0 : hcs_session_get (u32 thread_index, u32 hs_index)
      71             : {
      72           0 :   hcs_main_t *hcm = &hcs_main;
      73           0 :   if (pool_is_free_index (hcm->sessions[thread_index], hs_index))
      74           0 :     return 0;
      75           0 :   return pool_elt_at_index (hcm->sessions[thread_index], hs_index);
      76             : }
      77             : 
      78             : static void
      79           0 : hcs_session_free (hcs_session_t *hs)
      80             : {
      81           0 :   hcs_main_t *hcm = &hcs_main;
      82           0 :   u32 thread = hs->thread_index;
      83             :   if (CLIB_DEBUG)
      84           0 :     memset (hs, 0xfa, sizeof (*hs));
      85           0 :   pool_put (hcm->sessions[thread], hs);
      86           0 : }
      87             : 
      88             : static void
      89           0 : hcs_cli_process_free (hcs_cli_args_t *args)
      90             : {
      91           0 :   vlib_main_t *vm = vlib_get_first_main ();
      92           0 :   hcs_main_t *hcm = &hcs_main;
      93             :   hcs_cli_args_t **save_args;
      94             :   vlib_node_runtime_t *rt;
      95             :   vlib_node_t *n;
      96             :   u32 node_index;
      97             : 
      98           0 :   node_index = args->node_index;
      99           0 :   ASSERT (node_index != 0);
     100             : 
     101           0 :   n = vlib_get_node (vm, node_index);
     102           0 :   rt = vlib_node_get_runtime (vm, n->index);
     103           0 :   save_args = vlib_node_get_runtime_data (vm, n->index);
     104             : 
     105             :   /* Reset process session pointer */
     106           0 :   clib_mem_free (*save_args);
     107           0 :   *save_args = 0;
     108             : 
     109             :   /* Turn off the process node */
     110           0 :   vlib_node_set_state (vm, rt->node_index, VLIB_NODE_STATE_DISABLED);
     111             : 
     112             :   /* add node index to the freelist */
     113           0 :   vec_add1 (hcm->free_http_cli_process_node_indices, node_index);
     114           0 : }
     115             : 
     116             : /* Header, including incantation to suppress favicon.ico requests */
     117             : static const char *html_header_template =
     118             :     "<html><head><title>%v</title></head>"
     119             :     "<link rel=\"icon\" href=\"data:,\">"
     120             :     "<body><pre>";
     121             : 
     122             : static const char *html_footer =
     123             :     "</pre></body></html>\r\n";
     124             : 
     125             : static void
     126           0 : hcs_cli_output (uword arg, u8 *buffer, uword buffer_bytes)
     127             : {
     128           0 :   u8 **output_vecp = (u8 **) arg;
     129             :   u8 *output_vec;
     130             :   u32 offset;
     131             : 
     132           0 :   output_vec = *output_vecp;
     133             : 
     134           0 :   offset = vec_len (output_vec);
     135           0 :   vec_validate (output_vec, offset + buffer_bytes - 1);
     136           0 :   clib_memcpy_fast (output_vec + offset, buffer, buffer_bytes);
     137             : 
     138           0 :   *output_vecp = output_vec;
     139           0 : }
     140             : 
     141             : static void
     142           0 : start_send_data (hcs_session_t *hs, http_status_code_t status)
     143             : {
     144             :   http_msg_t msg;
     145             :   session_t *ts;
     146             :   int rv;
     147             : 
     148           0 :   msg.type = HTTP_MSG_REPLY;
     149           0 :   msg.code = status;
     150           0 :   msg.content_type = HTTP_CONTENT_TEXT_HTML;
     151           0 :   msg.data.type = HTTP_MSG_DATA_INLINE;
     152           0 :   msg.data.len = vec_len (hs->tx_buf);
     153             : 
     154           0 :   ts = session_get (hs->vpp_session_index, hs->thread_index);
     155           0 :   rv = svm_fifo_enqueue (ts->tx_fifo, sizeof (msg), (u8 *) &msg);
     156           0 :   ASSERT (rv == sizeof (msg));
     157             : 
     158           0 :   if (!msg.data.len)
     159           0 :     goto done;
     160             : 
     161           0 :   rv = svm_fifo_enqueue (ts->tx_fifo, vec_len (hs->tx_buf), hs->tx_buf);
     162             : 
     163           0 :   if (rv != vec_len (hs->tx_buf))
     164             :     {
     165           0 :       hs->tx_offset = rv;
     166           0 :       svm_fifo_add_want_deq_ntf (ts->tx_fifo, SVM_FIFO_WANT_DEQ_NOTIF);
     167             :     }
     168             :   else
     169             :     {
     170           0 :       vec_free (hs->tx_buf);
     171             :     }
     172             : 
     173           0 : done:
     174             : 
     175           0 :   if (svm_fifo_set_event (ts->tx_fifo))
     176           0 :     session_send_io_evt_to_thread (ts->tx_fifo, SESSION_IO_EVT_TX);
     177           0 : }
     178             : 
     179             : static void
     180           0 : send_data_to_http (void *rpc_args)
     181             : {
     182           0 :   hcs_cli_args_t *args = (hcs_cli_args_t *) rpc_args;
     183             :   hcs_session_t *hs;
     184             : 
     185           0 :   hs = hcs_session_get (args->thread_index, args->hs_index);
     186           0 :   if (!hs)
     187             :     {
     188           0 :       vec_free (args->buf);
     189           0 :       goto cleanup;
     190             :     }
     191             : 
     192           0 :   hs->tx_buf = args->buf;
     193           0 :   start_send_data (hs, HTTP_STATUS_OK);
     194             : 
     195           0 : cleanup:
     196             : 
     197           0 :   clib_mem_free (rpc_args);
     198           0 : }
     199             : 
     200             : static uword
     201           0 : hcs_cli_process (vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
     202             : {
     203           0 :   u8 *request = 0, *reply = 0, *html = 0;
     204             :   hcs_cli_args_t *args, *rpc_args;
     205           0 :   hcs_main_t *hcm = &hcs_main;
     206             :   hcs_cli_args_t **save_args;
     207             :   unformat_input_t input;
     208             :   int i;
     209             : 
     210           0 :   save_args = vlib_node_get_runtime_data (hcm->vlib_main, rt->node_index);
     211           0 :   args = *save_args;
     212             : 
     213           0 :   request = args->buf;
     214             : 
     215             :   /* Replace slashes with spaces, stop at the end of the path */
     216           0 :   i = 0;
     217           0 :   while (i < vec_len (request))
     218             :     {
     219           0 :       if (request[i] == '/')
     220           0 :         request[i] = ' ';
     221           0 :       else if (request[i] == ' ')
     222             :         {
     223             :           /* vlib_cli_input is vector-based, no need for a NULL */
     224           0 :           vec_set_len (request, i);
     225           0 :           break;
     226             :         }
     227           0 :       i++;
     228             :     }
     229             : 
     230             :   /* Generate the html header */
     231           0 :   html = format (0, html_header_template, request /* title */ );
     232             : 
     233             :   /* Run the command */
     234           0 :   unformat_init_vector (&input, vec_dup (request));
     235           0 :   vlib_cli_input (vm, &input, hcs_cli_output, (uword) &reply);
     236           0 :   unformat_free (&input);
     237           0 :   request = 0;
     238             : 
     239             :   /* Generate the html page */
     240           0 :   html = format (html, "%v", reply);
     241           0 :   html = format (html, html_footer);
     242             : 
     243             :   /* Send it */
     244           0 :   rpc_args = clib_mem_alloc (sizeof (*args));
     245           0 :   clib_memcpy_fast (rpc_args, args, sizeof (*args));
     246           0 :   rpc_args->buf = html;
     247             : 
     248           0 :   session_send_rpc_evt_to_thread_force (args->thread_index, send_data_to_http,
     249             :                                         rpc_args);
     250             : 
     251           0 :   vec_free (reply);
     252           0 :   vec_free (args->buf);
     253           0 :   hcs_cli_process_free (args);
     254             : 
     255           0 :   return (0);
     256             : }
     257             : 
     258             : static void
     259           0 : alloc_cli_process (hcs_cli_args_t *args)
     260             : {
     261           0 :   hcs_main_t *hcm = &hcs_main;
     262           0 :   vlib_main_t *vm = hcm->vlib_main;
     263             :   hcs_cli_args_t **save_args;
     264             :   vlib_node_t *n;
     265             :   uword l;
     266             : 
     267           0 :   l = vec_len (hcm->free_http_cli_process_node_indices);
     268           0 :   if (l > 0)
     269             :     {
     270           0 :       n = vlib_get_node (vm, hcm->free_http_cli_process_node_indices[l - 1]);
     271           0 :       vlib_node_set_state (vm, n->index, VLIB_NODE_STATE_POLLING);
     272           0 :       vec_set_len (hcm->free_http_cli_process_node_indices, l - 1);
     273             :     }
     274             :   else
     275             :     {
     276             :       static vlib_node_registration_t r = {
     277             :         .function = hcs_cli_process,
     278             :         .type = VLIB_NODE_TYPE_PROCESS,
     279             :         .process_log2_n_stack_bytes = 16,
     280             :         .runtime_data_bytes = sizeof (void *),
     281             :       };
     282             : 
     283           0 :       vlib_register_node (vm, &r, "http-cli-%d", l);
     284             : 
     285           0 :       n = vlib_get_node (vm, r.index);
     286             :     }
     287             : 
     288             :   /* Save the node index in the args. It won't be zero. */
     289           0 :   args->node_index = n->index;
     290             : 
     291             :   /* Save the args (pointer) in the node runtime */
     292           0 :   save_args = vlib_node_get_runtime_data (vm, n->index);
     293           0 :   *save_args = clib_mem_alloc (sizeof (*args));
     294           0 :   clib_memcpy_fast (*save_args, args, sizeof (*args));
     295             : 
     296           0 :   vlib_start_process (vm, n->runtime_index);
     297           0 : }
     298             : 
     299             : static void
     300           0 : alloc_cli_process_callback (void *cb_args)
     301             : {
     302           0 :   alloc_cli_process ((hcs_cli_args_t *) cb_args);
     303           0 : }
     304             : 
     305             : static int
     306           0 : hcs_ts_rx_callback (session_t *ts)
     307             : {
     308           0 :   hcs_cli_args_t args = {};
     309             :   hcs_session_t *hs;
     310             :   http_msg_t msg;
     311             :   int rv;
     312             : 
     313           0 :   hs = hcs_session_get (ts->thread_index, ts->opaque);
     314             : 
     315             :   /* Read the http message header */
     316           0 :   rv = svm_fifo_dequeue (ts->rx_fifo, sizeof (msg), (u8 *) &msg);
     317           0 :   ASSERT (rv == sizeof (msg));
     318             : 
     319           0 :   if (msg.type != HTTP_MSG_REQUEST || msg.method_type != HTTP_REQ_GET)
     320             :     {
     321           0 :       hs->tx_buf = 0;
     322           0 :       start_send_data (hs, HTTP_STATUS_METHOD_NOT_ALLOWED);
     323           0 :       return 0;
     324             :     }
     325             : 
     326             :   /* send the command to a new/recycled vlib process */
     327           0 :   vec_validate (args.buf, msg.data.len - 1);
     328           0 :   rv = svm_fifo_dequeue (ts->rx_fifo, msg.data.len, args.buf);
     329           0 :   ASSERT (rv == msg.data.len);
     330           0 :   vec_set_len (args.buf, rv);
     331             : 
     332           0 :   args.hs_index = hs->session_index;
     333           0 :   args.thread_index = ts->thread_index;
     334             : 
     335             :   /* Send RPC request to main thread */
     336           0 :   if (vlib_get_thread_index () != 0)
     337           0 :     vlib_rpc_call_main_thread (alloc_cli_process_callback, (u8 *) &args,
     338             :                                sizeof (args));
     339             :   else
     340           0 :     alloc_cli_process (&args);
     341           0 :   return 0;
     342             : }
     343             : 
     344             : static int
     345           0 : hcs_ts_tx_callback (session_t *ts)
     346             : {
     347             :   hcs_session_t *hs;
     348             :   u32 to_send;
     349             :   int rv;
     350             : 
     351           0 :   hs = hcs_session_get (ts->thread_index, ts->opaque);
     352           0 :   if (!hs || !hs->tx_buf)
     353           0 :     return 0;
     354             : 
     355           0 :   to_send = vec_len (hs->tx_buf) - hs->tx_offset;
     356           0 :   rv = svm_fifo_enqueue (ts->tx_fifo, to_send, hs->tx_buf + hs->tx_offset);
     357             : 
     358           0 :   if (rv <= 0)
     359             :     {
     360           0 :       svm_fifo_add_want_deq_ntf (ts->tx_fifo, SVM_FIFO_WANT_DEQ_NOTIF);
     361           0 :       return 0;
     362             :     }
     363             : 
     364           0 :   if (rv < to_send)
     365             :     {
     366           0 :       hs->tx_offset += rv;
     367           0 :       svm_fifo_add_want_deq_ntf (ts->tx_fifo, SVM_FIFO_WANT_DEQ_NOTIF);
     368             :     }
     369             :   else
     370             :     {
     371           0 :       vec_free (hs->tx_buf);
     372             :     }
     373             : 
     374           0 :   if (svm_fifo_set_event (ts->tx_fifo))
     375           0 :     session_send_io_evt_to_thread (ts->tx_fifo, SESSION_IO_EVT_TX);
     376             : 
     377           0 :   return 0;
     378             : }
     379             : 
     380             : static int
     381           0 : hcs_ts_accept_callback (session_t *ts)
     382             : {
     383             :   hcs_session_t *hs;
     384             : 
     385           0 :   hs = hcs_session_alloc (ts->thread_index);
     386           0 :   hs->vpp_session_index = ts->session_index;
     387             : 
     388           0 :   ts->opaque = hs->session_index;
     389           0 :   ts->session_state = SESSION_STATE_READY;
     390             : 
     391           0 :   return 0;
     392             : }
     393             : 
     394             : static int
     395           0 : hcs_ts_connected_callback (u32 app_index, u32 api_context, session_t *s,
     396             :                            session_error_t err)
     397             : {
     398           0 :   clib_warning ("called...");
     399           0 :   return -1;
     400             : }
     401             : 
     402             : static void
     403           0 : hcs_ts_disconnect_callback (session_t *s)
     404             : {
     405           0 :   hcs_main_t *hcm = &hcs_main;
     406           0 :   vnet_disconnect_args_t _a = { 0 }, *a = &_a;
     407             : 
     408           0 :   a->handle = session_handle (s);
     409           0 :   a->app_index = hcm->app_index;
     410           0 :   vnet_disconnect_session (a);
     411           0 : }
     412             : 
     413             : static void
     414           0 : hcs_ts_reset_callback (session_t *s)
     415             : {
     416           0 :   hcs_main_t *hcm = &hcs_main;
     417           0 :   vnet_disconnect_args_t _a = { 0 }, *a = &_a;
     418             : 
     419           0 :   a->handle = session_handle (s);
     420           0 :   a->app_index = hcm->app_index;
     421           0 :   vnet_disconnect_session (a);
     422           0 : }
     423             : 
     424             : static void
     425           0 : hcs_ts_cleanup_callback (session_t *s, session_cleanup_ntf_t ntf)
     426             : {
     427             :   hcs_session_t *hs;
     428             : 
     429           0 :   if (ntf == SESSION_CLEANUP_TRANSPORT)
     430           0 :     return;
     431             : 
     432           0 :   hs = hcs_session_get (s->thread_index, s->opaque);
     433           0 :   if (!hs)
     434           0 :     return;
     435             : 
     436           0 :   vec_free (hs->tx_buf);
     437           0 :   hcs_session_free (hs);
     438             : }
     439             : 
     440             : static int
     441           0 : hcs_add_segment_callback (u32 client_index, u64 segment_handle)
     442             : {
     443           0 :   return 0;
     444             : }
     445             : 
     446             : static int
     447           0 : hcs_del_segment_callback (u32 client_index, u64 segment_handle)
     448             : {
     449           0 :   return 0;
     450             : }
     451             : 
     452             : static session_cb_vft_t hcs_session_cb_vft = {
     453             :   .session_accept_callback = hcs_ts_accept_callback,
     454             :   .session_disconnect_callback = hcs_ts_disconnect_callback,
     455             :   .session_connected_callback = hcs_ts_connected_callback,
     456             :   .add_segment_callback = hcs_add_segment_callback,
     457             :   .del_segment_callback = hcs_del_segment_callback,
     458             :   .builtin_app_rx_callback = hcs_ts_rx_callback,
     459             :   .builtin_app_tx_callback = hcs_ts_tx_callback,
     460             :   .session_reset_callback = hcs_ts_reset_callback,
     461             :   .session_cleanup_callback = hcs_ts_cleanup_callback,
     462             : };
     463             : 
     464             : static int
     465           3 : hcs_attach ()
     466             : {
     467           3 :   vnet_app_add_cert_key_pair_args_t _ck_pair, *ck_pair = &_ck_pair;
     468           3 :   hcs_main_t *hcm = &hcs_main;
     469             :   u64 options[APP_OPTIONS_N_OPTIONS];
     470           3 :   vnet_app_attach_args_t _a, *a = &_a;
     471           3 :   u32 segment_size = 128 << 20;
     472             : 
     473           3 :   clib_memset (a, 0, sizeof (*a));
     474           3 :   clib_memset (options, 0, sizeof (options));
     475             : 
     476           3 :   if (hcm->private_segment_size)
     477           0 :     segment_size = hcm->private_segment_size;
     478             : 
     479           3 :   a->api_client_index = ~0;
     480           3 :   a->name = format (0, "http_cli_server");
     481           3 :   a->session_cb_vft = &hcs_session_cb_vft;
     482           3 :   a->options = options;
     483           3 :   a->options[APP_OPTIONS_SEGMENT_SIZE] = segment_size;
     484           3 :   a->options[APP_OPTIONS_ADD_SEGMENT_SIZE] = segment_size;
     485           3 :   a->options[APP_OPTIONS_RX_FIFO_SIZE] =
     486           3 :     hcm->fifo_size ? hcm->fifo_size : 8 << 10;
     487           3 :   a->options[APP_OPTIONS_TX_FIFO_SIZE] =
     488           3 :     hcm->fifo_size ? hcm->fifo_size : 32 << 10;
     489           3 :   a->options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
     490           3 :   a->options[APP_OPTIONS_PREALLOC_FIFO_PAIRS] = hcm->prealloc_fifos;
     491             : 
     492           3 :   if (vnet_application_attach (a))
     493             :     {
     494           0 :       vec_free (a->name);
     495           0 :       clib_warning ("failed to attach server");
     496           0 :       return -1;
     497             :     }
     498           3 :   vec_free (a->name);
     499           3 :   hcm->app_index = a->app_index;
     500             : 
     501           3 :   clib_memset (ck_pair, 0, sizeof (*ck_pair));
     502           3 :   ck_pair->cert = (u8 *) test_srv_crt_rsa;
     503           3 :   ck_pair->key = (u8 *) test_srv_key_rsa;
     504           3 :   ck_pair->cert_len = test_srv_crt_rsa_len;
     505           3 :   ck_pair->key_len = test_srv_key_rsa_len;
     506           3 :   vnet_app_add_cert_key_pair (ck_pair);
     507           3 :   hcm->ckpair_index = ck_pair->index;
     508             : 
     509           3 :   return 0;
     510             : }
     511             : 
     512             : static int
     513           3 : hcs_transport_needs_crypto (transport_proto_t proto)
     514             : {
     515           3 :   return proto == TRANSPORT_PROTO_TLS || proto == TRANSPORT_PROTO_DTLS ||
     516             :          proto == TRANSPORT_PROTO_QUIC;
     517             : }
     518             : 
     519             : static int
     520           3 : hcs_listen ()
     521             : {
     522           3 :   session_endpoint_cfg_t sep = SESSION_ENDPOINT_CFG_NULL;
     523           3 :   hcs_main_t *hcm = &hcs_main;
     524           3 :   vnet_listen_args_t _a, *a = &_a;
     525           3 :   char *uri = "tcp://0.0.0.0/80";
     526             :   u8 need_crypto;
     527             :   int rv;
     528             : 
     529           3 :   clib_memset (a, 0, sizeof (*a));
     530           3 :   a->app_index = hcm->app_index;
     531             : 
     532           3 :   if (hcm->uri)
     533           0 :     uri = (char *) hcm->uri;
     534             : 
     535           3 :   if (parse_uri (uri, &sep))
     536           0 :     return -1;
     537             : 
     538           3 :   need_crypto = hcs_transport_needs_crypto (sep.transport_proto);
     539             : 
     540           3 :   sep.transport_proto = TRANSPORT_PROTO_HTTP;
     541           3 :   clib_memcpy (&a->sep_ext, &sep, sizeof (sep));
     542             : 
     543           3 :   if (need_crypto)
     544             :     {
     545           0 :       session_endpoint_alloc_ext_cfg (&a->sep_ext,
     546             :                                       TRANSPORT_ENDPT_EXT_CFG_CRYPTO);
     547           0 :       a->sep_ext.ext_cfg->crypto.ckpair_index = hcm->ckpair_index;
     548             :     }
     549             : 
     550           3 :   rv = vnet_listen (a);
     551             : 
     552           3 :   if (need_crypto)
     553           0 :     clib_mem_free (a->sep_ext.ext_cfg);
     554             : 
     555           3 :   return rv;
     556             : }
     557             : 
     558             : static void
     559           0 : hcs_detach ()
     560             : {
     561           0 :   vnet_app_detach_args_t _a, *a = &_a;
     562           0 :   hcs_main_t *hcm = &hcs_main;
     563           0 :   a->app_index = hcm->app_index;
     564           0 :   a->api_client_index = APP_INVALID_INDEX;
     565           0 :   hcm->app_index = ~0;
     566           0 :   vnet_application_detach (a);
     567           0 : }
     568             : 
     569             : static int
     570           3 : hcs_create (vlib_main_t *vm)
     571             : {
     572           3 :   vlib_thread_main_t *vtm = vlib_get_thread_main ();
     573           3 :   hcs_main_t *hcm = &hcs_main;
     574             :   u32 num_threads;
     575             : 
     576           3 :   num_threads = 1 /* main thread */  + vtm->n_threads;
     577           3 :   vec_validate (hcm->sessions, num_threads - 1);
     578             : 
     579           3 :   if (hcs_attach ())
     580             :     {
     581           0 :       clib_warning ("failed to attach server");
     582           0 :       return -1;
     583             :     }
     584           3 :   if (hcs_listen ())
     585             :     {
     586           0 :       hcs_detach ();
     587           0 :       clib_warning ("failed to start listening");
     588           0 :       return -1;
     589             :     }
     590             : 
     591           3 :   return 0;
     592             : }
     593             : 
     594             : static clib_error_t *
     595           3 : hcs_create_command_fn (vlib_main_t *vm, unformat_input_t *input,
     596             :                        vlib_cli_command_t *cmd)
     597             : {
     598           3 :   unformat_input_t _line_input, *line_input = &_line_input;
     599           3 :   hcs_main_t *hcm = &hcs_main;
     600             :   u64 seg_size;
     601             :   int rv;
     602             : 
     603           3 :   hcm->prealloc_fifos = 0;
     604           3 :   hcm->private_segment_size = 0;
     605           3 :   hcm->fifo_size = 0;
     606             : 
     607             :   /* Get a line of input. */
     608           3 :   if (!unformat_user (input, unformat_line_input, line_input))
     609           3 :     goto start_server;
     610             : 
     611           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     612             :     {
     613           0 :       if (unformat (line_input, "prealloc-fifos %d", &hcm->prealloc_fifos))
     614             :         ;
     615           0 :       else if (unformat (line_input, "private-segment-size %U",
     616             :                          unformat_memory_size, &seg_size))
     617           0 :         hcm->private_segment_size = seg_size;
     618           0 :       else if (unformat (line_input, "fifo-size %d", &hcm->fifo_size))
     619           0 :         hcm->fifo_size <<= 10;
     620           0 :       else if (unformat (line_input, "uri %s", &hcm->uri))
     621             :         ;
     622             :       else
     623             :         {
     624           0 :           unformat_free (line_input);
     625           0 :           return clib_error_return (0, "unknown input `%U'",
     626             :                                     format_unformat_error, line_input);
     627             :         }
     628             :     }
     629             : 
     630           0 :   unformat_free (line_input);
     631             : 
     632           3 : start_server:
     633             : 
     634           3 :   if (hcm->app_index != (u32) ~0)
     635           0 :     return clib_error_return (0, "test http server is already running");
     636             : 
     637           3 :   vnet_session_enable_disable (vm, 1 /* turn on TCP, etc. */ );
     638             : 
     639           3 :   rv = hcs_create (vm);
     640           3 :   switch (rv)
     641             :     {
     642           3 :     case 0:
     643           3 :       break;
     644           0 :     default:
     645           0 :       return clib_error_return (0, "server_create returned %d", rv);
     646             :     }
     647             : 
     648           3 :   return 0;
     649             : }
     650             : 
     651      203447 : VLIB_CLI_COMMAND (hcs_create_command, static) = {
     652             :   .path = "http cli server",
     653             :   .short_help = "http cli server [uri <uri>] [fifo-size <nbytes>] "
     654             :                 "[private-segment-size <nMG>] [prealloc-fifos <n>]",
     655             :   .function = hcs_create_command_fn,
     656             : };
     657             : 
     658             : static clib_error_t *
     659         559 : hcs_main_init (vlib_main_t *vm)
     660             : {
     661         559 :   hcs_main_t *hcs = &hcs_main;
     662             : 
     663         559 :   hcs->app_index = ~0;
     664         559 :   hcs->vlib_main = vm;
     665         559 :   return 0;
     666             : }
     667             : 
     668        1679 : VLIB_INIT_FUNCTION (hcs_main_init);
     669             : 
     670             : /*
     671             : * fd.io coding-style-patch-verification: ON
     672             : *
     673             : * Local Variables:
     674             : * eval: (c-set-style "gnu")
     675             : * End:
     676             : */

Generated by: LCOV version 1.14