tokio-rustls: release 0.14.1 (#27)

* Support half-closed states #23
* Update examples
This commit is contained in:
quininer 2020-08-31 22:22:46 +08:00 committed by GitHub
parent 93d7c7590c
commit e8a8a59971
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 107 additions and 113 deletions

View File

@ -1,5 +1,7 @@
[workspace] [workspace]
members = [ members = [
"tokio-native-tls", "tokio-native-tls",
"tokio-rustls" "tokio-rustls",
"tokio-rustls/examples/client",
"tokio-rustls/examples/server"
] ]

View File

@ -1,6 +1,6 @@
[package] [package]
name = "tokio-rustls" name = "tokio-rustls"
version = "0.14.0" version = "0.14.1"
authors = ["quininer kel <quininer@live.com>"] authors = ["quininer kel <quininer@live.com>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
repository = "https://github.com/tokio-rs/tls" repository = "https://github.com/tokio-rs/tls"

View File

@ -5,8 +5,7 @@ authors = ["quininer <quininer@live.com>"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
futures-util = "0.3" tokio = { version = "0.2", features = [ "full" ] }
tokio = { version = "0.2", features = [ "net", "io-std", "io-util", "rt-threaded" ] } argh = "0.1"
structopt = "0.2"
tokio-rustls = { path = "../.." } tokio-rustls = { path = "../.." }
webpki-roots = "0.18" webpki-roots = "0.20"

View File

@ -1,88 +1,80 @@
use std::io; use argh::FromArgs;
use std::fs::File; use std::fs::File;
use std::io;
use std::io::BufReader;
use std::net::ToSocketAddrs;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
use std::net::ToSocketAddrs; use tokio::io::{copy, split, stdin as tokio_stdin, stdout as tokio_stdout, AsyncWriteExt};
use std::io::BufReader;
use futures_util::future;
use structopt::StructOpt;
use tokio::runtime;
use tokio::net::TcpStream; use tokio::net::TcpStream;
use tokio::io::{ use tokio_rustls::{rustls::ClientConfig, webpki::DNSNameRef, TlsConnector};
AsyncWriteExt,
copy, split,
stdin as tokio_stdin, stdout as tokio_stdout
};
use tokio_rustls::{ TlsConnector, rustls::ClientConfig, webpki::DNSNameRef };
/// Tokio Rustls client example
#[derive(StructOpt)] #[derive(FromArgs)]
struct Options { struct Options {
/// host
#[argh(positional)]
host: String, host: String,
/// port /// port
#[structopt(short="p", long="port", default_value="443")] #[argh(option, short = 'p', default = "443")]
port: u16, port: u16,
/// domain /// domain
#[structopt(short="d", long="domain")] #[argh(option, short = 'd')]
domain: Option<String>, domain: Option<String>,
/// cafile /// cafile
#[structopt(short="c", long="cafile", parse(from_os_str))] #[argh(option, short = 'c')]
cafile: Option<PathBuf> cafile: Option<PathBuf>,
} }
#[tokio::main]
fn main() -> io::Result<()> { async fn main() -> io::Result<()> {
let options = Options::from_args(); let options: Options = argh::from_env();
let addr = (options.host.as_str(), options.port) let addr = (options.host.as_str(), options.port)
.to_socket_addrs()? .to_socket_addrs()?
.next() .next()
.ok_or_else(|| io::Error::from(io::ErrorKind::NotFound))?; .ok_or_else(|| io::Error::from(io::ErrorKind::NotFound))?;
let domain = options.domain.unwrap_or(options.host); let domain = options.domain.unwrap_or(options.host);
let content = format!( let content = format!("GET / HTTP/1.0\r\nHost: {}\r\n\r\n", domain);
"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(); let mut config = ClientConfig::new();
if let Some(cafile) = &options.cafile { if let Some(cafile) = &options.cafile {
let mut pem = BufReader::new(File::open(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"))?; .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid cert"))?;
} else { } 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 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) let domain = DNSNameRef::try_from_ascii_str(&domain)
.map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid dnsname"))?; .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid dnsname"))?;
let mut stream = connector.connect(domain, stream).await?; let mut stream = connector.connect(domain, stream).await?;
stream.write_all(content.as_bytes()).await?; stream.write_all(content.as_bytes()).await?;
let (mut reader, mut writer) = split(stream); let (mut reader, mut writer) = split(stream);
future::select(
copy(&mut reader, &mut stdout),
copy(&mut stdin, &mut writer)
)
.await
.factor_first()
.0?;
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(())
} }

View File

@ -5,7 +5,6 @@ authors = ["quininer <quininer@live.com>"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
futures-util = "0.3" tokio = { version = "0.2", features = [ "full" ] }
tokio = { version = "0.2", features = [ "net", "io-util", "rt-threaded" ] } argh = "0.1"
structopt = "0.2"
tokio-rustls = { path = "../.." } tokio-rustls = { path = "../.." }

View File

@ -1,33 +1,33 @@
use argh::FromArgs;
use std::fs::File; use std::fs::File;
use std::sync::Arc; use std::io::{self, BufReader};
use std::net::ToSocketAddrs; use std::net::ToSocketAddrs;
use std::path::{ PathBuf, Path }; use std::path::{Path, PathBuf};
use std::io::{ self, BufReader }; use std::sync::Arc;
use futures_util::future::TryFutureExt; use tokio::io::{copy, sink, split, AsyncWriteExt};
use structopt::StructOpt;
use tokio::runtime;
use tokio::net::TcpListener; use tokio::net::TcpListener;
use tokio::io::{ AsyncWriteExt, copy, split }; use tokio_rustls::rustls::internal::pemfile::{certs, rsa_private_keys};
use tokio_rustls::rustls::{ Certificate, NoClientAuth, PrivateKey, ServerConfig }; use tokio_rustls::rustls::{Certificate, NoClientAuth, PrivateKey, ServerConfig};
use tokio_rustls::rustls::internal::pemfile::{ certs, rsa_private_keys };
use tokio_rustls::TlsAcceptor; use tokio_rustls::TlsAcceptor;
/// Tokio Rustls server example
#[derive(StructOpt)] #[derive(FromArgs)]
struct Options { struct Options {
/// bind addr
#[argh(positional)]
addr: String, addr: String,
/// cert file /// cert file
#[structopt(short="c", long="cert", parse(from_os_str))] #[argh(option, short = 'c')]
cert: PathBuf, cert: PathBuf,
/// key file /// key file
#[structopt(short="k", long="key", parse(from_os_str))] #[argh(option, short = 'k')]
key: PathBuf, key: PathBuf,
/// echo mode /// echo mode
#[structopt(short="e", long="echo-mode")] #[argh(switch, short = 'e')]
echo: bool echo_mode: bool,
} }
fn load_certs(path: &Path) -> io::Result<Vec<Certificate>> { fn load_certs(path: &Path) -> io::Result<Vec<Certificate>> {
@ -40,60 +40,62 @@ fn load_keys(path: &Path) -> io::Result<Vec<PrivateKey>> {
.map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid key")) .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 addr = options
let options = Options::from_args(); .addr
.to_socket_addrs()?
let addr = options.addr.to_socket_addrs()?
.next() .next()
.ok_or_else(|| io::Error::from(io::ErrorKind::AddrNotAvailable))?; .ok_or_else(|| io::Error::from(io::ErrorKind::AddrNotAvailable))?;
let certs = load_certs(&options.cert)?; let certs = load_certs(&options.cert)?;
let mut keys = load_keys(&options.key)?; 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()); 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))?; .map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err))?;
let acceptor = TlsAcceptor::from(Arc::new(config)); 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 { loop {
let (stream, peer_addr) = listener.accept().await?; let (stream, peer_addr) = listener.accept().await?;
let acceptor = acceptor.clone(); let acceptor = acceptor.clone();
let fut = async move { let fut = async move {
let mut stream = acceptor.accept(stream).await?; let mut stream = acceptor.accept(stream).await?;
if flag_echo { if flag_echo {
let (mut reader, mut writer) = split(stream); let (mut reader, mut writer) = split(stream);
let n = copy(&mut reader, &mut writer).await?; let n = copy(&mut reader, &mut writer).await?;
writer.flush().await?; writer.flush().await?;
println!("Echo: {} - {}", peer_addr, n); println!("Echo: {} - {}", peer_addr, n);
} else { } else {
stream.write_all( let mut output = sink();
stream
.write_all(
&b"HTTP/1.0 200 ok\r\n\ &b"HTTP/1.0 200 ok\r\n\
Connection: close\r\n\ Connection: close\r\n\
Content-length: 12\r\n\ Content-length: 12\r\n\
\r\n\ \r\n\
Hello world!"[..] Hello world!"[..],
).await?; )
stream.flush().await?; .await?;
println!("Hello: {}", peer_addr); 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))); tokio::spawn(async move {
} if let Err(err) = fut.await {
}; eprintln!("{:?}", err);
}
runtime.block_on(fut) });
}
} }