1
0

add option binding server to a specified IP

This commit is contained in:
EAimTY 2022-06-25 21:13:48 +09:00
parent 3929af931b
commit d1d61cf762
3 changed files with 51 additions and 20 deletions

View File

@ -9,14 +9,22 @@ use rustls::{version::TLS13, Error as RustlsError, ServerConfig as RustlsServerC
use serde::{de::Error as DeError, Deserialize, Deserializer}; use serde::{de::Error as DeError, Deserialize, Deserializer};
use serde_json::Error as JsonError; use serde_json::Error as JsonError;
use std::{ use std::{
collections::HashSet, env::ArgsOs, fmt::Display, fs::File, io::Error as IoError, collections::HashSet,
num::ParseIntError, str::FromStr, sync::Arc, time::Duration, env::ArgsOs,
fmt::Display,
fs::File,
io::Error as IoError,
net::{AddrParseError, IpAddr, Ipv4Addr, SocketAddr},
num::ParseIntError,
str::FromStr,
sync::Arc,
time::Duration,
}; };
use thiserror::Error; use thiserror::Error;
pub struct Config { pub struct Config {
pub server_config: ServerConfig, pub server_config: ServerConfig,
pub port: u16, pub listen_addr: SocketAddr,
pub token: HashSet<[u8; 32]>, pub token: HashSet<[u8; 32]>,
pub authentication_timeout: Duration, pub authentication_timeout: Duration,
pub max_udp_relay_packet_size: usize, pub max_udp_relay_packet_size: usize,
@ -68,7 +76,7 @@ impl Config {
config config
}; };
let port = raw.port.unwrap(); let listen_addr = SocketAddr::from((raw.ip, raw.port.unwrap()));
let token = raw let token = raw
.token .token
@ -82,7 +90,7 @@ impl Config {
Ok(Self { Ok(Self {
server_config, server_config,
port, listen_addr,
token, token,
authentication_timeout, authentication_timeout,
max_udp_relay_packet_size, max_udp_relay_packet_size,
@ -99,6 +107,9 @@ struct RawConfig {
certificate: Option<String>, certificate: Option<String>,
private_key: Option<String>, private_key: Option<String>,
#[serde(default = "default::ip")]
ip: IpAddr,
#[serde( #[serde(
default = "default::congestion_controller", default = "default::congestion_controller",
deserialize_with = "deserialize_from_str" deserialize_with = "deserialize_from_str"
@ -128,6 +139,7 @@ impl Default for RawConfig {
token: Vec::new(), token: Vec::new(),
certificate: None, certificate: None,
private_key: None, private_key: None,
ip: default::ip(),
congestion_controller: default::congestion_controller(), congestion_controller: default::congestion_controller(),
max_idle_time: default::max_idle_time(), max_idle_time: default::max_idle_time(),
authentication_timeout: default::authentication_timeout(), authentication_timeout: default::authentication_timeout(),
@ -172,6 +184,13 @@ impl RawConfig {
"PRIVATE_KEY", "PRIVATE_KEY",
); );
opts.optopt(
"",
"ip",
"Set the server listening IP. Default: 0.0.0.0",
"IP",
);
opts.optopt( opts.optopt(
"", "",
"congestion-controller", "congestion-controller",
@ -276,6 +295,10 @@ impl RawConfig {
} }
}; };
if let Some(ip) = matches.opt_str("ip") {
raw.ip = ip.parse()?;
};
if let Some(cgstn_ctrl) = matches.opt_str("congestion-controller") { if let Some(cgstn_ctrl) = matches.opt_str("congestion-controller") {
raw.congestion_controller = cgstn_ctrl.parse()?; raw.congestion_controller = cgstn_ctrl.parse()?;
}; };
@ -347,6 +370,10 @@ where
mod default { mod default {
use super::*; use super::*;
pub(super) fn ip() -> IpAddr {
IpAddr::V4(Ipv4Addr::UNSPECIFIED)
}
pub(super) const fn congestion_controller() -> CongestionController { pub(super) const fn congestion_controller() -> CongestionController {
CongestionController::Cubic CongestionController::Cubic
} }
@ -390,6 +417,8 @@ pub enum ConfigError {
MissingOption(&'static str), MissingOption(&'static str),
#[error(transparent)] #[error(transparent)]
ParseInt(#[from] ParseIntError), ParseInt(#[from] ParseIntError),
#[error(transparent)]
ParseAddr(#[from] AddrParseError),
#[error("Invalid congestion controller")] #[error("Invalid congestion controller")]
InvalidCongestionController, InvalidCongestionController,
#[error(transparent)] #[error(transparent)]

View File

@ -34,7 +34,7 @@ async fn main() {
let server = match Server::init( let server = match Server::init(
config.server_config, config.server_config,
config.port, config.listen_addr,
config.token, config.token,
config.authentication_timeout, config.authentication_timeout,
config.max_udp_relay_packet_size, config.max_udp_relay_packet_size,

View File

@ -4,15 +4,15 @@ use quinn::{Endpoint, EndpointConfig, Incoming, ServerConfig};
use socket2::{Domain, Protocol, SockAddr, Socket, Type}; use socket2::{Domain, Protocol, SockAddr, Socket, Type};
use std::{ use std::{
collections::HashSet, collections::HashSet,
io::Error as IoError, io::Result,
net::{Ipv6Addr, SocketAddr, UdpSocket}, net::{SocketAddr, UdpSocket},
sync::Arc, sync::Arc,
time::Duration, time::Duration,
}; };
pub struct Server { pub struct Server {
incoming: Incoming, incoming: Incoming,
port: u16, listen_addr: SocketAddr,
token: Arc<HashSet<[u8; 32]>>, token: Arc<HashSet<[u8; 32]>>,
authentication_timeout: Duration, authentication_timeout: Duration,
max_pkt_size: usize, max_pkt_size: usize,
@ -21,24 +21,26 @@ pub struct Server {
impl Server { impl Server {
pub fn init( pub fn init(
config: ServerConfig, config: ServerConfig,
port: u16, listen_addr: SocketAddr,
token: HashSet<[u8; 32]>, token: HashSet<[u8; 32]>,
auth_timeout: Duration, auth_timeout: Duration,
max_pkt_size: usize, max_pkt_size: usize,
) -> Result<Self, IoError> { ) -> Result<Self> {
let socket = match listen_addr {
SocketAddr::V4(_) => UdpSocket::bind(listen_addr)?,
SocketAddr::V6(_) => {
let socket = Socket::new(Domain::IPV6, Type::DGRAM, Some(Protocol::UDP))?; let socket = Socket::new(Domain::IPV6, Type::DGRAM, Some(Protocol::UDP))?;
socket.set_only_v6(false)?; socket.set_only_v6(false)?;
socket.bind(&SockAddr::from(SocketAddr::from(( socket.bind(&SockAddr::from(listen_addr))?;
Ipv6Addr::UNSPECIFIED, UdpSocket::from(socket)
port, }
))))?; };
let socket = UdpSocket::from(socket);
let (_, incoming) = Endpoint::new(EndpointConfig::default(), Some(config), socket)?; let (_, incoming) = Endpoint::new(EndpointConfig::default(), Some(config), socket)?;
Ok(Self { Ok(Self {
incoming, incoming,
port, listen_addr,
token: Arc::new(token), token: Arc::new(token),
authentication_timeout: auth_timeout, authentication_timeout: auth_timeout,
max_pkt_size, max_pkt_size,
@ -46,7 +48,7 @@ impl Server {
} }
pub async fn run(mut self) { pub async fn run(mut self) {
log::info!("Server started. Listening port: {}", self.port); log::info!("Server started. Listening: {}", self.listen_addr);
while let Some(conn) = self.incoming.next().await { while let Some(conn) = self.incoming.next().await {
let token = self.token.clone(); let token = self.token.clone();