correctly spawn multiple tcp listeners for each address

This commit is contained in:
Jan Wolff 2020-05-26 07:36:53 +02:00
parent 2ffc8ff0cc
commit 361aa9a5d7
4 changed files with 47 additions and 24 deletions

View file

@ -6,7 +6,7 @@ gem_root = ./doc
# you can define as many of these as you like # you can define as many of these as you like
listen = 0.0.0.0:1965 listen = 0.0.0.0:1965
listen = [::]:1965 listen = [::1]:1965
# privilege level for the server to drop to after initializing # privilege level for the server to drop to after initializing
user = nobody user = nobody

View file

@ -20,10 +20,10 @@ fn send_header(stream: &mut SslStream<TcpStream>, header: &response::Header) {
} }
pub fn handle_request(config: &ServerConfig, mut stream: SslStream<TcpStream>) { 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) { match stream.ssl_read(&mut buffer) {
Ok(s) => { Ok(s) => {
if s == 0 || s > 1025 { if s == 0 || s > 1024 {
send_header(&mut stream, &response::bad_request()); send_header(&mut stream, &response::bad_request());
return; return;
} }

View file

@ -114,12 +114,19 @@ impl Server {
println!("serving..."); println!("serving...");
let acceptor = Server::build_acceptor(&self.config); let acceptor = Server::build_acceptor(&self.config);
let mut listeners = Vec::new();
for addr in &self.config.addrs { 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); println!("listening on: {}", addr);
} }
let listener = TcpListener::bind(&self.config.addrs[..]).unwrap();
if self.config.user.is_root() { if self.config.user.is_root() {
panic!("refusing to run as root"); panic!("refusing to run as root");
} }
@ -140,12 +147,34 @@ impl Server {
} }
}; };
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!("failure! one listening thread exited");
},
};
}
}
}
fn listener_loop(config: ServerConfig, listener: TcpListener, acceptor: std::sync::Arc<SslAcceptor>) {
for stream in listener.incoming() { for stream in listener.incoming() {
println!("new connection"); println!("new connection");
match stream { match stream {
Ok(stream) => { Ok(stream) => {
let acceptor = acceptor.clone(); let acceptor = acceptor.clone();
let config = self.config.clone(); let config = config.clone();
thread::spawn(move || { thread::spawn(move || {
let stream = acceptor.accept(stream).unwrap(); let stream = acceptor.accept(stream).unwrap();
handler::handle_request(&config, stream); handler::handle_request(&config, stream);
@ -157,5 +186,4 @@ impl Server {
} }
} }
} }
}
} }

View file

@ -4,7 +4,6 @@ use std::vec::Vec;
pub enum Status { pub enum Status {
Success = 20, Success = 20,
RedirectPermanent = 31, RedirectPermanent = 31,
PermanentFailure = 50,
NotFound = 51, NotFound = 51,
ProxyRequestRefused = 53, ProxyRequestRefused = 53,
BadRequest = 59, BadRequest = 59,
@ -36,10 +35,6 @@ pub fn redirect_permanent(meta: &str) -> Header {
Header::new(Status::RedirectPermanent, meta) Header::new(Status::RedirectPermanent, meta)
} }
pub fn permanent_failure() -> Header {
Header::new(Status::PermanentFailure, "permanent failure")
}
pub fn not_found() -> Header { pub fn not_found() -> Header {
Header::new(Status::NotFound, "not found") Header::new(Status::NotFound, "not found")
} }