//! # 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, Config14//! };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 mut config = Config::new();45//! config.async_support(true);46//! let engine = Engine::new(&config)?;47//!48//! // Set up wasi-cli49//! let mut store = Store::new(&engine, ctx);50//! let mut linker = Linker::new(&engine);51//! wasmtime_wasi::p2::add_to_linker_async(&mut linker)?;52//!53//! // Add wasi-tls types and turn on the feature in linker54//! let mut opts = LinkOptions::default();55//! opts.tls(true);56//! wasmtime_wasi_tls::add_to_linker(&mut linker, &mut opts, |h: &mut Ctx| {57//! WasiTls::new(&h.wasi_tls_ctx, &mut h.table)58//! })?;59//!60//! // ... use `linker` to instantiate within `store` ...61//! Ok(())62//! }63//!64//! ```65//! [wasi-tls]: https://github.com/WebAssembly/wasi-tls66//! [wasi:cli]: https://docs.rs/wasmtime-wasi/latest6768#![deny(missing_docs)]69#![doc(test(attr(deny(warnings))))]70#![doc(test(attr(allow(dead_code, unused_variables, unused_mut))))]7172use tokio::io::{AsyncRead, AsyncWrite};73use wasmtime::component::{HasData, ResourceTable};7475pub mod bindings;76mod host;77mod io;78mod rustls;7980pub use bindings::types::LinkOptions;81pub use host::{HostClientConnection, HostClientHandshake, HostFutureClientStreams};82pub use rustls::RustlsProvider;8384/// Capture the state necessary for use in the `wasi-tls` API implementation.85pub struct WasiTls<'a> {86ctx: &'a WasiTlsCtx,87table: &'a mut ResourceTable,88}8990impl<'a> WasiTls<'a> {91/// Create a new Wasi TLS context92pub fn new(ctx: &'a WasiTlsCtx, table: &'a mut ResourceTable) -> Self {93Self { ctx, table }94}95}9697/// Add the `wasi-tls` world's types to a [`wasmtime::component::Linker`].98pub fn add_to_linker<T: Send + 'static>(99l: &mut wasmtime::component::Linker<T>,100opts: &mut LinkOptions,101f: fn(&mut T) -> WasiTls<'_>,102) -> anyhow::Result<()> {103bindings::types::add_to_linker::<_, HasWasiTls>(l, &opts, f)?;104Ok(())105}106107struct HasWasiTls;108impl HasData for HasWasiTls {109type Data<'a> = WasiTls<'a>;110}111112/// Builder-style structure used to create a [`WasiTlsCtx`].113pub struct WasiTlsCtxBuilder {114provider: Box<dyn TlsProvider>,115}116117impl WasiTlsCtxBuilder {118/// Creates a builder for a new context with default parameters set.119pub fn new() -> Self {120Default::default()121}122123/// Configure the TLS provider to use for this context.124///125/// By default, this is set to the [`RustlsProvider`].126pub fn provider(mut self, provider: Box<dyn TlsProvider>) -> Self {127self.provider = provider;128self129}130131/// Uses the configured context so far to construct the final [`WasiTlsCtx`].132pub fn build(self) -> WasiTlsCtx {133WasiTlsCtx {134provider: self.provider,135}136}137}138impl Default for WasiTlsCtxBuilder {139fn default() -> Self {140Self {141provider: Box::new(RustlsProvider::default()),142}143}144}145146/// Wasi TLS context needed for internal `wasi-tls` state.147pub struct WasiTlsCtx {148pub(crate) provider: Box<dyn TlsProvider>,149}150151/// The data stream that carries the encrypted TLS data.152/// Typically this is a TCP stream.153pub trait TlsTransport: AsyncRead + AsyncWrite + Send + Unpin + 'static {}154impl<T: AsyncRead + AsyncWrite + Send + Unpin + ?Sized + 'static> TlsTransport for T {}155156/// A TLS connection.157pub trait TlsStream: AsyncRead + AsyncWrite + Send + Unpin + 'static {}158159/// A TLS implementation.160pub trait TlsProvider: Send + Sync + 'static {161/// Set up a client TLS connection using the provided `server_name` and `transport`.162fn connect(163&self,164server_name: String,165transport: Box<dyn TlsTransport>,166) -> BoxFuture<std::io::Result<Box<dyn TlsStream>>>;167}168169pub(crate) type BoxFuture<T> = std::pin::Pin<Box<dyn Future<Output = T> + Send>>;170171172