]> git.proxmox.com Git - proxmox-backup.git/blob - src/bin/h2s-server.rs
use hyper/tokio-openssl instead of hyper/tokio-tls
[proxmox-backup.git] / src / bin / h2s-server.rs
1 use failure::*;
2 use futures::*;
3
4 // Simple H2 server to test H2 speed with h2s-client.rs
5
6 use hyper::{Request, Response, Body};
7 use tokio::net::TcpListener;
8
9 use proxmox_backup::configdir;
10
11 use openssl::ssl::{SslMethod, SslAcceptor, SslFiletype};
12 use std::sync::Arc;
13 use tokio_openssl::SslAcceptorExt;
14
15 pub fn main() -> Result<(), Error> {
16
17 start_h2_server()?;
18
19 Ok(())
20 }
21
22 pub fn start_h2_server() -> Result<(), Error> {
23
24 let key_path = configdir!("/proxy.key");
25 let cert_path = configdir!("/proxy.pem");
26
27 let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
28 acceptor.set_private_key_file(key_path, SslFiletype::PEM)
29 .map_err(|err| format_err!("unable to read proxy key {} - {}", key_path, err))?;
30 acceptor.set_certificate_chain_file(cert_path)
31 .map_err(|err| format_err!("unable to read proxy cert {} - {}", cert_path, err))?;
32 acceptor.check_private_key().unwrap();
33
34 let acceptor = Arc::new(acceptor.build());
35
36 let listener = TcpListener::bind(&"127.0.0.1:8008".parse().unwrap()).unwrap();
37
38 println!("listening on {:?}", listener.local_addr());
39
40 let server = listener
41 .incoming()
42 .map_err(Error::from)
43 .and_then(move |sock| {
44 sock.set_nodelay(true).unwrap();
45 sock.set_send_buffer_size(1024*1024).unwrap();
46 sock.set_recv_buffer_size(1024*1024).unwrap();
47 acceptor.accept_async(sock).map_err(|e| e.into())
48 })
49 .then(|r| match r {
50 // accept()s can fail here with an Err() when eg. the client rejects
51 // the cert and closes the connection, so we follow up with mapping
52 // it to an option and then filtering None with filter_map
53 Ok(c) => Ok::<_, Error>(Some(c)),
54 Err(e) => {
55 if let Some(_io) = e.downcast_ref::<std::io::Error>() {
56 // "real" IO errors should not simply be ignored
57 bail!("shutting down...");
58 } else {
59 // handshake errors just get filtered by filter_map() below:
60 Ok(None)
61 }
62 }
63 })
64 .filter_map(|r| {
65 // Filter out the Nones
66 r
67 })
68 .for_each(move |socket| {
69
70 let mut http = hyper::server::conn::Http::new();
71 http.http2_only(true);
72 // increase window size: todo - find optiomal size
73 let max_window_size = (1 << 31) - 2;
74 http.http2_initial_stream_window_size(max_window_size);
75 http.http2_initial_connection_window_size(max_window_size);
76
77 let service = hyper::service::service_fn(|_req: Request<Body>| {
78 println!("Got request");
79 let buffer = vec![65u8; 1024*1024]; // nonsense [A,A,A,A...]
80 let body = Body::from(buffer);
81
82 let response = Response::builder()
83 .status(http::StatusCode::OK)
84 .header(http::header::CONTENT_TYPE, "application/octet-stream")
85 .body(body)
86 .unwrap();
87 Ok::<_, Error>(response)
88 });
89 http.serve_connection(socket, service)
90 .map_err(Error::from)
91 })
92 .and_then(|_| {
93 println!("H2 connection CLOSE !");
94 Ok(())
95 })
96 .then(|res| {
97 if let Err(e) = res {
98 println!(" -> err={:?}", e);
99 }
100 Ok(())
101 });
102
103 tokio::run(server);
104
105 Ok(())
106 }