Rewrite URL handling + add example

This commit is contained in:
Mark 2021-03-16 22:02:31 +02:00
parent f5ff848ff8
commit ecb32b205c
13 changed files with 682 additions and 145 deletions

4
.gitignore vendored
View File

@ -1,3 +1 @@
/target
/data/*.pem
/data/*.pfx
target

1
Cargo.lock generated
View File

@ -4,6 +4,7 @@
name = "algem"
version = "0.1.0"
dependencies = [
"log",
"native-tls",
"url",
]

View File

@ -9,3 +9,4 @@ edition = "2018"
[dependencies]
native-tls = "*"
url = "*"
log = "*"

View File

@ -1,6 +0,0 @@
Hello
=> gemini://gemini.circumlunar.space Gemini Project
=> /index This page
=> /other/page Other page
=> relative Relative page

480
example/Cargo.lock generated Normal file
View File

@ -0,0 +1,480 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "aho-corasick"
version = "0.7.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
dependencies = [
"memchr",
]
[[package]]
name = "algem"
version = "0.1.0"
dependencies = [
"log",
"native-tls",
"url",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "cc"
version = "1.0.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "core-foundation"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"
[[package]]
name = "env_logger"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17392a012ea30ef05a610aa97dfb49496e71c9f676b27879922ea5bdf60d9d3f"
dependencies = [
"atty",
"humantime",
"log",
"regex",
"termcolor",
]
[[package]]
name = "example"
version = "0.1.0"
dependencies = [
"algem",
"env_logger",
]
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "form_urlencoded"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
dependencies = [
"matches",
"percent-encoding",
]
[[package]]
name = "getrandom"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "hermit-abi"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
dependencies = [
"libc",
]
[[package]]
name = "humantime"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "idna"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89829a5d69c23d348314a7ac337fe39173b61149a9864deabd260983aed48c21"
dependencies = [
"matches",
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "538c092e5586f4cdd7dd8078c4a79220e3e168880218124dcbce860f0ea938c6"
[[package]]
name = "log"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if",
]
[[package]]
name = "matches"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
[[package]]
name = "memchr"
version = "2.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
[[package]]
name = "native-tls"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8d96b2e1c8da3957d58100b09f102c6d9cfdfced01b7ec5a8974044bb09dbd4"
dependencies = [
"lazy_static",
"libc",
"log",
"openssl",
"openssl-probe",
"openssl-sys",
"schannel",
"security-framework",
"security-framework-sys",
"tempfile",
]
[[package]]
name = "once_cell"
version = "1.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
[[package]]
name = "openssl"
version = "0.10.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a61075b62a23fef5a29815de7536d940aa35ce96d18ce0cc5076272db678a577"
dependencies = [
"bitflags",
"cfg-if",
"foreign-types",
"libc",
"once_cell",
"openssl-sys",
]
[[package]]
name = "openssl-probe"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
[[package]]
name = "openssl-sys"
version = "0.9.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "313752393519e876837e09e1fa183ddef0be7735868dced3196f4472d536277f"
dependencies = [
"autocfg",
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "percent-encoding"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "pkg-config"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
[[package]]
name = "ppv-lite86"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "rand"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
"rand_hc",
]
[[package]]
name = "rand_chacha"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_hc"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
dependencies = [
"rand_core",
]
[[package]]
name = "redox_syscall"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9"
dependencies = [
"bitflags",
]
[[package]]
name = "regex"
version = "1.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
[[package]]
name = "remove_dir_all"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
dependencies = [
"winapi",
]
[[package]]
name = "schannel"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75"
dependencies = [
"lazy_static",
"winapi",
]
[[package]]
name = "security-framework"
version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d493c5f39e02dfb062cd8f33301f90f9b13b650e8c1b1d0fd75c19dd64bff69d"
dependencies = [
"bitflags",
"core-foundation",
"core-foundation-sys",
"libc",
"security-framework-sys",
]
[[package]]
name = "security-framework-sys"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dee48cdde5ed250b0d3252818f646e174ab414036edb884dde62d80a3ac6082d"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "tempfile"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
dependencies = [
"cfg-if",
"libc",
"rand",
"redox_syscall",
"remove_dir_all",
"winapi",
]
[[package]]
name = "termcolor"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
dependencies = [
"winapi-util",
]
[[package]]
name = "tinyvec"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "317cca572a0e89c3ce0ca1f1bdc9369547fe318a683418e42ac8f59d14701023"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "unicode-bidi"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
dependencies = [
"matches",
]
[[package]]
name = "unicode-normalization"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef"
dependencies = [
"tinyvec",
]
[[package]]
name = "url"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b"
dependencies = [
"form_urlencoded",
"idna",
"matches",
"percent-encoding",
]
[[package]]
name = "vcpkg"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb"
[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

9
example/Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "example"
version = "0.1.0"
authors = ["Mark <alnyan@airmail.cc>"]
edition = "2018"
[dependencies]
algem = { path = "../" }
env_logger = "*"

BIN
example/identity.pfx Normal file

Binary file not shown.

12
example/src/main.rs Normal file
View File

@ -0,0 +1,12 @@
use algem::{server, ServerConfig};
fn main() {
let config = ServerConfig {
bind_address: "0.0.0.0:1965".to_string(),
identity_file: "identity.pfx".to_string(),
thread_count: 4
};
env_logger::init();
server::run(&config);
}

View File

@ -1,15 +0,0 @@
#!/bin/sh
openssl req \
-x509 \
-nodes \
-newkey rsa:4096 \
-keyout data/key.pem \
-out data/cert.pem \
-days 365
openssl pkcs12 \
-export \
-out data/identity.pfx \
-inkey data/key.pem \
-in data/cert.pem

6
src/lib.rs Normal file
View File

@ -0,0 +1,6 @@
pub mod proto;
pub mod server;
mod pool;
pub use proto::*;
pub use server::ServerConfig;

View File

@ -1,121 +0,0 @@
use native_tls::{Identity, TlsAcceptor};
use std::fs::File;
use std::io::{self, Read, Write};
use std::net::TcpListener;
use std::path::Path;
use url::Url;
mod pool;
use pool::ThreadPool;
fn read_line<T: Read>(s: &mut String, stream: &mut T) -> Result<(), io::Error> {
let mut byte = [0; 1];
s.clear();
loop {
stream.read_exact(&mut byte)?;
if byte[0] == b'\r' {
continue;
}
if byte[0] == b'\n' {
break;
}
s.push(byte[0] as char);
}
Ok(())
}
enum ResponseError {
// TODO handle malformed URLs
// TODO handle malformed paths
FileError(String, io::Error),
SocketError(io::Error),
}
fn handle_stream<S: Read + Write>(stream: &mut S) -> Result<String, ResponseError> {
let mut line = String::new();
read_line(&mut line, stream).map_err(|e| ResponseError::SocketError(e))?;
let url = Url::parse(&line).unwrap();
let path = String::from("data/pages/") + url.path();
let path = Path::new(&path);
match File::open(path) {
Ok(mut file) => {
let mut buf = [0; 4096];
// TODO ability to serve different kinds of objects?
stream
.write_all(b"20 text/gemini; charset=utf8\r\n")
.map_err(|e| ResponseError::SocketError(e))?;
loop {
let count = file
.read(&mut buf)
.map_err(|e| ResponseError::FileError(path.to_str().unwrap().to_string(), e))?;
if count == 0 {
break;
}
stream
.write(&buf[0..count])
.map_err(|e| ResponseError::SocketError(e))?;
}
Ok(line)
}
Err(err) => {
// TODO better errors
stream
.write_fmt(format_args!("40 {:?}\r\n", err))
.map_err(|e| ResponseError::SocketError(e))?;
Err(ResponseError::FileError(path.to_str().unwrap().to_string(), err))
}
}
}
fn main() {
let mut der = vec![];
let mut file = File::open("data/identity.pfx").unwrap();
file.read_to_end(&mut der).unwrap();
let identity = Identity::from_pkcs12(&der, "").unwrap();
let pool = ThreadPool::new(4);
let listener = TcpListener::bind("0.0.0.0:1965").unwrap();
let acceptor = TlsAcceptor::new(identity).unwrap();
for stream in listener.incoming() {
match stream {
Ok(stream) => {
let peer = stream.peer_addr().unwrap();
let mut stream = match acceptor.accept(stream) {
Ok(r) => r,
Err(e) => {
eprintln!("TLS handshake failed: {}", e);
continue;
}
};
pool.execute(move || {
eprint!("{} ", peer.ip());
match handle_stream(&mut stream) {
Err(err) => {
match err {
ResponseError::FileError(path, err) => {
eprintln!("ERR {}: {:?}", path, err);
},
ResponseError::SocketError(err) => {
eprintln!("ERR SOCK {:?}", err);
},
}
},
Ok(req) => {
println!(" OK {}", req);
}
}
});
}
Err(e) => {
eprintln!("accept() failed: {}", e);
break;
}
}
}
}

49
src/proto.rs Normal file
View File

@ -0,0 +1,49 @@
use std::fmt;
pub enum ResponseBody {
File(String, String),
GeminiText(String)
}
#[derive(Clone)]
pub enum ErrorCode {
Input = 10,
SensitiveInput = 11,
RedirectTemporary = 30,
RedirectPermanent = 31,
TemporaryFailure = 40,
ServerUnavailable = 41,
CgiError = 42,
ProxyError = 43,
SlowDown = 44,
PermanentFailure = 50,
NotFound = 51,
Gone = 52,
ProxyRequestRefused = 53,
BadRequest = 59,
// TODO certificate something
}
pub struct Error {
code: ErrorCode,
meta: Option<String>
}
impl Error {
pub fn new(code: ErrorCode, meta: Option<&str>) -> Error {
Error {
code,
meta: meta.map(str::to_string)
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.code.clone() as u32)?;
if let Some(meta) = self.meta.as_ref() {
write!(f, " {}", meta)?;
}
Ok(())
}
}

123
src/server.rs Normal file
View File

@ -0,0 +1,123 @@
use native_tls::{Identity, TlsAcceptor};
use std::fs::File;
use std::io::{self, Read, Write};
use std::net::{SocketAddr, TcpListener};
use url::Url;
use log::{warn, info, error};
use crate::proto::{self, ErrorCode, ResponseBody};
use crate::pool::ThreadPool;
pub struct ServerConfig {
pub thread_count: usize,
pub identity_file: String,
pub bind_address: String,
}
fn read_line<T: Read>(s: &mut String, stream: &mut T) -> Result<(), io::Error> {
let mut byte = [0; 1];
s.clear();
loop {
stream.read_exact(&mut byte)?;
if byte[0] == b'\r' {
continue;
}
if byte[0] == b'\n' {
break;
}
s.push(byte[0] as char);
}
Ok(())
}
fn read_request(stream: &mut impl Read) -> Result<Url, proto::Error> {
let mut line = String::new();
if read_line(&mut line, stream).is_err() {
return Err(proto::Error::new(
ErrorCode::BadRequest,
Some("Bad Request")
));
}
match Url::parse(&line) {
Ok(url) => Ok(url),
Err(_) => Err(proto::Error::new(
ErrorCode::BadRequest,
Some("Malformed URL"),
)),
}
}
fn send_response_body(stream: &mut impl Write, response: ResponseBody) -> Result<(), io::Error> {
match response {
ResponseBody::GeminiText(data) => {
write!(stream, "20 text/gemini; charset=utf8\r\n{}", data)
},
ResponseBody::File(_, _) => todo!()
}
}
fn handle_request(_peer: SocketAddr, url: Url) -> Result<ResponseBody, proto::Error> {
// TODO url logic
if url.path() == "/ping" {
return Ok(ResponseBody::GeminiText("pong".to_string()));
}
Err(proto::Error::new(ErrorCode::NotFound, Some(url.path())))
}
fn handle_stream<S: Read + Write>(peer: SocketAddr, stream: &mut S) {
let url = match read_request(stream) {
// TODO fix duplicate code here?
Ok(url) => url,
Err(err) => {
let _ = writeln!(stream, "{}\r\n", err);
error!("{} {}", peer, err);
return;
}
};
match handle_request(peer, url.clone()) {
Ok(response) => {
let _ = send_response_body(stream, response);
info!("{} {} 20", peer, url);
},
Err(err) => {
let _ = writeln!(stream, "{}\r\n", err);
error!("{} {} {}", peer, url, err);
}
};
}
// TODO Result
pub fn run(config: &ServerConfig) {
info!("Listening to gemini requests on {}", &config.bind_address);
let mut der = vec![];
let mut file = File::open(&config.identity_file).unwrap();
file.read_to_end(&mut der).unwrap();
let identity = Identity::from_pkcs12(&der, "").unwrap();
let listener = TcpListener::bind(&config.bind_address).unwrap();
let acceptor = TlsAcceptor::new(identity).unwrap();
let pool = ThreadPool::new(config.thread_count);
for stream in listener.incoming() {
match stream {
Ok(stream) => {
let peer = stream.peer_addr().unwrap();
let mut stream = match acceptor.accept(stream) {
Ok(r) => r,
Err(e) => {
warn!("TLS handshake failed: {}", e);
continue;
}
};
pool.execute(move || {
handle_stream(peer, &mut stream);
});
}
Err(e) => {
error!("accept() failed: {}", e);
break;
}
}
}
}