]> git.proxmox.com Git - proxmox-backup.git/blame - examples/h2s-client.rs
bin: use extract_output_format where necessary
[proxmox-backup.git] / examples / h2s-client.rs
CommitLineData
55d8a631
WB
1use std::future::Future;
2use std::pin::Pin;
3use std::task::{Context, Poll};
4
f7d4e4b5 5use anyhow::{format_err, Error};
55d8a631
WB
6use futures::future::TryFutureExt;
7use futures::stream::Stream;
19f5aa25 8use tokio::net::TcpStream;
5ed2277f
DM
9
10// Simple H2 client to test H2 download speed using h2s-server.rs
11
34f71311
DM
12struct Process {
13 body: h2::RecvStream,
14 trailers: bool,
15 bytes: usize,
16}
17
18impl Future for Process {
55d8a631
WB
19 type Output = Result<usize, Error>;
20
21 fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
22 let this = self.get_mut();
34f71311 23
34f71311 24 loop {
55d8a631
WB
25 if this.trailers {
26 match futures::ready!(this.body.poll_trailers(cx)) {
27 Ok(Some(trailers)) => println!("trailers: {:?}", trailers),
28 Ok(None) => (),
29 Err(err) => return Poll::Ready(Err(Error::from(err))),
34f71311 30 }
34f71311 31
55d8a631
WB
32 println!("Received {} bytes", this.bytes);
33
34 return Poll::Ready(Ok(this.bytes));
34f71311 35 } else {
55d8a631
WB
36 match futures::ready!(Pin::new(&mut this.body).poll_next(cx)) {
37 Some(Ok(chunk)) => {
db0cb9ce 38 this.body.flow_control().release_capacity(chunk.len())?;
55d8a631 39 this.bytes += chunk.len();
34f71311 40 // println!("GOT FRAME {}", chunk.len());
19f5aa25 41 }
55d8a631 42 Some(Err(err)) => return Poll::Ready(Err(Error::from(err))),
34f71311 43 None => {
55d8a631 44 this.trailers = true;
19f5aa25 45 }
34f71311
DM
46 }
47 }
48 }
49 }
50}
51
55d8a631
WB
52fn send_request(
53 mut client: h2::client::SendRequest<bytes::Bytes>,
54) -> impl Future<Output = Result<usize, Error>> {
34f71311
DM
55 println!("sending request");
56
57 let request = http::Request::builder()
58 .uri("http://localhost/")
59 .body(())
60 .unwrap();
61
62 let (response, _stream) = client.send_request(request, true).unwrap();
63
19f5aa25
FG
64 response.map_err(Error::from).and_then(|response| Process {
65 body: response.into_body(),
66 trailers: false,
67 bytes: 0,
68 })
5ed2277f
DM
69}
70
d973aa82
WB
71fn main() -> Result<(), Error> {
72 proxmox_backup::tools::runtime::main(run())
73}
74
75async fn run() -> Result<(), Error> {
5ed2277f
DM
76 let start = std::time::SystemTime::now();
77
19f5aa25 78 let conn = TcpStream::connect(std::net::SocketAddr::from(([127, 0, 0, 1], 8008))).await?;
55d8a631 79 conn.set_nodelay(true).unwrap();
55d8a631
WB
80
81 use openssl::ssl::{SslConnector, SslMethod};
82
83 let mut ssl_connector_builder = SslConnector::builder(SslMethod::tls()).unwrap();
84 ssl_connector_builder.set_verify(openssl::ssl::SslVerifyMode::NONE);
19f5aa25
FG
85 let ssl = ssl_connector_builder
86 .build()
87 .configure()?
88 .into_ssl("localhost")?;
89
90 let conn = tokio_openssl::SslStream::new(ssl, conn)?;
91 let mut conn = Box::pin(conn);
92 conn.as_mut()
93 .connect()
55d8a631
WB
94 .await
95 .map_err(|err| format_err!("connect failed - {}", err))?;
96
97 let (client, h2) = h2::client::Builder::new()
19f5aa25
FG
98 .initial_connection_window_size(1024 * 1024 * 1024)
99 .initial_window_size(1024 * 1024 * 1024)
100 .max_frame_size(4 * 1024 * 1024)
55d8a631
WB
101 .handshake(conn)
102 .await?;
103
55d8a631 104 tokio::spawn(async move {
19f5aa25
FG
105 if let Err(err) = h2.await {
106 println!("GOT ERR={:?}", err);
55d8a631
WB
107 }
108 });
5ed2277f 109
55d8a631 110 let mut bytes = 0;
19f5aa25
FG
111 for _ in 0..2000 {
112 bytes += send_request(client.clone()).await?;
55d8a631
WB
113 }
114
115 let elapsed = start.elapsed().unwrap();
19f5aa25 116 let elapsed = (elapsed.as_secs() as f64) + (elapsed.subsec_millis() as f64) / 1000.0;
5ed2277f 117
19f5aa25
FG
118 println!(
119 "Downloaded {} bytes, {} MB/s",
120 bytes,
121 (bytes as f64) / (elapsed * 1024.0 * 1024.0)
122 );
5ed2277f
DM
123
124 Ok(())
125}