summaryrefslogtreecommitdiff
path: root/vendor/hyper/src/ffi
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-15 16:37:08 -0600
committermo khan <mo@mokhan.ca>2025-07-17 16:30:22 -0600
commit45df4d0d9b577fecee798d672695fe24ff57fb1b (patch)
tree1b99bf645035b58e0d6db08c7a83521f41f7a75b /vendor/hyper/src/ffi
parentf94f79608393d4ab127db63cc41668445ef6b243 (diff)
feat: migrate from Cedar to SpiceDB authorization system
This is a major architectural change that replaces the Cedar policy-based authorization system with SpiceDB's relation-based authorization. Key changes: - Migrate from Rust to Go implementation - Replace Cedar policies with SpiceDB schema and relationships - Switch from envoy `ext_authz` with Cedar to SpiceDB permission checks - Update build system and dependencies for Go ecosystem - Maintain Envoy integration for external authorization This change enables more flexible permission modeling through SpiceDB's Google Zanzibar inspired relation-based system, supporting complex hierarchical permissions that were difficult to express in Cedar. Breaking change: Existing Cedar policies and Rust-based configuration will no longer work and need to be migrated to SpiceDB schema.
Diffstat (limited to 'vendor/hyper/src/ffi')
-rw-r--r--vendor/hyper/src/ffi/body.rs302
-rw-r--r--vendor/hyper/src/ffi/client.rs274
-rw-r--r--vendor/hyper/src/ffi/error.rs96
-rw-r--r--vendor/hyper/src/ffi/http_types.rs703
-rw-r--r--vendor/hyper/src/ffi/io.rs198
-rw-r--r--vendor/hyper/src/ffi/macros.rs53
-rw-r--r--vendor/hyper/src/ffi/mod.rs99
-rw-r--r--vendor/hyper/src/ffi/task.rs549
8 files changed, 0 insertions, 2274 deletions
diff --git a/vendor/hyper/src/ffi/body.rs b/vendor/hyper/src/ffi/body.rs
deleted file mode 100644
index e5a09e57..00000000
--- a/vendor/hyper/src/ffi/body.rs
+++ /dev/null
@@ -1,302 +0,0 @@
-use std::ffi::{c_int, c_void};
-use std::mem::ManuallyDrop;
-use std::ptr;
-use std::task::{Context, Poll};
-
-use http_body_util::BodyExt as _;
-
-use super::task::{hyper_context, hyper_task, hyper_task_return_type, AsTaskType};
-use super::{UserDataPointer, HYPER_ITER_CONTINUE};
-use crate::body::{Bytes, Frame, Incoming as IncomingBody};
-use crate::ffi::size_t;
-
-/// A streaming HTTP body.
-///
-/// This is used both for sending requests (with `hyper_request_set_body`) and
-/// for receiving responses (with `hyper_response_body`).
-///
-/// For outgoing request bodies, call `hyper_body_set_data_func` to provide the
-/// data.
-///
-/// For incoming response bodies, call `hyper_body_data` to get a task that will
-/// yield a chunk of data each time it is polled. That task must be then be
-/// added to the executor with `hyper_executor_push`.
-///
-/// Methods:
-///
-/// - hyper_body_new: Create a new “empty” body.
-/// - hyper_body_set_userdata: Set userdata on this body, which will be passed to callback functions.
-/// - hyper_body_set_data_func: Set the data callback for this body.
-/// - hyper_body_data: Creates a task that will poll a response body for the next buffer of data.
-/// - hyper_body_foreach: Creates a task to execute the callback with each body chunk received.
-/// - hyper_body_free: Free a body.
-pub struct hyper_body(pub(super) IncomingBody);
-
-/// A buffer of bytes that is sent or received on a `hyper_body`.
-///
-/// Obtain one of these in the callback of `hyper_body_foreach` or by receiving
-/// a task of type `HYPER_TASK_BUF` from `hyper_executor_poll` (after calling
-/// `hyper_body_data` and pushing the resulting task).
-///
-/// Methods:
-///
-/// - hyper_buf_bytes: Get a pointer to the bytes in this buffer.
-/// - hyper_buf_copy: Create a new hyper_buf * by copying the provided bytes.
-/// - hyper_buf_free: Free this buffer.
-/// - hyper_buf_len: Get the length of the bytes this buffer contains.
-pub struct hyper_buf(pub(crate) Bytes);
-
-pub(crate) struct UserBody {
- data_func: hyper_body_data_callback,
- userdata: *mut c_void,
-}
-
-// ===== Body =====
-
-type hyper_body_foreach_callback = extern "C" fn(*mut c_void, *const hyper_buf) -> c_int;
-
-type hyper_body_data_callback =
- extern "C" fn(*mut c_void, *mut hyper_context<'_>, *mut *mut hyper_buf) -> c_int;
-
-ffi_fn! {
- /// Creates a new "empty" body.
- ///
- /// If not configured, this body acts as an empty payload.
- ///
- /// To avoid a memory leak, the body must eventually be consumed by
- /// `hyper_body_free`, `hyper_body_foreach`, or `hyper_request_set_body`.
- fn hyper_body_new() -> *mut hyper_body {
- Box::into_raw(Box::new(hyper_body(IncomingBody::ffi())))
- } ?= ptr::null_mut()
-}
-
-ffi_fn! {
- /// Free a body.
- ///
- /// This should only be used if the request isn't consumed by
- /// `hyper_body_foreach` or `hyper_request_set_body`.
- fn hyper_body_free(body: *mut hyper_body) {
- drop(non_null!(Box::from_raw(body) ?= ()));
- }
-}
-
-ffi_fn! {
- /// Creates a task that will poll a response body for the next buffer of data.
- ///
- /// The task may have different types depending on the outcome:
- ///
- /// - `HYPER_TASK_BUF`: Success, and more data was received.
- /// - `HYPER_TASK_ERROR`: An error retrieving the data.
- /// - `HYPER_TASK_EMPTY`: The body has finished streaming data.
- ///
- /// When the application receives the task from `hyper_executor_poll`,
- /// if the task type is `HYPER_TASK_BUF`, it should cast the task to
- /// `hyper_buf *` and consume all the bytes in the buffer. Then
- /// the application should call `hyper_body_data` again for the same
- /// `hyper_body *`, to create a task for the next buffer of data.
- /// Repeat until the polled task type is `HYPER_TASK_ERROR` or
- /// `HYPER_TASK_EMPTY`.
- ///
- /// To avoid a memory leak, the task must eventually be consumed by
- /// `hyper_task_free`, or taken ownership of by `hyper_executor_push`
- /// without subsequently being given back by `hyper_executor_poll`.
- ///
- /// This does not consume the `hyper_body *`, so it may be used again.
- /// However, the `hyper_body *` MUST NOT be used or freed until the
- /// related task is returned from `hyper_executor_poll`.
- ///
- /// For a more convenient method, see also `hyper_body_foreach`.
- fn hyper_body_data(body: *mut hyper_body) -> *mut hyper_task {
- // This doesn't take ownership of the Body, so don't allow destructor
- let mut body = ManuallyDrop::new(non_null!(Box::from_raw(body) ?= ptr::null_mut()));
-
- Box::into_raw(hyper_task::boxed(async move {
- loop {
- match body.0.frame().await {
- Some(Ok(frame)) => {
- if let Ok(data) = frame.into_data() {
- return Ok(Some(hyper_buf(data)));
- } else {
- continue;
- }
- },
- Some(Err(e)) => return Err(e),
- None => return Ok(None),
- }
- }
- }))
- } ?= ptr::null_mut()
-}
-
-ffi_fn! {
- /// Creates a task to execute the callback with each body chunk received.
- ///
- /// To avoid a memory leak, the task must eventually be consumed by
- /// `hyper_task_free`, or taken ownership of by `hyper_executor_push`
- /// without subsequently being given back by `hyper_executor_poll`.
- ///
- /// The `hyper_buf` pointer is only a borrowed reference. It cannot live outside
- /// the execution of the callback. You must make a copy of the bytes to retain them.
- ///
- /// The callback should return `HYPER_ITER_CONTINUE` to continue iterating
- /// chunks as they are received, or `HYPER_ITER_BREAK` to cancel. Each
- /// invocation of the callback must consume all the bytes it is provided.
- /// There is no mechanism to signal to Hyper that only a subset of bytes were
- /// consumed.
- ///
- /// This will consume the `hyper_body *`, you shouldn't use it anymore or free it.
- fn hyper_body_foreach(body: *mut hyper_body, func: hyper_body_foreach_callback, userdata: *mut c_void) -> *mut hyper_task {
- let mut body = non_null!(Box::from_raw(body) ?= ptr::null_mut());
- let userdata = UserDataPointer(userdata);
-
- Box::into_raw(hyper_task::boxed(async move {
- let _ = &userdata;
- while let Some(item) = body.0.frame().await {
- let frame = item?;
- if let Ok(chunk) = frame.into_data() {
- if HYPER_ITER_CONTINUE != func(userdata.0, &hyper_buf(chunk)) {
- return Err(crate::Error::new_user_aborted_by_callback());
- }
- }
- }
- Ok(())
- }))
- } ?= ptr::null_mut()
-}
-
-ffi_fn! {
- /// Set userdata on this body, which will be passed to callback functions.
- fn hyper_body_set_userdata(body: *mut hyper_body, userdata: *mut c_void) {
- let b = non_null!(&mut *body ?= ());
- b.0.as_ffi_mut().userdata = userdata;
- }
-}
-
-ffi_fn! {
- /// Set the outgoing data callback for this body.
- ///
- /// The callback is called each time hyper needs to send more data for the
- /// body. It is passed the value from `hyper_body_set_userdata`.
- ///
- /// If there is data available, the `hyper_buf **` argument should be set
- /// to a `hyper_buf *` containing the data, and `HYPER_POLL_READY` should
- /// be returned.
- ///
- /// Returning `HYPER_POLL_READY` while the `hyper_buf **` argument points
- /// to `NULL` will indicate the body has completed all data.
- ///
- /// If there is more data to send, but it isn't yet available, a
- /// `hyper_waker` should be saved from the `hyper_context *` argument, and
- /// `HYPER_POLL_PENDING` should be returned. You must wake the saved waker
- /// to signal the task when data is available.
- ///
- /// If some error has occurred, you can return `HYPER_POLL_ERROR` to abort
- /// the body.
- fn hyper_body_set_data_func(body: *mut hyper_body, func: hyper_body_data_callback) {
- let b = non_null!{ &mut *body ?= () };
- b.0.as_ffi_mut().data_func = func;
- }
-}
-
-// ===== impl UserBody =====
-
-impl UserBody {
- pub(crate) fn new() -> UserBody {
- UserBody {
- data_func: data_noop,
- userdata: std::ptr::null_mut(),
- }
- }
-
- pub(crate) fn poll_data(
- &mut self,
- cx: &mut Context<'_>,
- ) -> Poll<Option<crate::Result<Frame<Bytes>>>> {
- let mut out = std::ptr::null_mut();
- match (self.data_func)(self.userdata, hyper_context::wrap(cx), &mut out) {
- super::task::HYPER_POLL_READY => {
- if out.is_null() {
- Poll::Ready(None)
- } else {
- let buf = unsafe { Box::from_raw(out) };
- Poll::Ready(Some(Ok(Frame::data(buf.0))))
- }
- }
- super::task::HYPER_POLL_PENDING => Poll::Pending,
- super::task::HYPER_POLL_ERROR => {
- Poll::Ready(Some(Err(crate::Error::new_body_write_aborted())))
- }
- unexpected => Poll::Ready(Some(Err(crate::Error::new_body_write(format!(
- "unexpected hyper_body_data_func return code {}",
- unexpected
- ))))),
- }
- }
-}
-
-/// cbindgen:ignore
-extern "C" fn data_noop(
- _userdata: *mut c_void,
- _: *mut hyper_context<'_>,
- _: *mut *mut hyper_buf,
-) -> c_int {
- super::task::HYPER_POLL_READY
-}
-
-unsafe impl Send for UserBody {}
-unsafe impl Sync for UserBody {}
-
-// ===== Bytes =====
-
-ffi_fn! {
- /// Create a new `hyper_buf *` by copying the provided bytes.
- ///
- /// This makes an owned copy of the bytes, so the `buf` argument can be
- /// freed (with `hyper_buf_free`) or changed afterwards.
- ///
- /// To avoid a memory leak, the copy must eventually be consumed by
- /// `hyper_buf_free`.
- ///
- /// This returns `NULL` if allocating a new buffer fails.
- fn hyper_buf_copy(buf: *const u8, len: size_t) -> *mut hyper_buf {
- let slice = unsafe {
- std::slice::from_raw_parts(buf, len)
- };
- Box::into_raw(Box::new(hyper_buf(Bytes::copy_from_slice(slice))))
- } ?= ptr::null_mut()
-}
-
-ffi_fn! {
- /// Get a pointer to the bytes in this buffer.
- ///
- /// This should be used in conjunction with `hyper_buf_len` to get the length
- /// of the bytes data.
- ///
- /// This pointer is borrowed data, and not valid once the `hyper_buf` is
- /// consumed/freed.
- fn hyper_buf_bytes(buf: *const hyper_buf) -> *const u8 {
- unsafe { (*buf).0.as_ptr() }
- } ?= ptr::null()
-}
-
-ffi_fn! {
- /// Get the length of the bytes this buffer contains.
- fn hyper_buf_len(buf: *const hyper_buf) -> size_t {
- unsafe { (*buf).0.len() }
- }
-}
-
-ffi_fn! {
- /// Free this buffer.
- ///
- /// This should be used for any buffer once it is no longer needed.
- fn hyper_buf_free(buf: *mut hyper_buf) {
- drop(unsafe { Box::from_raw(buf) });
- }
-}
-
-unsafe impl AsTaskType for hyper_buf {
- fn as_task_type(&self) -> hyper_task_return_type {
- hyper_task_return_type::HYPER_TASK_BUF
- }
-}
diff --git a/vendor/hyper/src/ffi/client.rs b/vendor/hyper/src/ffi/client.rs
deleted file mode 100644
index 63b03d87..00000000
--- a/vendor/hyper/src/ffi/client.rs
+++ /dev/null
@@ -1,274 +0,0 @@
-use std::ffi::c_int;
-use std::ptr;
-use std::sync::Arc;
-
-use crate::client::conn;
-use crate::rt::Executor as _;
-
-use super::error::hyper_code;
-use super::http_types::{hyper_request, hyper_response};
-use super::io::hyper_io;
-use super::task::{hyper_executor, hyper_task, hyper_task_return_type, AsTaskType, WeakExec};
-
-/// An options builder to configure an HTTP client connection.
-///
-/// Methods:
-///
-/// - hyper_clientconn_options_new: Creates a new set of HTTP clientconn options to be used in a handshake.
-/// - hyper_clientconn_options_exec: Set the client background task executor.
-/// - hyper_clientconn_options_http2: Set whether to use HTTP2.
-/// - hyper_clientconn_options_set_preserve_header_case: Set whether header case is preserved.
-/// - hyper_clientconn_options_set_preserve_header_order: Set whether header order is preserved.
-/// - hyper_clientconn_options_http1_allow_multiline_headers: Set whether HTTP/1 connections accept obsolete line folding for header values.
-/// - hyper_clientconn_options_free: Free a set of HTTP clientconn options.
-pub struct hyper_clientconn_options {
- http1_allow_obsolete_multiline_headers_in_responses: bool,
- http1_preserve_header_case: bool,
- http1_preserve_header_order: bool,
- http2: bool,
- /// Use a `Weak` to prevent cycles.
- exec: WeakExec,
-}
-
-/// An HTTP client connection handle.
-///
-/// These are used to send one or more requests on a single connection.
-///
-/// It's possible to send multiple requests on a single connection, such
-/// as when HTTP/1 keep-alive or HTTP/2 is used.
-///
-/// To create a `hyper_clientconn`:
-///
-/// 1. Create a `hyper_io` with `hyper_io_new`.
-/// 2. Create a `hyper_clientconn_options` with `hyper_clientconn_options_new`.
-/// 3. Call `hyper_clientconn_handshake` with the `hyper_io` and `hyper_clientconn_options`.
-/// This creates a `hyper_task`.
-/// 5. Call `hyper_task_set_userdata` to assign an application-specific pointer to the task.
-/// This allows keeping track of multiple connections that may be handshaking
-/// simultaneously.
-/// 4. Add the `hyper_task` to an executor with `hyper_executor_push`.
-/// 5. Poll that executor until it yields a task of type `HYPER_TASK_CLIENTCONN`.
-/// 6. Extract the `hyper_clientconn` from the task with `hyper_task_value`.
-/// This will require a cast from `void *` to `hyper_clientconn *`.
-///
-/// This process results in a `hyper_clientconn` that permanently owns the
-/// `hyper_io`. Because the `hyper_io` in turn owns a TCP or TLS connection, that means
-/// the `hyper_clientconn` owns the connection for both the clientconn's lifetime
-/// and the connection's lifetime.
-///
-/// In other words, each connection (`hyper_io`) must have exactly one `hyper_clientconn`
-/// associated with it. That's because `hyper_clientconn_handshake` sends the
-/// [HTTP/2 Connection Preface] (for HTTP/2 connections). Since that preface can't
-/// be sent twice, handshake can't be called twice.
-///
-/// [HTTP/2 Connection Preface]: https://datatracker.ietf.org/doc/html/rfc9113#name-http-2-connection-preface
-///
-/// Methods:
-///
-/// - hyper_clientconn_handshake: Creates an HTTP client handshake task.
-/// - hyper_clientconn_send: Creates a task to send a request on the client connection.
-/// - hyper_clientconn_free: Free a hyper_clientconn *.
-pub struct hyper_clientconn {
- tx: Tx,
-}
-
-enum Tx {
- #[cfg(feature = "http1")]
- Http1(conn::http1::SendRequest<crate::body::Incoming>),
- #[cfg(feature = "http2")]
- Http2(conn::http2::SendRequest<crate::body::Incoming>),
-}
-
-// ===== impl hyper_clientconn =====
-
-ffi_fn! {
- /// Creates an HTTP client handshake task.
- ///
- /// Both the `io` and the `options` are consumed in this function call.
- /// They should not be used or freed afterwards.
- ///
- /// The returned task must be polled with an executor until the handshake
- /// completes, at which point the value can be taken.
- ///
- /// To avoid a memory leak, the task must eventually be consumed by
- /// `hyper_task_free`, or taken ownership of by `hyper_executor_push`
- /// without subsequently being given back by `hyper_executor_poll`.
- fn hyper_clientconn_handshake(io: *mut hyper_io, options: *mut hyper_clientconn_options) -> *mut hyper_task {
- let options = non_null! { Box::from_raw(options) ?= ptr::null_mut() };
- let io = non_null! { Box::from_raw(io) ?= ptr::null_mut() };
-
- Box::into_raw(hyper_task::boxed(async move {
- #[cfg(feature = "http2")]
- {
- if options.http2 {
- return conn::http2::Builder::new(options.exec.clone())
- .handshake::<_, crate::body::Incoming>(io)
- .await
- .map(|(tx, conn)| {
- options.exec.execute(Box::pin(async move {
- let _ = conn.await;
- }));
- hyper_clientconn { tx: Tx::Http2(tx) }
- });
- }
- }
-
- conn::http1::Builder::new()
- .allow_obsolete_multiline_headers_in_responses(options.http1_allow_obsolete_multiline_headers_in_responses)
- .preserve_header_case(options.http1_preserve_header_case)
- .preserve_header_order(options.http1_preserve_header_order)
- .handshake::<_, crate::body::Incoming>(io)
- .await
- .map(|(tx, conn)| {
- options.exec.execute(Box::pin(async move {
- let _ = conn.await;
- }));
- hyper_clientconn { tx: Tx::Http1(tx) }
- })
- }))
- } ?= std::ptr::null_mut()
-}
-
-ffi_fn! {
- /// Creates a task to send a request on the client connection.
- ///
- /// This consumes the request. You should not use or free the request
- /// afterwards.
- ///
- /// Returns a task that needs to be polled until it is ready. When ready, the
- /// task yields a `hyper_response *`.
- ///
- /// To avoid a memory leak, the task must eventually be consumed by
- /// `hyper_task_free`, or taken ownership of by `hyper_executor_push`
- /// without subsequently being given back by `hyper_executor_poll`.
- fn hyper_clientconn_send(conn: *mut hyper_clientconn, req: *mut hyper_request) -> *mut hyper_task {
- let mut req = non_null! { Box::from_raw(req) ?= ptr::null_mut() };
-
- // Update request with original-case map of headers
- req.finalize_request();
-
- let fut = match non_null! { &mut *conn ?= ptr::null_mut() }.tx {
- Tx::Http1(ref mut tx) => futures_util::future::Either::Left(tx.send_request(req.0)),
- Tx::Http2(ref mut tx) => futures_util::future::Either::Right(tx.send_request(req.0)),
- };
-
- let fut = async move {
- fut.await.map(hyper_response::wrap)
- };
-
- Box::into_raw(hyper_task::boxed(fut))
- } ?= std::ptr::null_mut()
-}
-
-ffi_fn! {
- /// Free a `hyper_clientconn *`.
- ///
- /// This should be used for any connection once it is no longer needed.
- fn hyper_clientconn_free(conn: *mut hyper_clientconn) {
- drop(non_null! { Box::from_raw(conn) ?= () });
- }
-}
-
-unsafe impl AsTaskType for hyper_clientconn {
- fn as_task_type(&self) -> hyper_task_return_type {
- hyper_task_return_type::HYPER_TASK_CLIENTCONN
- }
-}
-
-// ===== impl hyper_clientconn_options =====
-
-ffi_fn! {
- /// Creates a new set of HTTP clientconn options to be used in a handshake.
- ///
- /// To avoid a memory leak, the options must eventually be consumed by
- /// `hyper_clientconn_options_free` or `hyper_clientconn_handshake`.
- fn hyper_clientconn_options_new() -> *mut hyper_clientconn_options {
- Box::into_raw(Box::new(hyper_clientconn_options {
- http1_allow_obsolete_multiline_headers_in_responses: false,
- http1_preserve_header_case: false,
- http1_preserve_header_order: false,
- http2: false,
- exec: WeakExec::new(),
- }))
- } ?= std::ptr::null_mut()
-}
-
-ffi_fn! {
- /// Set whether header case is preserved.
- ///
- /// Pass `0` to allow lowercase normalization (default), `1` to retain original case.
- fn hyper_clientconn_options_set_preserve_header_case(opts: *mut hyper_clientconn_options, enabled: c_int) {
- let opts = non_null! { &mut *opts ?= () };
- opts.http1_preserve_header_case = enabled != 0;
- }
-}
-
-ffi_fn! {
- /// Set whether header order is preserved.
- ///
- /// Pass `0` to allow reordering (default), `1` to retain original ordering.
- fn hyper_clientconn_options_set_preserve_header_order(opts: *mut hyper_clientconn_options, enabled: c_int) {
- let opts = non_null! { &mut *opts ?= () };
- opts.http1_preserve_header_order = enabled != 0;
- }
-}
-
-ffi_fn! {
- /// Free a set of HTTP clientconn options.
- ///
- /// This should only be used if the options aren't consumed by
- /// `hyper_clientconn_handshake`.
- fn hyper_clientconn_options_free(opts: *mut hyper_clientconn_options) {
- drop(non_null! { Box::from_raw(opts) ?= () });
- }
-}
-
-ffi_fn! {
- /// Set the client background task executor.
- ///
- /// This does not consume the `options` or the `exec`.
- fn hyper_clientconn_options_exec(opts: *mut hyper_clientconn_options, exec: *const hyper_executor) {
- let opts = non_null! { &mut *opts ?= () };
-
- let exec = non_null! { Arc::from_raw(exec) ?= () };
- let weak_exec = hyper_executor::downgrade(&exec);
- std::mem::forget(exec);
-
- opts.exec = weak_exec;
- }
-}
-
-ffi_fn! {
- /// Set whether to use HTTP2.
- ///
- /// Pass `0` to disable, `1` to enable.
- fn hyper_clientconn_options_http2(opts: *mut hyper_clientconn_options, enabled: c_int) -> hyper_code {
- #[cfg(feature = "http2")]
- {
- let opts = non_null! { &mut *opts ?= hyper_code::HYPERE_INVALID_ARG };
- opts.http2 = enabled != 0;
- hyper_code::HYPERE_OK
- }
-
- #[cfg(not(feature = "http2"))]
- {
- drop(opts);
- drop(enabled);
- hyper_code::HYPERE_FEATURE_NOT_ENABLED
- }
- }
-}
-
-ffi_fn! {
- /// Set whether HTTP/1 connections accept obsolete line folding for header values.
- ///
- /// Newline codepoints (\r and \n) will be transformed to spaces when parsing.
- ///
- /// Pass `0` to disable, `1` to enable.
- ///
- fn hyper_clientconn_options_http1_allow_multiline_headers(opts: *mut hyper_clientconn_options, enabled: c_int) -> hyper_code {
- let opts = non_null! { &mut *opts ?= hyper_code::HYPERE_INVALID_ARG };
- opts.http1_allow_obsolete_multiline_headers_in_responses = enabled != 0;
- hyper_code::HYPERE_OK
- }
-}
diff --git a/vendor/hyper/src/ffi/error.rs b/vendor/hyper/src/ffi/error.rs
deleted file mode 100644
index cc289ed7..00000000
--- a/vendor/hyper/src/ffi/error.rs
+++ /dev/null
@@ -1,96 +0,0 @@
-use crate::ffi::size_t;
-
-/// A more detailed error object returned by some hyper functions.
-///
-/// Compare with `hyper_code`, which is a simpler error returned from
-/// some hyper functions.
-///
-/// Methods:
-///
-/// - hyper_error_code: Get an equivalent hyper_code from this error.
-/// - hyper_error_print: Print the details of this error to a buffer.
-/// - hyper_error_free: Frees a hyper_error.
-pub struct hyper_error(crate::Error);
-
-/// A return code for many of hyper's methods.
-#[repr(C)]
-pub enum hyper_code {
- /// All is well.
- HYPERE_OK,
- /// General error, details in the `hyper_error *`.
- HYPERE_ERROR,
- /// A function argument was invalid.
- HYPERE_INVALID_ARG,
- /// The IO transport returned an EOF when one wasn't expected.
- ///
- /// This typically means an HTTP request or response was expected, but the
- /// connection closed cleanly without sending (all of) it.
- HYPERE_UNEXPECTED_EOF,
- /// Aborted by a user supplied callback.
- HYPERE_ABORTED_BY_CALLBACK,
- /// An optional hyper feature was not enabled.
- #[cfg_attr(feature = "http2", allow(unused))]
- HYPERE_FEATURE_NOT_ENABLED,
- /// The peer sent an HTTP message that could not be parsed.
- HYPERE_INVALID_PEER_MESSAGE,
-}
-
-// ===== impl hyper_error =====
-
-impl hyper_error {
- fn code(&self) -> hyper_code {
- use crate::error::Kind as ErrorKind;
- use crate::error::User;
-
- match self.0.kind() {
- ErrorKind::Parse(_) => hyper_code::HYPERE_INVALID_PEER_MESSAGE,
- ErrorKind::IncompleteMessage => hyper_code::HYPERE_UNEXPECTED_EOF,
- ErrorKind::User(User::AbortedByCallback) => hyper_code::HYPERE_ABORTED_BY_CALLBACK,
- // TODO: add more variants
- _ => hyper_code::HYPERE_ERROR,
- }
- }
-
- fn print_to(&self, dst: &mut [u8]) -> usize {
- use std::io::Write;
-
- let mut dst = std::io::Cursor::new(dst);
-
- // A write! error doesn't matter. As much as possible will have been
- // written, and the Cursor position will know how far that is (even
- // if that is zero).
- let _ = write!(dst, "{}", &self.0);
- dst.position() as usize
- }
-}
-
-ffi_fn! {
- /// Frees a `hyper_error`.
- ///
- /// This should be used for any error once it is no longer needed.
- fn hyper_error_free(err: *mut hyper_error) {
- drop(non_null!(Box::from_raw(err) ?= ()));
- }
-}
-
-ffi_fn! {
- /// Get an equivalent `hyper_code` from this error.
- fn hyper_error_code(err: *const hyper_error) -> hyper_code {
- non_null!(&*err ?= hyper_code::HYPERE_INVALID_ARG).code()
- }
-}
-
-ffi_fn! {
- /// Print the details of this error to a buffer.
- ///
- /// The `dst_len` value must be the maximum length that the buffer can
- /// store.
- ///
- /// The return value is number of bytes that were written to `dst`.
- fn hyper_error_print(err: *const hyper_error, dst: *mut u8, dst_len: size_t) -> size_t {
- let dst = unsafe {
- std::slice::from_raw_parts_mut(dst, dst_len)
- };
- non_null!(&*err ?= 0).print_to(dst)
- }
-}
diff --git a/vendor/hyper/src/ffi/http_types.rs b/vendor/hyper/src/ffi/http_types.rs
deleted file mode 100644
index 3dc4a254..00000000
--- a/vendor/hyper/src/ffi/http_types.rs
+++ /dev/null
@@ -1,703 +0,0 @@
-use std::ffi::{c_int, c_void};
-
-use bytes::Bytes;
-
-use super::body::hyper_body;
-use super::error::hyper_code;
-use super::task::{hyper_task_return_type, AsTaskType};
-use super::{UserDataPointer, HYPER_ITER_CONTINUE};
-use crate::body::Incoming as IncomingBody;
-use crate::ext::{HeaderCaseMap, OriginalHeaderOrder, ReasonPhrase};
-use crate::ffi::size_t;
-use crate::header::{HeaderName, HeaderValue};
-use crate::{HeaderMap, Method, Request, Response, Uri};
-
-/// An HTTP request.
-///
-/// Once you've finished constructing a request, you can send it with
-/// `hyper_clientconn_send`.
-///
-/// Methods:
-///
-/// - hyper_request_new: Construct a new HTTP request.
-/// - hyper_request_headers: Gets a mutable reference to the HTTP headers of this request
-/// - hyper_request_set_body: Set the body of the request.
-/// - hyper_request_set_method: Set the HTTP Method of the request.
-/// - hyper_request_set_uri: Set the URI of the request.
-/// - hyper_request_set_uri_parts: Set the URI of the request with separate scheme, authority, and path/query strings.
-/// - hyper_request_set_version: Set the preferred HTTP version of the request.
-/// - hyper_request_on_informational: Set an informational (1xx) response callback.
-/// - hyper_request_free: Free an HTTP request.
-pub struct hyper_request(pub(super) Request<IncomingBody>);
-
-/// An HTTP response.
-///
-/// Obtain one of these by making a request with `hyper_clientconn_send`, then
-/// polling the executor unntil you get a `hyper_task` of type
-/// `HYPER_TASK_RESPONSE`. To figure out which request this response
-/// corresponds to, check the userdata of the task, which you should
-/// previously have set to an application-specific identifier for the
-/// request.
-///
-/// Methods:
-///
-/// - hyper_response_status: Get the HTTP-Status code of this response.
-/// - hyper_response_version: Get the HTTP version used by this response.
-/// - hyper_response_reason_phrase: Get a pointer to the reason-phrase of this response.
-/// - hyper_response_reason_phrase_len: Get the length of the reason-phrase of this response.
-/// - hyper_response_headers: Gets a reference to the HTTP headers of this response.
-/// - hyper_response_body: Take ownership of the body of this response.
-/// - hyper_response_free: Free an HTTP response.
-pub struct hyper_response(pub(super) Response<IncomingBody>);
-
-/// An HTTP header map.
-///
-/// These can be part of a request or response.
-///
-/// Obtain a pointer to read or modify these from `hyper_request_headers`
-/// or `hyper_response_headers`.
-///
-/// Methods:
-///
-/// - hyper_headers_add: Adds the provided value to the list of the provided name.
-/// - hyper_headers_foreach: Iterates the headers passing each name and value pair to the callback.
-/// - hyper_headers_set: Sets the header with the provided name to the provided value.
-#[derive(Clone)]
-pub struct hyper_headers {
- pub(super) headers: HeaderMap,
- orig_casing: HeaderCaseMap,
- orig_order: OriginalHeaderOrder,
-}
-
-#[derive(Clone)]
-struct OnInformational {
- func: hyper_request_on_informational_callback,
- data: UserDataPointer,
-}
-
-type hyper_request_on_informational_callback = extern "C" fn(*mut c_void, *mut hyper_response);
-
-// ===== impl hyper_request =====
-
-ffi_fn! {
- /// Construct a new HTTP request.
- ///
- /// The default request has an empty body. To send a body, call `hyper_request_set_body`.
- ///
- ///
- /// To avoid a memory leak, the request must eventually be consumed by
- /// `hyper_request_free` or `hyper_clientconn_send`.
- fn hyper_request_new() -> *mut hyper_request {
- Box::into_raw(Box::new(hyper_request(Request::new(IncomingBody::empty()))))
- } ?= std::ptr::null_mut()
-}
-
-ffi_fn! {
- /// Free an HTTP request.
- ///
- /// This should only be used if the request isn't consumed by
- /// `hyper_clientconn_send`.
- fn hyper_request_free(req: *mut hyper_request) {
- drop(non_null!(Box::from_raw(req) ?= ()));
- }
-}
-
-ffi_fn! {
- /// Set the HTTP Method of the request.
- fn hyper_request_set_method(req: *mut hyper_request, method: *const u8, method_len: size_t) -> hyper_code {
- let bytes = unsafe {
- std::slice::from_raw_parts(method, method_len as usize)
- };
- let req = non_null!(&mut *req ?= hyper_code::HYPERE_INVALID_ARG);
- match Method::from_bytes(bytes) {
- Ok(m) => {
- *req.0.method_mut() = m;
- hyper_code::HYPERE_OK
- },
- Err(_) => {
- hyper_code::HYPERE_INVALID_ARG
- }
- }
- }
-}
-
-ffi_fn! {
- /// Set the URI of the request.
- ///
- /// The request's URI is best described as the `request-target` from the RFCs. So in HTTP/1,
- /// whatever is set will get sent as-is in the first line (GET $uri HTTP/1.1). It
- /// supports the 4 defined variants, origin-form, absolute-form, authority-form, and
- /// asterisk-form.
- ///
- /// The underlying type was built to efficiently support HTTP/2 where the request-target is
- /// split over :scheme, :authority, and :path. As such, each part can be set explicitly, or the
- /// type can parse a single contiguous string and if a scheme is found, that slot is "set". If
- /// the string just starts with a path, only the path portion is set. All pseudo headers that
- /// have been parsed/set are sent when the connection type is HTTP/2.
- ///
- /// To set each slot explicitly, use `hyper_request_set_uri_parts`.
- fn hyper_request_set_uri(req: *mut hyper_request, uri: *const u8, uri_len: size_t) -> hyper_code {
- let bytes = unsafe {
- std::slice::from_raw_parts(uri, uri_len as usize)
- };
- let req = non_null!(&mut *req ?= hyper_code::HYPERE_INVALID_ARG);
- match Uri::from_maybe_shared(bytes) {
- Ok(u) => {
- *req.0.uri_mut() = u;
- hyper_code::HYPERE_OK
- },
- Err(_) => {
- hyper_code::HYPERE_INVALID_ARG
- }
- }
- }
-}
-
-ffi_fn! {
- /// Set the URI of the request with separate scheme, authority, and
- /// path/query strings.
- ///
- /// Each of `scheme`, `authority`, and `path_and_query` should either be
- /// null, to skip providing a component, or point to a UTF-8 encoded
- /// string. If any string pointer argument is non-null, its corresponding
- /// `len` parameter must be set to the string's length.
- fn hyper_request_set_uri_parts(
- req: *mut hyper_request,
- scheme: *const u8,
- scheme_len: size_t,
- authority: *const u8,
- authority_len: size_t,
- path_and_query: *const u8,
- path_and_query_len: size_t
- ) -> hyper_code {
- let mut builder = Uri::builder();
- if !scheme.is_null() {
- let scheme_bytes = unsafe {
- std::slice::from_raw_parts(scheme, scheme_len as usize)
- };
- builder = builder.scheme(scheme_bytes);
- }
- if !authority.is_null() {
- let authority_bytes = unsafe {
- std::slice::from_raw_parts(authority, authority_len as usize)
- };
- builder = builder.authority(authority_bytes);
- }
- if !path_and_query.is_null() {
- let path_and_query_bytes = unsafe {
- std::slice::from_raw_parts(path_and_query, path_and_query_len as usize)
- };
- builder = builder.path_and_query(path_and_query_bytes);
- }
- match builder.build() {
- Ok(u) => {
- *unsafe { &mut *req }.0.uri_mut() = u;
- hyper_code::HYPERE_OK
- },
- Err(_) => {
- hyper_code::HYPERE_INVALID_ARG
- }
- }
- }
-}
-
-ffi_fn! {
- /// Set the preferred HTTP version of the request.
- ///
- /// The version value should be one of the `HYPER_HTTP_VERSION_` constants.
- ///
- /// Note that this won't change the major HTTP version of the connection,
- /// since that is determined at the handshake step.
- fn hyper_request_set_version(req: *mut hyper_request, version: c_int) -> hyper_code {
- use http::Version;
-
- let req = non_null!(&mut *req ?= hyper_code::HYPERE_INVALID_ARG);
- *req.0.version_mut() = match version {
- super::HYPER_HTTP_VERSION_NONE => Version::HTTP_11,
- super::HYPER_HTTP_VERSION_1_0 => Version::HTTP_10,
- super::HYPER_HTTP_VERSION_1_1 => Version::HTTP_11,
- super::HYPER_HTTP_VERSION_2 => Version::HTTP_2,
- _ => {
- // We don't know this version
- return hyper_code::HYPERE_INVALID_ARG;
- }
- };
- hyper_code::HYPERE_OK
- }
-}
-
-ffi_fn! {
- /// Gets a mutable reference to the HTTP headers of this request
- ///
- /// This is not an owned reference, so it should not be accessed after the
- /// `hyper_request` has been consumed.
- fn hyper_request_headers(req: *mut hyper_request) -> *mut hyper_headers {
- hyper_headers::get_or_default(unsafe { &mut *req }.0.extensions_mut())
- } ?= std::ptr::null_mut()
-}
-
-ffi_fn! {
- /// Set the body of the request.
- ///
- /// You can get a `hyper_body` by calling `hyper_body_new`.
- ///
- /// This takes ownership of the `hyper_body *`, you must not use it or
- /// free it after setting it on the request.
- fn hyper_request_set_body(req: *mut hyper_request, body: *mut hyper_body) -> hyper_code {
- let body = non_null!(Box::from_raw(body) ?= hyper_code::HYPERE_INVALID_ARG);
- let req = non_null!(&mut *req ?= hyper_code::HYPERE_INVALID_ARG);
- *req.0.body_mut() = body.0;
- hyper_code::HYPERE_OK
- }
-}
-
-ffi_fn! {
- /// Set an informational (1xx) response callback.
- ///
- /// The callback is called each time hyper receives an informational (1xx)
- /// response for this request.
- ///
- /// The third argument is an opaque user data pointer, which is passed to
- /// the callback each time.
- ///
- /// The callback is passed the `void *` data pointer, and a
- /// `hyper_response *` which can be inspected as any other response. The
- /// body of the response will always be empty.
- ///
- /// NOTE: The `hyper_response *` is just borrowed data, and will not
- /// be valid after the callback finishes. You must copy any data you wish
- /// to persist.
- fn hyper_request_on_informational(req: *mut hyper_request, callback: hyper_request_on_informational_callback, data: *mut c_void) -> hyper_code {
- #[cfg(feature = "client")]
- {
- let ext = OnInformational {
- func: callback,
- data: UserDataPointer(data),
- };
- let req = non_null!(&mut *req ?= hyper_code::HYPERE_INVALID_ARG);
- crate::ext::on_informational_raw(&mut req.0, ext);
- hyper_code::HYPERE_OK
- }
- #[cfg(not(feature = "client"))]
- {
- drop((req, callback, data));
- hyper_code::HYPERE_FEATURE_NOT_ENABLED
- }
- }
-}
-
-impl hyper_request {
- pub(super) fn finalize_request(&mut self) {
- if let Some(headers) = self.0.extensions_mut().remove::<hyper_headers>() {
- *self.0.headers_mut() = headers.headers;
- self.0.extensions_mut().insert(headers.orig_casing);
- self.0.extensions_mut().insert(headers.orig_order);
- }
- }
-}
-
-// ===== impl hyper_response =====
-
-ffi_fn! {
- /// Free an HTTP response.
- ///
- /// This should be used for any response once it is no longer needed.
- fn hyper_response_free(resp: *mut hyper_response) {
- drop(non_null!(Box::from_raw(resp) ?= ()));
- }
-}
-
-ffi_fn! {
- /// Get the HTTP-Status code of this response.
- ///
- /// It will always be within the range of 100-599.
- fn hyper_response_status(resp: *const hyper_response) -> u16 {
- non_null!(&*resp ?= 0).0.status().as_u16()
- }
-}
-
-ffi_fn! {
- /// Get a pointer to the reason-phrase of this response.
- ///
- /// This buffer is not null-terminated.
- ///
- /// This buffer is owned by the response, and should not be used after
- /// the response has been freed.
- ///
- /// Use `hyper_response_reason_phrase_len()` to get the length of this
- /// buffer.
- fn hyper_response_reason_phrase(resp: *const hyper_response) -> *const u8 {
- non_null!(&*resp ?= std::ptr::null()).reason_phrase().as_ptr()
- } ?= std::ptr::null()
-}
-
-ffi_fn! {
- /// Get the length of the reason-phrase of this response.
- ///
- /// Use `hyper_response_reason_phrase()` to get the buffer pointer.
- fn hyper_response_reason_phrase_len(resp: *const hyper_response) -> size_t {
- non_null!(&*resp ?= 0).reason_phrase().len()
- }
-}
-
-ffi_fn! {
- /// Get the HTTP version used by this response.
- ///
- /// The returned value could be:
- ///
- /// - `HYPER_HTTP_VERSION_1_0`
- /// - `HYPER_HTTP_VERSION_1_1`
- /// - `HYPER_HTTP_VERSION_2`
- /// - `HYPER_HTTP_VERSION_NONE` if newer (or older).
- fn hyper_response_version(resp: *const hyper_response) -> c_int {
- use http::Version;
-
- match non_null!(&*resp ?= 0).0.version() {
- Version::HTTP_10 => super::HYPER_HTTP_VERSION_1_0,
- Version::HTTP_11 => super::HYPER_HTTP_VERSION_1_1,
- Version::HTTP_2 => super::HYPER_HTTP_VERSION_2,
- _ => super::HYPER_HTTP_VERSION_NONE,
- }
- }
-}
-
-ffi_fn! {
- /// Gets a reference to the HTTP headers of this response.
- ///
- /// This is not an owned reference, so it should not be accessed after the
- /// `hyper_response` has been freed.
- fn hyper_response_headers(resp: *mut hyper_response) -> *mut hyper_headers {
- hyper_headers::get_or_default(unsafe { &mut *resp }.0.extensions_mut())
- } ?= std::ptr::null_mut()
-}
-
-ffi_fn! {
- /// Take ownership of the body of this response.
- ///
- /// It is safe to free the response even after taking ownership of its body.
- ///
- /// To avoid a memory leak, the body must eventually be consumed by
- /// `hyper_body_free`, `hyper_body_foreach`, or `hyper_request_set_body`.
- fn hyper_response_body(resp: *mut hyper_response) -> *mut hyper_body {
- let body = std::mem::replace(non_null!(&mut *resp ?= std::ptr::null_mut()).0.body_mut(), IncomingBody::empty());
- Box::into_raw(Box::new(hyper_body(body)))
- } ?= std::ptr::null_mut()
-}
-
-impl hyper_response {
- pub(super) fn wrap(mut resp: Response<IncomingBody>) -> hyper_response {
- let headers = std::mem::take(resp.headers_mut());
- let orig_casing = resp
- .extensions_mut()
- .remove::<HeaderCaseMap>()
- .unwrap_or_else(HeaderCaseMap::default);
- let orig_order = resp
- .extensions_mut()
- .remove::<OriginalHeaderOrder>()
- .unwrap_or_else(OriginalHeaderOrder::default);
- resp.extensions_mut().insert(hyper_headers {
- headers,
- orig_casing,
- orig_order,
- });
-
- hyper_response(resp)
- }
-
- fn reason_phrase(&self) -> &[u8] {
- if let Some(reason) = self.0.extensions().get::<ReasonPhrase>() {
- return reason.as_bytes();
- }
-
- if let Some(reason) = self.0.status().canonical_reason() {
- return reason.as_bytes();
- }
-
- &[]
- }
-}
-
-unsafe impl AsTaskType for hyper_response {
- fn as_task_type(&self) -> hyper_task_return_type {
- hyper_task_return_type::HYPER_TASK_RESPONSE
- }
-}
-
-// ===== impl Headers =====
-
-type hyper_headers_foreach_callback =
- extern "C" fn(*mut c_void, *const u8, size_t, *const u8, size_t) -> c_int;
-
-impl hyper_headers {
- pub(super) fn get_or_default(ext: &mut http::Extensions) -> &mut hyper_headers {
- if let None = ext.get_mut::<hyper_headers>() {
- ext.insert(hyper_headers::default());
- }
-
- ext.get_mut::<hyper_headers>().unwrap()
- }
-}
-
-ffi_fn! {
- /// Iterates the headers passing each name and value pair to the callback.
- ///
- /// The `userdata` pointer is also passed to the callback.
- ///
- /// The callback should return `HYPER_ITER_CONTINUE` to keep iterating, or
- /// `HYPER_ITER_BREAK` to stop.
- fn hyper_headers_foreach(headers: *const hyper_headers, func: hyper_headers_foreach_callback, userdata: *mut c_void) {
- let headers = non_null!(&*headers ?= ());
- // For each header name/value pair, there may be a value in the casemap
- // that corresponds to the HeaderValue. So, we iterator all the keys,
- // and for each one, try to pair the originally cased name with the value.
- //
- // TODO: consider adding http::HeaderMap::entries() iterator
- let mut ordered_iter = headers.orig_order.get_in_order().peekable();
- if ordered_iter.peek().is_some() {
- for (name, idx) in ordered_iter {
- let (name_ptr, name_len) = if let Some(orig_name) = headers.orig_casing.get_all(name).nth(*idx) {
- (orig_name.as_ref().as_ptr(), orig_name.as_ref().len())
- } else {
- (
- name.as_str().as_bytes().as_ptr(),
- name.as_str().as_bytes().len(),
- )
- };
-
- let val_ptr;
- let val_len;
- if let Some(value) = headers.headers.get_all(name).iter().nth(*idx) {
- val_ptr = value.as_bytes().as_ptr();
- val_len = value.as_bytes().len();
- } else {
- // Stop iterating, something has gone wrong.
- return;
- }
-
- if HYPER_ITER_CONTINUE != func(userdata, name_ptr, name_len, val_ptr, val_len) {
- return;
- }
- }
- } else {
- for name in headers.headers.keys() {
- let mut names = headers.orig_casing.get_all(name);
-
- for value in headers.headers.get_all(name) {
- let (name_ptr, name_len) = if let Some(orig_name) = names.next() {
- (orig_name.as_ref().as_ptr(), orig_name.as_ref().len())
- } else {
- (
- name.as_str().as_bytes().as_ptr(),
- name.as_str().as_bytes().len(),
- )
- };
-
- let val_ptr = value.as_bytes().as_ptr();
- let val_len = value.as_bytes().len();
-
- if HYPER_ITER_CONTINUE != func(userdata, name_ptr, name_len, val_ptr, val_len) {
- return;
- }
- }
- }
- }
- }
-}
-
-ffi_fn! {
- /// Sets the header with the provided name to the provided value.
- ///
- /// This overwrites any previous value set for the header.
- fn hyper_headers_set(headers: *mut hyper_headers, name: *const u8, name_len: size_t, value: *const u8, value_len: size_t) -> hyper_code {
- let headers = non_null!(&mut *headers ?= hyper_code::HYPERE_INVALID_ARG);
- match unsafe { raw_name_value(name, name_len, value, value_len) } {
- Ok((name, value, orig_name)) => {
- headers.headers.insert(&name, value);
- headers.orig_casing.insert(name.clone(), orig_name.clone());
- headers.orig_order.insert(name);
- hyper_code::HYPERE_OK
- }
- Err(code) => code,
- }
- }
-}
-
-ffi_fn! {
- /// Adds the provided value to the list of the provided name.
- ///
- /// If there were already existing values for the name, this will append the
- /// new value to the internal list.
- fn hyper_headers_add(headers: *mut hyper_headers, name: *const u8, name_len: size_t, value: *const u8, value_len: size_t) -> hyper_code {
- let headers = non_null!(&mut *headers ?= hyper_code::HYPERE_INVALID_ARG);
-
- match unsafe { raw_name_value(name, name_len, value, value_len) } {
- Ok((name, value, orig_name)) => {
- headers.headers.append(&name, value);
- headers.orig_casing.append(&name, orig_name.clone());
- headers.orig_order.append(name);
- hyper_code::HYPERE_OK
- }
- Err(code) => code,
- }
- }
-}
-
-impl Default for hyper_headers {
- fn default() -> Self {
- Self {
- headers: Default::default(),
- orig_casing: HeaderCaseMap::default(),
- orig_order: OriginalHeaderOrder::default(),
- }
- }
-}
-
-unsafe fn raw_name_value(
- name: *const u8,
- name_len: size_t,
- value: *const u8,
- value_len: size_t,
-) -> Result<(HeaderName, HeaderValue, Bytes), hyper_code> {
- let name = std::slice::from_raw_parts(name, name_len);
- let orig_name = Bytes::copy_from_slice(name);
- let name = match HeaderName::from_bytes(name) {
- Ok(name) => name,
- Err(_) => return Err(hyper_code::HYPERE_INVALID_ARG),
- };
- let value = std::slice::from_raw_parts(value, value_len);
- let value = match HeaderValue::from_bytes(value) {
- Ok(val) => val,
- Err(_) => return Err(hyper_code::HYPERE_INVALID_ARG),
- };
-
- Ok((name, value, orig_name))
-}
-
-// ===== impl OnInformational =====
-
-#[cfg(feature = "client")]
-impl crate::ext::OnInformationalCallback for OnInformational {
- fn on_informational(&self, res: http::Response<()>) {
- let res = res.map(|()| IncomingBody::empty());
- let mut res = hyper_response::wrap(res);
- (self.func)(self.data.0, &mut res);
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn test_headers_foreach_cases_preserved() {
- let mut headers = hyper_headers::default();
-
- let name1 = b"Set-CookiE";
- let value1 = b"a=b";
- hyper_headers_add(
- &mut headers,
- name1.as_ptr(),
- name1.len(),
- value1.as_ptr(),
- value1.len(),
- );
-
- let name2 = b"SET-COOKIE";
- let value2 = b"c=d";
- hyper_headers_add(
- &mut headers,
- name2.as_ptr(),
- name2.len(),
- value2.as_ptr(),
- value2.len(),
- );
-
- let mut vec = Vec::<u8>::new();
- hyper_headers_foreach(&headers, concat, &mut vec as *mut _ as *mut c_void);
-
- assert_eq!(vec, b"Set-CookiE: a=b\r\nSET-COOKIE: c=d\r\n");
-
- extern "C" fn concat(
- vec: *mut c_void,
- name: *const u8,
- name_len: usize,
- value: *const u8,
- value_len: usize,
- ) -> c_int {
- unsafe {
- let vec = &mut *(vec as *mut Vec<u8>);
- let name = std::slice::from_raw_parts(name, name_len);
- let value = std::slice::from_raw_parts(value, value_len);
- vec.extend(name);
- vec.extend(b": ");
- vec.extend(value);
- vec.extend(b"\r\n");
- }
- HYPER_ITER_CONTINUE
- }
- }
-
- #[cfg(all(feature = "http1", feature = "ffi"))]
- #[test]
- fn test_headers_foreach_order_preserved() {
- let mut headers = hyper_headers::default();
-
- let name1 = b"Set-CookiE";
- let value1 = b"a=b";
- hyper_headers_add(
- &mut headers,
- name1.as_ptr(),
- name1.len(),
- value1.as_ptr(),
- value1.len(),
- );
-
- let name2 = b"Content-Encoding";
- let value2 = b"gzip";
- hyper_headers_add(
- &mut headers,
- name2.as_ptr(),
- name2.len(),
- value2.as_ptr(),
- value2.len(),
- );
-
- let name3 = b"SET-COOKIE";
- let value3 = b"c=d";
- hyper_headers_add(
- &mut headers,
- name3.as_ptr(),
- name3.len(),
- value3.as_ptr(),
- value3.len(),
- );
-
- let mut vec = Vec::<u8>::new();
- hyper_headers_foreach(&headers, concat, &mut vec as *mut _ as *mut c_void);
-
- println!("{}", std::str::from_utf8(&vec).unwrap());
- assert_eq!(
- vec,
- b"Set-CookiE: a=b\r\nContent-Encoding: gzip\r\nSET-COOKIE: c=d\r\n"
- );
-
- extern "C" fn concat(
- vec: *mut c_void,
- name: *const u8,
- name_len: usize,
- value: *const u8,
- value_len: usize,
- ) -> c_int {
- unsafe {
- let vec = &mut *(vec as *mut Vec<u8>);
- let name = std::slice::from_raw_parts(name, name_len);
- let value = std::slice::from_raw_parts(value, value_len);
- vec.extend(name);
- vec.extend(b": ");
- vec.extend(value);
- vec.extend(b"\r\n");
- }
- HYPER_ITER_CONTINUE
- }
- }
-}
diff --git a/vendor/hyper/src/ffi/io.rs b/vendor/hyper/src/ffi/io.rs
deleted file mode 100644
index 89978b9e..00000000
--- a/vendor/hyper/src/ffi/io.rs
+++ /dev/null
@@ -1,198 +0,0 @@
-use std::ffi::c_void;
-use std::pin::Pin;
-use std::task::{Context, Poll};
-
-use super::task::hyper_context;
-use crate::ffi::size_t;
-use crate::rt::{Read, Write};
-
-/// Sentinel value to return from a read or write callback that the operation
-/// is pending.
-pub const HYPER_IO_PENDING: size_t = 0xFFFFFFFF;
-/// Sentinel value to return from a read or write callback that the operation
-/// has errored.
-pub const HYPER_IO_ERROR: size_t = 0xFFFFFFFE;
-
-type hyper_io_read_callback =
- extern "C" fn(*mut c_void, *mut hyper_context<'_>, *mut u8, size_t) -> size_t;
-type hyper_io_write_callback =
- extern "C" fn(*mut c_void, *mut hyper_context<'_>, *const u8, size_t) -> size_t;
-
-/// A read/write handle for a specific connection.
-///
-/// This owns a specific TCP or TLS connection for the lifetime of
-/// that connection. It contains a read and write callback, as well as a
-/// void *userdata. Typically the userdata will point to a struct
-/// containing a file descriptor and a TLS context.
-///
-/// Methods:
-///
-/// - hyper_io_new: Create a new IO type used to represent a transport.
-/// - hyper_io_set_read: Set the read function for this IO transport.
-/// - hyper_io_set_write: Set the write function for this IO transport.
-/// - hyper_io_set_userdata: Set the user data pointer for this IO to some value.
-/// - hyper_io_free: Free an IO handle.
-pub struct hyper_io {
- read: hyper_io_read_callback,
- write: hyper_io_write_callback,
- userdata: *mut c_void,
-}
-
-ffi_fn! {
- /// Create a new IO type used to represent a transport.
- ///
- /// The read and write functions of this transport should be set with
- /// `hyper_io_set_read` and `hyper_io_set_write`.
- ///
- /// It is expected that the underlying transport is non-blocking. When
- /// a read or write callback can't make progress because there is no
- /// data available yet, it should use the `hyper_waker` mechanism to
- /// arrange to be called again when data is available.
- ///
- /// To avoid a memory leak, the IO handle must eventually be consumed by
- /// `hyper_io_free` or `hyper_clientconn_handshake`.
- fn hyper_io_new() -> *mut hyper_io {
- Box::into_raw(Box::new(hyper_io {
- read: read_noop,
- write: write_noop,
- userdata: std::ptr::null_mut(),
- }))
- } ?= std::ptr::null_mut()
-}
-
-ffi_fn! {
- /// Free an IO handle.
- ///
- /// This should only be used if the request isn't consumed by
- /// `hyper_clientconn_handshake`.
- fn hyper_io_free(io: *mut hyper_io) {
- drop(non_null!(Box::from_raw(io) ?= ()));
- }
-}
-
-ffi_fn! {
- /// Set the user data pointer for this IO to some value.
- ///
- /// This value is passed as an argument to the read and write callbacks.
- fn hyper_io_set_userdata(io: *mut hyper_io, data: *mut c_void) {
- non_null!(&mut *io ?= ()).userdata = data;
- }
-}
-
-ffi_fn! {
- /// Set the read function for this IO transport.
- ///
- /// Data that is read from the transport should be put in the `buf` pointer,
- /// up to `buf_len` bytes. The number of bytes read should be the return value.
- ///
- /// It is undefined behavior to try to access the bytes in the `buf` pointer,
- /// unless you have already written them yourself. It is also undefined behavior
- /// to return that more bytes have been written than actually set on the `buf`.
- ///
- /// If there is no data currently available, the callback should create a
- /// `hyper_waker` from its `hyper_context` argument and register the waker
- /// with whatever polling mechanism is used to signal when data is available
- /// later on. The return value should be `HYPER_IO_PENDING`. See the
- /// documentation for `hyper_waker`.
- ///
- /// If there is an irrecoverable error reading data, then `HYPER_IO_ERROR`
- /// should be the return value.
- fn hyper_io_set_read(io: *mut hyper_io, func: hyper_io_read_callback) {
- non_null!(&mut *io ?= ()).read = func;
- }
-}
-
-ffi_fn! {
- /// Set the write function for this IO transport.
- ///
- /// Data from the `buf` pointer should be written to the transport, up to
- /// `buf_len` bytes. The number of bytes written should be the return value.
- ///
- /// If there is no data currently available, the callback should create a
- /// `hyper_waker` from its `hyper_context` argument and register the waker
- /// with whatever polling mechanism is used to signal when data is available
- /// later on. The return value should be `HYPER_IO_PENDING`. See the documentation
- /// for `hyper_waker`.
- ///
- /// If there is an irrecoverable error reading data, then `HYPER_IO_ERROR`
- /// should be the return value.
- fn hyper_io_set_write(io: *mut hyper_io, func: hyper_io_write_callback) {
- non_null!(&mut *io ?= ()).write = func;
- }
-}
-
-/// cbindgen:ignore
-extern "C" fn read_noop(
- _userdata: *mut c_void,
- _: *mut hyper_context<'_>,
- _buf: *mut u8,
- _buf_len: size_t,
-) -> size_t {
- 0
-}
-
-/// cbindgen:ignore
-extern "C" fn write_noop(
- _userdata: *mut c_void,
- _: *mut hyper_context<'_>,
- _buf: *const u8,
- _buf_len: size_t,
-) -> size_t {
- 0
-}
-
-impl Read for hyper_io {
- fn poll_read(
- self: Pin<&mut Self>,
- cx: &mut Context<'_>,
- mut buf: crate::rt::ReadBufCursor<'_>,
- ) -> Poll<std::io::Result<()>> {
- let buf_ptr = unsafe { buf.as_mut() }.as_mut_ptr() as *mut u8;
- let buf_len = buf.remaining();
-
- match (self.read)(self.userdata, hyper_context::wrap(cx), buf_ptr, buf_len) {
- HYPER_IO_PENDING => Poll::Pending,
- HYPER_IO_ERROR => Poll::Ready(Err(std::io::Error::new(
- std::io::ErrorKind::Other,
- "io error",
- ))),
- ok => {
- // We have to trust that the user's read callback actually
- // filled in that many bytes... :(
- unsafe { buf.advance(ok) };
- Poll::Ready(Ok(()))
- }
- }
- }
-}
-
-impl Write for hyper_io {
- fn poll_write(
- self: Pin<&mut Self>,
- cx: &mut Context<'_>,
- buf: &[u8],
- ) -> Poll<std::io::Result<usize>> {
- let buf_ptr = buf.as_ptr();
- let buf_len = buf.len();
-
- match (self.write)(self.userdata, hyper_context::wrap(cx), buf_ptr, buf_len) {
- HYPER_IO_PENDING => Poll::Pending,
- HYPER_IO_ERROR => Poll::Ready(Err(std::io::Error::new(
- std::io::ErrorKind::Other,
- "io error",
- ))),
- ok => Poll::Ready(Ok(ok)),
- }
- }
-
- fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<std::io::Result<()>> {
- Poll::Ready(Ok(()))
- }
-
- fn poll_shutdown(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<std::io::Result<()>> {
- Poll::Ready(Ok(()))
- }
-}
-
-unsafe impl Send for hyper_io {}
-unsafe impl Sync for hyper_io {}
diff --git a/vendor/hyper/src/ffi/macros.rs b/vendor/hyper/src/ffi/macros.rs
deleted file mode 100644
index 022711ba..00000000
--- a/vendor/hyper/src/ffi/macros.rs
+++ /dev/null
@@ -1,53 +0,0 @@
-macro_rules! ffi_fn {
- ($(#[$doc:meta])* fn $name:ident($($arg:ident: $arg_ty:ty),*) -> $ret:ty $body:block ?= $default:expr) => {
- $(#[$doc])*
- #[no_mangle]
- pub extern fn $name($($arg: $arg_ty),*) -> $ret {
- use std::panic::{self, AssertUnwindSafe};
-
- match panic::catch_unwind(AssertUnwindSafe(move || $body)) {
- Ok(v) => v,
- Err(_) => {
- $default
- }
- }
- }
- };
-
- ($(#[$doc:meta])* fn $name:ident($($arg:ident: $arg_ty:ty),*) -> $ret:ty $body:block) => {
- ffi_fn!($(#[$doc])* fn $name($($arg: $arg_ty),*) -> $ret $body ?= {
- eprintln!("panic unwind caught, aborting");
- std::process::abort()
- });
- };
-
- ($(#[$doc:meta])* fn $name:ident($($arg:ident: $arg_ty:ty),*) $body:block ?= $default:expr) => {
- ffi_fn!($(#[$doc])* fn $name($($arg: $arg_ty),*) -> () $body ?= $default);
- };
-
- ($(#[$doc:meta])* fn $name:ident($($arg:ident: $arg_ty:ty),*) $body:block) => {
- ffi_fn!($(#[$doc])* fn $name($($arg: $arg_ty),*) -> () $body);
- };
-}
-
-macro_rules! non_null {
- ($ptr:ident, $eval:expr, $err:expr) => {{
- debug_assert!(!$ptr.is_null(), "{:?} must not be null", stringify!($ptr));
- if $ptr.is_null() {
- return $err;
- }
- unsafe { $eval }
- }};
- (&*$ptr:ident ?= $err:expr) => {{
- non_null!($ptr, &*$ptr, $err)
- }};
- (&mut *$ptr:ident ?= $err:expr) => {{
- non_null!($ptr, &mut *$ptr, $err)
- }};
- (Box::from_raw($ptr:ident) ?= $err:expr) => {{
- non_null!($ptr, Box::from_raw($ptr), $err)
- }};
- (Arc::from_raw($ptr:ident) ?= $err:expr) => {{
- non_null!($ptr, Arc::from_raw($ptr), $err)
- }};
-}
diff --git a/vendor/hyper/src/ffi/mod.rs b/vendor/hyper/src/ffi/mod.rs
deleted file mode 100644
index cdcbc482..00000000
--- a/vendor/hyper/src/ffi/mod.rs
+++ /dev/null
@@ -1,99 +0,0 @@
-// We have a lot of c-types in here, stop warning about their names!
-#![allow(non_camel_case_types)]
-// fmt::Debug isn't helpful on FFI types
-#![allow(missing_debug_implementations)]
-// unreachable_pub warns `#[no_mangle] pub extern fn` in private mod.
-#![allow(unreachable_pub)]
-
-//! # hyper C API
-//!
-//! This part of the documentation describes the C API for hyper. That is, how
-//! to *use* the hyper library in C code. This is **not** a regular Rust
-//! module, and thus it is not accessible in Rust.
-//!
-//! ## Unstable
-//!
-//! The C API of hyper is currently **unstable**, which means it's not part of
-//! the semver contract as the rest of the Rust API is. Because of that, it's
-//! only accessible if `--cfg hyper_unstable_ffi` is passed to `rustc` when
-//! compiling. The easiest way to do that is setting the `RUSTFLAGS`
-//! environment variable.
-//!
-//! ## Building
-//!
-//! The C API is part of the Rust library, but isn't compiled by default. Using
-//! `cargo`, staring with `1.64.0`, it can be compiled with the following command:
-//!
-//! ```notrust
-//! RUSTFLAGS="--cfg hyper_unstable_ffi" cargo rustc --crate-type cdylib --features client,http1,http2,ffi
-//! ```
-
-// We may eventually allow the FFI to be enabled without `client` or `http1`,
-// that is why we don't auto enable them as `ffi = ["client", "http1"]` in
-// the `Cargo.toml`.
-//
-// But for now, give a clear message that this compile error is expected.
-#[cfg(not(all(feature = "client", feature = "http1")))]
-compile_error!("The `ffi` feature currently requires the `client` and `http1` features.");
-
-#[cfg(not(hyper_unstable_ffi))]
-compile_error!(
- "\
- The `ffi` feature is unstable, and requires the \
- `RUSTFLAGS='--cfg hyper_unstable_ffi'` environment variable to be set.\
-"
-);
-
-#[macro_use]
-mod macros;
-
-mod body;
-mod client;
-mod error;
-mod http_types;
-mod io;
-mod task;
-
-pub use self::body::*;
-pub use self::client::*;
-pub use self::error::*;
-pub use self::http_types::*;
-pub use self::io::*;
-pub use self::task::*;
-
-/// Return in iter functions to continue iterating.
-pub const HYPER_ITER_CONTINUE: std::ffi::c_int = 0;
-/// Return in iter functions to stop iterating.
-#[allow(unused)]
-pub const HYPER_ITER_BREAK: std::ffi::c_int = 1;
-
-/// An HTTP Version that is unspecified.
-pub const HYPER_HTTP_VERSION_NONE: std::ffi::c_int = 0;
-/// The HTTP/1.0 version.
-pub const HYPER_HTTP_VERSION_1_0: std::ffi::c_int = 10;
-/// The HTTP/1.1 version.
-pub const HYPER_HTTP_VERSION_1_1: std::ffi::c_int = 11;
-/// The HTTP/2 version.
-pub const HYPER_HTTP_VERSION_2: std::ffi::c_int = 20;
-
-#[derive(Clone)]
-struct UserDataPointer(*mut std::ffi::c_void);
-
-// We don't actually know anything about this pointer, it's up to the user
-// to do the right thing.
-unsafe impl Send for UserDataPointer {}
-unsafe impl Sync for UserDataPointer {}
-
-/// cbindgen:ignore
-static VERSION_CSTR: &str = concat!(env!("CARGO_PKG_VERSION"), "\0");
-
-// `core::ffi::c_size_t` is a nightly-only experimental API.
-// https://github.com/rust-lang/rust/issues/88345
-type size_t = usize;
-
-ffi_fn! {
- /// Returns a static ASCII (null terminated) string of the hyper version.
- fn hyper_version() -> *const std::ffi::c_char {
- VERSION_CSTR.as_ptr() as _
- } ?= std::ptr::null()
-}
diff --git a/vendor/hyper/src/ffi/task.rs b/vendor/hyper/src/ffi/task.rs
deleted file mode 100644
index 5b33d42b..00000000
--- a/vendor/hyper/src/ffi/task.rs
+++ /dev/null
@@ -1,549 +0,0 @@
-use std::ffi::{c_int, c_void};
-use std::future::Future;
-use std::pin::Pin;
-use std::ptr;
-use std::sync::{
- atomic::{AtomicBool, Ordering},
- Arc, Mutex, Weak,
-};
-use std::task::{Context, Poll};
-
-use futures_util::stream::{FuturesUnordered, Stream};
-
-use super::error::hyper_code;
-use super::UserDataPointer;
-
-type BoxFuture<T> = Pin<Box<dyn Future<Output = T> + Send>>;
-type BoxAny = Box<dyn AsTaskType + Send + Sync>;
-
-/// Return in a poll function to indicate it was ready.
-pub const HYPER_POLL_READY: c_int = 0;
-/// Return in a poll function to indicate it is still pending.
-///
-/// The passed in `hyper_waker` should be registered to wake up the task at
-/// some later point.
-pub const HYPER_POLL_PENDING: c_int = 1;
-/// Return in a poll function indicate an error.
-pub const HYPER_POLL_ERROR: c_int = 3;
-
-/// A task executor for `hyper_task`s.
-///
-/// A task is a unit of work that may be blocked on IO, and can be polled to
-/// make progress on that work.
-///
-/// An executor can hold many tasks, included from unrelated HTTP connections.
-/// An executor is single threaded. Typically you might have one executor per
-/// thread. Or, for simplicity, you may choose one executor per connection.
-///
-/// Progress on tasks happens only when `hyper_executor_poll` is called, and only
-/// on tasks whose corresponding `hyper_waker` has been called to indicate they
-/// are ready to make progress (for instance, because the OS has indicated there
-/// is more data to read or more buffer space available to write).
-///
-/// Deadlock potential: `hyper_executor_poll` must not be called from within a task's
-/// callback. Doing so will result in a deadlock.
-///
-/// Methods:
-///
-/// - hyper_executor_new: Creates a new task executor.
-/// - hyper_executor_push: Push a task onto the executor.
-/// - hyper_executor_poll: Polls the executor, trying to make progress on any tasks that have notified that they are ready again.
-/// - hyper_executor_free: Frees an executor and any incomplete tasks still part of it.
-pub struct hyper_executor {
- /// The executor of all task futures.
- ///
- /// There should never be contention on the mutex, as it is only locked
- /// to drive the futures. However, we cannot guarantee proper usage from
- /// `hyper_executor_poll()`, which in C could potentially be called inside
- /// one of the stored futures. The mutex isn't re-entrant, so doing so
- /// would result in a deadlock, but that's better than data corruption.
- driver: Mutex<FuturesUnordered<TaskFuture>>,
-
- /// The queue of futures that need to be pushed into the `driver`.
- ///
- /// This is has a separate mutex since `spawn` could be called from inside
- /// a future, which would mean the driver's mutex is already locked.
- spawn_queue: Mutex<Vec<TaskFuture>>,
-
- /// This is used to track when a future calls `wake` while we are within
- /// `hyper_executor::poll_next`.
- is_woken: Arc<ExecWaker>,
-}
-
-#[derive(Clone)]
-pub(crate) struct WeakExec(Weak<hyper_executor>);
-
-struct ExecWaker(AtomicBool);
-
-/// An async task.
-///
-/// A task represents a chunk of work that will eventually yield exactly one
-/// `hyper_task_value`. Tasks are pushed onto an executor, and that executor is
-/// responsible for calling the necessary private functions on the task to make
-/// progress. In most cases those private functions will eventually cause read
-/// or write callbacks on a `hyper_io` object to be called.
-///
-/// Tasks are created by various functions:
-///
-/// - hyper_clientconn_handshake: Creates an HTTP client handshake task.
-/// - hyper_clientconn_send: Creates a task to send a request on the client connection.
-/// - hyper_body_data: Creates a task that will poll a response body for the next buffer of data.
-/// - hyper_body_foreach: Creates a task to execute the callback with each body chunk received.
-///
-/// Tasks then have a userdata associated with them using `hyper_task_set_userdata``. This
-/// is important, for instance, to associate a request id with a given request. When multiple
-/// tasks are running on the same executor, this allows distinguishing tasks for different
-/// requests.
-///
-/// Tasks are then pushed onto an executor, and eventually yielded from hyper_executor_poll:
-///
-/// - hyper_executor_push: Push a task onto the executor.
-/// - hyper_executor_poll: Polls the executor, trying to make progress on any tasks that have notified that they are ready again.
-///
-/// Once a task is yielded from poll, retrieve its userdata, check its type,
-/// and extract its value. This will require a case from void* to the appropriate type.
-///
-/// Methods on hyper_task:
-///
-/// - hyper_task_type: Query the return type of this task.
-/// - hyper_task_value: Takes the output value of this task.
-/// - hyper_task_set_userdata: Set a user data pointer to be associated with this task.
-/// - hyper_task_userdata: Retrieve the userdata that has been set via hyper_task_set_userdata.
-/// - hyper_task_free: Free a task.
-pub struct hyper_task {
- future: BoxFuture<BoxAny>,
- output: Option<BoxAny>,
- userdata: UserDataPointer,
-}
-
-struct TaskFuture {
- task: Option<Box<hyper_task>>,
-}
-
-/// An async context for a task that contains the related waker.
-///
-/// This is provided to `hyper_io`'s read and write callbacks. Currently
-/// its only purpose is to provide access to the waker. See `hyper_waker`.
-///
-/// Corresponding Rust type: <https://doc.rust-lang.org/std/task/struct.Context.html>
-pub struct hyper_context<'a>(Context<'a>);
-
-/// A waker that is saved and used to waken a pending task.
-///
-/// This is provided to `hyper_io`'s read and write callbacks via `hyper_context`
-/// and `hyper_context_waker`.
-///
-/// When nonblocking I/O in one of those callbacks can't make progress (returns
-/// `EAGAIN` or `EWOULDBLOCK`), the callback has to return to avoid blocking the
-/// executor. But it also has to arrange to get called in the future when more
-/// data is available. That's the role of the async context and the waker. The
-/// waker can be used to tell the executor "this task is ready to make progress."
-///
-/// The read or write callback, upon finding it can't make progress, must get a
-/// waker from the context (`hyper_context_waker`), arrange for that waker to be
-/// called in the future, and then return `HYPER_POLL_PENDING`.
-///
-/// The arrangements for the waker to be called in the future are up to the
-/// application, but usually it will involve one big `select(2)` loop that checks which
-/// FDs are ready, and a correspondence between FDs and waker objects. For each
-/// FD that is ready, the corresponding waker must be called. Then `hyper_executor_poll`
-/// must be called. That will cause the executor to attempt to make progress on each
-/// woken task.
-///
-/// Corresponding Rust type: <https://doc.rust-lang.org/std/task/struct.Waker.html>
-pub struct hyper_waker {
- waker: std::task::Waker,
-}
-
-/// A descriptor for what type a `hyper_task` value is.
-#[repr(C)]
-pub enum hyper_task_return_type {
- /// The value of this task is null (does not imply an error).
- HYPER_TASK_EMPTY,
- /// The value of this task is `hyper_error *`.
- HYPER_TASK_ERROR,
- /// The value of this task is `hyper_clientconn *`.
- HYPER_TASK_CLIENTCONN,
- /// The value of this task is `hyper_response *`.
- HYPER_TASK_RESPONSE,
- /// The value of this task is `hyper_buf *`.
- HYPER_TASK_BUF,
-}
-
-pub(crate) unsafe trait AsTaskType {
- fn as_task_type(&self) -> hyper_task_return_type;
-}
-
-pub(crate) trait IntoDynTaskType {
- fn into_dyn_task_type(self) -> BoxAny;
-}
-
-// ===== impl hyper_executor =====
-
-impl hyper_executor {
- fn new() -> Arc<hyper_executor> {
- Arc::new(hyper_executor {
- driver: Mutex::new(FuturesUnordered::new()),
- spawn_queue: Mutex::new(Vec::new()),
- is_woken: Arc::new(ExecWaker(AtomicBool::new(false))),
- })
- }
-
- pub(crate) fn downgrade(exec: &Arc<hyper_executor>) -> WeakExec {
- WeakExec(Arc::downgrade(exec))
- }
-
- fn spawn(&self, task: Box<hyper_task>) {
- self.spawn_queue
- .lock()
- .unwrap()
- .push(TaskFuture { task: Some(task) });
- }
-
- fn poll_next(&self) -> Option<Box<hyper_task>> {
- // Drain the queue first.
- self.drain_queue();
-
- let waker = futures_util::task::waker_ref(&self.is_woken);
- let mut cx = Context::from_waker(&waker);
-
- loop {
- {
- // Scope the lock on the driver to ensure it is dropped before
- // calling drain_queue below.
- let mut driver = self.driver.lock().unwrap();
- match Pin::new(&mut *driver).poll_next(&mut cx) {
- Poll::Ready(val) => return val,
- Poll::Pending => {}
- };
- }
-
- // poll_next returned Pending.
- // Check if any of the pending tasks tried to spawn
- // some new tasks. If so, drain into the driver and loop.
- if self.drain_queue() {
- continue;
- }
-
- // If the driver called `wake` while we were polling,
- // we should poll again immediately!
- if self.is_woken.0.swap(false, Ordering::SeqCst) {
- continue;
- }
-
- return None;
- }
- }
-
- /// drain_queue locks both self.spawn_queue and self.driver, so it requires
- /// that neither of them be locked already.
- fn drain_queue(&self) -> bool {
- let mut queue = self.spawn_queue.lock().unwrap();
- if queue.is_empty() {
- return false;
- }
-
- let driver = self.driver.lock().unwrap();
-
- for task in queue.drain(..) {
- driver.push(task);
- }
-
- true
- }
-}
-
-impl futures_util::task::ArcWake for ExecWaker {
- fn wake_by_ref(me: &Arc<ExecWaker>) {
- me.0.store(true, Ordering::SeqCst);
- }
-}
-
-// ===== impl WeakExec =====
-
-impl WeakExec {
- pub(crate) fn new() -> Self {
- WeakExec(Weak::new())
- }
-}
-
-impl<F> crate::rt::Executor<F> for WeakExec
-where
- F: Future + Send + 'static,
- F::Output: Send + Sync + AsTaskType,
-{
- fn execute(&self, fut: F) {
- if let Some(exec) = self.0.upgrade() {
- exec.spawn(hyper_task::boxed(fut));
- }
- }
-}
-
-ffi_fn! {
- /// Creates a new task executor.
- ///
- /// To avoid a memory leak, the executor must eventually be consumed by
- /// `hyper_executor_free`.
- fn hyper_executor_new() -> *const hyper_executor {
- Arc::into_raw(hyper_executor::new())
- } ?= ptr::null()
-}
-
-ffi_fn! {
- /// Frees an executor and any incomplete tasks still part of it.
- ///
- /// This should be used for any executor once it is no longer needed.
- fn hyper_executor_free(exec: *const hyper_executor) {
- drop(non_null!(Arc::from_raw(exec) ?= ()));
- }
-}
-
-ffi_fn! {
- /// Push a task onto the executor.
- ///
- /// The executor takes ownership of the task, which must not be accessed
- /// again.
- ///
- /// Ownership of the task will eventually be returned to the user from
- /// `hyper_executor_poll`.
- ///
- /// To distinguish multiple tasks running on the same executor, use
- /// hyper_task_set_userdata.
- fn hyper_executor_push(exec: *const hyper_executor, task: *mut hyper_task) -> hyper_code {
- let exec = non_null!(&*exec ?= hyper_code::HYPERE_INVALID_ARG);
- let task = non_null!(Box::from_raw(task) ?= hyper_code::HYPERE_INVALID_ARG);
- exec.spawn(task);
- hyper_code::HYPERE_OK
- }
-}
-
-ffi_fn! {
- /// Polls the executor, trying to make progress on any tasks that can do so.
- ///
- /// If any task from the executor is ready, returns one of them. The way
- /// tasks signal being finished is internal to Hyper. The order in which tasks
- /// are returned is not guaranteed. Use userdata to distinguish between tasks.
- ///
- /// To avoid a memory leak, the task must eventually be consumed by
- /// `hyper_task_free`.
- ///
- /// If there are no ready tasks, this returns `NULL`.
- fn hyper_executor_poll(exec: *const hyper_executor) -> *mut hyper_task {
- let exec = non_null!(&*exec ?= ptr::null_mut());
- match exec.poll_next() {
- Some(task) => Box::into_raw(task),
- None => ptr::null_mut(),
- }
- } ?= ptr::null_mut()
-}
-
-// ===== impl hyper_task =====
-
-impl hyper_task {
- pub(crate) fn boxed<F>(fut: F) -> Box<hyper_task>
- where
- F: Future + Send + 'static,
- F::Output: IntoDynTaskType + Send + Sync + 'static,
- {
- Box::new(hyper_task {
- future: Box::pin(async move { fut.await.into_dyn_task_type() }),
- output: None,
- userdata: UserDataPointer(ptr::null_mut()),
- })
- }
-
- fn output_type(&self) -> hyper_task_return_type {
- match self.output {
- None => hyper_task_return_type::HYPER_TASK_EMPTY,
- Some(ref val) => val.as_task_type(),
- }
- }
-}
-
-impl Future for TaskFuture {
- type Output = Box<hyper_task>;
-
- fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
- match Pin::new(&mut self.task.as_mut().unwrap().future).poll(cx) {
- Poll::Ready(val) => {
- let mut task = self.task.take().unwrap();
- task.output = Some(val);
- Poll::Ready(task)
- }
- Poll::Pending => Poll::Pending,
- }
- }
-}
-
-ffi_fn! {
- /// Free a task.
- ///
- /// This should only be used if the task isn't consumed by
- /// `hyper_clientconn_handshake` or taken ownership of by
- /// `hyper_executor_push`.
- fn hyper_task_free(task: *mut hyper_task) {
- drop(non_null!(Box::from_raw(task) ?= ()));
- }
-}
-
-ffi_fn! {
- /// Takes the output value of this task.
- ///
- /// This must only be called once polling the task on an executor has finished
- /// this task.
- ///
- /// Use `hyper_task_type` to determine the type of the `void *` return value.
- ///
- /// To avoid a memory leak, a non-empty return value must eventually be
- /// consumed by a function appropriate for its type, one of
- /// `hyper_error_free`, `hyper_clientconn_free`, `hyper_response_free`, or
- /// `hyper_buf_free`.
- fn hyper_task_value(task: *mut hyper_task) -> *mut c_void {
- let task = non_null!(&mut *task ?= ptr::null_mut());
-
- if let Some(val) = task.output.take() {
- let p = Box::into_raw(val) as *mut c_void;
- // protect from returning fake pointers to empty types
- if p == std::ptr::NonNull::<c_void>::dangling().as_ptr() {
- ptr::null_mut()
- } else {
- p
- }
- } else {
- ptr::null_mut()
- }
- } ?= ptr::null_mut()
-}
-
-ffi_fn! {
- /// Query the return type of this task.
- fn hyper_task_type(task: *mut hyper_task) -> hyper_task_return_type {
- // instead of blowing up spectacularly, just say this null task
- // doesn't have a value to retrieve.
- non_null!(&*task ?= hyper_task_return_type::HYPER_TASK_EMPTY).output_type()
- }
-}
-
-ffi_fn! {
- /// Set a user data pointer to be associated with this task.
- ///
- /// This value will be passed to task callbacks, and can be checked later
- /// with `hyper_task_userdata`.
- ///
- /// This is useful for telling apart tasks for different requests that are
- /// running on the same executor.
- fn hyper_task_set_userdata(task: *mut hyper_task, userdata: *mut c_void) {
- if task.is_null() {
- return;
- }
-
- unsafe { (*task).userdata = UserDataPointer(userdata) };
- }
-}
-
-ffi_fn! {
- /// Retrieve the userdata that has been set via `hyper_task_set_userdata`.
- fn hyper_task_userdata(task: *mut hyper_task) -> *mut c_void {
- non_null!(&*task ?= ptr::null_mut()).userdata.0
- } ?= ptr::null_mut()
-}
-
-// ===== impl AsTaskType =====
-
-unsafe impl AsTaskType for () {
- fn as_task_type(&self) -> hyper_task_return_type {
- hyper_task_return_type::HYPER_TASK_EMPTY
- }
-}
-
-unsafe impl AsTaskType for crate::Error {
- fn as_task_type(&self) -> hyper_task_return_type {
- hyper_task_return_type::HYPER_TASK_ERROR
- }
-}
-
-impl<T> IntoDynTaskType for T
-where
- T: AsTaskType + Send + Sync + 'static,
-{
- fn into_dyn_task_type(self) -> BoxAny {
- Box::new(self)
- }
-}
-
-impl<T> IntoDynTaskType for crate::Result<T>
-where
- T: IntoDynTaskType + Send + Sync + 'static,
-{
- fn into_dyn_task_type(self) -> BoxAny {
- match self {
- Ok(val) => val.into_dyn_task_type(),
- Err(err) => Box::new(err),
- }
- }
-}
-
-impl<T> IntoDynTaskType for Option<T>
-where
- T: IntoDynTaskType + Send + Sync + 'static,
-{
- fn into_dyn_task_type(self) -> BoxAny {
- match self {
- Some(val) => val.into_dyn_task_type(),
- None => ().into_dyn_task_type(),
- }
- }
-}
-
-// ===== impl hyper_context =====
-
-impl hyper_context<'_> {
- pub(crate) fn wrap<'a, 'b>(cx: &'a mut Context<'b>) -> &'a mut hyper_context<'b> {
- // A struct with only one field has the same layout as that field.
- unsafe { std::mem::transmute::<&mut Context<'_>, &mut hyper_context<'_>>(cx) }
- }
-}
-
-ffi_fn! {
- /// Creates a waker associated with the task context.
- ///
- /// The waker can be used to inform the task's executor that the task is
- /// ready to make progress (using `hyper_waker_wake``).
- ///
- /// Typically this only needs to be called once, but it can be called
- /// multiple times, returning a new waker each time.
- ///
- /// To avoid a memory leak, the waker must eventually be consumed by
- /// `hyper_waker_free` or `hyper_waker_wake`.
- fn hyper_context_waker(cx: *mut hyper_context<'_>) -> *mut hyper_waker {
- let waker = non_null!(&mut *cx ?= ptr::null_mut()).0.waker().clone();
- Box::into_raw(Box::new(hyper_waker { waker }))
- } ?= ptr::null_mut()
-}
-
-// ===== impl hyper_waker =====
-
-ffi_fn! {
- /// Free a waker.
- ///
- /// This should only be used if the request isn't consumed by
- /// `hyper_waker_wake`.
- fn hyper_waker_free(waker: *mut hyper_waker) {
- drop(non_null!(Box::from_raw(waker) ?= ()));
- }
-}
-
-ffi_fn! {
- /// Wake up the task associated with a waker.
- ///
- /// This does not do work towards associated task. Instead, it signals
- /// to the task's executor that the task is ready to make progress. The
- /// application is responsible for calling hyper_executor_poll, which
- /// will in turn do work on all tasks that are ready to make progress.
- ///
- /// NOTE: This consumes the waker. You should not use or free the waker afterwards.
- fn hyper_waker_wake(waker: *mut hyper_waker) {
- let waker = non_null!(Box::from_raw(waker) ?= ());
- waker.waker.wake();
- }
-}