-
Notifications
You must be signed in to change notification settings - Fork 70
/
server.rs
92 lines (77 loc) · 2.54 KB
/
server.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
use std::io;
use std::net::ToSocketAddrs;
use std::path::PathBuf;
use std::error::Error as StdError;
use std::sync::Arc;
use argh::FromArgs;
use rustls::pki_types::pem::PemObject;
use rustls::pki_types::{CertificateDer, PrivateKeyDer};
use tokio::io::{copy, sink, split, AsyncWriteExt};
use tokio::net::TcpListener;
use tokio_rustls::{rustls, TlsAcceptor};
/// Tokio Rustls server example
#[derive(FromArgs)]
struct Options {
/// bind addr
#[argh(positional)]
addr: String,
/// cert file
#[argh(option, short = 'c')]
cert: PathBuf,
/// key file
#[argh(option, short = 'k')]
key: PathBuf,
/// echo mode
#[argh(switch, short = 'e')]
echo_mode: bool,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn StdError + Send + Sync + 'static>> {
let options: Options = argh::from_env();
let addr = options
.addr
.to_socket_addrs()?
.next()
.ok_or_else(|| io::Error::from(io::ErrorKind::AddrNotAvailable))?;
let certs = CertificateDer::pem_file_iter(&options.cert)?.collect::<Result<Vec<_>, _>>()?;
let key = PrivateKeyDer::from_pem_file(&options.key)?;
let flag_echo = options.echo_mode;
let config = rustls::ServerConfig::builder()
.with_no_client_auth()
.with_single_cert(certs, key)?;
let acceptor = TlsAcceptor::from(Arc::new(config));
let listener = TcpListener::bind(&addr).await?;
loop {
let (stream, peer_addr) = listener.accept().await?;
let acceptor = acceptor.clone();
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 {
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.shutdown().await?;
copy(&mut stream, &mut output).await?;
println!("Hello: {}", peer_addr);
}
Ok(()) as io::Result<()>
};
tokio::spawn(async move {
if let Err(err) = fut.await {
eprintln!("{:?}", err);
}
});
}
}