Better error handling (where it's needed)

This commit is contained in:
Mark 2021-03-16 22:10:47 +02:00
parent ecb32b205c
commit 570b0617ef
2 changed files with 22 additions and 20 deletions

View File

@ -42,7 +42,6 @@ impl ThreadPool {
} }
pub fn execute<F: FnOnce() + Send + 'static>(&self, f: F) { pub fn execute<F: FnOnce() + Send + 'static>(&self, f: F) {
// TODO error handling
self.sender.send(Box::new(f)).unwrap(); self.sender.send(Box::new(f)).unwrap();
} }
} }

View File

@ -4,9 +4,9 @@ use std::io::{self, Read, Write};
use std::net::{SocketAddr, TcpListener}; use std::net::{SocketAddr, TcpListener};
use url::Url; use url::Url;
use log::{warn, info, error};
use crate::proto::{self, ErrorCode, ResponseBody};
use crate::pool::ThreadPool; use crate::pool::ThreadPool;
use crate::proto::{self, ErrorCode, ResponseBody};
use log::{error, info, warn};
pub struct ServerConfig { pub struct ServerConfig {
pub thread_count: usize, pub thread_count: usize,
@ -35,7 +35,7 @@ fn read_request(stream: &mut impl Read) -> Result<Url, proto::Error> {
if read_line(&mut line, stream).is_err() { if read_line(&mut line, stream).is_err() {
return Err(proto::Error::new( return Err(proto::Error::new(
ErrorCode::BadRequest, ErrorCode::BadRequest,
Some("Bad Request") Some("Bad Request"),
)); ));
} }
match Url::parse(&line) { match Url::parse(&line) {
@ -51,12 +51,12 @@ fn send_response_body(stream: &mut impl Write, response: ResponseBody) -> Result
match response { match response {
ResponseBody::GeminiText(data) => { ResponseBody::GeminiText(data) => {
write!(stream, "20 text/gemini; charset=utf8\r\n{}", data) write!(stream, "20 text/gemini; charset=utf8\r\n{}", data)
}, }
ResponseBody::File(_, _) => todo!() ResponseBody::File(_, _) => todo!(),
} }
} }
fn handle_request(_peer: SocketAddr, url: Url) -> Result<ResponseBody, proto::Error> { fn handle_request(_peer: Option<SocketAddr>, url: Url) -> Result<ResponseBody, proto::Error> {
// TODO url logic // TODO url logic
if url.path() == "/ping" { if url.path() == "/ping" {
return Ok(ResponseBody::GeminiText("pong".to_string())); return Ok(ResponseBody::GeminiText("pong".to_string()));
@ -64,44 +64,45 @@ fn handle_request(_peer: SocketAddr, url: Url) -> Result<ResponseBody, proto::Er
Err(proto::Error::new(ErrorCode::NotFound, Some(url.path()))) Err(proto::Error::new(ErrorCode::NotFound, Some(url.path())))
} }
fn handle_stream<S: Read + Write>(peer: SocketAddr, stream: &mut S) { fn handle_stream<S: Read + Write>(peer: Option<SocketAddr>, stream: &mut S) {
let url = match read_request(stream) { let url = match read_request(stream) {
// TODO fix duplicate code here? // TODO fix duplicate code here?
Ok(url) => url, Ok(url) => url,
Err(err) => { Err(err) => {
let _ = writeln!(stream, "{}\r\n", err); let _ = writeln!(stream, "{}\r\n", err);
error!("{} {}", peer, err); error!("{:?} {}", peer, err);
return; return;
} }
}; };
match handle_request(peer, url.clone()) { match handle_request(peer, url.clone()) {
Ok(response) => { Ok(response) => {
let _ = send_response_body(stream, response); let _ = send_response_body(stream, response);
info!("{} {} 20", peer, url); info!("{:?} {} 20", peer, url);
}, }
Err(err) => { Err(err) => {
let _ = writeln!(stream, "{}\r\n", err); let _ = writeln!(stream, "{}\r\n", err);
error!("{} {} {}", peer, url, err); error!("{:?} {} {}", peer, url, err);
} }
}; };
} }
// TODO Result // TODO Result
pub fn run(config: &ServerConfig) { pub fn run(config: &ServerConfig) -> Result<(), io::Error> {
info!("Listening to gemini requests on {}", &config.bind_address); info!("Listening to gemini requests on {}", &config.bind_address);
let mut der = vec![]; let mut der = vec![];
let mut file = File::open(&config.identity_file).unwrap(); let mut file = File::open(&config.identity_file)?;
file.read_to_end(&mut der).unwrap(); file.read_to_end(&mut der)?;
let identity = Identity::from_pkcs12(&der, "").unwrap(); let identity =
Identity::from_pkcs12(&der, "").map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
let listener = TcpListener::bind(&config.bind_address).unwrap(); let listener = TcpListener::bind(&config.bind_address)?;
let acceptor = TlsAcceptor::new(identity).unwrap(); let acceptor = TlsAcceptor::new(identity).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
let pool = ThreadPool::new(config.thread_count); let pool = ThreadPool::new(config.thread_count);
for stream in listener.incoming() { for stream in listener.incoming() {
match stream { match stream {
Ok(stream) => { Ok(stream) => {
let peer = stream.peer_addr().unwrap(); let peer = stream.peer_addr();
let mut stream = match acceptor.accept(stream) { let mut stream = match acceptor.accept(stream) {
Ok(r) => r, Ok(r) => r,
Err(e) => { Err(e) => {
@ -111,7 +112,7 @@ pub fn run(config: &ServerConfig) {
}; };
pool.execute(move || { pool.execute(move || {
handle_stream(peer, &mut stream); handle_stream(peer.ok(), &mut stream);
}); });
} }
Err(e) => { Err(e) => {
@ -120,4 +121,6 @@ pub fn run(config: &ServerConfig) {
} }
} }
} }
Ok(())
} }