2019-08-28 15:05:45 +02:00
use std ::future ::Future ;
use std ::pin ::Pin ;
use std ::task ::{ Context , Poll } ;
2019-06-29 14:57:54 +02:00
use failure ::* ;
2019-08-28 15:05:45 +02:00
use futures ::future ::TryFutureExt ;
use futures ::stream ::Stream ;
2019-06-29 14:57:54 +02:00
// Simple H2 client to test H2 download speed using h2s-server.rs
2019-06-29 15:58:18 +02:00
struct Process {
body : h2 ::RecvStream ,
trailers : bool ,
bytes : usize ,
}
impl Future for Process {
2019-08-28 15:05:45 +02:00
type Output = Result < usize , Error > ;
fn poll ( self : Pin < & mut Self > , cx : & mut Context ) -> Poll < Self ::Output > {
let this = self . get_mut ( ) ;
2019-06-29 15:58:18 +02:00
loop {
2019-08-28 15:05:45 +02:00
if this . trailers {
match futures ::ready! ( this . body . poll_trailers ( cx ) ) {
Ok ( Some ( trailers ) ) = > println! ( " trailers: {:?} " , trailers ) ,
Ok ( None ) = > ( ) ,
Err ( err ) = > return Poll ::Ready ( Err ( Error ::from ( err ) ) ) ,
2019-06-29 15:58:18 +02:00
}
2019-08-28 15:05:45 +02:00
println! ( " Received {} bytes " , this . bytes ) ;
return Poll ::Ready ( Ok ( this . bytes ) ) ;
2019-06-29 15:58:18 +02:00
} else {
2019-08-28 15:05:45 +02:00
match futures ::ready! ( Pin ::new ( & mut this . body ) . poll_next ( cx ) ) {
Some ( Ok ( chunk ) ) = > {
2019-12-12 15:27:07 +01:00
this . body . flow_control ( ) . release_capacity ( chunk . len ( ) ) ? ;
2019-08-28 15:05:45 +02:00
this . bytes + = chunk . len ( ) ;
2019-06-29 15:58:18 +02:00
// println!("GOT FRAME {}", chunk.len());
} ,
2019-08-28 15:05:45 +02:00
Some ( Err ( err ) ) = > return Poll ::Ready ( Err ( Error ::from ( err ) ) ) ,
2019-06-29 15:58:18 +02:00
None = > {
2019-08-28 15:05:45 +02:00
this . trailers = true ;
2019-06-29 15:58:18 +02:00
} ,
}
}
}
}
}
2019-08-28 15:05:45 +02:00
fn send_request (
mut client : h2 ::client ::SendRequest < bytes ::Bytes > ,
) -> impl Future < Output = Result < usize , Error > > {
2019-06-29 15:58:18 +02:00
println! ( " sending request " ) ;
let request = http ::Request ::builder ( )
. uri ( " http://localhost/ " )
. body ( ( ) )
. unwrap ( ) ;
let ( response , _stream ) = client . send_request ( request , true ) . unwrap ( ) ;
response
. map_err ( Error ::from )
. and_then ( | response | {
Process { body : response . into_body ( ) , trailers : false , bytes : 0 }
} )
2019-06-29 14:57:54 +02:00
}
2019-08-28 15:05:45 +02:00
#[ tokio::main ]
async fn main ( ) -> Result < ( ) , Error > {
2019-06-29 14:57:54 +02:00
let start = std ::time ::SystemTime ::now ( ) ;
2019-09-02 15:16:21 +02:00
let conn =
tokio ::net ::TcpStream ::connect ( std ::net ::SocketAddr ::from ( ( [ 127 , 0 , 0 , 1 ] , 8008 ) ) ) . await ? ;
2019-08-28 15:05:45 +02:00
conn . set_nodelay ( true ) . unwrap ( ) ;
conn . set_recv_buffer_size ( 1024 * 1024 ) . unwrap ( ) ;
use openssl ::ssl ::{ SslConnector , SslMethod } ;
let mut ssl_connector_builder = SslConnector ::builder ( SslMethod ::tls ( ) ) . unwrap ( ) ;
ssl_connector_builder . set_verify ( openssl ::ssl ::SslVerifyMode ::NONE ) ;
let conn =
tokio_openssl ::connect (
ssl_connector_builder . build ( ) . configure ( ) ? ,
" localhost " ,
conn ,
)
. await
. map_err ( | err | format_err! ( " connect failed - {} " , err ) ) ? ;
let ( client , h2 ) = h2 ::client ::Builder ::new ( )
. initial_connection_window_size ( 1024 * 1024 * 1024 )
. initial_window_size ( 1024 * 1024 * 1024 )
. max_frame_size ( 4 * 1024 * 1024 )
. handshake ( conn )
. await ? ;
// Spawn a task to run the conn...
tokio ::spawn ( async move {
if let Err ( e ) = h2 . await {
println! ( " GOT ERR= {:?} " , e ) ;
}
} ) ;
2019-06-29 14:57:54 +02:00
2019-08-28 15:05:45 +02:00
let mut bytes = 0 ;
for _ in 0 .. 100 {
match send_request ( client . clone ( ) ) . await {
Ok ( b ) = > {
bytes + = b ;
}
Err ( e ) = > {
println! ( " ERROR {} " , e ) ;
return Ok ( ( ) ) ;
2019-06-29 14:57:54 +02:00
}
2019-08-28 15:05:45 +02:00
}
}
let elapsed = start . elapsed ( ) . unwrap ( ) ;
let elapsed = ( elapsed . as_secs ( ) as f64 ) +
( elapsed . subsec_millis ( ) as f64 ) / 1000.0 ;
2019-06-29 14:57:54 +02:00
2019-08-28 15:05:45 +02:00
println! ( " Downloaded {} bytes, {} MB/s " , bytes , ( bytes as f64 ) / ( elapsed * 1024.0 * 1024.0 ) ) ;
2019-06-29 14:57:54 +02:00
Ok ( ( ) )
}