diff --git a/Cargo.lock b/Cargo.lock index eb5ec0a..7507241 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -680,9 +680,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7" +checksum = "56d855069fafbb9b344c0f962150cd2c1187975cb1c22c1522c240d8c4986714" [[package]] name = "libsqlite3-sys" @@ -696,9 +696,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" +checksum = "5a3c91c24eae6777794bb1997ad98bbb87daf92890acab859f7eaa4320333176" dependencies = [ "scopeguard", ] @@ -929,9 +929,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.24" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" dependencies = [ "unicode-xid", ] @@ -1130,6 +1130,7 @@ dependencies = [ "serde", "serde_json", "shared", + "socket2", "structopt", "tempfile", "thiserror", @@ -1234,9 +1235,9 @@ checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2" [[package]] name = "syn" -version = "1.0.67" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6498a9efc342871f91cc2d0d694c674368b4ceb40f62b65a7a08c3792935e702" +checksum = "3ce15dd3ed8aa2f8eeac4716d6ef5ab58b6b9256db41d7e1a0224c2788e8fd87" dependencies = [ "proc-macro2", "quote", @@ -1329,9 +1330,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317cca572a0e89c3ce0ca1f1bdc9369547fe318a683418e42ac8f59d14701023" +checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342" dependencies = [ "tinyvec_macros", ] @@ -1551,8 +1552,7 @@ dependencies = [ [[package]] name = "warp" version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332d47745e9a0c38636dbd454729b147d16bd1ed08ae67b3ab281c4506771054" +source = "git+https://github.com/tonarino/warp#bd70fb6249810eb63e9acdfe2dcc79e41ab53304" dependencies = [ "bytes", "futures", diff --git a/server/Cargo.toml b/server/Cargo.toml index 3466162..715e345 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -34,9 +34,13 @@ structopt = "0.3" thiserror = "1" tokio = { version = "1", features = ["macros", "rt-multi-thread"] } toml = "0.5" -warp = { version = "0.3", default-features = false } +warp = { git = "https://github.com/tonarino/warp", default-features = false } wgctrl = { path = "../wgctrl-rs" } + +[target.'cfg(target_os = "linux")'.dependencies] +socket2 = { version = "0.4", features = ["all"] } + [dev-dependencies] anyhow = "1" tempfile = "3" diff --git a/server/src/main.rs b/server/src/main.rs index 6039a10..7cbe9fc 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,5 +1,6 @@ use colored::*; use error::handle_rejection; +use hyper::{server::conn::AddrStream, Body, Request}; use indoc::printdoc; use ipnetwork::IpNetwork; use parking_lot::Mutex; @@ -7,10 +8,11 @@ use rusqlite::Connection; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use shared::IoErrorContext; use std::{ + convert::Infallible, env, fs::File, io::prelude::*, - net::{IpAddr, SocketAddr}, + net::{IpAddr, SocketAddr, TcpListener}, ops::Deref, path::{Path, PathBuf}, sync::Arc, @@ -304,13 +306,43 @@ async fn serve(interface: &str, conf: &ServerConfig) -> Result<(), Error> { log::info!("innernet-server {} starting.", VERSION); let routes = routes(context.clone()).with(warp::log("warp")).boxed(); - warp::serve(routes) - .run((config.address, config.listen_port)) - .await; + + let listener = get_listener((config.address, config.listen_port).into(), interface)?; + + let warp_svc = warp::service(routes); + let make_svc = hyper::service::make_service_fn(move |socket: &AddrStream| { + let remote_addr = socket.remote_addr(); + let warp_svc = warp_svc.clone(); + async move { + let svc = hyper::service::service_fn(move |req: Request| { + let warp_svc = warp_svc.clone(); + async move { warp_svc.call_with_addr(req, Some(remote_addr)).await } + }); + Ok::<_, Infallible>(svc) + } + }); + + hyper::Server::from_tcp(listener)?.serve(make_svc).await?; Ok(()) } +#[cfg(target_os = "linux")] +fn get_listener(addr: SocketAddr, interface: &str) -> Result { + let listener = TcpListener::bind(&addr)?; + listener.set_nonblocking(true)?; + let sock = socket2::Socket::from(listener); + sock.bind_device(Some(interface.as_bytes()))?; + Ok(sock.into()) +} + +#[cfg(not(target_os = "linux"))] +fn get_listener(addr: SocketAddr, _interface: &str) -> Result { + let listener = TcpListener::bind(&addr)?; + listener.set_nonblocking(true)?; + Ok(listener) +} + pub fn routes( context: Context, ) -> impl Filter + Clone {