listen on multiple addresses concurrently

This commit is contained in:
dece 2021-12-17 19:54:54 +01:00
parent f31b973435
commit 7a26b7c011
2 changed files with 39 additions and 20 deletions

View file

@ -27,13 +27,18 @@ Usage
Use `opal -h` to get a list of options. There is no config file, every setting
can be configured from the command line.
- `-a, --address <address>`: specify the address to listen to.
- `-a, --address <address>`: specify the address(es) to listen to.
- `-c, --cert <cert>`: server certificate path.
- `-k, --key <key>`: server private key path.
- `-r, --root-path <root_path>`: path to CGI scripts root.
- `-e, --env <key=value>`: additional environment variables for CGI scripts;
this option can be used multiple times.
You can specify multiple addresses to listen to by using several `-a` options.
Note that if you just want to listen to both IPv4 and IPv6 on any interface,
listening only on `[::]:1965` should suffice for systems with dual-stack
enabled (default on many Linux systems, maybe not BSD).
CGI support
@ -103,9 +108,8 @@ Roadmap
Things to consider:
- Multiple listening addresses, at least so we can easily listen on both IPv4
and IPv6.
- Support SCGI; a bit more complex but should save resources on smol hardware.
- Chroot; quite cheap and can bring a bit of peace of mind.
Things that probably won't be considered:

View file

@ -41,7 +41,8 @@ fn run() -> Result<(), i32> {
.short("a")
.long("address")
.help("Address to listen to")
.takes_value(true),
.takes_value(true)
.multiple(true),
)
.arg(
clap::Arg::with_name("cert")
@ -110,24 +111,38 @@ fn run() -> Result<(), i32> {
)
.map_err(|err| run_failure("Can't create TLS acceptor", &err))?;
let address = matches.value_of("address").unwrap();
let listener = net::TcpListener::bind(address)
.map_err(|err| run_failure("Can't create TCP listener", &err))?;
for stream in listener.incoming() {
match stream {
Ok(stream) => {
let acceptor = acceptor.clone();
let cgi_config = cgi_config.clone();
thread::spawn(move || match acceptor.accept(stream) {
Ok(mut tls_stream) => handle_client(&mut tls_stream, &cgi_config),
Err(err) => error!("Can't initiate TLS stream: {}", err),
});
}
let mut threads = vec![];
for address in matches.values_of("address").unwrap() {
let listener = match net::TcpListener::bind(address) {
Ok(l) => l,
Err(err) => {
error!("Can't accept connection: {}", err);
error!("Can't create TCP listener: {}", &err);
continue
}
}
};
info!("Listening on {}", address);
let acceptor = acceptor.clone();
let cgi_config = cgi_config.clone();
threads.push(thread::spawn(move || {
for stream in listener.incoming() {
match stream {
Ok(stream) => {
let acceptor = acceptor.clone();
let cgi_config = cgi_config.clone();
thread::spawn(move || match acceptor.accept(stream) {
Ok(mut tls_stream) => handle_client(&mut tls_stream, &cgi_config),
Err(err) => error!("Can't initiate TLS stream: {}", err),
});
}
Err(err) => {
error!("Can't accept connection: {}", err);
}
}
}
}));
}
for t in threads.into_iter() {
t.join().unwrap();
}
Ok(())
}