Better error handling (where it's needed)
This commit is contained in:
parent
ecb32b205c
commit
570b0617ef
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user