summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Wolff <janw@mailbox.org>2020-05-26 07:36:53 +0200
committerJan Wolff <janw@mailbox.org>2020-05-26 07:36:53 +0200
commit361aa9a5d76e08aa6b369e1d072fe20a9fd468e1 (patch)
tree1055aa375250dc761c12ae7a9c0725515323a9ed
parent2ffc8ff0ccb0bfad7d69104cbc00b167589c780b (diff)
correctly spawn multiple tcp listeners for each address
-rw-r--r--doc/sheldond.conf2
-rw-r--r--src/server/handler.rs4
-rw-r--r--src/server/mod.rs60
-rw-r--r--src/server/response.rs5
4 files changed, 47 insertions, 24 deletions
diff --git a/doc/sheldond.conf b/doc/sheldond.conf
index 1c04c87..cbcdc59 100644
--- a/doc/sheldond.conf
+++ b/doc/sheldond.conf
@@ -6,7 +6,7 @@ gem_root = ./doc
# you can define as many of these as you like
listen = 0.0.0.0:1965
-listen = [::]:1965
+listen = [::1]:1965
# privilege level for the server to drop to after initializing
user = nobody
diff --git a/src/server/handler.rs b/src/server/handler.rs
index db45073..0522f50 100644
--- a/src/server/handler.rs
+++ b/src/server/handler.rs
@@ -20,10 +20,10 @@ fn send_header(stream: &mut SslStream<TcpStream>, header: &response::Header) {
}
pub fn handle_request(config: &ServerConfig, mut stream: SslStream<TcpStream>) {
- let mut buffer = [0; 1024];
+ let mut buffer = [0; 1025];
match stream.ssl_read(&mut buffer) {
Ok(s) => {
- if s == 0 || s > 1025 {
+ if s == 0 || s > 1024 {
send_header(&mut stream, &response::bad_request());
return;
}
diff --git a/src/server/mod.rs b/src/server/mod.rs
index a38e194..54a936c 100644
--- a/src/server/mod.rs
+++ b/src/server/mod.rs
@@ -114,12 +114,19 @@ impl Server {
println!("serving...");
let acceptor = Server::build_acceptor(&self.config);
+ let mut listeners = Vec::new();
for addr in &self.config.addrs {
+ let listener = match TcpListener::bind(addr) {
+ Ok(listener) => listener,
+ Err(_) => {
+ println!("failed listening on: {}", addr);
+ return;
+ }
+ };
+ listeners.push(listener);
println!("listening on: {}", addr);
}
- let listener = TcpListener::bind(&self.config.addrs[..]).unwrap();
-
if self.config.user.is_root() {
panic!("refusing to run as root");
}
@@ -140,21 +147,42 @@ impl Server {
}
};
- for stream in listener.incoming() {
- println!("new connection");
- match stream {
- Ok(stream) => {
- let acceptor = acceptor.clone();
- let config = self.config.clone();
- thread::spawn(move || {
- let stream = acceptor.accept(stream).unwrap();
- handler::handle_request(&config, stream);
- println!("closing connection");
- });
- }
+ let mut threads = Vec::new();
+ for listener in listeners {
+ let config = self.config.clone();
+ let acceptor = acceptor.clone();
+ let t = thread::spawn(move || listener_loop(config, listener, acceptor));
+ threads.push(t);
+ }
+
+ for t in threads {
+ match t.join() {
+ Ok(_) => {
+ println!("failure! one listening thread exited");
+ },
Err(_) => {
- println!("connection failed");
- }
+ println!("failure! one listening thread exited");
+ },
+ };
+ }
+ }
+}
+
+fn listener_loop(config: ServerConfig, listener: TcpListener, acceptor: std::sync::Arc<SslAcceptor>) {
+ for stream in listener.incoming() {
+ println!("new connection");
+ match stream {
+ Ok(stream) => {
+ let acceptor = acceptor.clone();
+ let config = config.clone();
+ thread::spawn(move || {
+ let stream = acceptor.accept(stream).unwrap();
+ handler::handle_request(&config, stream);
+ println!("closing connection");
+ });
+ }
+ Err(_) => {
+ println!("connection failed");
}
}
}
diff --git a/src/server/response.rs b/src/server/response.rs
index 263b2e3..7e2e542 100644
--- a/src/server/response.rs
+++ b/src/server/response.rs
@@ -4,7 +4,6 @@ use std::vec::Vec;
pub enum Status {
Success = 20,
RedirectPermanent = 31,
- PermanentFailure = 50,
NotFound = 51,
ProxyRequestRefused = 53,
BadRequest = 59,
@@ -36,10 +35,6 @@ pub fn redirect_permanent(meta: &str) -> Header {
Header::new(Status::RedirectPermanent, meta)
}
-pub fn permanent_failure() -> Header {
- Header::new(Status::PermanentFailure, "permanent failure")
-}
-
pub fn not_found() -> Header {
Header::new(Status::NotFound, "not found")
}