move all "admin_netcat" stuff to a new admin_netcat module in the gateway-bin, not in the gateway lib
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
//! Admin netcat TCP client for forwarding messages to a TCP server
|
||||
//!
|
||||
//! This module handles admin messages not handled by the gateway by opening a TCP connection,
|
||||
//! writing the message terminated with CRLF, and reading the response until CRLF.
|
||||
|
||||
use conf::Conf;
|
||||
use signal_gateway::MessageHandlerResult;
|
||||
use std::time::Duration;
|
||||
use tokio::{
|
||||
io::{AsyncBufReadExt, AsyncWriteExt, BufReader},
|
||||
net::TcpStream,
|
||||
time::timeout,
|
||||
};
|
||||
|
||||
/// Configuration for the admin netcat TCP client
|
||||
#[derive(Clone, Conf, Debug)]
|
||||
pub struct AdminNetcatConfig {
|
||||
/// TCP address to forward admin commands to
|
||||
#[conf(long, env)]
|
||||
pub tcp_addr: String,
|
||||
/// Timeout for connecting, writing, and reading
|
||||
#[conf(long, env, default_value = "5s", value_parser = conf_extra::parse_duration)]
|
||||
pub timeout: Duration,
|
||||
}
|
||||
|
||||
impl AdminNetcatConfig {
|
||||
/// Create a message handler function from this config.
|
||||
///
|
||||
/// The returned handler opens a TCP connection to the configured address,
|
||||
/// writes the message terminated with CRLF, and reads the response until CRLF.
|
||||
pub fn into_handler(
|
||||
self,
|
||||
) -> Box<
|
||||
dyn Fn(
|
||||
String,
|
||||
)
|
||||
-> std::pin::Pin<Box<dyn std::future::Future<Output = MessageHandlerResult> + Send>>
|
||||
+ Send
|
||||
+ Sync,
|
||||
> {
|
||||
Box::new(move |message: String| {
|
||||
let config = self.clone();
|
||||
Box::pin(async move { handle_message(&config, message).await })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle a message by forwarding it to the configured TCP server
|
||||
async fn handle_message(config: &AdminNetcatConfig, message: String) -> MessageHandlerResult {
|
||||
// Connect to server
|
||||
let mut stream = timeout(config.timeout, TcpStream::connect(&config.tcp_addr))
|
||||
.await
|
||||
.map_err(|_| (504u16, "connecting: timeout".into()))?
|
||||
.map_err(|err| (502u16, format!("connecting: {err}").into()))?;
|
||||
|
||||
// Write message with CRLF terminator
|
||||
let message = format!("{message}\r\n");
|
||||
timeout(config.timeout, stream.write_all(message.as_bytes()))
|
||||
.await
|
||||
.map_err(|_| (504u16, "writing: timeout".into()))?
|
||||
.map_err(|err| (502u16, format!("writing: {err}").into()))?;
|
||||
|
||||
// Read response until CR
|
||||
let mut reader = BufReader::new(stream);
|
||||
let mut buf = Vec::new();
|
||||
timeout(config.timeout, reader.read_until(b'\r', &mut buf))
|
||||
.await
|
||||
.map_err(|_| (504u16, "reading: timeout".into()))?
|
||||
.map_err(|err| (502u16, format!("reading: {err}").into()))?;
|
||||
|
||||
// Convert to string and trim the trailing CR
|
||||
let text = std::str::from_utf8(&buf)
|
||||
.map_err(|err| (502u16, format!("utf8: {err}").into()))?
|
||||
.trim_end_matches(['\r', '\n'])
|
||||
.to_owned();
|
||||
|
||||
Ok((text, vec![]))
|
||||
}
|
||||
@@ -9,6 +9,9 @@ use tokio_util::sync::CancellationToken;
|
||||
use tracing::{error, info, warn};
|
||||
use tracing_subscriber::EnvFilter;
|
||||
|
||||
mod admin_netcat;
|
||||
use admin_netcat::AdminNetcatConfig;
|
||||
|
||||
mod syslog;
|
||||
use syslog::SyslogUdpConfig;
|
||||
|
||||
@@ -22,6 +25,8 @@ struct Config {
|
||||
http_listen_addr: SocketAddr,
|
||||
#[conf(flatten, prefix)]
|
||||
syslog_udp: Option<SyslogUdpConfig>,
|
||||
#[conf(flatten, prefix)]
|
||||
admin_netcat: Option<AdminNetcatConfig>,
|
||||
#[conf(flatten)]
|
||||
gateway: GatewayConfig,
|
||||
}
|
||||
@@ -68,7 +73,8 @@ async fn main() {
|
||||
|
||||
let token = CancellationToken::new();
|
||||
|
||||
let gateway = Arc::new(Gateway::new(config.gateway, token.clone()).await);
|
||||
let message_handler = config.admin_netcat.map(|c| c.into_handler());
|
||||
let gateway = Arc::new(Gateway::new(config.gateway, token.clone(), message_handler).await);
|
||||
|
||||
let listener = TcpListener::bind(config.http_listen_addr).await.unwrap();
|
||||
info!("Listening for http on {}", config.http_listen_addr);
|
||||
|
||||
Reference in New Issue
Block a user