hyper-simple-server 0.5.1

Simple friendly wrapper around hyper HTTP server
Documentation


use crate::prelude::*;




#[ cfg (feature = "hss-accepter") ]
pub enum Accepter {
	TcpListener (Arc<tokio::TcpListener>),
	#[ cfg (feature = "hss-tls-rust") ]
	RustTlsTcpListener (Arc<tokio_rustls::TlsAcceptor>, Arc<tokio::TcpListener>),
	#[ cfg (feature = "hss-tls-native") ]
	NativeTlsTcpListener (Arc<tokio_natls::TlsAcceptor>, Arc<tokio::TcpListener>),
}




#[ cfg (feature = "hss-accepter") ]
impl Accepter {
	
	pub fn poll (self : Pin<&mut Self>, _context : &mut Context<'_>) -> Poll<Option<ServerResult<Connection>>> {
		
		let _self = Pin::into_inner (self);
		
		let _listener = _self.listener ();
		let (_socket, _address) = match futures::ready! (_listener.poll_accept (_context)) {
			Ok ((_socket, _address)) =>
				(_socket, _address),
			Err (_error) =>
				return Poll::Ready (Some (Err (_error))),
		};
		
		match _self {
			
			Accepter::TcpListener (_) => {
				let _connection = Connection::TcpStream (_socket, _address);
				Poll::Ready (Some (Ok (_connection)))
			}
			
			#[ cfg (feature = "hss-tls-rust") ]
			Accepter::RustTlsTcpListener (_tls, _) => {
				let _accepter = _tls.accept (_socket);
				let _connection = Connection::RustTlsTcpStreamPending (_accepter, _address);
				Poll::Ready (Some (Ok (_connection)))
			}
			
			#[ cfg (feature = "hss-tls-native") ]
			Accepter::NativeTlsTcpListener (_tls, _) => {
				let _tls = _tls.clone ();
				#[ allow (unsafe_code) ]
				let _tls_static = unsafe { mem::transmute::<&tokio_natls::TlsAcceptor, &'static tokio_natls::TlsAcceptor> (_tls.deref ()) };
				let _accepter = _tls_static.accept (_socket);
				let _accepter = Box::pin (_accepter);
				let _connection = Connection::NativeTlsTcpStreamPending (_tls, _accepter, _address);
				Poll::Ready (Some (Ok (_connection)))
			}
		}
	}
}




#[ cfg (feature = "hss-accepter") ]
impl Accepter {
	
	pub fn new (_endpoint : &Endpoint) -> ServerResult<Self> {
		
		let _listener = new_listener (&_endpoint.address) ?;
		let _listener = Arc::new (_listener);
		
		match &_endpoint.security {
			
			EndpointSecurity::Insecure =>
				Ok (Accepter::TcpListener (_listener)),
			
			#[ cfg (feature = "hss-tls-rust") ]
			EndpointSecurity::RustTls (_certificate) => {
				let _accepter = new_rustls_accepter (_certificate, &_endpoint.protocol) ?;
				Ok (Accepter::RustTlsTcpListener (Arc::new (_accepter), _listener))
			}
			
			#[ cfg (feature = "hss-tls-native") ]
			EndpointSecurity::NativeTls (_certificate) => {
				let _accepter = new_native_accepter (_certificate, &_endpoint.protocol) ?;
				Ok (Accepter::NativeTlsTcpListener (Arc::new (_accepter), _listener))
			}
		}
	}
	
	pub(crate) fn listener (&self) -> &tokio::TcpListener {
		match self {
			Accepter::TcpListener (_listener) =>
				_listener,
			#[ cfg (feature = "hss-tls-rust") ]
			Accepter::RustTlsTcpListener (_, _listener) =>
				_listener,
			#[ cfg (feature = "hss-tls-native") ]
			Accepter::NativeTlsTcpListener (_, _listener) =>
				_listener,
		}
	}
}




#[ cfg (feature = "hss-accepter") ]
#[ cfg (feature = "hyper--server") ]
impl hyper::Accept for Accepter {
	
	type Conn = Connection;
	type Error = ServerError;
	
	fn poll_accept (self : Pin<&mut Self>, _context : &mut Context<'_>) -> Poll<Option<Result<Self::Conn, Self::Error>>> {
		self.poll (_context)
	}
}




#[ cfg (feature = "hss-accepter") ]
fn new_listener (_address : &EndpointAddress) -> ServerResult<tokio::TcpListener> {
	
	#[ allow (unsafe_code) ]
	let _listener = match _address {
		EndpointAddress::Socket (_address) =>
			net::TcpListener::bind (_address) ?,
		#[ cfg (unix) ]
		EndpointAddress::Descriptor (_descriptor) =>
			unsafe {
				os::unix::io::FromRawFd::from_raw_fd (*_descriptor as i32)
			},
	};
	
	_listener.set_nonblocking (true) ?;
	
	let _listener = tokio::TcpListener::from_std (_listener) ?;
	
	Ok (_listener)
}




#[ cfg (feature = "hss-accepter") ]
#[ cfg (feature = "hss-tls-rust") ]
fn new_rustls_accepter (_certificate : &RustTlsCertificate, _protocol : &EndpointProtocol) -> ServerResult<tokio_rustls::TlsAcceptor> {
	
	let _resolver = {
		struct Resolver (RustTlsCertificate);
		impl rustls::ResolvesServerCert for Resolver {
			fn resolve (&self, _ : rustls::ClientHello<'_>) -> Option<rustls::sign::CertifiedKey> {
				Some (self.0.certified.clone ())
			}
		}
		Resolver (_certificate.clone ())
	};
	
	let _configuration = {
		let mut _builder = rustls::ServerConfig::new (rustls::NoClientAuth::new ());
		_builder.cert_resolver = Arc::new (_resolver);
		if _protocol.supports_http1 () {
			_builder.alpn_protocols.push ("http/1.1".into ());
		}
		if _protocol.supports_http2 () {
			_builder.alpn_protocols.push ("h2".into ());
		}
		Arc::new (_builder)
	};
	
	let _accepter = tokio_rustls::TlsAcceptor::from (_configuration);
	
	Ok (_accepter)
}




#[ cfg (feature = "hss-accepter") ]
#[ cfg (feature = "hss-tls-native") ]
fn new_native_accepter (_certificate : &NativeTlsCertificate, _protocol : &EndpointProtocol) -> ServerResult<tokio_natls::TlsAcceptor> {
	
	let _configuration = {
		let mut _builder = natls::TlsAcceptor::builder (_certificate.identity.clone ());
		_builder.min_protocol_version (Some (natls::Protocol::Tlsv12));
		_builder.build () .or_wrap (0xaf2c7136) ?
	};
	
	let _accepter = tokio_natls::TlsAcceptor::from (_configuration);
	
	Ok (_accepter)
}