rv = SSL_do_handshake (oc->ssl);
err = SSL_get_error (oc->ssl, rv);
+
+ if (err == SSL_ERROR_SSL)
+ {
+ char buf[512];
+ ERR_error_string (ERR_get_error (), buf);
+ clib_warning ("Err: %s", buf);
+
+ /*
+ * Cleanup pre-allocated app session and close transport
+ */
+ if (SSL_is_server (oc->ssl))
+ {
+ session_free (session_get (ctx->c_s_index,
+ ctx->c_thread_index));
+ ctx->no_app_session = 1;
+ ctx->c_s_index = SESSION_INVALID_INDEX;
+ tls_disconnect_transport (ctx);
+ }
+ else
+ tls_notify_app_connected (ctx, /* is failed */ 1);
+ return -1;
+ }
+
openssl_try_handshake_write (oc, tls_session);
#ifdef HAVE_OPENSSL_ASYNC
if (err == SSL_ERROR_WANT_ASYNC)
#endif
if (err != SSL_ERROR_WANT_WRITE)
- {
- if (err == SSL_ERROR_SSL)
- {
- char buf[512];
- ERR_error_string (ERR_get_error (), buf);
- clib_warning ("Err: %s", buf);
- }
- break;
- }
+ break;
}
TLS_DBG (2, "tls state for %u is %s", oc->openssl_ctx_index,
SSL_state_string_long (oc->ssl));
return rv;
}
+static void
+openssl_confirm_app_close (tls_ctx_t * ctx)
+{
+ tls_disconnect_transport (ctx);
+ session_transport_closed_notify (&ctx->connection);
+}
+
static inline int
openssl_ctx_write (tls_ctx_t * ctx, session_t * app_session)
{
if (BIO_ctrl_pending (oc->rbio) > 0)
tls_add_vpp_q_builtin_tx_evt (app_session);
+ else if (ctx->app_closed)
+ openssl_confirm_app_close (ctx);
return wrote;
}
static int
openssl_app_close (tls_ctx_t * ctx)
{
- tls_disconnect_transport (ctx);
- session_transport_delete_notify (&ctx->connection);
- openssl_ctx_free (ctx);
+ openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
+ session_t *app_session;
+
+ /* Wait for all data to be written to tcp */
+ app_session = session_get_from_handle (ctx->app_session_handle);
+ if (BIO_ctrl_pending (oc->rbio) <= 0
+ && !svm_fifo_max_dequeue_cons (app_session->tx_fifo))
+ openssl_confirm_app_close (ctx);
+ else
+ ctx->app_closed = 1;
return 0;
}
return 0;
failed:
+ /* Free app session pre-allocated when transport was established */
+ session_free (session_get (ctx->c_s_index, ctx->c_thread_index));
+ ctx->no_app_session = 1;
tls_disconnect (ctx->tls_ctx_handle, vlib_get_thread_index ());
return app_worker_connect_notify (app_wrk, 0, ctx->parent_app_api_context);
}
void
tls_ctx_free (tls_ctx_t * ctx)
{
- vec_free (ctx->srv_hostname);
tls_vfts[ctx->tls_ctx_engine].ctx_free (ctx);
}
return tls_ctx_init_client (ctx);
}
+static void
+tls_app_session_cleanup (session_t * s, session_cleanup_ntf_t ntf)
+{
+ tls_ctx_t *ctx;
+
+ if (ntf == SESSION_CLEANUP_TRANSPORT)
+ return;
+
+ ctx = tls_ctx_get (s->opaque);
+ if (!ctx->no_app_session)
+ session_transport_delete_notify (&ctx->connection);
+ tls_ctx_free (ctx);
+}
+
/* *INDENT-OFF* */
static session_cb_vft_t tls_app_cb_vft = {
.session_accept_callback = tls_session_accept_callback,
.add_segment_callback = tls_add_segment_callback,
.del_segment_callback = tls_del_segment_callback,
.builtin_app_rx_callback = tls_app_rx_callback,
+ .session_cleanup_callback = tls_app_session_cleanup,
};
/* *INDENT-ON* */