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]
members = [
"tokio-native-tls",
"tokio-rustls"
"tokio-rustls",
"tokio-rustls/examples/client",
"tokio-rustls/examples/server"
]

View File

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

View File

@ -5,8 +5,7 @@ authors = ["quininer <quininer@live.com>"]
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"

View File

@ -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<String>,
/// cafile
#[structopt(short="c", long="cafile", parse(from_os_str))]
cafile: Option<PathBuf>
#[argh(option, short = 'c')]
cafile: Option<PathBuf>,
}
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(())
}

View File

@ -5,7 +5,6 @@ authors = ["quininer <quininer@live.com>"]
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 = "../.." }

View File

@ -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<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"))
}
#[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);
}
});
}
}