diff --git a/README.md b/README.md
index 13001c7..2e501e8 100644
--- a/README.md
+++ b/README.md
@@ -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
`: specify the address to listen to.
+- `-a, --address `: specify the address(es) to listen to.
- `-c, --cert `: server certificate path.
- `-k, --key `: server private key path.
- `-r, --root-path `: path to CGI scripts root.
- `-e, --env `: 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:
diff --git a/src/main.rs b/src/main.rs
index b119f98..6d9e78b 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -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(())
}