From e597250fb875df7ec1f36b72de66a6af5f29a66f Mon Sep 17 00:00:00 2001 From: quininer kel Date: Thu, 30 Mar 2017 14:49:24 +0800 Subject: [PATCH] [Added] example std-client --- Cargo.toml | 2 ++ examples/client.rs | 2 ++ examples/std-client.rs | 72 ++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 6 ++-- 4 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 examples/std-client.rs diff --git a/Cargo.toml b/Cargo.toml index b432583..4663061 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,4 +21,6 @@ tokio-proto = { version = "0.1", optional = true } tokio-core = "0.1" clap = "2.20" webpki-roots = "0.7" + +[target.'cfg(unix)'.dev-dependencies] tokio-file-unix = "0.2" diff --git a/examples/client.rs b/examples/client.rs index 2643aba..052c8fe 100644 --- a/examples/client.rs +++ b/examples/client.rs @@ -1,3 +1,5 @@ +#![cfg(unix)] + extern crate clap; extern crate rustls; extern crate futures; diff --git a/examples/std-client.rs b/examples/std-client.rs new file mode 100644 index 0000000..95ed719 --- /dev/null +++ b/examples/std-client.rs @@ -0,0 +1,72 @@ +extern crate clap; +extern crate rustls; +extern crate futures; +extern crate tokio_io; +extern crate tokio_core; +extern crate webpki_roots; +extern crate tokio_rustls; + +use std::sync::Arc; +use std::net::ToSocketAddrs; +use std::io::{ Read, Write, BufReader, stdout, stdin }; +use std::fs; +use futures::Future; +use tokio_io::io; +use tokio_core::net::TcpStream; +use tokio_core::reactor::Core; +use clap::{ App, Arg }; +use rustls::ClientConfig; +use tokio_rustls::ClientConfigExt; + + +fn app() -> App<'static, 'static> { + App::new("client") + .about("tokio-rustls client example") + .arg(Arg::with_name("host").value_name("HOST").required(true)) + .arg(Arg::with_name("port").short("p").long("port").value_name("PORT").help("port, default `443`")) + .arg(Arg::with_name("domain").short("d").long("domain").value_name("DOMAIN").help("domain")) + .arg(Arg::with_name("cafile").short("c").long("cafile").value_name("FILE").help("CA certificate chain")) +} + + +fn main() { + let matches = app().get_matches(); + + let host = matches.value_of("host").unwrap(); + let port = if let Some(port) = matches.value_of("port") { + port.parse().unwrap() + } else { + 443 + }; + let domain = matches.value_of("domain").unwrap_or(host); + let cafile = matches.value_of("cafile"); + let text = format!("GET / HTTP/1.0\r\nHost: {}\r\n\r\n", domain); + + let mut core = Core::new().unwrap(); + let handle = core.handle(); + let addr = (host, port) + .to_socket_addrs().unwrap() + .next().unwrap(); + + let mut input = Vec::new(); + stdin().read_to_end(&mut input).unwrap(); + + let mut config = ClientConfig::new(); + if let Some(cafile) = cafile { + let mut pem = BufReader::new(fs::File::open(cafile).unwrap()); + config.root_store.add_pem_file(&mut pem).unwrap(); + } else { + config.root_store.add_trust_anchors(&webpki_roots::ROOTS); + } + let arc_config = Arc::new(config); + + let socket = TcpStream::connect(&addr, &handle); + let resp = socket + .and_then(|stream| arc_config.connect_async(domain, stream)) + .and_then(|stream| io::write_all(stream, text.as_bytes())) + .and_then(|(stream, _)| io::write_all(stream, &input)) + .and_then(|(stream, _)| io::read_to_end(stream, Vec::new())) + .and_then(|(_, output)| stdout().write_all(&output)); + + core.run(resp).unwrap(); +} diff --git a/src/lib.rs b/src/lib.rs index e94534c..fa945c4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,8 +11,10 @@ use std::io; use std::sync::Arc; use futures::{ Future, Poll, Async }; use tokio_io::{ AsyncRead, AsyncWrite }; -use rustls::{ Session, ClientSession, ServerSession }; -use rustls::{ ClientConfig, ServerConfig }; +use rustls::{ + Session, ClientSession, ServerSession, + ClientConfig, ServerConfig +}; /// Extension trait for the `Arc` type in the `rustls` crate.