Skip to content

Commit

Permalink
Add stubs for shielding hostcalls
Browse files Browse the repository at this point in the history
  • Loading branch information
ulyssa committed Nov 11, 2024
1 parent f457b28 commit 5f08d6a
Show file tree
Hide file tree
Showing 10 changed files with 305 additions and 0 deletions.
161 changes: 161 additions & 0 deletions crates/adapter/src/fastly/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3547,3 +3547,164 @@ pub mod fastly_purge {
)
}
}

pub mod fastly_shielding {
use super::*;
use crate::bindings::fastly::api::{shielding as host, types};
use std::slice;

bitflags::bitflags! {
#[derive(Default)]
#[repr(transparent)]
pub struct ShieldBackendOptions: u32 {
const RESERVED = 1 << 0;
const CACHE_KEY = 1 << 1;
}
}

#[repr(C)]
pub struct ShieldBackendConfig {
pub cache_key: *const u8,
pub cache_key_len: u32,
}

impl Default for ShieldBackendConfig {
fn default() -> Self {
ShieldBackendConfig {
cache_key: std::ptr::null(),
cache_key_len: 0,
}
}
}

#[export_name = "fastly_shielding#shield_info"]
pub fn shield_info(
name: *const u8,
name_len: usize,
info_block: *mut u8,
info_block_len: usize,
nwritten_out: *mut u32,
) -> FastlyStatus {
let name = unsafe { slice::from_raw_parts(name, name_len) };
with_buffer!(
info_block,
info_block_len,
{ host::shield_info(name, u64::try_from(info_block_len).trapping_unwrap()) },
|res| {
match res {
Ok(res) => {
unsafe {
*nwritten_out = u32::try_from(res.len()).unwrap_or(0);
}
std::mem::forget(res);
}

Err(e) => {
if let types::Error::BufferLen(needed) = e {
unsafe {
*nwritten_out = u32::try_from(needed).unwrap_or(0);
}
}

return Err(e.into());
}
}
}
)
}

impl From<ShieldBackendOptions> for host::ShieldBackendOptionsMask {
fn from(value: ShieldBackendOptions) -> Self {
let mut flags = Self::empty();

flags.set(
Self::RESERVED,
value.contains(ShieldBackendOptions::RESERVED),
);
flags.set(
Self::CACHE_KEY,
value.contains(ShieldBackendOptions::CACHE_KEY),
);

flags
}
}

fn shield_backend_options(
mask: ShieldBackendOptions,
options: *const ShieldBackendConfig,
) -> (host::ShieldBackendOptionsMask, host::ShieldBackendOptions) {
let mask = host::ShieldBackendOptionsMask::from(mask);

// NOTE: this is only really safe because we never mutate the vectors -- we only need
// vectors to satisfy the interface produced by the DynamicBackendConfig record,
// `register_dynamic_backend` will never mutate the vectors it's given.
macro_rules! make_vec {
($ptr_field:ident, $len_field:ident) => {
unsafe {
let len = usize::try_from((*options).$len_field).trapping_unwrap();
Vec::from_raw_parts((*options).$ptr_field as *mut _, len, len)
}
};
}

let options = host::ShieldBackendOptions {
cache_key: if mask.contains(host::ShieldBackendOptionsMask::CACHE_KEY) {
make_vec!(cache_key, cache_key_len)
} else {
Vec::new()
},
};

(mask, options)
}

/// Turn a pop name into a backend that we can send requests to.
#[export_name = "fastly_shielding#backend_for_shield"]
pub fn backend_for_shield(
name: *const u8,
name_len: usize,
options_mask: ShieldBackendOptions,
options: *const ShieldBackendConfig,
backend_name: *mut u8,
backend_name_len: usize,
nwritten_out: *mut u32,
) -> FastlyStatus {
let name = unsafe { slice::from_raw_parts(name, name_len) };
let (mask, options) = shield_backend_options(options_mask, options);
with_buffer!(
backend_name,
backend_name_len,
{
let res = host::backend_for_shield(
name,
mask,
&options,
u64::try_from(backend_name_len).trapping_unwrap(),
);
std::mem::forget(options);
res
},
|res| {
match res {
Ok(res) => {
unsafe {
*nwritten_out = u32::try_from(res.len()).unwrap_or(0);
}
std::mem::forget(res);
}

Err(e) => {
if let types::Error::BufferLen(needed) = e {
unsafe {
*nwritten_out = u32::try_from(needed).unwrap_or(0);
}
}

return Err(e.into());
}
}
}
)
}
}
1 change: 1 addition & 0 deletions lib/compute-at-edge-abi/compute-at-edge.witx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
(use "cache.witx")
(use "config-store.witx")
(use "http-cache.witx")
(use "shielding.witx")

(module $fastly_abi
(@interface func (export "init")
Expand Down
31 changes: 31 additions & 0 deletions lib/compute-at-edge-abi/shielding.witx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
(typename $shield_backend_options
(flags (@witx repr u32)
$reserved
$use_cache_key
))

(typename $shield_backend_config
(record
(field $cache_key (@witx pointer (@witx char8)))
(field $cache_key_len u32)
))

(module $fastly_shielding

(@interface func (export "shield_info")
(param $name string)
(param $info_block (@witx pointer (@witx char8)))
(param $info_block_max_len (@witx usize))
(result $err (expected $num_bytes (error $fastly_status)))
)

(@interface func (export "backend_for_shield")
(param $shield_name string)
(param $backend_config_mask $shield_backend_options)
(param $backend_configuration (@witx pointer $shield_backend_config))
(param $backend_name_out (@witx pointer (@witx char8)))
(param $backend_name_max_len (@witx usize))
(result $err (expected $num_bytes (error $fastly_status)))
)

)
Binary file modified lib/data/viceroy-component-adapter.wasm
Binary file not shown.
2 changes: 2 additions & 0 deletions lib/src/component/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ pub fn link_host_functions(linker: &mut component::Linker<ComponentCtx>) -> anyh
fastly::api::object_store::add_to_linker(linker, |x| x)?;
fastly::api::purge::add_to_linker(linker, |x| x)?;
fastly::api::secret_store::add_to_linker(linker, |x| x)?;
fastly::api::shielding::add_to_linker(linker, |x| x)?;
fastly::api::types::add_to_linker(linker, |x| x)?;
fastly::api::uap::add_to_linker(linker, |x| x)?;

Expand Down Expand Up @@ -91,5 +92,6 @@ pub mod log;
pub mod object_store;
pub mod purge;
pub mod secret_store;
pub mod shielding;
pub mod types;
pub mod uap;
29 changes: 29 additions & 0 deletions lib/src/component/shielding.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use super::fastly::api::{shielding, types};
use crate::linking::ComponentCtx;

#[async_trait::async_trait]
impl shielding::Host for ComponentCtx {
async fn shield_info(&mut self, name: Vec<u8>, _max_len: u64) -> Result<Vec<u8>, types::Error> {
// Validate input name and return the unsupported error.
let _name = String::from_utf8(name)?;

Err(types::Error::Unsupported)
}

async fn backend_for_shield(
&mut self,
name: Vec<u8>,
options_mask: shielding::ShieldBackendOptionsMask,
options: shielding::ShieldBackendOptions,
_max_len: u64,
) -> Result<Vec<u8>, types::Error> {
// Validate our inputs and return the unsupported error.
let _target_shield = String::from_utf8(name)?;

if options_mask.contains(shielding::ShieldBackendOptionsMask::CACHE_KEY) {
let _ = String::from_utf8(options.cache_key)?;
}

Err(types::Error::Unsupported)
}
}
1 change: 1 addition & 0 deletions lib/src/linking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ pub fn link_host_functions(
wiggle_abi::fastly_object_store::add_to_linker(linker, WasmCtx::session)?;
wiggle_abi::fastly_purge::add_to_linker(linker, WasmCtx::session)?;
wiggle_abi::fastly_secret_store::add_to_linker(linker, WasmCtx::session)?;
wiggle_abi::fastly_shielding::add_to_linker(linker, WasmCtx::session)?;
wiggle_abi::fastly_uap::add_to_linker(linker, WasmCtx::session)?;
link_legacy_aliases(linker)?;
Ok(())
Expand Down
1 change: 1 addition & 0 deletions lib/src/wiggle_abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ mod obj_store_impl;
mod req_impl;
mod resp_impl;
mod secret_store_impl;
mod shielding;
mod uap_impl;

// Expand the `.witx` interface definition into a collection of modules. The `types` module will
Expand Down
53 changes: 53 additions & 0 deletions lib/src/wiggle_abi/shielding.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use crate::error::Error;
use crate::session::Session;
use crate::wiggle_abi::{fastly_shielding, types};

impl fastly_shielding::FastlyShielding for Session {
fn shield_info(
&mut self,
memory: &mut wiggle::GuestMemory<'_>,
name: wiggle::GuestPtr<str>,
_out_buffer: wiggle::GuestPtr<u8>,
_out_buffer_max_len: u32,
) -> Result<u32, Error> {
// Validate the input name and then return the unsupported error.
let name_bytes = memory.to_vec(name.as_bytes())?;
let _name = String::from_utf8(name_bytes).map_err(|_| Error::InvalidArgument)?;

Err(Error::Unsupported {
msg: "shielding hostcalls are not supported",
})
}

fn backend_for_shield(
&mut self,
memory: &mut wiggle::GuestMemory<'_>,
shield_name: wiggle::GuestPtr<str>,
shield_backend_options: types::ShieldBackendOptions,
shield_backend_config: wiggle::GuestPtr<types::ShieldBackendConfig>,
_out_buffer: wiggle::GuestPtr<u8>,
_out_buffer_max_len: u32,
) -> Result<u32, Error> {
// Validate our inputs and then return the unsupported error.
let Some(_) = memory.as_str(shield_name)?.map(str::to_string) else {
return Err(Error::ValueAbsent);
};

if shield_backend_options.contains(types::ShieldBackendOptions::RESERVED) {
return Err(Error::InvalidArgument);
}

let config = memory.read(shield_backend_config)?;

if shield_backend_options.contains(types::ShieldBackendOptions::USE_CACHE_KEY) {
let field_string = config.cache_key.as_array(config.cache_key_len).cast();
if memory.as_str(field_string)?.is_none() {
return Err(Error::InvalidArgument);
}
}

Err(Error::Unsupported {
msg: "shielding hostcalls are not supported",
})
}
}
26 changes: 26 additions & 0 deletions lib/wit/deps/fastly/compute.wit
Original file line number Diff line number Diff line change
Expand Up @@ -1334,6 +1334,31 @@ interface config-store {
) -> result<option<list<u8>>, error>;
}

interface shielding {
use types.{error};

shield-info: func(
name: list<u8>,
max-len: u64,
) -> result<list<u8>, error>;

flags shield-backend-options-mask {
reserved,
cache-key,
}

record shield-backend-options {
cache-key: list<u8>,
}

backend-for-shield: func(
name: list<u8>,
options-mask: shield-backend-options-mask,
options: shield-backend-options,
max-len: u64,
) -> result<list<u8>, error>;
}

interface reactor {
use http-types.{request-handle, body-handle};

Expand Down Expand Up @@ -1381,6 +1406,7 @@ world compute {
import object-store;
import purge;
import secret-store;
import shielding;
import config-store;
import uap;

Expand Down

0 comments on commit 5f08d6a

Please sign in to comment.