refactor(client): minimize the amount of instantiated code (#2391)
* Halve the amount of conn_task instantiations * Extract non-generic parts of client::handshake * Extract the non-generic parts of call_async
This commit is contained in:
		
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							446dd2f0c7
						
					
				
				
					commit
					a15f3f7f0f
				
			| @@ -272,54 +272,60 @@ where | ||||
|     } | ||||
| } | ||||
|  | ||||
| fn get_host_port<'u>(config: &Config, dst: &'u Uri) -> Result<(&'u str, u16), ConnectError> { | ||||
|     trace!( | ||||
|         "Http::connect; scheme={:?}, host={:?}, port={:?}", | ||||
|         dst.scheme(), | ||||
|         dst.host(), | ||||
|         dst.port(), | ||||
|     ); | ||||
|  | ||||
|     if config.enforce_http { | ||||
|         if dst.scheme() != Some(&Scheme::HTTP) { | ||||
|             return Err(ConnectError { | ||||
|                 msg: INVALID_NOT_HTTP.into(), | ||||
|                 cause: None, | ||||
|             }); | ||||
|         } | ||||
|     } else if dst.scheme().is_none() { | ||||
|         return Err(ConnectError { | ||||
|             msg: INVALID_MISSING_SCHEME.into(), | ||||
|             cause: None, | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     let host = match dst.host() { | ||||
|         Some(s) => s, | ||||
|         None => { | ||||
|             return Err(ConnectError { | ||||
|                 msg: INVALID_MISSING_HOST.into(), | ||||
|                 cause: None, | ||||
|             }) | ||||
|         } | ||||
|     }; | ||||
|     let port = match dst.port() { | ||||
|         Some(port) => port.as_u16(), | ||||
|         None => { | ||||
|             if dst.scheme() == Some(&Scheme::HTTPS) { | ||||
|                 443 | ||||
|             } else { | ||||
|                 80 | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     Ok((host, port)) | ||||
| } | ||||
|  | ||||
| impl<R> HttpConnector<R> | ||||
| where | ||||
|     R: Resolve, | ||||
| { | ||||
|     async fn call_async(&mut self, dst: Uri) -> Result<TcpStream, ConnectError> { | ||||
|         trace!( | ||||
|             "Http::connect; scheme={:?}, host={:?}, port={:?}", | ||||
|             dst.scheme(), | ||||
|             dst.host(), | ||||
|             dst.port(), | ||||
|         ); | ||||
|  | ||||
|         if self.config.enforce_http { | ||||
|             if dst.scheme() != Some(&Scheme::HTTP) { | ||||
|                 return Err(ConnectError { | ||||
|                     msg: INVALID_NOT_HTTP.into(), | ||||
|                     cause: None, | ||||
|                 }); | ||||
|             } | ||||
|         } else if dst.scheme().is_none() { | ||||
|             return Err(ConnectError { | ||||
|                 msg: INVALID_MISSING_SCHEME.into(), | ||||
|                 cause: None, | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         let host = match dst.host() { | ||||
|             Some(s) => s, | ||||
|             None => { | ||||
|                 return Err(ConnectError { | ||||
|                     msg: INVALID_MISSING_HOST.into(), | ||||
|                     cause: None, | ||||
|                 }) | ||||
|             } | ||||
|         }; | ||||
|         let port = match dst.port() { | ||||
|             Some(port) => port.as_u16(), | ||||
|             None => { | ||||
|                 if dst.scheme() == Some(&Scheme::HTTPS) { | ||||
|                     443 | ||||
|                 } else { | ||||
|                     80 | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         let config = &self.config; | ||||
|  | ||||
|         let (host, port) = get_host_port(config, &dst)?; | ||||
|  | ||||
|         // If the host is already an IP addr (v4 or v6), | ||||
|         // skip resolving the dns and start connecting right away. | ||||
|         let addrs = if let Some(addrs) = dns::SocketAddrs::try_parse(host, port) { | ||||
| @@ -328,10 +334,12 @@ where | ||||
|             let addrs = resolve(&mut self.resolver, dns::Name::new(host.into())) | ||||
|                 .await | ||||
|                 .map_err(ConnectError::dns)?; | ||||
|             let addrs = addrs.map(|mut addr| { | ||||
|                 addr.set_port(port); | ||||
|                 addr | ||||
|             }).collect(); | ||||
|             let addrs = addrs | ||||
|                 .map(|mut addr| { | ||||
|                     addr.set_port(port); | ||||
|                     addr | ||||
|                 }) | ||||
|                 .collect(); | ||||
|             dns::SocketAddrs::new(addrs) | ||||
|         }; | ||||
|  | ||||
|   | ||||
| @@ -63,6 +63,32 @@ impl Default for Config { | ||||
|     } | ||||
| } | ||||
|  | ||||
| fn new_builder(config: &Config) -> Builder { | ||||
|     let mut builder = Builder::default(); | ||||
|     builder | ||||
|         .initial_window_size(config.initial_stream_window_size) | ||||
|         .initial_connection_window_size(config.initial_conn_window_size) | ||||
|         .max_frame_size(config.max_frame_size) | ||||
|         .enable_push(false); | ||||
|     builder | ||||
| } | ||||
|  | ||||
| fn new_ping_config(config: &Config) -> ping::Config { | ||||
|     ping::Config { | ||||
|         bdp_initial_window: if config.adaptive_window { | ||||
|             Some(config.initial_stream_window_size) | ||||
|         } else { | ||||
|             None | ||||
|         }, | ||||
|         #[cfg(feature = "runtime")] | ||||
|         keep_alive_interval: config.keep_alive_interval, | ||||
|         #[cfg(feature = "runtime")] | ||||
|         keep_alive_timeout: config.keep_alive_timeout, | ||||
|         #[cfg(feature = "runtime")] | ||||
|         keep_alive_while_idle: config.keep_alive_while_idle, | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub(crate) async fn handshake<T, B>( | ||||
|     io: T, | ||||
|     req_rx: ClientRx<B>, | ||||
| @@ -74,11 +100,7 @@ where | ||||
|     B: HttpBody, | ||||
|     B::Data: Send + 'static, | ||||
| { | ||||
|     let (h2_tx, mut conn) = Builder::default() | ||||
|         .initial_window_size(config.initial_stream_window_size) | ||||
|         .initial_connection_window_size(config.initial_conn_window_size) | ||||
|         .max_frame_size(config.max_frame_size) | ||||
|         .enable_push(false) | ||||
|     let (h2_tx, mut conn) = new_builder(config) | ||||
|         .handshake::<_, SendBuf<B::Data>>(io) | ||||
|         .await | ||||
|         .map_err(crate::Error::new_h2)?; | ||||
| @@ -96,21 +118,9 @@ where | ||||
|         } | ||||
|     }); | ||||
|  | ||||
|     let ping_config = ping::Config { | ||||
|         bdp_initial_window: if config.adaptive_window { | ||||
|             Some(config.initial_stream_window_size) | ||||
|         } else { | ||||
|             None | ||||
|         }, | ||||
|         #[cfg(feature = "runtime")] | ||||
|         keep_alive_interval: config.keep_alive_interval, | ||||
|         #[cfg(feature = "runtime")] | ||||
|         keep_alive_timeout: config.keep_alive_timeout, | ||||
|         #[cfg(feature = "runtime")] | ||||
|         keep_alive_while_idle: config.keep_alive_while_idle, | ||||
|     }; | ||||
|     let ping_config = new_ping_config(&config); | ||||
|  | ||||
|     let ping = if ping_config.is_enabled() { | ||||
|     let (conn, ping) = if ping_config.is_enabled() { | ||||
|         let pp = conn.ping_pong().expect("conn.ping_pong"); | ||||
|         let (recorder, mut ponger) = ping::channel(pp, ping_config); | ||||
|  | ||||
| @@ -130,16 +140,13 @@ where | ||||
|  | ||||
|             Pin::new(&mut conn).poll(cx) | ||||
|         }); | ||||
|         let conn = conn.map_err(|e| debug!("connection error: {}", e)); | ||||
|  | ||||
|         exec.execute(conn_task(conn, conn_drop_rx, cancel_tx)); | ||||
|         recorder | ||||
|         (Either::Left(conn), recorder) | ||||
|     } else { | ||||
|         let conn = conn.map_err(|e| debug!("connection error: {}", e)); | ||||
|  | ||||
|         exec.execute(conn_task(conn, conn_drop_rx, cancel_tx)); | ||||
|         ping::disabled() | ||||
|         (Either::Right(conn), ping::disabled()) | ||||
|     }; | ||||
|     let conn = conn.map_err(|e| debug!("connection error: {}", e)); | ||||
|  | ||||
|     exec.execute(conn_task(conn, conn_drop_rx, cancel_tx)); | ||||
|  | ||||
|     Ok(ClientTask { | ||||
|         ping, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user