diff options
author | Stefan Midjich <swehack@gmail.com> | 2021-05-25 22:39:00 +0200 |
---|---|---|
committer | Stefan Midjich <swehack@gmail.com> | 2021-05-25 22:39:00 +0200 |
commit | 7fe5b5278cc715cdc0a7a78dda29c9c2b6791b2c (patch) | |
tree | 81542d52e1cc39daf3b523a26868dddf3412fdbd | |
parent | 7bc4ea5d34fac53d33ff2ed53bb7a70a2c1aca93 (diff) | |
download | roughenough-7fe5b5278cc715cdc0a7a78dda29c9c2b6791b2c.zip |
WIP: tcp listener setup.
-rw-r--r-- | src/bin/roughenough-server.rs | 5 | ||||
-rw-r--r-- | src/config/environment.rs | 14 | ||||
-rw-r--r-- | src/config/file.rs | 10 | ||||
-rw-r--r-- | src/config/memory.rs | 6 | ||||
-rw-r--r-- | src/config/mod.rs | 3 | ||||
-rw-r--r-- | src/server.rs | 23 |
6 files changed, 60 insertions, 1 deletions
diff --git a/src/bin/roughenough-server.rs b/src/bin/roughenough-server.rs index bb20b21..7d7ddc1 100644 --- a/src/bin/roughenough-server.rs +++ b/src/bin/roughenough-server.rs @@ -65,7 +65,10 @@ fn display_config(server: &Server, cfg: &dyn ServerConfig) { info!("Online public key : {}", server.get_online_key()); info!("Max response batch size : {}", cfg.batch_size()); info!("Status updates every : {} seconds", cfg.status_interval().as_secs()); - info!("Server listening on : {}:{}", cfg.interface(), cfg.port()); + info!("Server listening on : udp:{}:{}", cfg.interface(), cfg.port()); + if cfg.tcp_listener() { + info!("Server listening on : tcp:{}:{}", cfg.interface(), cfg.port()); + } if let Some(hc_port) = cfg.health_check_port() { info!("TCP health check : {}:{}", cfg.interface(), hc_port); } else { diff --git a/src/config/environment.rs b/src/config/environment.rs index 434ba04..60af07e 100644 --- a/src/config/environment.rs +++ b/src/config/environment.rs @@ -32,6 +32,7 @@ use crate::Error; /// batch_size | `ROUGHENOUGH_BATCH_SIZE` /// status_interval | `ROUGHENOUGH_STATUS_INTERVAL` /// kms_protection | `ROUGHENOUGH_KMS_PROTECTION` +/// tcp_listener | `ROUGHENOUGH_TCP_LISTENER` /// health_check_port | `ROUGHENOUGH_HEALTH_CHECK_PORT` /// client_stats | `ROUGHENOUGH_CLIENT_STATS` /// fault_percentage | `ROUGHENOUGH_FAULT_PERCENTAGE` @@ -43,6 +44,7 @@ pub struct EnvironmentConfig { batch_size: u8, status_interval: Duration, kms_protection: KmsProtection, + tcp_listener: bool, health_check_port: Option<u16>, client_stats: bool, fault_percentage: u8, @@ -54,6 +56,7 @@ const ROUGHENOUGH_SEED: &str = "ROUGHENOUGH_SEED"; const ROUGHENOUGH_BATCH_SIZE: &str = "ROUGHENOUGH_BATCH_SIZE"; const ROUGHENOUGH_STATUS_INTERVAL: &str = "ROUGHENOUGH_STATUS_INTERVAL"; const ROUGHENOUGH_KMS_PROTECTION: &str = "ROUGHENOUGH_KMS_PROTECTION"; +const ROUGHENOUGH_TCP_LISTENER: &str = "ROUGHENOUGH_TCP_LISTENER"; const ROUGHENOUGH_HEALTH_CHECK_PORT: &str = "ROUGHENOUGH_HEALTH_CHECK_PORT"; const ROUGHENOUGH_CLIENT_STATS: &str = "ROUGHENOUGH_CLIENT_STATS"; const ROUGHENOUGH_FAULT_PERCENTAGE: &str = "ROUGHENOUGH_FAULT_PERCENTAGE"; @@ -67,6 +70,7 @@ impl EnvironmentConfig { batch_size: DEFAULT_BATCH_SIZE, status_interval: DEFAULT_STATUS_INTERVAL, kms_protection: KmsProtection::Plaintext, + tcp_listener: false, health_check_port: None, client_stats: false, fault_percentage: 0, @@ -107,6 +111,12 @@ impl EnvironmentConfig { .unwrap_or_else(|_| panic!("invalid kms_protection value: {}", kms_protection)); } + if let Ok(mut tcp_listener) = env::var(ROUGHENOUGH_TCP_LISTENER) { + tcp_listener.make_ascii_lowercase(); + + cfg.tcp_listener = tcp_listener == "yes" || tcp_listener == "on" || tcp_listener == "true"; + }; + if let Ok(health_check_port) = env::var(ROUGHENOUGH_HEALTH_CHECK_PORT) { let val: u16 = health_check_port .parse() @@ -156,6 +166,10 @@ impl ServerConfig for EnvironmentConfig { &self.kms_protection } + fn tcp_listener(&self) -> bool { + self.tcp_listener + } + fn health_check_port(&self) -> Option<u16> { self.health_check_port } diff --git a/src/config/file.rs b/src/config/file.rs index f523fed..6a8be32 100644 --- a/src/config/file.rs +++ b/src/config/file.rs @@ -41,6 +41,7 @@ pub struct FileConfig { batch_size: u8, status_interval: Duration, kms_protection: KmsProtection, + tcp_listener: bool, health_check_port: Option<u16>, client_stats: bool, fault_percentage: u8, @@ -72,6 +73,7 @@ impl FileConfig { batch_size: DEFAULT_BATCH_SIZE, status_interval: DEFAULT_STATUS_INTERVAL, kms_protection: KmsProtection::Plaintext, + tcp_listener: false, health_check_port: None, client_stats: false, fault_percentage: 0, @@ -97,6 +99,10 @@ impl FileConfig { }); config.kms_protection = val } + "tcp_listener" => { + let val = value.as_str().unwrap().to_ascii_lowercase(); + config.tcp_listener = val == "yes" || val == "on" || val == "true"; + } "health_check_port" => { let val = value.as_i64().unwrap() as u16; config.health_check_port = Some(val); @@ -147,6 +153,10 @@ impl ServerConfig for FileConfig { &self.kms_protection } + fn tcp_listener(&self) -> bool { + self.tcp_listener + } + fn health_check_port(&self) -> Option<u16> { self.health_check_port } diff --git a/src/config/memory.rs b/src/config/memory.rs index 2128bb6..e5dfa78 100644 --- a/src/config/memory.rs +++ b/src/config/memory.rs @@ -29,6 +29,7 @@ pub struct MemoryConfig { pub batch_size: u8, pub status_interval: Duration, pub kms_protection: KmsProtection, + pub tcp_listener: bool, pub health_check_port: Option<u16>, pub client_stats: bool, pub fault_percentage: u8, @@ -44,6 +45,7 @@ impl MemoryConfig { batch_size: DEFAULT_BATCH_SIZE, status_interval: DEFAULT_STATUS_INTERVAL, kms_protection: KmsProtection::Plaintext, + tcp_listener: false, health_check_port: None, client_stats: false, fault_percentage: 0 @@ -76,6 +78,10 @@ impl ServerConfig for MemoryConfig { &self.kms_protection } + fn tcp_listener(&self) -> bool { + self.tcp_listener + } + fn health_check_port(&self) -> Option<u16> { self.health_check_port } diff --git a/src/config/mod.rs b/src/config/mod.rs index c7c8ae6..185d764 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -92,6 +92,9 @@ pub trait ServerConfig { /// Defaults to "`plaintext`" (no encryption, seed is in the clear). fn kms_protection(&self) -> &KmsProtection; + /// [Optional] If present the server will also serve clients over TCP on the same port. + fn tcp_listener(&self) -> bool; + /// [Optional] If present, the TCP port to respond to Google-style HTTP "legacy health check". /// This is a *very* simplistic check, it emits a fixed HTTP response to all TCP connections. /// https://cloud.google.com/load-balancing/docs/health-checks#legacy-health-checks diff --git a/src/server.rs b/src/server.rs index 3a216d1..ff57971 100644 --- a/src/server.rs +++ b/src/server.rs @@ -43,6 +43,7 @@ use crate::{Error, RtMessage, Tag, MIN_REQUEST_LENGTH}; const EVT_MESSAGE: Token = Token(0); const EVT_STATUS_UPDATE: Token = Token(1); const EVT_HEALTH_CHECK: Token = Token(2); +const EVT_TCP_MESSAGE: Token = Token(3); // Canned response to health check request const HTTP_RESPONSE: &str = "HTTP/1.1 200 OK\nContent-Length: 0\nConnection: close\n\n"; @@ -63,6 +64,7 @@ pub struct Server { cert_bytes: Vec<u8>, socket: UdpSocket, + tcp_listener: Option<TcpListener>, health_listener: Option<TcpListener>, poll_duration: Option<Duration>, grease: Grease, @@ -118,6 +120,22 @@ impl Server { poll.register(&timer, EVT_STATUS_UPDATE, Ready::readable(), PollOpt::edge()) .unwrap(); + let tcp_listener = if config.tcp_listener() { + let tcp_sock_addr: SocketAddr = format!("{}:{}", config.interface(), config.port()) + .parse() + .unwrap(); + + let listener = TcpListener::bind(&tcp_sock_addr) + .expect("Failed to bind TCP listener"); + + poll.register(&listener, EVT_TCP_MESSAGE, Ready::readable(), PollOpt::edge()) + .unwrap(); + + Some(listener) + } else { + None + }; + let health_listener = if let Some(hc_port) = config.health_check_port() { let hc_sock_addr: SocketAddr = format!("{}:{}", config.interface(), hc_port) .parse() @@ -150,6 +168,7 @@ impl Server { cert_bytes, socket, + tcp_listener, health_listener, poll_duration, @@ -218,6 +237,10 @@ impl Server { break; } }, + EVT_TCP_MESSAGE => loop { + info!("EVT_TCP_MESSAGE received"); + break; + }, EVT_HEALTH_CHECK => self.handle_health_check(), EVT_STATUS_UPDATE => self.handle_status_update(), _ => unreachable!(), |