Merge std-client.rs into client.rs to unbreak Windows build.
The Windows build is failing because client.rs doesn't define main on non-Unixy platforms because of its `#![cfg(unix)]`. Merge std-client.rs into client.rs to solve this and to reduce redundancy. Continue using blocking stdin/stdout I/O on non-Unixy platforms until we get nonblocking stdin/stdout working on those platforms.
This commit is contained in:
parent
0913af1af9
commit
22fbb7497f
@ -27,7 +27,14 @@ TcpStream::connect(&addr, &handle)
|
|||||||
See [examples/client.rs](examples/client.rs). You can run it with:
|
See [examples/client.rs](examples/client.rs). You can run it with:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cargo run --example client google.com
|
cargo run --example client hsts.badssl.com
|
||||||
|
```
|
||||||
|
|
||||||
|
Currently on Windows the example client reads from stdin and writes to stdout using
|
||||||
|
blocking I/O. Until this is fixed, do something this on Windows:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
echo | cargo run --example client hsts.badssl.com
|
||||||
```
|
```
|
||||||
|
|
||||||
### Server Example Program
|
### Server Example Program
|
||||||
|
@ -1,27 +1,34 @@
|
|||||||
#![cfg(unix)]
|
|
||||||
|
|
||||||
extern crate clap;
|
extern crate clap;
|
||||||
extern crate rustls;
|
extern crate rustls;
|
||||||
extern crate futures;
|
extern crate futures;
|
||||||
extern crate tokio_io;
|
extern crate tokio_io;
|
||||||
extern crate tokio_core;
|
extern crate tokio_core;
|
||||||
extern crate webpki_roots;
|
extern crate webpki_roots;
|
||||||
extern crate tokio_file_unix;
|
|
||||||
extern crate tokio_rustls;
|
extern crate tokio_rustls;
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
extern crate tokio_file_unix;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::net::ToSocketAddrs;
|
use std::net::ToSocketAddrs;
|
||||||
use std::io::{ BufReader, stdout, stdin };
|
use std::io::{ BufReader, stdout, stdin };
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
use tokio_io::{ io, AsyncRead };
|
|
||||||
use tokio_core::net::TcpStream;
|
use tokio_core::net::TcpStream;
|
||||||
use tokio_core::reactor::Core;
|
use tokio_core::reactor::Core;
|
||||||
|
use tokio_io::io;
|
||||||
use clap::{ App, Arg };
|
use clap::{ App, Arg };
|
||||||
use rustls::ClientConfig;
|
use rustls::ClientConfig;
|
||||||
use tokio_file_unix::{ StdFile, File };
|
|
||||||
use tokio_rustls::ClientConfigExt;
|
use tokio_rustls::ClientConfigExt;
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
use tokio_io::AsyncRead;
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
use tokio_file_unix::{ StdFile, File };
|
||||||
|
|
||||||
|
#[cfg(not(unix))]
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
|
||||||
fn app() -> App<'static, 'static> {
|
fn app() -> App<'static, 'static> {
|
||||||
App::new("client")
|
App::new("client")
|
||||||
@ -52,13 +59,6 @@ fn main() {
|
|||||||
.to_socket_addrs().unwrap()
|
.to_socket_addrs().unwrap()
|
||||||
.next().unwrap();
|
.next().unwrap();
|
||||||
|
|
||||||
let stdin = stdin();
|
|
||||||
let stdin = File::new_nb(StdFile(stdin.lock())).unwrap()
|
|
||||||
.into_io(&handle).unwrap();
|
|
||||||
let stdout = stdout();
|
|
||||||
let stdout = File::new_nb(StdFile(stdout.lock())).unwrap()
|
|
||||||
.into_io(&handle).unwrap();
|
|
||||||
|
|
||||||
let mut config = ClientConfig::new();
|
let mut config = ClientConfig::new();
|
||||||
if let Some(cafile) = cafile {
|
if let Some(cafile) = cafile {
|
||||||
let mut pem = BufReader::new(fs::File::open(cafile).unwrap());
|
let mut pem = BufReader::new(fs::File::open(cafile).unwrap());
|
||||||
@ -69,6 +69,24 @@ fn main() {
|
|||||||
let arc_config = Arc::new(config);
|
let arc_config = Arc::new(config);
|
||||||
|
|
||||||
let socket = TcpStream::connect(&addr, &handle);
|
let socket = TcpStream::connect(&addr, &handle);
|
||||||
|
|
||||||
|
// Use async non-blocking I/O for stdin/stdout on Unixy platforms.
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
let stdin = stdin();
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
let stdin = File::new_nb(StdFile(stdin.lock())).unwrap()
|
||||||
|
.into_io(&handle).unwrap();
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
let stdout = stdout();
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
let stdout = File::new_nb(StdFile(stdout.lock())).unwrap()
|
||||||
|
.into_io(&handle).unwrap();
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
let resp = socket
|
let resp = socket
|
||||||
.and_then(|stream| arc_config.connect_async(domain, stream))
|
.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, text.as_bytes()))
|
||||||
@ -80,5 +98,22 @@ fn main() {
|
|||||||
.map_err(|(e, _)| e)
|
.map_err(|(e, _)| e)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// XXX: For now, just use blocking I/O for stdin/stdout on other platforms.
|
||||||
|
// The network I/O will still be asynchronous and non-blocking.
|
||||||
|
|
||||||
|
#[cfg(not(unix))]
|
||||||
|
let mut input = Vec::new();
|
||||||
|
|
||||||
|
#[cfg(not(unix))]
|
||||||
|
stdin().read_to_end(&mut input).unwrap();
|
||||||
|
|
||||||
|
#[cfg(not(unix))]
|
||||||
|
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();
|
core.run(resp).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -1,72 +0,0 @@
|
|||||||
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();
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user