Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ compio-log = { path = "./compio-log", version = "0.1.0" }
compio-tls = { path = "./compio-tls", version = "0.7.2", default-features = false }
compio-process = { path = "./compio-process", version = "0.6.0" }
compio-quic = { path = "./compio-quic", version = "0.5.1", default-features = false }
compio-ws = { path = "./compio-ws", version = "0.1.0", default-features = false }
compio-ws = { path = "./compio-ws", version = "0.2.0", default-features = false }

bytes = "1.7.1"
cfg_aliases = "0.2.1"
Expand All @@ -51,19 +51,22 @@ futures-channel = "0.3.29"
futures-rustls = { version = "0.26.0", default-features = false }
futures-util = "0.3.29"
libc = "0.2.164"
native-tls = "0.2.11"
nix = "0.30.1"
once_cell = "1.18.0"
os_pipe = "1.1.4"
paste = "1.0.14"
pin-project-lite = "0.2.16"
rand = "0.9.0"
rustls = { version = "0.23.1", default-features = false }
rustls-platform-verifier = "0.6.0"
rustls-native-certs = "0.8.0"
slab = "0.4.9"
socket2 = "0.6.0"
tempfile = "3.8.1"
tokio = "1.33.0"
tracing-subscriber = "0.3.18"
webpki-roots = "1.0.0"
widestring = "1.0.2"
windows-sys = "0.61.0"
thiserror = "2.0.3"
Expand Down
4 changes: 2 additions & 2 deletions compio-quic/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ compio-runtime = { workspace = true, features = ["time"] }

quinn-proto = { version = "0.11.10", default-features = false }
rustls = { workspace = true }
rustls-platform-verifier = { version = "0.6.0", optional = true }
rustls-platform-verifier = { workspace = true, optional = true }
rustls-native-certs = { workspace = true, optional = true }
webpki-roots = { version = "1.0.0", optional = true }
webpki-roots = { workspace = true, optional = true }
h3 = { version = "0.0.8", optional = true }
h3-datagram = { version = "0.0.2", optional = true }

Expand Down
2 changes: 1 addition & 1 deletion compio-tls/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ rustdoc-args = ["--cfg", "docsrs"]
compio-buf = { workspace = true }
compio-io = { workspace = true, features = ["compat"] }

native-tls = { version = "0.2.11", optional = true, features = ["alpn"] }
native-tls = { workspace = true, optional = true, features = ["alpn"] }
rustls = { workspace = true, default-features = false, optional = true, features = [
"logging",
"std",
Expand Down
41 changes: 22 additions & 19 deletions compio-tls/src/maybe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,33 @@ use compio_io::{AsyncRead, AsyncWrite};

use crate::TlsStream;

/// Stream that can be either plain TCP or TLS-encrypted
#[derive(Debug)]
#[allow(clippy::large_enum_variant)]
pub enum MaybeTlsStream<S> {
enum MaybeTlsStreamInner<S> {
/// Plain, unencrypted stream
Plain(S),
/// TLS-encrypted stream
Tls(TlsStream<S>),
}

/// Stream that can be either plain TCP or TLS-encrypted
#[derive(Debug)]
pub struct MaybeTlsStream<S>(MaybeTlsStreamInner<S>);

impl<S> MaybeTlsStream<S> {
/// Create an unencrypted stream.
pub fn plain(stream: S) -> Self {
MaybeTlsStream::Plain(stream)
pub fn new_plain(stream: S) -> Self {
Self(MaybeTlsStreamInner::Plain(stream))
}

/// Create a TLS-encrypted stream.
pub fn tls(stream: TlsStream<S>) -> Self {
MaybeTlsStream::Tls(stream)
pub fn new_tls(stream: TlsStream<S>) -> Self {
Self(MaybeTlsStreamInner::Tls(stream))
}

/// Whether the stream is TLS-encrypted.
pub fn is_tls(&self) -> bool {
matches!(self, MaybeTlsStream::Tls(_))
matches!(self.0, MaybeTlsStreamInner::Tls(_))
}
}

Expand All @@ -37,9 +40,9 @@ where
S: AsyncRead + AsyncWrite + Unpin + 'static,
{
async fn read<B: IoBufMut>(&mut self, buf: B) -> BufResult<usize, B> {
match self {
MaybeTlsStream::Plain(stream) => stream.read(buf).await,
MaybeTlsStream::Tls(stream) => stream.read(buf).await,
match &mut self.0 {
MaybeTlsStreamInner::Plain(stream) => stream.read(buf).await,
MaybeTlsStreamInner::Tls(stream) => stream.read(buf).await,
}
}
}
Expand All @@ -49,23 +52,23 @@ where
S: AsyncRead + AsyncWrite + Unpin + 'static,
{
async fn write<B: IoBuf>(&mut self, buf: B) -> BufResult<usize, B> {
match self {
MaybeTlsStream::Plain(stream) => stream.write(buf).await,
MaybeTlsStream::Tls(stream) => stream.write(buf).await,
match &mut self.0 {
MaybeTlsStreamInner::Plain(stream) => stream.write(buf).await,
MaybeTlsStreamInner::Tls(stream) => stream.write(buf).await,
}
}

async fn flush(&mut self) -> io::Result<()> {
match self {
MaybeTlsStream::Plain(stream) => stream.flush().await,
MaybeTlsStream::Tls(stream) => stream.flush().await,
match &mut self.0 {
MaybeTlsStreamInner::Plain(stream) => stream.flush().await,
MaybeTlsStreamInner::Tls(stream) => stream.flush().await,
}
}

async fn shutdown(&mut self) -> io::Result<()> {
match self {
MaybeTlsStream::Plain(stream) => stream.shutdown().await,
MaybeTlsStream::Tls(stream) => stream.shutdown().await,
match &mut self.0 {
MaybeTlsStreamInner::Plain(stream) => stream.shutdown().await,
MaybeTlsStreamInner::Tls(stream) => stream.shutdown().await,
}
}
}
77 changes: 39 additions & 38 deletions compio-ws/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "compio-ws"
version = "0.1.1"
version = "0.2.0"
description = "WebSocket library for the compio runtime"
edition = { workspace = true }
authors = { workspace = true }
Expand All @@ -13,60 +13,61 @@ all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[dependencies]
rustls = { workspace = true, optional = true, default-features = false }
rustls-platform-verifier = { version = "0.6.0", optional = true }
tungstenite = "0.28.0"
compio-buf = { workspace = true }
compio-io = { workspace = true, features = ["compat"] }
compio-net = { workspace = true, optional = true }
compio-tls = { workspace = true, optional = true, default-features = false, features = [
"rustls",
] }
compio-buf = { workspace = true }
webpki-roots = { version = "1.0.4", optional = true }
rustls-pemfile = "2.0"
log = "0.4"
compio-log = { workspace = true }

[features]
default = []
connect = ["dep:compio-net"]
rustls = ["connect", "dep:compio-tls", "dep:rustls", "compio-tls/rustls"]
rustls-platform-verifier = ["rustls", "dep:rustls-platform-verifier"]
webpki-roots = ["rustls", "dep:webpki-roots"]
ring = ["rustls?/ring", "compio-tls?/ring"]
tungstenite = "0.28.0"

native-tls = { workspace = true, optional = true }
Comment thread
Berrysoft marked this conversation as resolved.
Outdated

rustls = { workspace = true, optional = true, default-features = false }
rustls-platform-verifier = { workspace = true, optional = true }
rustls-native-certs = { workspace = true, optional = true }
webpki-roots = { workspace = true, optional = true }

[dev-dependencies]
log = "0.4"
env_logger = "0.11"
compio-net = { workspace = true }
compio-macros = { workspace = true }
futures-channel = { workspace = true }
compio-runtime = { workspace = true }
compio-driver = { workspace = true }

[[example]]
name = "echo_server"
required-features = ["connect"]

[[example]]
name = "client"
required-features = ["connect"]

[[example]]
name = "autobahn-client"
required-features = ["connect"]
futures-channel = { workspace = true }
rustls-pemfile = "2.0"
tracing-subscriber = { workspace = true, features = ["env-filter"] }

[[example]]
name = "autobahn-server"
required-features = ["connect"]
[features]
default = []
# Deprecated
connect = []
native-tls = [
"dep:compio-net",
"dep:native-tls",
"compio-tls/native-tls",
"tungstenite/native-tls",
]
rustls = [
"dep:compio-net",
"dep:compio-tls",
"dep:rustls",
"compio-tls/rustls",
"tungstenite/__rustls-tls",
]
rustls-platform-verifier = ["rustls", "dep:rustls-platform-verifier"]
rustls-native-certs = ["rustls", "dep:rustls-native-certs"]
webpki-roots = ["rustls", "dep:webpki-roots"]
ring = ["compio-tls?/ring"]
aws-lc-rs = ["compio-tls?/aws-lc-rs"]
aws-lc-rs-fips = ["compio-tls?/aws-lc-rs-fips"]

[[example]]
name = "echo_server_tls"
required-features = ["connect", "rustls", "ring"]
required-features = ["rustls"]

[[example]]
name = "client_tls"
required-features = ["connect", "rustls", "ring"]

[[test]]
name = "websocket"
required-features = ["connect", "compio-driver/io-uring"]
required-features = ["rustls"]
12 changes: 9 additions & 3 deletions compio-ws/examples/autobahn-client.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#![allow(clippy::collapsible_match)]

use compio_log::*;
use compio_net::TcpStream;
use compio_ws::client_async;
use log::*;
use tungstenite::{Error, Result};

const AGENT: &str = "Tungstenite";
Expand Down Expand Up @@ -54,15 +56,19 @@ async fn run_test(case: u32) -> Result<()> {

#[compio_macros::main]
async fn main() {
env_logger::init();
tracing_subscriber::fmt()
.with_max_level(Level::TRACE)
.init();

let total = get_case_count().await.expect("Error getting case count");

for case in 1..=total {
if let Err(e) = run_test(case).await {
match e {
Error::ConnectionClosed | Error::Protocol(_) | Error::Utf8(_) => (),
err => error!("Testcase failed: {err}"),
_err => {
error!("Testcase failed: {_err}");
}
}
}
}
Expand Down
22 changes: 14 additions & 8 deletions compio-ws/examples/autobahn-server.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
#![allow(clippy::collapsible_match)]

use std::net::SocketAddr;

use compio_log::*;
use compio_net::{TcpListener, TcpStream};
use compio_ws::{WebSocketConfig, accept_async_with_config};
use log::*;
use tungstenite::{Error, Result};

async fn accept_connection(peer: SocketAddr, stream: TcpStream) {
if let Err(e) = handle_connection(peer, stream).await {
match e {
Error::ConnectionClosed | Error::Protocol(_) | Error::Utf8(_) => (),
err => error!("Error processing connection: {err}"),
_err => {
Comment thread
George-Miao marked this conversation as resolved.
error!("Error processing connection: {_err}");
}
}
}
}

async fn handle_connection(peer: SocketAddr, stream: TcpStream) -> Result<()> {
async fn handle_connection(_peer: SocketAddr, stream: TcpStream) -> Result<()> {
let mut config = WebSocketConfig::default();
config.max_message_size = Some(64 * 1024 * 1024);
config.max_frame_size = Some(16 * 1024 * 1024);
Expand All @@ -23,7 +27,7 @@ async fn handle_connection(peer: SocketAddr, stream: TcpStream) -> Result<()> {
.await
.expect("Failed to accept");

info!("New WebSocket connection: {peer}");
info!("New WebSocket connection: {_peer}");

loop {
match ws_stream.read().await {
Expand All @@ -34,7 +38,7 @@ async fn handle_connection(peer: SocketAddr, stream: TcpStream) -> Result<()> {
}
Err(e) => match e {
Error::ConnectionClosed => {
info!("Connection closed normally: {peer}");
info!("Connection closed normally: {_peer}");
break;
}
_ => {
Expand All @@ -50,7 +54,9 @@ async fn handle_connection(peer: SocketAddr, stream: TcpStream) -> Result<()> {

#[compio_macros::main]
async fn main() {
env_logger::init();
tracing_subscriber::fmt()
.with_max_level(Level::TRACE)
.init();

let addr = "127.0.0.1:9002";
let listener = TcpListener::bind(addr).await.expect("Can't listen");
Expand All @@ -62,8 +68,8 @@ async fn main() {
info!("Peer address: {addr}");
compio_runtime::spawn(accept_connection(addr, stream)).detach();
}
Err(e) => {
error!("Error accepting connection: {e}");
Err(_e) => {
error!("Error accepting connection: {_e}");
}
}
}
Expand Down
9 changes: 5 additions & 4 deletions compio-ws/examples/client_tls.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::sync::Arc;

use compio_ws::{Connector, connect_async_with_tls_connector};
use compio_tls::TlsConnector;
use compio_ws::connect_async_tls_with_config;
use rustls::ClientConfig;
use tungstenite::Message;

async fn create_insecure_tls_connector() -> Result<Connector, Box<dyn std::error::Error>> {
async fn create_insecure_tls_connector() -> Result<TlsConnector, Box<dyn std::error::Error>> {
// Create a TLS connector that accepts self-signed certificates
// This is needed for testing with localhost self-signed certificates
// WARNING: This is insecure and should only be used for testing!
Expand Down Expand Up @@ -66,7 +67,7 @@ async fn create_insecure_tls_connector() -> Result<Connector, Box<dyn std::error
.with_custom_certificate_verifier(Arc::new(AcceptAllVerifier))
.with_no_client_auth();

Ok(Connector::from(Arc::new(config)))
Ok(TlsConnector::from(Arc::new(config)))
}

#[compio_macros::main]
Expand All @@ -76,7 +77,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let connector = create_insecure_tls_connector().await?;

let (mut websocket, _response) =
connect_async_with_tls_connector("wss://127.0.0.1:9002", Some(connector)).await?;
connect_async_tls_with_config("wss://127.0.0.1:9002", None, false, Some(connector)).await?;

println!("Successfully connected to WebSocket TLS server!");
println!();
Expand Down
Loading
Loading