83 lines
2.9 KiB
Rust
83 lines
2.9 KiB
Rust
//! Small TCP and TLS servers for tests, using the TEST-ONLY certificates in `fixtures/tls/`.
|
|
//! Each serves connections on its own thread with a function of the connection. Do not edit.
|
|
|
|
#![allow(dead_code)] // each test file uses a different part of this module
|
|
|
|
use std::io::{Read, Write};
|
|
use std::net::{SocketAddr, TcpListener, TcpStream};
|
|
use std::path::PathBuf;
|
|
use std::sync::Arc;
|
|
|
|
use rustls::pki_types::pem::PemObject;
|
|
use rustls::pki_types::{CertificateDer, PrivateKeyDer};
|
|
use rustls::{ServerConfig, ServerConnection, StreamOwned};
|
|
|
|
pub fn fixture(name: &str) -> PathBuf {
|
|
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
|
.join("tests/fixtures/tls")
|
|
.join(name)
|
|
}
|
|
|
|
/// A server certificate (`server`, `wrong-name`, `other-server`) and its key.
|
|
pub fn server_config(which: &str) -> Arc<ServerConfig> {
|
|
let certs: Vec<CertificateDer<'static>> =
|
|
CertificateDer::pem_file_iter(fixture(&format!("{which}.pem")))
|
|
.unwrap()
|
|
.collect::<Result<_, _>>()
|
|
.unwrap();
|
|
let key = PrivateKeyDer::from_pem_file(fixture(&format!("{which}.key"))).unwrap();
|
|
let provider = Arc::new(rustls::crypto::ring::default_provider());
|
|
let config = ServerConfig::builder_with_provider(provider)
|
|
.with_safe_default_protocol_versions()
|
|
.unwrap()
|
|
.with_no_client_auth()
|
|
.with_single_cert(certs, key)
|
|
.unwrap();
|
|
Arc::new(config)
|
|
}
|
|
|
|
/// Anything a test server can serve: plain TCP, or TLS over it.
|
|
pub trait Conn: Read + Write + Send {}
|
|
impl<T: Read + Write + Send> Conn for T {}
|
|
|
|
/// Serve every connection on 127.0.0.1 with `handle`, in plain TCP (`tls` None) or TLS.
|
|
pub fn serve<F>(tls: Option<Arc<ServerConfig>>, handle: F) -> SocketAddr
|
|
where
|
|
F: Fn(Box<dyn Conn>) + Send + Sync + 'static,
|
|
{
|
|
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
|
|
let addr = listener.local_addr().unwrap();
|
|
let handle = Arc::new(handle);
|
|
std::thread::spawn(move || {
|
|
for stream in listener.incoming() {
|
|
let Ok(stream) = stream else { continue };
|
|
let handle = Arc::clone(&handle);
|
|
let tls = tls.clone();
|
|
std::thread::spawn(move || match tls {
|
|
None => handle(Box::new(stream)),
|
|
Some(config) => {
|
|
let conn = ServerConnection::new(config).unwrap();
|
|
let tls_stream: StreamOwned<ServerConnection, TcpStream> =
|
|
StreamOwned::new(conn, stream);
|
|
handle(Box::new(tls_stream));
|
|
}
|
|
});
|
|
}
|
|
});
|
|
addr
|
|
}
|
|
|
|
/// A handler that reads one line and writes it back.
|
|
pub fn echo_line(mut conn: Box<dyn Conn>) {
|
|
let mut line = Vec::new();
|
|
let mut byte = [0u8; 1];
|
|
while conn.read(&mut byte).map(|n| n == 1).unwrap_or(false) {
|
|
line.push(byte[0]);
|
|
if byte[0] == b'\n' {
|
|
break;
|
|
}
|
|
}
|
|
let _ = conn.write_all(&line);
|
|
let _ = conn.flush();
|
|
}
|