aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorin Coras <fcoras@cisco.com>2022-02-01 13:17:13 -0800
committerDamjan Marion <dmarion@me.com>2022-02-02 10:35:23 +0000
commitbd8013ee8cf3522230f413cf2b7ec0b895cd5979 (patch)
treeca414f3d489ce2eab2ae196ab5ae12c2fdcacfe8
parentd6eed1bb207291e4541f45f229d71358bfb35165 (diff)
http_static: add support for async tx from handlers
URL handlers can send data asynchronously if needed. Type: improvement Signed-off-by: Florin Coras <fcoras@cisco.com> Change-Id: I89eae690cb26543479c7659b5dc46604cbb22eba
-rw-r--r--src/plugins/builtinurl/builtins.c49
-rw-r--r--src/plugins/http_static/builtinurl/json_urls.c49
-rw-r--r--src/plugins/http_static/http_static.c2
-rw-r--r--src/plugins/http_static/http_static.h57
-rw-r--r--src/plugins/http_static/static_server.c76
-rw-r--r--src/plugins/mactime/builtins.c15
6 files changed, 161 insertions, 87 deletions
diff --git a/src/plugins/builtinurl/builtins.c b/src/plugins/builtinurl/builtins.c
index 4ebcd64888f..14b68ce4a58 100644
--- a/src/plugins/builtinurl/builtins.c
+++ b/src/plugins/builtinurl/builtins.c
@@ -18,8 +18,8 @@
#include <http_static/http_static.h>
#include <vpp/app/version.h>
-int
-handle_get_version (http_req_method_t reqtype, u8 *request, hss_session_t *hs)
+hss_url_handler_rc_t
+handle_get_version (hss_url_handler_args_t *args)
{
u8 *s = 0;
@@ -28,11 +28,10 @@ handle_get_version (http_req_method_t reqtype, u8 *request, hss_session_t *hs)
s = format (s, " \"version\": \"%s\",", VPP_BUILD_VER);
s = format (s, " \"build_date\": \"%s\"}}\r\n", VPP_BUILD_DATE);
- hs->data = s;
- hs->data_offset = 0;
- hs->cache_pool_index = ~0;
- hs->free_data = 1;
- return 0;
+ args->data = s;
+ args->data_len = vec_len (s);
+ args->free_vec_data = 1;
+ return HSS_URL_HANDLER_OK;
}
void
@@ -62,9 +61,8 @@ trim_path_from_request (u8 * s, char *path)
}
}
-int
-handle_get_interface_stats (http_req_method_t reqtype, u8 *request,
- hss_session_t *hs)
+hss_url_handler_rc_t
+handle_get_interface_stats (hss_url_handler_args_t *args)
{
u8 *s = 0, *stats = 0;
uword *p;
@@ -80,16 +78,16 @@ handle_get_interface_stats (http_req_method_t reqtype, u8 *request,
vnet_interface_main_t *im = &vnm->interface_main;
/* Get stats for a single interface via http POST */
- if (reqtype == HTTP_REQ_POST)
+ if (args->reqtype == HTTP_REQ_POST)
{
- trim_path_from_request (request, "interface_stats.json");
+ trim_path_from_request (args->request, "interface_stats.json");
/* Find the sw_if_index */
- p = hash_get (im->hw_interface_by_name, request);
+ p = hash_get (im->hw_interface_by_name, args->request);
if (!p)
{
s = format (s, "{\"interface_stats\": {[\n");
- s = format (s, " \"name\": \"%s\",", request);
+ s = format (s, " \"name\": \"%s\",", args->request);
s = format (s, " \"error\": \"%s\"", "UnknownInterface");
s = format (s, "]}\n");
goto out;
@@ -132,18 +130,16 @@ handle_get_interface_stats (http_req_method_t reqtype, u8 *request,
s = format (s, "]}\n");
out:
- hs->data = s;
- hs->data_offset = 0;
- hs->cache_pool_index = ~0;
- hs->free_data = 1;
+ args->data = s;
+ args->data_len = vec_len (s);
+ args->free_vec_data = 1;
vec_free (sw_if_indices);
vec_free (stats);
- return 0;
+ return HSS_URL_HANDLER_OK;
}
-int
-handle_get_interface_list (http_req_method_t reqtype, u8 *request,
- hss_session_t *hs)
+hss_url_handler_rc_t
+handle_get_interface_list (hss_url_handler_args_t *args)
{
u8 *s = 0;
int i;
@@ -176,11 +172,10 @@ handle_get_interface_list (http_req_method_t reqtype, u8 *request,
s = format (s, "]}\n");
vec_free (hw_if_indices);
- hs->data = s;
- hs->data_offset = 0;
- hs->cache_pool_index = ~0;
- hs->free_data = 1;
- return 0;
+ args->data = s;
+ args->data_len = vec_len (s);
+ args->free_vec_data = 1;
+ return HSS_URL_HANDLER_OK;
}
void
diff --git a/src/plugins/http_static/builtinurl/json_urls.c b/src/plugins/http_static/builtinurl/json_urls.c
index ccd70fb1799..0d83d39fade 100644
--- a/src/plugins/http_static/builtinurl/json_urls.c
+++ b/src/plugins/http_static/builtinurl/json_urls.c
@@ -16,8 +16,8 @@
#include <http_static/http_static.h>
#include <vpp/app/version.h>
-int
-handle_get_version (http_req_method_t reqtype, u8 *request, hss_session_t *hs)
+hss_url_handler_rc_t
+handle_get_version (hss_url_handler_args_t *args)
{
u8 *s = 0;
@@ -25,11 +25,10 @@ handle_get_version (http_req_method_t reqtype, u8 *request, hss_session_t *hs)
s = format (s, " \"version\": \"%s\",", VPP_BUILD_VER);
s = format (s, " \"build_date\": \"%s\"}}\r\n", VPP_BUILD_DATE);
- hs->data = s;
- hs->data_offset = 0;
- hs->cache_pool_index = ~0;
- hs->free_data = 1;
- return 0;
+ args->data = s;
+ args->data_len = vec_len (s);
+ args->free_vec_data = 1;
+ return HSS_URL_HANDLER_OK;
}
void
@@ -59,9 +58,8 @@ trim_path_from_request (u8 *s, char *path)
}
}
-int
-handle_get_interface_stats (http_req_method_t reqtype, u8 *request,
- hss_session_t *hs)
+hss_url_handler_rc_t
+handle_get_interface_stats (hss_url_handler_args_t *args)
{
u8 *s = 0, *stats = 0;
uword *p;
@@ -77,16 +75,16 @@ handle_get_interface_stats (http_req_method_t reqtype, u8 *request,
vnet_interface_main_t *im = &vnm->interface_main;
/* Get stats for a single interface via http POST */
- if (reqtype == HTTP_REQ_POST)
+ if (args->reqtype == HTTP_REQ_POST)
{
- trim_path_from_request (request, "interface_stats.json");
+ trim_path_from_request (args->request, "interface_stats.json");
/* Find the sw_if_index */
- p = hash_get (im->hw_interface_by_name, request);
+ p = hash_get (im->hw_interface_by_name, args->request);
if (!p)
{
s = format (s, "{\"interface_stats\": {[\n");
- s = format (s, " \"name\": \"%s\",", request);
+ s = format (s, " \"name\": \"%s\",", args->request);
s = format (s, " \"error\": \"%s\"", "UnknownInterface");
s = format (s, "]}\n");
goto out;
@@ -127,18 +125,16 @@ handle_get_interface_stats (http_req_method_t reqtype, u8 *request,
s = format (s, "]}\n");
out:
- hs->data = s;
- hs->data_offset = 0;
- hs->cache_pool_index = ~0;
- hs->free_data = 1;
+ args->data = s;
+ args->data_len = vec_len (s);
+ args->free_vec_data = 1;
vec_free (sw_if_indices);
vec_free (stats);
- return 0;
+ return HSS_URL_HANDLER_OK;
}
-int
-handle_get_interface_list (http_req_method_t reqtype, u8 *request,
- hss_session_t *hs)
+hss_url_handler_rc_t
+handle_get_interface_list (hss_url_handler_args_t *args)
{
u8 *s = 0;
int i;
@@ -169,11 +165,10 @@ handle_get_interface_list (http_req_method_t reqtype, u8 *request,
s = format (s, "]}\n");
vec_free (hw_if_indices);
- hs->data = s;
- hs->data_offset = 0;
- hs->cache_pool_index = ~0;
- hs->free_data = 1;
- return 0;
+ args->data = s;
+ args->data_len = vec_len (s);
+ args->free_vec_data = 1;
+ return HSS_URL_HANDLER_OK;
}
void
diff --git a/src/plugins/http_static/http_static.c b/src/plugins/http_static/http_static.c
index b8d6931b4c6..4afe42291db 100644
--- a/src/plugins/http_static/http_static.c
+++ b/src/plugins/http_static/http_static.c
@@ -33,7 +33,7 @@
#include <vlibapi/api_helper_macros.h>
__clib_export void
-hss_register_url_handler (hss_url_handler_t fp, const char *url,
+hss_register_url_handler (hss_url_handler_fn fp, const char *url,
http_req_method_t request_type)
{
hss_main_t *hsm = &hss_main;
diff --git a/src/plugins/http_static/http_static.h b/src/plugins/http_static/http_static.h
index 05d6ee05a4c..d3fa29b068d 100644
--- a/src/plugins/http_static/http_static.h
+++ b/src/plugins/http_static/http_static.h
@@ -40,8 +40,10 @@ typedef struct
session_handle_t vpp_session_handle;
/** Fully-resolved file path */
u8 *path;
- /** File data, a vector */
+ /** Data to send */
u8 *data;
+ /** Data length */
+ u32 data_len;
/** Current data send offset */
u32 data_offset;
/** Need to free data in detach_cache_entry */
@@ -50,6 +52,21 @@ typedef struct
u32 cache_pool_index;
} hss_session_t;
+typedef struct hss_session_handle_
+{
+ union
+ {
+ struct
+ {
+ u32 session_index;
+ u32 thread_index;
+ };
+ u64 as_u64;
+ };
+} hss_session_handle_t;
+
+STATIC_ASSERT_SIZEOF (hss_session_handle_t, sizeof (u64));
+
/** \brief In-memory file data cache entry
*/
typedef struct
@@ -67,7 +84,40 @@ typedef struct
int inuse;
} hss_cache_entry_t;
-typedef int (*hss_url_handler_t) (http_req_method_t, u8 *, hss_session_t *);
+typedef struct hss_url_handler_args_
+{
+ hss_session_handle_t sh;
+
+ union
+ {
+ /* Request args */
+ struct
+ {
+ u8 *request;
+ http_req_method_t reqtype;
+ };
+
+ /* Reply args */
+ struct
+ {
+ u8 *data;
+ uword data_len;
+ u8 free_vec_data;
+ http_status_code_t sc;
+ };
+ };
+} hss_url_handler_args_t;
+
+typedef enum hss_url_handler_rc_
+{
+ HSS_URL_HANDLER_OK,
+ HSS_URL_HANDLER_ERROR,
+ HSS_URL_HANDLER_ASYNC,
+} hss_url_handler_rc_t;
+
+typedef hss_url_handler_rc_t (*hss_url_handler_fn) (hss_url_handler_args_t *);
+typedef void (*hss_register_url_fn) (hss_url_handler_fn, char *, int);
+typedef void (*hss_session_send_fn) (hss_url_handler_args_t *args);
/** \brief Main data structure
*/
@@ -139,8 +189,9 @@ int hss_create (vlib_main_t *vm);
/**
* Register a GET or POST URL handler
*/
-void hss_register_url_handler (hss_url_handler_t fp, const char *url,
+void hss_register_url_handler (hss_url_handler_fn fp, const char *url,
http_req_method_t type);
+void hss_session_send_data (hss_url_handler_args_t *args);
void hss_builtinurl_json_handlers_init (void);
#endif /* __included_http_static_h__ */
diff --git a/src/plugins/http_static/static_server.c b/src/plugins/http_static/static_server.c
index a78b5fe4f2b..a9b3fdbb08a 100644
--- a/src/plugins/http_static/static_server.c
+++ b/src/plugins/http_static/static_server.c
@@ -257,9 +257,9 @@ start_send_data (hss_session_t *hs, http_status_code_t status)
msg.type = HTTP_MSG_REPLY;
msg.code = status;
msg.content_type = HTTP_CONTENT_TEXT_HTML;
- msg.data.len = vec_len (hs->data);
+ msg.data.len = hs->data_len;
- if (vec_len (hs->data) > hss_main.use_ptr_thresh)
+ if (hs->data_len > hss_main.use_ptr_thresh)
{
msg.data.type = HTTP_MSG_DATA_PTR;
rv = svm_fifo_enqueue (ts->tx_fifo, sizeof (msg), (u8 *) &msg);
@@ -280,9 +280,9 @@ start_send_data (hss_session_t *hs, http_status_code_t status)
if (!msg.data.len)
goto done;
- rv = svm_fifo_enqueue (ts->tx_fifo, vec_len (hs->data), hs->data);
+ rv = svm_fifo_enqueue (ts->tx_fifo, hs->data_len, hs->data);
- if (rv != vec_len (hs->data))
+ if (rv != hs->data_len)
{
hs->data_offset = rv;
svm_fifo_add_want_deq_ntf (ts->tx_fifo, SVM_FIFO_WANT_DEQ_NOTIF);
@@ -294,12 +294,25 @@ done:
session_send_io_evt_to_thread (ts->tx_fifo, SESSION_IO_EVT_TX);
}
+__clib_export void
+hss_session_send_data (hss_url_handler_args_t *args)
+{
+ hss_session_t *hs;
+
+ hs = hss_session_get (args->sh.thread_index, args->sh.session_index);
+ hs->data = args->data;
+ hs->data_len = args->data_len;
+ hs->free_data = args->free_vec_data;
+ start_send_data (hs, args->sc);
+}
+
static int
try_url_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt,
- u8 *request, http_status_code_t *sc)
+ u8 *request)
{
+ http_status_code_t sc = HTTP_STATUS_OK;
+ hss_url_handler_args_t args = {};
uword *p, *url_table;
- hss_url_handler_t fp;
int rv;
if (!hsm->enable_url_handlers)
@@ -313,24 +326,45 @@ try_url_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt,
if (!p)
return -1;
+ hs->path = 0;
+ hs->data_offset = 0;
+ hs->cache_pool_index = ~0;
+
if (hsm->debug_level > 0)
clib_warning ("%s '%s'", (rt == HTTP_REQ_GET) ? "GET" : "POST", request);
- fp = (hss_url_handler_t) p[0];
- hs->path = 0;
- rv = fp (rt, request, hs);
- if (rv)
+ args.reqtype = rt;
+ args.request = request;
+ args.sh.thread_index = hs->thread_index;
+ args.sh.session_index = hs->session_index;
+
+ rv = ((hss_url_handler_fn) p[0]) (&args);
+
+ /* Wait for data from handler */
+ if (rv == HSS_URL_HANDLER_ASYNC)
+ return 0;
+
+ if (rv == HSS_URL_HANDLER_ERROR)
{
clib_warning ("builtin handler %llx hit on %s '%s' but failed!", p[0],
(rt == HTTP_REQ_GET) ? "GET" : "POST", request);
- *sc = HTTP_STATUS_NOT_FOUND;
+ sc = HTTP_STATUS_NOT_FOUND;
}
+ hs->data = args.data;
+ hs->data_len = args.data_len;
+ hs->free_data = args.free_vec_data;
+
+ start_send_data (hs, sc);
+
+ if (!hs->data)
+ hss_session_disconnect_transport (hs);
+
return 0;
}
static int
-find_data (hss_session_t *hs, http_req_method_t rt, u8 *request)
+handle_request (hss_session_t *hs, http_req_method_t rt, u8 *request)
{
http_status_code_t sc = HTTP_STATUS_OK;
hss_main_t *hsm = &hss_main;
@@ -338,8 +372,8 @@ find_data (hss_session_t *hs, http_req_method_t rt, u8 *request)
clib_error_t *error;
u8 *path;
- if (!try_url_handler (hsm, hs, rt, request, &sc))
- goto done;
+ if (!try_url_handler (hsm, hs, rt, request))
+ return 0;
/*
* Construct the file to open
@@ -541,6 +575,10 @@ find_data (hss_session_t *hs, http_req_method_t rt, u8 *request)
done:
+ start_send_data (hs, sc);
+ if (!hs->data)
+ hss_session_disconnect_transport (hs);
+
return sc;
}
@@ -551,7 +589,6 @@ hss_ts_rx_callback (session_t *ts)
u8 *request = 0;
http_msg_t msg;
int rv;
- http_status_code_t sc;
hs = hss_session_get (ts->thread_index, ts->opaque);
@@ -573,12 +610,9 @@ hss_ts_rx_callback (session_t *ts)
ASSERT (rv == msg.data.len);
/* Find and send data */
- sc = find_data (hs, msg.method_type, request);
- start_send_data (hs, sc);
+ handle_request (hs, msg.method_type, request);
vec_free (request);
- if (!hs->data)
- hss_session_disconnect_transport (hs);
return 0;
}
@@ -594,7 +628,7 @@ hss_ts_tx_callback (session_t *ts)
if (!hs || !hs->data)
return 0;
- to_send = vec_len (hs->data) - hs->data_offset;
+ to_send = hs->data_len - hs->data_offset;
rv = svm_fifo_enqueue (ts->tx_fifo, to_send, hs->data + hs->data_offset);
if (rv <= 0)
@@ -982,7 +1016,7 @@ format_hss_session (u8 *s, va_list *args)
int __clib_unused verbose = va_arg (*args, int);
s = format (s, "\n path %s, data length %u, data_offset %u",
- hs->path ? hs->path : (u8 *) "[none]", vec_len (hs->data),
+ hs->path ? hs->path : (u8 *) "[none]", hs->data_len,
hs->data_offset);
return s;
}
diff --git a/src/plugins/mactime/builtins.c b/src/plugins/mactime/builtins.c
index d039f7bff7f..c487d0375bf 100644
--- a/src/plugins/mactime/builtins.c
+++ b/src/plugins/mactime/builtins.c
@@ -14,8 +14,8 @@ mactime_ip_neighbor_copy (index_t ipni, void *ctx)
return (WALK_CONTINUE);
}
-static int
-handle_get_mactime (http_req_method_t reqtype, u8 *request, hss_session_t *hs)
+static hss_url_handler_rc_t
+handle_get_mactime (hss_url_handler_args_t *args)
{
mactime_main_t *mm = &mactime_main;
mactime_device_t *dp;
@@ -145,17 +145,16 @@ handle_get_mactime (http_req_method_t reqtype, u8 *request, hss_session_t *hs)
vec_free (macstring);
vec_free (pool_indices);
- hs->data = s;
- hs->data_offset = 0;
- hs->cache_pool_index = ~0;
- hs->free_data = 1;
- return 0;
+ args->data = s;
+ args->data_len = vec_len (s);
+ args->free_vec_data = 1;
+ return HSS_URL_HANDLER_OK;
}
void
mactime_url_init (vlib_main_t * vm)
{
- void (*fp) (void *, char *, int);
+ hss_register_url_fn fp;
/* Look up the builtin URL registration handler */
fp = vlib_get_plugin_symbol ("http_static_plugin.so",