From e8a8a599713e044525d133264665091130598b05 Mon Sep 17 00:00:00 2001 From: quininer Date: Mon, 31 Aug 2020 22:22:46 +0800 Subject: [PATCH] tokio-rustls: release 0.14.1 (#27) * Support half-closed states #23 * Update examples --- Cargo.toml | 4 +- tokio-rustls/Cargo.toml | 2 +- tokio-rustls/examples/client/Cargo.toml | 7 +- tokio-rustls/examples/client/src/main.rs | 90 +++++++++--------- tokio-rustls/examples/server/Cargo.toml | 5 +- tokio-rustls/examples/server/src/main.rs | 112 ++++++++++++----------- 6 files changed, 107 insertions(+), 113 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 141e94b..ebea3ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,7 @@ [workspace] members = [ "tokio-native-tls", - "tokio-rustls" + "tokio-rustls", + "tokio-rustls/examples/client", + "tokio-rustls/examples/server" ] diff --git a/tokio-rustls/Cargo.toml b/tokio-rustls/Cargo.toml index dfce549..94e55e0 100644 --- a/tokio-rustls/Cargo.toml +++ b/tokio-rustls/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tokio-rustls" -version = "0.14.0" +version = "0.14.1" authors = ["quininer kel "] license = "MIT/Apache-2.0" repository = "https://github.com/tokio-rs/tls" diff --git a/tokio-rustls/examples/client/Cargo.toml b/tokio-rustls/examples/client/Cargo.toml index 40162f8..b3a48b1 100644 --- a/tokio-rustls/examples/client/Cargo.toml +++ b/tokio-rustls/examples/client/Cargo.toml @@ -5,8 +5,7 @@ authors = ["quininer "] edition = "2018" [dependencies] -futures-util = "0.3" -tokio = { version = "0.2", features = [ "net", "io-std", "io-util", "rt-threaded" ] } -structopt = "0.2" +tokio = { version = "0.2", features = [ "full" ] } +argh = "0.1" tokio-rustls = { path = "../.." } -webpki-roots = "0.18" +webpki-roots = "0.20" diff --git a/tokio-rustls/examples/client/src/main.rs b/tokio-rustls/examples/client/src/main.rs index 6012c7e..3527e20 100644 --- a/tokio-rustls/examples/client/src/main.rs +++ b/tokio-rustls/examples/client/src/main.rs @@ -1,88 +1,80 @@ -use std::io; +use argh::FromArgs; use std::fs::File; +use std::io; +use std::io::BufReader; +use std::net::ToSocketAddrs; use std::path::PathBuf; use std::sync::Arc; -use std::net::ToSocketAddrs; -use std::io::BufReader; -use futures_util::future; -use structopt::StructOpt; -use tokio::runtime; +use tokio::io::{copy, split, stdin as tokio_stdin, stdout as tokio_stdout, AsyncWriteExt}; use tokio::net::TcpStream; -use tokio::io::{ - AsyncWriteExt, - copy, split, - stdin as tokio_stdin, stdout as tokio_stdout -}; -use tokio_rustls::{ TlsConnector, rustls::ClientConfig, webpki::DNSNameRef }; +use tokio_rustls::{rustls::ClientConfig, webpki::DNSNameRef, TlsConnector}; - -#[derive(StructOpt)] +/// Tokio Rustls client example +#[derive(FromArgs)] struct Options { + /// host + #[argh(positional)] host: String, /// port - #[structopt(short="p", long="port", default_value="443")] + #[argh(option, short = 'p', default = "443")] port: u16, /// domain - #[structopt(short="d", long="domain")] + #[argh(option, short = 'd')] domain: Option, /// cafile - #[structopt(short="c", long="cafile", parse(from_os_str))] - cafile: Option + #[argh(option, short = 'c')] + cafile: Option, } - -fn main() -> io::Result<()> { - let options = Options::from_args(); +#[tokio::main] +async fn main() -> io::Result<()> { + let options: Options = argh::from_env(); let addr = (options.host.as_str(), options.port) .to_socket_addrs()? .next() .ok_or_else(|| io::Error::from(io::ErrorKind::NotFound))?; let domain = options.domain.unwrap_or(options.host); - let content = format!( - "GET / HTTP/1.0\r\nHost: {}\r\n\r\n", - domain - ); + let content = format!("GET / HTTP/1.0\r\nHost: {}\r\n\r\n", domain); - let mut runtime = runtime::Builder::new() - .basic_scheduler() - .enable_io() - .build()?; let mut config = ClientConfig::new(); if let Some(cafile) = &options.cafile { let mut pem = BufReader::new(File::open(cafile)?); - config.root_store.add_pem_file(&mut pem) + config + .root_store + .add_pem_file(&mut pem) .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid cert"))?; } else { - config.root_store.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS); + config + .root_store + .add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS); } let connector = TlsConnector::from(Arc::new(config)); - let fut = async { - let stream = TcpStream::connect(&addr).await?; + let stream = TcpStream::connect(&addr).await?; - let (mut stdin, mut stdout) = (tokio_stdin(), tokio_stdout()); + let (mut stdin, mut stdout) = (tokio_stdin(), tokio_stdout()); - let domain = DNSNameRef::try_from_ascii_str(&domain) - .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid dnsname"))?; + let domain = DNSNameRef::try_from_ascii_str(&domain) + .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid dnsname"))?; - let mut stream = connector.connect(domain, stream).await?; - stream.write_all(content.as_bytes()).await?; + let mut stream = connector.connect(domain, stream).await?; + stream.write_all(content.as_bytes()).await?; - let (mut reader, mut writer) = split(stream); - future::select( - copy(&mut reader, &mut stdout), - copy(&mut stdin, &mut writer) - ) - .await - .factor_first() - .0?; + let (mut reader, mut writer) = split(stream); - Ok(()) - }; + tokio::select! { + ret = copy(&mut reader, &mut stdout) => { + ret?; + }, + ret = copy(&mut stdin, &mut writer) => { + ret?; + writer.shutdown().await? + } + } - runtime.block_on(fut) + Ok(()) } diff --git a/tokio-rustls/examples/server/Cargo.toml b/tokio-rustls/examples/server/Cargo.toml index cd42662..f425e31 100644 --- a/tokio-rustls/examples/server/Cargo.toml +++ b/tokio-rustls/examples/server/Cargo.toml @@ -5,7 +5,6 @@ authors = ["quininer "] edition = "2018" [dependencies] -futures-util = "0.3" -tokio = { version = "0.2", features = [ "net", "io-util", "rt-threaded" ] } -structopt = "0.2" +tokio = { version = "0.2", features = [ "full" ] } +argh = "0.1" tokio-rustls = { path = "../.." } diff --git a/tokio-rustls/examples/server/src/main.rs b/tokio-rustls/examples/server/src/main.rs index 1fcb0e4..af340e9 100644 --- a/tokio-rustls/examples/server/src/main.rs +++ b/tokio-rustls/examples/server/src/main.rs @@ -1,33 +1,33 @@ +use argh::FromArgs; use std::fs::File; -use std::sync::Arc; +use std::io::{self, BufReader}; use std::net::ToSocketAddrs; -use std::path::{ PathBuf, Path }; -use std::io::{ self, BufReader }; -use futures_util::future::TryFutureExt; -use structopt::StructOpt; -use tokio::runtime; +use std::path::{Path, PathBuf}; +use std::sync::Arc; +use tokio::io::{copy, sink, split, AsyncWriteExt}; use tokio::net::TcpListener; -use tokio::io::{ AsyncWriteExt, copy, split }; -use tokio_rustls::rustls::{ Certificate, NoClientAuth, PrivateKey, ServerConfig }; -use tokio_rustls::rustls::internal::pemfile::{ certs, rsa_private_keys }; +use tokio_rustls::rustls::internal::pemfile::{certs, rsa_private_keys}; +use tokio_rustls::rustls::{Certificate, NoClientAuth, PrivateKey, ServerConfig}; use tokio_rustls::TlsAcceptor; - -#[derive(StructOpt)] +/// Tokio Rustls server example +#[derive(FromArgs)] struct Options { + /// bind addr + #[argh(positional)] addr: String, /// cert file - #[structopt(short="c", long="cert", parse(from_os_str))] + #[argh(option, short = 'c')] cert: PathBuf, /// key file - #[structopt(short="k", long="key", parse(from_os_str))] + #[argh(option, short = 'k')] key: PathBuf, /// echo mode - #[structopt(short="e", long="echo-mode")] - echo: bool + #[argh(switch, short = 'e')] + echo_mode: bool, } fn load_certs(path: &Path) -> io::Result> { @@ -40,60 +40,62 @@ fn load_keys(path: &Path) -> io::Result> { .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid key")) } +#[tokio::main] +async fn main() -> io::Result<()> { + let options: Options = argh::from_env(); -fn main() -> io::Result<()> { - let options = Options::from_args(); - - let addr = options.addr.to_socket_addrs()? + let addr = options + .addr + .to_socket_addrs()? .next() .ok_or_else(|| io::Error::from(io::ErrorKind::AddrNotAvailable))?; let certs = load_certs(&options.cert)?; let mut keys = load_keys(&options.key)?; - let flag_echo = options.echo; + let flag_echo = options.echo_mode; - let mut runtime = runtime::Builder::new() - .threaded_scheduler() - .enable_io() - .build()?; - let handle = runtime.handle().clone(); let mut config = ServerConfig::new(NoClientAuth::new()); - config.set_single_cert(certs, keys.remove(0)) + config + .set_single_cert(certs, keys.remove(0)) .map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err))?; let acceptor = TlsAcceptor::from(Arc::new(config)); - let fut = async { - let mut listener = TcpListener::bind(&addr).await?; + let mut listener = TcpListener::bind(&addr).await?; - loop { - let (stream, peer_addr) = listener.accept().await?; - let acceptor = acceptor.clone(); + loop { + let (stream, peer_addr) = listener.accept().await?; + let acceptor = acceptor.clone(); - let fut = async move { - let mut stream = acceptor.accept(stream).await?; + let fut = async move { + let mut stream = acceptor.accept(stream).await?; - if flag_echo { - let (mut reader, mut writer) = split(stream); - let n = copy(&mut reader, &mut writer).await?; - writer.flush().await?; - println!("Echo: {} - {}", peer_addr, n); - } else { - stream.write_all( + if flag_echo { + let (mut reader, mut writer) = split(stream); + let n = copy(&mut reader, &mut writer).await?; + writer.flush().await?; + println!("Echo: {} - {}", peer_addr, n); + } else { + let mut output = sink(); + stream + .write_all( &b"HTTP/1.0 200 ok\r\n\ - Connection: close\r\n\ - Content-length: 12\r\n\ - \r\n\ - Hello world!"[..] - ).await?; - stream.flush().await?; - println!("Hello: {}", peer_addr); - } + Connection: close\r\n\ + Content-length: 12\r\n\ + \r\n\ + Hello world!"[..], + ) + .await?; + stream.shutdown().await?; + copy(&mut stream, &mut output).await?; + println!("Hello: {}", peer_addr); + } - Ok(()) as io::Result<()> - }; + Ok(()) as io::Result<()> + }; - handle.spawn(fut.unwrap_or_else(|err| eprintln!("{:?}", err))); - } - }; - - runtime.block_on(fut) + tokio::spawn(async move { + if let Err(err) = fut.await { + eprintln!("{:?}", err); + } + }); + } }