Skip to content

Commit

Permalink
Merge db0cb30 into 21732b1
Browse files Browse the repository at this point in the history
  • Loading branch information
hishamhm authored Oct 26, 2023
2 parents 21732b1 + db0cb30 commit 8307833
Show file tree
Hide file tree
Showing 9 changed files with 1,632 additions and 40 deletions.
4 changes: 4 additions & 0 deletions lib/resty/wasmx.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@ ffi.cdef [[
ngx_str_t *config;
} ngx_wasm_filter_t;

typedef intptr_t ngx_int_t;
typedef unsigned char u_char;
typedef struct ngx_wavm_t ngx_wasm_vm_t;
typedef struct ngx_wasm_ops_plan_t ngx_wasm_plan_t;

typedef ngx_int_t (*ngx_wasm_host_prop_fn_t)(void *data, ngx_str_t *key,
ngx_str_t *value);

ngx_wasm_vm_t *ngx_wasm_ffi_main_vm();
]]

Expand Down
220 changes: 200 additions & 20 deletions lib/resty/wasmx/proxy_wasm.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ local C = ffi.C
local ngx = ngx
local error = error
local type = type
local pcall = pcall
local ffi_gc = ffi.gc
local ffi_new = ffi.new
local ffi_str = ffi.string
local tostring = tostring
local subsystem = ngx.config.subsystem
local get_request = wasmx.get_request
local get_err_ptr = wasmx.get_err_ptr
Expand Down Expand Up @@ -38,23 +40,32 @@ local _M = {

if subsystem == "http" then
ffi.cdef [[
int ngx_http_wasm_ffi_plan_new(ngx_wasm_vm_t *vm,
ngx_wasm_filter_t *filters,
size_t n_filters,
ngx_wasm_plan_t **out,
u_char *err, size_t *errlen);
int ngx_http_wasm_ffi_plan_free(ngx_wasm_plan_t *plan);
int ngx_http_wasm_ffi_plan_load(ngx_wasm_plan_t *plan);
int ngx_http_wasm_ffi_plan_attach(ngx_http_request_t *r,
ngx_wasm_plan_t *plan,
unsigned int isolation);
int ngx_http_wasm_ffi_start(ngx_http_request_t *r);
int ngx_http_wasm_ffi_set_property(ngx_http_request_t *r,
ngx_str_t *key,
ngx_str_t *value);
int ngx_http_wasm_ffi_get_property(ngx_http_request_t *r,
ngx_str_t *key,
ngx_str_t *out);
ngx_int_t ngx_http_wasm_ffi_plan_new(ngx_wasm_vm_t *vm,
ngx_wasm_filter_t *filters,
size_t n_filters,
ngx_wasm_plan_t **out,
u_char *err, size_t *errlen);
ngx_int_t ngx_http_wasm_ffi_plan_free(ngx_wasm_plan_t *plan);
ngx_int_t ngx_http_wasm_ffi_plan_load(ngx_wasm_plan_t *plan);
ngx_int_t ngx_http_wasm_ffi_plan_attach(ngx_http_request_t *r,
ngx_wasm_plan_t *plan,
unsigned int isolation);
ngx_int_t ngx_http_wasm_ffi_start(ngx_http_request_t *r);
ngx_int_t ngx_http_wasm_ffi_set_property(ngx_http_request_t *r,
ngx_str_t *key,
ngx_str_t *value);
ngx_int_t ngx_http_wasm_ffi_get_property(ngx_http_request_t *r,
ngx_str_t *key,
ngx_str_t *out);
ngx_int_t ngx_http_wasm_ffi_set_host_property(ngx_http_request_t *r,
ngx_str_t *key,
ngx_str_t *value,
unsigned is_const,
unsigned retrieve);
ngx_int_t ngx_http_wasm_ffi_set_property_setter(ngx_http_request_t *r,
ngx_wasm_host_prop_fn_t fn);
ngx_int_t ngx_http_wasm_ffi_set_property_getter(ngx_http_request_t *r,
ngx_wasm_host_prop_fn_t fn);
]]

else
Expand Down Expand Up @@ -229,7 +240,7 @@ function _M.set_property(key, value)
error("key must be a string", 2)
end

if type(value) ~= "string" then
if value ~= nil and type(value) ~= "string" then
error("value must be a string", 2)
end

Expand All @@ -238,8 +249,14 @@ function _M.set_property(key, value)
error("no request found", 2)
end

local ckey = ffi_new("ngx_str_t", { data = key, len = #key })
local cvalue = ffi_new("ngx_str_t", { data = value, len = #value })
local ckey = ffi_new("ngx_str_t", {
data = key,
len = #key
})
local cvalue = ffi_new("ngx_str_t", {
data = value,
len = value and #value or 0
})

local rc = C.ngx_http_wasm_ffi_set_property(r, ckey, cvalue)
if rc == FFI_ERROR then
Expand Down Expand Up @@ -280,4 +297,167 @@ function _M.get_property(key)
end


do
-- LuaJIT C callbacks are a limited resource:
-- We can't create one of these on each request,
-- so we prepare these wrappers, which in turn call a Lua function.
local lua_prop_setter
local lua_prop_getter
local c_prop_setter
local c_prop_getter


local function update_cvalue(cvalue, lvalue)
if lvalue == nil then
cvalue.data = nil
cvalue.len = 0
return
end

local value = tostring(lvalue)
cvalue.data = value
cvalue.len = #value
end


local function jit_wrap(fn)
return function(r, ckey, cvalue)
jit.off()
local rc = fn(r, ckey, cvalue)
jit.on()
return rc
end
end


c_prop_setter = ffi.cast("ngx_wasm_host_prop_fn_t",
jit_wrap(function(r, ckey, cvalue)
local lkey = ffi_str(ckey.data, ckey.len)
local lval
if cvalue.data ~= nil then
lval = ffi_str(cvalue.data, cvalue.len)
end

local pok, ok, lvalue, is_const = pcall(lua_prop_setter, lkey, lval)
if not pok then
ngx.log(ngx.ERR, "error setting property from Lua: ", ok)
return FFI_ERROR
end

if not ok then
local err = lvalue or "unknown error"
ngx.log(ngx.ERR, "error setting property: ", err)
return FFI_ERROR
end

update_cvalue(cvalue, lvalue)

return C.ngx_http_wasm_ffi_set_host_property(r, ckey, cvalue,
is_const and 1 or 0,
0)
end))


c_prop_getter = ffi.cast("ngx_wasm_host_prop_fn_t",
jit_wrap(function(r, ckey, cvalue)
local lkey = ffi_str(ckey.data, ckey.len)

local pok, ok, lvalue, is_const = pcall(lua_prop_getter, lkey)
if not pok then
ngx.log(ngx.ERR, "error getting property from Lua: ", ok)
return FFI_ERROR
end

if not ok then
if lvalue then
ngx.log(ngx.ERR, "error setting property: ", lvalue)
return FFI_ERROR
end

return FFI_DECLINED
end

update_cvalue(cvalue, lvalue)

local rc = C.ngx_http_wasm_ffi_set_host_property(r, ckey, cvalue,
is_const and 1 or 0,
1)
if rc == FFI_OK and lvalue == nil then
return FFI_DECLINED
end

return rc
end))


---
-- Define a setter function for host-managed properties.
--
-- @param setter The setter function is the handler for updating properties.
-- Its type signature is `function(string, string): boolean, string`,
-- where the inputs are the property key and value and the results are:
-- * `truthy` - success setting the property
-- * `truthy, value` - success, cache property value (useful if hosts
-- sets only a setter but not a getter)
-- * `truthy, value, truthy` - success, constant property value: further
-- requests to the same property during a request are cached by
-- ngx_wasm_module and do not invoke the Lua getter.
-- * `falsy, err` - failure, and an optional error message
-- @return true on success setting the getter, or nil and an error message.
function _M.set_property_setter(setter)
if type(setter) ~= "function" then
error("setter must be a function", 2)
end

local r = get_request()
if not r then
error("no request found", 2)
end

lua_prop_setter = setter

local rc = C.ngx_http_wasm_ffi_set_property_setter(r, c_prop_setter)
if rc == FFI_OK then
return true
end

return nil, "could not set property setter"
end


---
-- Define a getter function for host-managed properties.
--
-- @param getter The getter function is the handler for resolving properties.
-- Its type signature is `function(string): boolean, string, boolean`,
-- where the input is the property key and the results are:
-- * `truthy, value` - success, property value
-- * `truthy, value, truthy` - success, constant property value: further
-- requests to the same property during a request are cached by
-- ngx_wasm_module and do not invoke the Lua getter.
-- * `falsy` - property not found
-- * `falsy, err` - failure, error message
-- @return true on success setting the getter, or nil and an error message.
function _M.set_property_getter(getter)
if type(getter) ~= "function" then
error("getter must be a function", 2)
end

local r = get_request()
if not r then
error("no request found", 2)
end

lua_prop_getter = getter

local rc = C.ngx_http_wasm_ffi_set_property_getter(r, c_prop_getter)
if rc == FFI_OK then
return true
end

return nil, "could not set property getter"
end
end


return _M
58 changes: 58 additions & 0 deletions src/common/lua/ngx_wasm_lua_ffi.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,21 @@ ngx_http_wasm_ffi_start(ngx_http_request_t *r)
}


static ngx_inline ngx_proxy_wasm_ctx_t *
get_pwctx(ngx_http_request_t *r)
{
ngx_http_wasm_req_ctx_t *rctx;

if (ngx_http_wasm_rctx(r, &rctx) != NGX_OK) {
return NULL;
}

return ngx_proxy_wasm_ctx(NULL, 0,
NGX_PROXY_WASM_ISOLATION_STREAM,
&ngx_http_proxy_wasm, rctx);
}


ngx_int_t
ngx_http_wasm_ffi_set_property(ngx_http_request_t *r,
ngx_str_t *key, ngx_str_t *value)
Expand Down Expand Up @@ -226,4 +241,47 @@ ngx_http_wasm_ffi_get_property(ngx_http_request_t *r,

return ngx_proxy_wasm_properties_get(pwctx, key, value);
}


ngx_int_t
ngx_http_wasm_ffi_set_host_property(ngx_http_request_t *r,
ngx_str_t *key, ngx_str_t *value, unsigned is_const, unsigned retrieve)
{
ngx_proxy_wasm_ctx_t *pwctx = get_pwctx(r);

if (pwctx == NULL) {
return NGX_ERROR;
}

return ngx_proxy_wasm_properties_set_host(pwctx, key, value, is_const,
retrieve);
}


ngx_int_t
ngx_http_wasm_ffi_set_property_setter(ngx_http_request_t *r,
ngx_wasm_host_prop_fn_t fn)
{
ngx_proxy_wasm_ctx_t *pwctx = get_pwctx(r);

if (pwctx == NULL) {
return NGX_ERROR;
}

return ngx_proxy_wasm_properties_set_host_prop_setter(pwctx, fn, r);
}


ngx_int_t
ngx_http_wasm_ffi_set_property_getter(ngx_http_request_t *r,
ngx_wasm_host_prop_fn_t fn)
{
ngx_proxy_wasm_ctx_t *pwctx = get_pwctx(r);

if (pwctx == NULL) {
return NGX_ERROR;
}

return ngx_proxy_wasm_properties_set_host_prop_getter(pwctx, fn, r);
}
#endif
6 changes: 6 additions & 0 deletions src/common/lua/ngx_wasm_lua_ffi.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ ngx_int_t ngx_http_wasm_ffi_set_property(ngx_http_request_t *r,
ngx_str_t *key, ngx_str_t *value);
ngx_int_t ngx_http_wasm_ffi_get_property(ngx_http_request_t *r,
ngx_str_t *key, ngx_str_t *value);
ngx_int_t ngx_http_wasm_ffi_set_host_property(ngx_http_request_t *r,
ngx_str_t *key, ngx_str_t *value, unsigned is_const, unsigned retrieve);
ngx_int_t ngx_http_wasm_ffi_set_property_setter(ngx_http_request_t *r,
ngx_wasm_host_prop_fn_t fn);
ngx_int_t ngx_http_wasm_ffi_set_property_getter(ngx_http_request_t *r,
ngx_wasm_host_prop_fn_t fn);
#endif


Expand Down
9 changes: 8 additions & 1 deletion src/common/proxy_wasm/ngx_proxy_wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@ typedef struct ngx_http_proxy_wasm_dispatch_s ngx_http_proxy_wasm_dispatch_t;

typedef ngx_str_t ngx_proxy_wasm_marshalled_map_t;

typedef ngx_int_t (*ngx_wasm_host_prop_fn_t)(void *data, ngx_str_t *key,
ngx_str_t *value);


typedef struct {
ngx_queue_t busy;
Expand Down Expand Up @@ -245,10 +248,14 @@ struct ngx_proxy_wasm_ctx_s {
ngx_uint_t call_code;
ngx_uint_t response_code;

/* host properties rbtree */
/* host properties */

ngx_rbtree_t host_props_tree;
ngx_rbtree_node_t host_props_sentinel;
ngx_wasm_host_prop_fn_t host_prop_getter;
ngx_wasm_host_prop_fn_t host_prop_setter;
void *host_prop_getter_data;
void *host_prop_setter_data;

/* flags */

Expand Down
Loading

0 comments on commit 8307833

Please sign in to comment.