aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/plugins/hs_apps/http_client_cli.c23
-rw-r--r--src/plugins/http/http.c76
-rw-r--r--src/plugins/http/http1.c7
-rw-r--r--src/plugins/http/http_private.h25
-rw-r--r--src/plugins/http/http_timer.h2
5 files changed, 117 insertions, 16 deletions
diff --git a/src/plugins/hs_apps/http_client_cli.c b/src/plugins/hs_apps/http_client_cli.c
index 4ee3b49444c..8df5bfd10b8 100644
--- a/src/plugins/hs_apps/http_client_cli.c
+++ b/src/plugins/hs_apps/http_client_cli.c
@@ -62,6 +62,8 @@ typedef struct
u8 *http_response;
u8 *appns_id;
u64 appns_secret;
+ u32 ckpair_index;
+ u8 need_crypto;
} hcc_main_t;
typedef enum
@@ -333,6 +335,7 @@ hcc_attach ()
vnet_app_attach_args_t _a, *a = &_a;
u64 options[18];
u32 segment_size = 128 << 20;
+ vnet_app_add_cert_key_pair_args_t _ck_pair, *ck_pair = &_ck_pair;
int rv;
if (hcm->private_segment_size)
@@ -353,6 +356,7 @@ hcc_attach ()
hcm->fifo_size ? hcm->fifo_size : 32 << 10;
a->options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
a->options[APP_OPTIONS_PREALLOC_FIFO_PAIRS] = hcm->prealloc_fifos;
+ a->options[APP_OPTIONS_TLS_ENGINE] = CRYPTO_ENGINE_OPENSSL;
if (hcm->appns_id)
{
a->namespace_id = hcm->appns_id;
@@ -365,6 +369,15 @@ hcc_attach ()
hcm->app_index = a->app_index;
vec_free (a->name);
hcm->test_client_attached = 1;
+
+ clib_memset (ck_pair, 0, sizeof (*ck_pair));
+ ck_pair->cert = (u8 *) test_srv_crt_rsa;
+ ck_pair->key = (u8 *) test_srv_key_rsa;
+ ck_pair->cert_len = test_srv_crt_rsa_len;
+ ck_pair->key_len = test_srv_key_rsa_len;
+ vnet_app_add_cert_key_pair (ck_pair);
+ hcm->ckpair_index = ck_pair->index;
+
return 0;
}
@@ -411,6 +424,14 @@ hcc_connect ()
&a->sep_ext, TRANSPORT_ENDPT_EXT_CFG_HTTP, sizeof (http_cfg));
clib_memcpy (ext_cfg->data, &http_cfg, sizeof (http_cfg));
+ if (hcm->need_crypto)
+ {
+ ext_cfg = session_endpoint_add_ext_cfg (
+ &a->sep_ext, TRANSPORT_ENDPT_EXT_CFG_CRYPTO,
+ sizeof (transport_endpt_crypto_cfg_t));
+ ext_cfg->crypto.ckpair_index = hcm->ckpair_index;
+ }
+
/* allocate http session on main thread */
wrk = hcc_worker_get (0);
hs = hcc_session_alloc (wrk);
@@ -581,6 +602,8 @@ hcc_command_fn (vlib_main_t *vm, unformat_input_t *input,
err = clib_error_return (0, "Uri parse error: %d", rv);
goto done;
}
+ hcm->need_crypto = hcm->connect_sep.transport_proto == TRANSPORT_PROTO_TLS;
+ hcm->connect_sep.transport_proto = TRANSPORT_PROTO_HTTP;
session_enable_disable_args_t args = { .is_en = 1,
.rt_engine_type =
diff --git a/src/plugins/http/http.c b/src/plugins/http/http.c
index c995c996433..fc5b7d5d72d 100644
--- a/src/plugins/http/http.c
+++ b/src/plugins/http/http.c
@@ -179,6 +179,13 @@ http_conn_free (http_conn_t *hc)
pool_put (wrk->conn_pool, hc);
}
+static void
+http_add_postponed_ho_cleanups (u32 ho_hc_index)
+{
+ http_main_t *hm = &http_main;
+ vec_add1 (hm->postponed_ho_free, ho_hc_index);
+}
+
static inline http_conn_t *
http_ho_conn_get (u32 ho_hc_index)
{
@@ -195,12 +202,49 @@ http_ho_conn_free (http_conn_t *ho_hc)
pool_put (hm->ho_conn_pool, ho_hc);
}
+static void
+http_ho_try_free (u32 ho_hc_index)
+{
+ http_conn_t *ho_hc;
+ HTTP_DBG (1, "half open: %x", ho_hc_index);
+ ho_hc = http_ho_conn_get (ho_hc_index);
+ if (!(ho_hc->flags & HTTP_CONN_F_HO_DONE))
+ {
+ HTTP_DBG (1, "postponed cleanup");
+ ho_hc->h_tc_session_handle = SESSION_INVALID_HANDLE;
+ http_add_postponed_ho_cleanups (ho_hc_index);
+ return;
+ }
+ if (!(ho_hc->flags & HTTP_CONN_F_NO_APP_SESSION))
+ session_half_open_delete_notify (&ho_hc->connection);
+ http_ho_conn_free (ho_hc);
+}
+
+static void
+http_flush_postponed_ho_cleanups ()
+{
+ http_main_t *hm = &http_main;
+ u32 *ho_indexp, *tmp;
+
+ tmp = hm->postponed_ho_free;
+ hm->postponed_ho_free = hm->ho_free_list;
+ hm->ho_free_list = tmp;
+
+ vec_foreach (ho_indexp, hm->ho_free_list)
+ http_ho_try_free (*ho_indexp);
+
+ vec_reset_length (hm->ho_free_list);
+}
+
static inline u32
http_ho_conn_alloc (void)
{
http_main_t *hm = &http_main;
http_conn_t *hc;
+ if (vec_len (hm->postponed_ho_free))
+ http_flush_postponed_ho_cleanups ();
+
pool_get_aligned_safe (hm->ho_conn_pool, hc, CLIB_CACHE_LINE_BYTES);
clib_memset (hc, 0, sizeof (*hc));
hc->h_hc_index = hc - hm->ho_conn_pool;
@@ -361,7 +405,7 @@ http_conn_invalidate_timer_cb (u32 hs_handle)
}
hc->timer_handle = HTTP_TIMER_HANDLE_INVALID;
- hc->pending_timer = 1;
+ hc->flags |= HTTP_CONN_F_PENDING_TIMER;
}
static void
@@ -381,7 +425,7 @@ http_conn_timeout_cb (void *hc_handlep)
return;
}
- if (!hc->pending_timer)
+ if (!(hc->flags & HTTP_CONN_F_PENDING_TIMER))
{
HTTP_DBG (1, "timer not pending");
return;
@@ -492,6 +536,7 @@ http_ts_connected_callback (u32 http_app_index, u32 ho_hc_index, session_t *ts,
{
clib_warning ("half-open hc index %d, error: %U", ho_hc_index,
format_session_error, err);
+ ho_hc->flags |= HTTP_CONN_F_HO_DONE;
app_wrk = app_worker_get_if_valid (ho_hc->h_pa_wrk_index);
if (app_wrk)
app_worker_connect_notify (app_wrk, 0, err, ho_hc->h_pa_app_api_ctx);
@@ -503,6 +548,9 @@ http_ts_connected_callback (u32 http_app_index, u32 ho_hc_index, session_t *ts,
clib_memcpy_fast (hc, ho_hc, sizeof (*hc));
+ /* in chain with TLS there is race on half-open cleanup */
+ __atomic_fetch_or (&ho_hc->flags, HTTP_CONN_F_HO_DONE, __ATOMIC_RELEASE);
+
hc->timer_handle = HTTP_TIMER_HANDLE_INVALID;
hc->c_thread_index = ts->thread_index;
hc->h_tc_session_handle = session_handle (ts);
@@ -642,12 +690,12 @@ http_ts_cleanup_callback (session_t *ts, session_cleanup_ntf_t ntf)
}
pool_free (hc->req_pool);
- if (hc->pending_timer == 0)
+ if (!(hc->flags & HTTP_CONN_F_PENDING_TIMER))
http_conn_timer_stop (hc);
session_transport_delete_notify (&hc->connection);
- if (!hc->is_server)
+ if (!(hc->flags & HTTP_CONN_F_IS_SERVER))
{
vec_free (hc->app_name);
vec_free (hc->host);
@@ -658,12 +706,9 @@ http_ts_cleanup_callback (session_t *ts, session_cleanup_ntf_t ntf)
static void
http_ts_ho_cleanup_callback (session_t *ts)
{
- http_conn_t *ho_hc;
u32 ho_hc_index = http_conn_index_from_handle (ts->opaque);
HTTP_DBG (1, "half open: %x", ho_hc_index);
- ho_hc = http_ho_conn_get (ho_hc_index);
- session_half_open_delete_notify (&ho_hc->connection);
- http_ho_conn_free (ho_hc);
+ http_ho_try_free (ho_hc_index);
}
int
@@ -803,7 +848,12 @@ http_transport_connect (transport_endpoint_cfg_t *tep)
hc->timeout = http_cfg->timeout;
}
- hc->is_server = 0;
+ ext_cfg = session_endpoint_get_ext_cfg (sep, TRANSPORT_ENDPT_EXT_CFG_CRYPTO);
+ if (ext_cfg)
+ {
+ HTTP_DBG (1, "app set tls");
+ cargs->sep.transport_proto = TRANSPORT_PROTO_TLS;
+ }
if (vec_len (app->name))
hc->app_name = vec_dup (app->name);
@@ -895,7 +945,7 @@ http_start_listen (u32 app_listener_index, transport_endpoint_cfg_t *tep)
lhc->c_s_index = app_listener_index;
lhc->c_flags |= TRANSPORT_CONNECTION_F_NO_LOOKUP;
- lhc->is_server = 1;
+ lhc->flags |= HTTP_CONN_F_IS_SERVER;
if (vec_len (app->name))
lhc->app_name = vec_dup (app->name);
@@ -1142,6 +1192,12 @@ http_transport_cleanup_ho (u32 ho_hc_index)
HTTP_DBG (1, "half open: %x", ho_hc_index);
ho_hc = http_ho_conn_get (ho_hc_index);
+ if (ho_hc->h_tc_session_handle == SESSION_INVALID_HANDLE)
+ {
+ HTTP_DBG (1, "already pending cleanup");
+ ho_hc->flags |= HTTP_CONN_F_NO_APP_SESSION;
+ return;
+ }
session_cleanup_half_open (ho_hc->h_tc_session_handle);
http_ho_conn_free (ho_hc);
}
diff --git a/src/plugins/http/http1.c b/src/plugins/http/http1.c
index 44dd099ccee..c152956e43c 100644
--- a/src/plugins/http/http1.c
+++ b/src/plugins/http/http1.c
@@ -1028,7 +1028,7 @@ http1_req_state_transport_io_more_data (http_conn_t *hc, http_req_t *req,
* server back to HTTP_REQ_STATE_WAIT_APP_REPLY
* client to HTTP_REQ_STATE_WAIT_APP_METHOD */
if (req->to_recv == 0)
- http_req_state_change (req, hc->is_server ?
+ http_req_state_change (req, (hc->flags & HTTP_CONN_F_IS_SERVER) ?
HTTP_REQ_STATE_WAIT_APP_REPLY :
HTTP_REQ_STATE_WAIT_APP_METHOD);
@@ -1456,7 +1456,7 @@ http1_req_state_app_io_more_data (http_conn_t *hc, http_req_t *req,
/* Finished transaction:
* server back to HTTP_REQ_STATE_WAIT_TRANSPORT_METHOD
* client to HTTP_REQ_STATE_WAIT_TRANSPORT_REPLY */
- http_req_state_change (req, hc->is_server ?
+ http_req_state_change (req, (hc->flags & HTTP_CONN_F_IS_SERVER) ?
HTTP_REQ_STATE_WAIT_TRANSPORT_METHOD :
HTTP_REQ_STATE_WAIT_TRANSPORT_REPLY);
http_buffer_free (hb);
@@ -1635,7 +1635,8 @@ http1_app_tx_callback (http_conn_t *hc, transport_send_params_t *sp)
{
/* Sometimes the server apps can send the response earlier
* than expected (e.g when rejecting a bad request)*/
- if (req->state == HTTP_REQ_STATE_TRANSPORT_IO_MORE_DATA && hc->is_server)
+ if (req->state == HTTP_REQ_STATE_TRANSPORT_IO_MORE_DATA &&
+ (hc->flags & HTTP_CONN_F_IS_SERVER))
{
http_io_ts_drain_all (hc);
http_req_state_change (req, HTTP_REQ_STATE_WAIT_APP_REPLY);
diff --git a/src/plugins/http/http_private.h b/src/plugins/http/http_private.h
index 187d1fe8215..154a63d2402 100644
--- a/src/plugins/http/http_private.h
+++ b/src/plugins/http/http_private.h
@@ -138,6 +138,26 @@ typedef struct http_req_
http_upgrade_proto_t upgrade_proto;
} http_req_t;
+#define foreach_http_conn_flags \
+ _ (HO_DONE, "ho-done") \
+ _ (NO_APP_SESSION, "no-app-session") \
+ _ (PENDING_TIMER, "pending-timer") \
+ _ (IS_SERVER, "is-server")
+
+typedef enum http_conn_flags_bit_
+{
+#define _(sym, str) HTTP_CONN_F_BIT_##sym,
+ foreach_http_conn_flags
+#undef _
+} http_conn_flags_bit_t;
+
+typedef enum http_conn_flags_
+{
+#define _(sym, str) HTTP_CONN_F_##sym = 1 << HTTP_CONN_F_BIT_##sym,
+ foreach_http_conn_flags
+#undef _
+} __clib_packed http_conn_flags_t;
+
typedef struct http_tc_
{
union
@@ -155,10 +175,9 @@ typedef struct http_tc_
http_conn_state_t state;
u32 timer_handle;
u32 timeout;
- u8 pending_timer;
u8 *app_name;
u8 *host;
- u8 is_server;
+ http_conn_flags_t flags;
http_udp_tunnel_mode_t udp_tunnel_mode;
http_req_t *req_pool; /* multiplexing => request per stream */
@@ -174,6 +193,8 @@ typedef struct http_main_
http_worker_t *wrk;
http_conn_t *listener_pool;
http_conn_t *ho_conn_pool;
+ u32 *postponed_ho_free;
+ u32 *ho_free_list;
u32 app_index;
u8 **rx_bufs;
diff --git a/src/plugins/http/http_timer.h b/src/plugins/http/http_timer.h
index 3bd12f7821d..50f634c5397 100644
--- a/src/plugins/http/http_timer.h
+++ b/src/plugins/http/http_timer.h
@@ -59,7 +59,7 @@ http_conn_timer_stop (http_conn_t *hc)
{
http_tw_ctx_t *twc = &http_tw_ctx;
- hc->pending_timer = 0;
+ hc->flags &= ~HTTP_CONN_F_PENDING_TIMER;
if (hc->timer_handle == HTTP_TIMER_HANDLE_INVALID)
return;