//! # Wasmtime's [wasi-tls] (Transport Layer Security) Implementation1//!2//! This crate provides the Wasmtime host implementation for the [wasi-tls] API.3//! The [wasi-tls] world allows WebAssembly modules to perform SSL/TLS operations,4//! such as establishing secure connections to servers. TLS often relies on other wasi networking systems5//! to provide the stream so it will be common to enable the [wasi:cli] world as well with the networking features enabled.6//!7//! # An example of how to configure [wasi-tls] is the following:8//!9//! ```rust10//! use wasmtime_wasi::{WasiCtx, WasiCtxView, WasiView};11//! use wasmtime::{12//! component::{Linker, ResourceTable},13//! Store, Engine, Result,14//! };15//! use wasmtime_wasi_tls::{LinkOptions, WasiTls, WasiTlsCtx, WasiTlsCtxBuilder};16//!17//! struct Ctx {18//! table: ResourceTable,19//! wasi_ctx: WasiCtx,20//! wasi_tls_ctx: WasiTlsCtx,21//! }22//!23//! impl WasiView for Ctx {24//! fn ctx(&mut self) -> WasiCtxView<'_> {25//! WasiCtxView { ctx: &mut self.wasi_ctx, table: &mut self.table }26//! }27//! }28//!29//! #[tokio::main]30//! async fn main() -> Result<()> {31//! let ctx = Ctx {32//! table: ResourceTable::new(),33//! wasi_ctx: WasiCtx::builder()34//! .inherit_stderr()35//! .inherit_network()36//! .allow_ip_name_lookup(true)37//! .build(),38//! wasi_tls_ctx: WasiTlsCtxBuilder::new()39//! // Optionally, configure a different TLS provider:40//! // .provider(Box::new(wasmtime_wasi_tls_nativetls::NativeTlsProvider::default()))41//! .build(),42//! };43//!44//! let engine = Engine::default();45//!46//! // Set up wasi-cli47//! let mut store = Store::new(&engine, ctx);48//! let mut linker = Linker::new(&engine);49//! wasmtime_wasi::p2::add_to_linker_async(&mut linker)?;50//!51//! // Add wasi-tls types and turn on the feature in linker52//! let mut opts = LinkOptions::default();53//! opts.tls(true);54//! wasmtime_wasi_tls::add_to_linker(&mut linker, &mut opts, |h: &mut Ctx| {55//! WasiTls::new(&h.wasi_tls_ctx, &mut h.table)56//! })?;57//!58//! // ... use `linker` to instantiate within `store` ...59//! Ok(())60//! }61//!62//! ```63//! [wasi-tls]: https://github.com/WebAssembly/wasi-tls64//! [wasi:cli]: https://docs.rs/wasmtime-wasi/latest6566#![deny(missing_docs)]67#![doc(test(attr(deny(warnings))))]68#![doc(test(attr(allow(dead_code, unused_variables, unused_mut))))]6970use tokio::io::{AsyncRead, AsyncWrite};71use wasmtime::component::{HasData, ResourceTable};7273pub mod bindings;74mod host;75mod io;76mod rustls;7778pub use bindings::types::LinkOptions;79pub use host::{HostClientConnection, HostClientHandshake, HostFutureClientStreams};80pub use rustls::RustlsProvider;8182/// Capture the state necessary for use in the `wasi-tls` API implementation.83pub struct WasiTls<'a> {84ctx: &'a WasiTlsCtx,85table: &'a mut ResourceTable,86}8788impl<'a> WasiTls<'a> {89/// Create a new Wasi TLS context90pub fn new(ctx: &'a WasiTlsCtx, table: &'a mut ResourceTable) -> Self {91Self { ctx, table }92}93}9495/// Add the `wasi-tls` world's types to a [`wasmtime::component::Linker`].96pub fn add_to_linker<T: Send + 'static>(97l: &mut wasmtime::component::Linker<T>,98opts: &mut LinkOptions,99f: fn(&mut T) -> WasiTls<'_>,100) -> wasmtime::Result<()> {101bindings::types::add_to_linker::<_, HasWasiTls>(l, &opts, f)?;102Ok(())103}104105struct HasWasiTls;106impl HasData for HasWasiTls {107type Data<'a> = WasiTls<'a>;108}109110/// Builder-style structure used to create a [`WasiTlsCtx`].111pub struct WasiTlsCtxBuilder {112provider: Box<dyn TlsProvider>,113}114115impl WasiTlsCtxBuilder {116/// Creates a builder for a new context with default parameters set.117pub fn new() -> Self {118Default::default()119}120121/// Configure the TLS provider to use for this context.122///123/// By default, this is set to the [`RustlsProvider`].124pub fn provider(mut self, provider: Box<dyn TlsProvider>) -> Self {125self.provider = provider;126self127}128129/// Uses the configured context so far to construct the final [`WasiTlsCtx`].130pub fn build(self) -> WasiTlsCtx {131WasiTlsCtx {132provider: self.provider,133}134}135}136impl Default for WasiTlsCtxBuilder {137fn default() -> Self {138Self {139provider: Box::new(RustlsProvider::default()),140}141}142}143144/// Wasi TLS context needed for internal `wasi-tls` state.145pub struct WasiTlsCtx {146pub(crate) provider: Box<dyn TlsProvider>,147}148149/// The data stream that carries the encrypted TLS data.150/// Typically this is a TCP stream.151pub trait TlsTransport: AsyncRead + AsyncWrite + Send + Unpin + 'static {}152impl<T: AsyncRead + AsyncWrite + Send + Unpin + ?Sized + 'static> TlsTransport for T {}153154/// A TLS connection.155pub trait TlsStream: AsyncRead + AsyncWrite + Send + Unpin + 'static {}156157/// A TLS implementation.158pub trait TlsProvider: Send + Sync + 'static {159/// Set up a client TLS connection using the provided `server_name` and `transport`.160fn connect(161&self,162server_name: String,163transport: Box<dyn TlsTransport>,164) -> BoxFuture<std::io::Result<Box<dyn TlsStream>>>;165}166167pub(crate) type BoxFuture<T> = std::pin::Pin<Box<dyn Future<Output = T> + Send>>;168169170