Skip to content

Commit

Permalink
🌭 Update ABI definitions and stub out some hostcalls (#307)
Browse files Browse the repository at this point in the history
Adds several new hostcalls and type definitions to the ABI. The level of implementation varies:

- `fastly_http_body::abandon` is fully implemented.

- `fastly_http_req::send_v2` and friends will work, but do not yet populate the new `$error_detail`
  field with information about the failure.

- `fastly_http_req` hostcalls `downstream_client_oh_fingerprint`, `redirect_to_websocket_proxy_v2`,
  `redirect_to_grip_proxy_v2`, and `fastly_key_is_valid` are stubs that return
  `Error::NotAvailable`.

Beyond these added functions, there are a number of formatting fixes in the witx to make the Viceroy
copy of these files more precisely match what we use internally to define the platform.
  • Loading branch information
acfoltzer authored Sep 12, 2023
1 parent ec827ab commit 542dc04
Show file tree
Hide file tree
Showing 5 changed files with 269 additions and 29 deletions.
112 changes: 97 additions & 15 deletions lib/compute-at-edge-abi/compute-at-edge.witx
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,21 @@
(result $err (expected $num_bytes (error $fastly_status)))
)

;;; Frees the body on the host.
;;;
;;; For streaming bodies, this is a _successful_ stream termination, which will signal
;;; via framing that the body transfer is complete.
(@interface func (export "close")
(param $h $body_handle)
(result $err (expected (error $fastly_status)))
)

;;; Frees a streaming body on the host _unsuccessfully_, so that framing makes clear that
;;; the body is incomplete.
(@interface func (export "abandon")
(param $h $body_handle)
(result $err (expected (error $fastly_status)))
)
)

(module $fastly_log
Expand All @@ -81,8 +92,7 @@
(@interface func (export "body_downstream_get")
(result $err (expected
(tuple $request_handle $body_handle)
(error $fastly_status))
)
(error $fastly_status)))
)

(@interface func (export "cache_override_set")
Expand All @@ -103,7 +113,7 @@
)

(@interface func (export "downstream_client_ip_addr")
;;; must be a 16-byte array
;; must be a 16-byte array
(param $addr_octets_out (@witx pointer (@witx char8)))
(result $err (expected $num_bytes (error $fastly_status)))
)
Expand All @@ -122,6 +132,13 @@
(result $err (expected (error $fastly_status)))
)

(@interface func (export "downstream_client_oh_fingerprint")
(param $ohfp_out (@witx pointer (@witx char8)))
(param $ohfp_max_len (@witx usize))
(param $nwritten_out (@witx pointer (@witx usize)))
(result $err (expected (error $fastly_status)))
)

(@interface func (export "downstream_tls_cipher_openssl_name")
(param $cipher_out (@witx pointer (@witx char8)))
(param $cipher_max_len (@witx usize))
Expand Down Expand Up @@ -280,17 +297,37 @@
(param $backend string)
(result $err (expected
(tuple $response_handle $body_handle)
(error $fastly_status))
)
(error $fastly_status)))
)

;; The behavior of this method is identical to the original except for the `$error_detail`
;; out-parameter.
;;
;; If the returned `$fastly_status` is OK, `$error_detail` will not be read. Otherwise,
;; the status is returned identically to the original `send`, but `$error_detail` is populated.
;; Since `$send_error_detail` provides much more granular information about failures, it should
;; be used by SDKs as the primary source of error information in favor of `$fastly_status`.
;;
;; Make sure to initialize `$error_detail` with the full complement of mask values that the
;; guest supports. If the corresponding bits in the mask are not set, the host will not populate
;; fields in the `$error_detail` struct even if there are values available for those fields.
;; This allows forward compatibility when new fields are added.
(@interface func (export "send_v2")
(param $h $request_handle)
(param $b $body_handle)
(param $backend string)
(param $error_detail (@witx pointer $send_error_detail))
(result $err (expected
(tuple $response_handle $body_handle)
(error $fastly_status)))
)

(@interface func (export "send_async")
(param $h $request_handle)
(param $b $body_handle)
(param $backend string)
(result $err (expected $pending_request_handle
(error $fastly_status))
)
(error $fastly_status)))
)

(@interface func (export "send_async_streaming")
Expand All @@ -306,27 +343,60 @@
(tuple $is_done
$response_handle
$body_handle)
(error $fastly_status))
)
(error $fastly_status)))
)

;; See `send_v2` for an explanation of the `$error_detail` out-parameter.
(@interface func (export "pending_req_poll_v2")
(param $h $pending_request_handle)
(param $error_detail (@witx pointer $send_error_detail))
(result $err (expected
(tuple $is_done
$response_handle
$body_handle)
(error $fastly_status)))
)

(@interface func (export "pending_req_wait")
(param $h $pending_request_handle)
(result $err (expected
(tuple $response_handle $body_handle)
(error $fastly_status))
)
(error $fastly_status)))
)

;; See `send_v2` for an explanation of the `$error_detail` out-parameter.
(@interface func (export "pending_req_wait_v2")
(param $h $pending_request_handle)
(param $error_detail (@witx pointer $send_error_detail))
(result $err (expected
(tuple $response_handle $body_handle)
(error $fastly_status)))
)

(@interface func (export "pending_req_select")
(param $hs (list $pending_request_handle))
(result $err (expected
(tuple $done_idx $response_handle $body_handle)
(error $fastly_status))
)
(error $fastly_status)))
)

;; See `send_v2` for an explanation of the `$error_detail` out-parameter.
(@interface func (export "pending_req_select_v2")
(param $hs (list $pending_request_handle))
(param $error_detail (@witx pointer $send_error_detail))
(result $err (expected
(tuple $done_idx $response_handle $body_handle)
(error $fastly_status)))
)

;;; Returns whether or not the original client request arrived with a
;;; Fastly-Key belonging to a user with the rights to purge content on this
;;; service.
(@interface func (export "fastly_key_is_valid")
(result $err (expected $is_valid (error $fastly_status)))
)

(@interface func(export "close")
(@interface func (export "close")
(param $h $request_handle)
(result $err (expected (error $fastly_status)))
)
Expand All @@ -352,6 +422,18 @@
(result $err (expected (error $fastly_status)))
)

(@interface func (export "redirect_to_websocket_proxy_v2")
(param $h $request_handle)
(param $backend_name string)
(result $err (expected (error $fastly_status)))
)

(@interface func (export "redirect_to_grip_proxy_v2")
(param $h $request_handle)
(param $backend_name string)
(result $err (expected (error $fastly_status)))
)

;;; Adjust how this requests's framing headers are determined.
(@interface func (export "framing_headers_mode_set")
(param $h $request_handle)
Expand Down Expand Up @@ -464,7 +546,7 @@
(result $err (expected (error $fastly_status)))
)

(@interface func(export "close")
(@interface func (export "close")
(param $h $response_handle)
(result $err (expected (error $fastly_status)))
)
Expand Down
108 changes: 95 additions & 13 deletions lib/compute-at-edge-abi/typenames.witx
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,9 @@
$httpinvalidstatus
;;; Limit exceeded
;;;
;;; This is returned when an attempt to allocate a resource has exceeded the maximum number of
;;; This is returned when an attempt to allocate a resource has exceeded the maximum number of
;;; resources permitted. For example, creating too many response handles.
$limitexceeded
)
)
$limitexceeded))

;;; A tag indicating HTTP protocol versions.
(typename $http_version
Expand All @@ -66,19 +64,15 @@
$http_10
$http_11
$h2
$h3
)
)
$h3))

;;; HTTP status codes.
(typename $http_status u16)

(typename $body_write_end
(enum (@witx tag u32)
$back
$front
)
)
$front))

;;; A handle to an HTTP request or response body.
(typename $body_handle (handle))
Expand Down Expand Up @@ -126,13 +120,12 @@
$pass
$ttl
$stale_while_revalidate
$pci
)
)
$pci))
(typename $num_bytes (@witx usize))
(typename $header_count u32)
(typename $is_done u32)
(typename $done_idx u32)
(typename $is_valid u32)
(typename $inserted u32)
(typename $ready_idx u32)

Expand Down Expand Up @@ -184,6 +177,7 @@
$sni_hostname
$dont_pool
$client_cert
$grpc
))

(typename $dynamic_backend_config
Expand Down Expand Up @@ -260,3 +254,91 @@
(field $ret_buf_nwritten_out (@witx pointer (@witx usize)))
)
)

(typename $send_error_detail_tag
(enum (@witx tag u32)
;;; The $send_error_detail struct has not been populated.
$uninitialized
;;; There was no send error.
$ok
;;; The system encountered a timeout when trying to find an IP address for the backend
;;; hostname.
$dns_timeout
;;; The system encountered a DNS error when trying to find an IP address for the backend
;;; hostname. The fields $dns_error_rcode and $dns_error_info_code may be set in the
;;; $send_error_detail.
$dns_error
;;; The system cannot determine which backend to use, or the specified backend was invalid.
$destination_not_found
;;; The system considers the backend to be unavailable; e.g., recent attempts to communicate
;;; with it may have failed, or a health check may indicate that it is down.
$destination_unavailable
;;; The system cannot find a route to the next-hop IP address.
$destination_ip_unroutable
;;; The system's connection to the backend was refused.
$connection_refused
;;; The system's connection to the backend was closed before a complete response was
;;; received.
$connection_terminated
;;; The system's attempt to open a connection to the backend timed out.
$connection_timeout
;;; The system is configured to limit the number of connections it has to the backend, and
;;; that limit has been exceeded.
$connection_limit_reached
;;; The system encountered an error when verifying the certificate presented by the backend.
$tls_certificate_error
;;; The system encountered an error with the backend TLS configuration.
$tls_configuration_error
;;; The system received an incomplete response to the request from the backend.
$http_incomplete_response
;;; The system received a response to the request whose header section was considered too
;;; large.
$http_response_header_section_too_large
;;; The system received a response to the request whose body was considered too large.
$http_response_body_too_large
;;; The system reached a configured time limit waiting for the complete response.
$http_response_timeout
;;; The system received a response to the request whose status code or reason phrase was
;;; invalid.
$http_response_status_invalid
;;; The process of negotiating an upgrade of the HTTP version between the system and the
;;; backend failed.
$http_upgrade_failed
;;; The system encountered an HTTP protocol error when communicating with the backend. This
;;; error will only be used when a more specific one is not defined.
$http_protocol_error
;;; An invalid cache key was provided for the request.
$http_request_cache_key_invalid
;;; An invalid URI was provided for the request.
$http_request_uri_invalid
;;; The system encountered an unexpected internal error.
$internal_error
;;; The system received a TLS alert from the backend. The field $tls_alert_id may be set in
;;; the $send_error_detail.
$tls_alert_received
;;; The system encountered a TLS error when communicating with the backend, either during
;;; the handshake or afterwards.
$tls_protocol_error
))

;;; Mask representing which fields are understood by the guest, and which have been set by the host.
;;;
;;; When the guest calls hostcalls with a mask, it should set every bit in the mask that corresponds
;;; to a defined flag. This signals the host to write only to fields with a set bit, allowing
;;; forward compatibility for existing guest programs even after new fields are added to the struct.
(typename $send_error_detail_mask
(flags (@witx repr u32)
$reserved
$dns_error_rcode
$dns_error_info_code
$tls_alert_id
))

(typename $send_error_detail
(record
(field $tag $send_error_detail_tag)
(field $mask $send_error_detail_mask)
(field $dns_error_rcode u16)
(field $dns_error_info_code u16)
(field $tls_alert_id u8)
))
5 changes: 4 additions & 1 deletion lib/src/wiggle_abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,10 @@ wiggle::from_witx!({
fastly_async_io::{select},
fastly_object_store::{insert, lookup_async, pending_lookup_wait},
fastly_http_body::{append, read, write},
fastly_http_req::{pending_req_select, pending_req_poll, pending_req_wait, send, send_async, send_async_streaming},
fastly_http_req::{
pending_req_select, pending_req_select_v2, pending_req_poll, pending_req_poll_v2,
pending_req_wait, pending_req_wait_v2, send, send_v2, send_async, send_async_streaming
},
}
});

Expand Down
5 changes: 5 additions & 0 deletions lib/src/wiggle_abi/body_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,9 @@ impl FastlyHttpBody for Session {
Ok(self.drop_body(body_handle)?)
}
}

fn abandon(&mut self, body_handle: BodyHandle) -> Result<(), Error> {
// Drop the body without a `finish` message
Ok(self.drop_body(body_handle)?)
}
}
Loading

0 comments on commit 542dc04

Please sign in to comment.