Skip to content

Commit

Permalink
Add downstream_compliance_region hostcall (#403)
Browse files Browse the repository at this point in the history
  • Loading branch information
ulyssa authored Jul 27, 2024
1 parent 0596f51 commit cc717db
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 3 deletions.
9 changes: 8 additions & 1 deletion lib/compute-at-edge-abi/compute-at-edge.witx
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,14 @@
(param $ja4_max_len (@witx usize))
(param $nwritten_out (@witx pointer (@witx usize)))
(result $err (expected (error $fastly_status)))
)
)

(@interface func (export "downstream_compliance_region")
(param $region_out (@witx pointer (@witx char8)))
(param $region_max_len (@witx usize))
(param $nwritten_out (@witx pointer (@witx usize)))
(result $err (expected (error $fastly_status)))
)

(@interface func (export "new")
(result $err (expected $request_handle (error $fastly_status)))
Expand Down
10 changes: 8 additions & 2 deletions lib/src/component/http_req.rs
Original file line number Diff line number Diff line change
Expand Up @@ -810,9 +810,15 @@ impl http_req::Host for Session {

async fn downstream_compliance_region(
&mut self,
_max_len: u64,
region_max_len: u64,
) -> Result<Vec<u8>, types::Error> {
Err(Error::NotAvailable("Client TLS JA4 hash").into())
let region = Session::downstream_compliance_region(self);
let region_len = region.len();

match u64::try_from(region_len) {
Ok(region_len) if region_len <= region_max_len => Ok(region.into()),
too_large => Err(types::Error::BufferLen(too_large.unwrap_or(0))),
}
}

async fn original_header_names_get(
Expand Down
13 changes: 13 additions & 0 deletions lib/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,20 @@ use {
tokio::sync::oneshot::Sender,
};

const REGION_NONE: &[u8] = b"none";

/// Data specific to an individual request, including any host-side
/// allocations on behalf of the guest processing the request.
pub struct Session {
/// The downstream IP address and port for this session.
downstream_client_addr: SocketAddr,
/// The IP address and port that received this session.
downstream_server_addr: SocketAddr,
/// The compliance region that this request was received in.
///
/// For now this is just always `"none"`, but we place the field in the session
/// to make it easier to implement custom configuration values later on.
downstream_compliance_region: Vec<u8>,
/// Handle for the downstream request "parts". NB the backing parts data can be mutated
/// or even removed from the relevant map.
downstream_req_handle: RequestHandle,
Expand Down Expand Up @@ -165,6 +172,7 @@ impl Session {
Session {
downstream_server_addr: server_addr,
downstream_client_addr: client_addr,
downstream_compliance_region: Vec::from(REGION_NONE),
downstream_req_handle,
downstream_req_body_handle,
downstream_req_original_headers,
Expand Down Expand Up @@ -204,6 +212,11 @@ impl Session {
self.downstream_server_addr.ip()
}

/// Retrieve the compliance region that received the request for this session.
pub fn downstream_compliance_region(&self) -> &[u8] {
self.downstream_compliance_region.as_slice()
}

/// Retrieve the handle corresponding to the downstream request.
pub fn downstream_request(&self) -> RequestHandle {
self.downstream_req_handle
Expand Down
29 changes: 29 additions & 0 deletions lib/src/wiggle_abi/req_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,35 @@ impl FastlyHttpReq for Session {
Err(Error::NotAvailable("Client TLS JA4 hash"))
}

fn downstream_compliance_region(
&mut self,
memory: &mut GuestMemory<'_>,
// Must be a 16-byte array:
region_out: GuestPtr<u8>,
region_max_len: u32,
nwritten_out: GuestPtr<u32>,
) -> Result<(), Error> {
let region = Session::downstream_compliance_region(self);
let region_len = region.len();

match u32::try_from(region_len) {
Ok(region_len) if region_len <= region_max_len => {
memory.copy_from_slice(region, region_out.as_array(region_max_len))?;
memory.write(nwritten_out, region_len.try_into().unwrap_or(0))?;

Ok(())
}
too_large => {
memory.write(nwritten_out, too_large.unwrap_or(0))?;

Err(Error::BufferLengthError {
buf: "region_out",
len: "region_max_len",
})
}
}
}

fn framing_headers_mode_set(
&mut self,
_memory: &mut GuestMemory<'_>,
Expand Down

0 comments on commit cc717db

Please sign in to comment.