move Logfilter to the Logmessage module, change MessageHandler to a proper trait
This commit is contained in:
@@ -3,8 +3,11 @@
|
||||
//! This module handles admin messages not handled by the gateway by making an HTTP POST request
|
||||
//! with the message as the body, and returning the response body as the reply.
|
||||
|
||||
use async_trait::async_trait;
|
||||
use conf::Conf;
|
||||
use signal_gateway::{AdminMessageResponse, MessageHandler, MessageHandlerResult};
|
||||
use signal_gateway::{
|
||||
AdminMessageResponse, Context, MessageHandler, MessageHandlerResult, VerifiedSignalMessage,
|
||||
};
|
||||
use std::time::Duration;
|
||||
|
||||
/// Configuration for the admin HTTP client
|
||||
@@ -19,46 +22,54 @@ pub struct AdminHttpConfig {
|
||||
}
|
||||
|
||||
impl AdminHttpConfig {
|
||||
/// Create a message handler function from this config.
|
||||
/// Create a message handler from this config.
|
||||
///
|
||||
/// The returned handler makes an HTTP POST request to the configured URL
|
||||
/// with the message as the body, and returns the response body.
|
||||
pub fn into_handler(self) -> MessageHandler {
|
||||
pub fn into_handler(self) -> Box<dyn MessageHandler> {
|
||||
let client = reqwest::Client::builder()
|
||||
.timeout(self.timeout)
|
||||
.build()
|
||||
.expect("Failed to build HTTP client");
|
||||
|
||||
Box::new(move |message: String| {
|
||||
let client = client.clone();
|
||||
let url = self.url.clone();
|
||||
Box::pin(async move { handle_message(&client, &url, message).await })
|
||||
Box::new(AdminHttpHandler {
|
||||
client,
|
||||
url: self.url,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle a message by POSTing it to the configured HTTP server
|
||||
async fn handle_message(
|
||||
client: &reqwest::Client,
|
||||
url: &str,
|
||||
message: String,
|
||||
) -> MessageHandlerResult {
|
||||
let response = client
|
||||
.post(url)
|
||||
.body(message)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|err| (502u16, format!("HTTP request failed: {err}").into()))?;
|
||||
|
||||
let status = response.status();
|
||||
let body = response
|
||||
.text()
|
||||
.await
|
||||
.map_err(|err| (502u16, format!("Failed to read response body: {err}").into()))?;
|
||||
|
||||
if !status.is_success() {
|
||||
return Err((status.as_u16(), body.into()));
|
||||
}
|
||||
|
||||
Ok(AdminMessageResponse::new(body))
|
||||
/// Message handler that forwards messages to an HTTP server.
|
||||
struct AdminHttpHandler {
|
||||
client: reqwest::Client,
|
||||
url: String,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl MessageHandler for AdminHttpHandler {
|
||||
async fn handle_verified_signal_message(
|
||||
&self,
|
||||
msg: VerifiedSignalMessage,
|
||||
_context: &dyn Context,
|
||||
) -> MessageHandlerResult {
|
||||
let response = self
|
||||
.client
|
||||
.post(&self.url)
|
||||
.body(msg.message)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|err| (502u16, format!("HTTP request failed: {err}").into()))?;
|
||||
|
||||
let status = response.status();
|
||||
let body = response
|
||||
.text()
|
||||
.await
|
||||
.map_err(|err| (502u16, format!("Failed to read response body: {err}").into()))?;
|
||||
|
||||
if !status.is_success() {
|
||||
return Err((status.as_u16(), body.into()));
|
||||
}
|
||||
|
||||
Ok(AdminMessageResponse::new(body))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,11 @@
|
||||
//! 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 async_trait::async_trait;
|
||||
use conf::Conf;
|
||||
use signal_gateway::{AdminMessageResponse, MessageHandler, MessageHandlerResult};
|
||||
use signal_gateway::{
|
||||
AdminMessageResponse, Context, MessageHandler, MessageHandlerResult, VerifiedSignalMessage,
|
||||
};
|
||||
use std::time::Duration;
|
||||
use tokio::{
|
||||
io::{AsyncBufReadExt, AsyncWriteExt, BufReader},
|
||||
@@ -24,46 +27,55 @@ pub struct AdminNetcatConfig {
|
||||
}
|
||||
|
||||
impl AdminNetcatConfig {
|
||||
/// Create a message handler function from this config.
|
||||
/// Create a message handler 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) -> MessageHandler {
|
||||
Box::new(move |message: String| {
|
||||
let config = self.clone();
|
||||
Box::pin(async move { handle_message(&config, message).await })
|
||||
})
|
||||
pub fn into_handler(self) -> Box<dyn MessageHandler> {
|
||||
Box::new(AdminNetcatHandler { config: self })
|
||||
}
|
||||
}
|
||||
|
||||
/// 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(AdminMessageResponse::new(text))
|
||||
/// Message handler that forwards messages to a TCP server.
|
||||
struct AdminNetcatHandler {
|
||||
config: AdminNetcatConfig,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl MessageHandler for AdminNetcatHandler {
|
||||
async fn handle_verified_signal_message(
|
||||
&self,
|
||||
msg: VerifiedSignalMessage,
|
||||
_context: &dyn Context,
|
||||
) -> MessageHandlerResult {
|
||||
// Connect to server
|
||||
let mut stream =
|
||||
timeout(self.config.timeout, TcpStream::connect(&self.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!("{}\r\n", msg.message);
|
||||
timeout(self.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(self.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(AdminMessageResponse::new(text))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ use conf::{Conf, Subcommands};
|
||||
use hyper::service::service_fn;
|
||||
use hyper_util::rt::TokioIo;
|
||||
use hyper_util::server::conn::auto;
|
||||
use signal_gateway::{Gateway, GatewayConfig, MessageHandler};
|
||||
use signal_gateway::{Gateway, GatewayConfig};
|
||||
use std::{net::SocketAddr, sync::Arc, time::Duration};
|
||||
use tokio::net::TcpListener;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
@@ -34,7 +34,7 @@ enum AdminHandlerCommand {
|
||||
}
|
||||
|
||||
impl AdminHandlerCommand {
|
||||
fn into_handler(self) -> MessageHandler {
|
||||
fn into_handler(self) -> Box<dyn signal_gateway::MessageHandler> {
|
||||
match self {
|
||||
AdminHandlerCommand::Netcat(config) => config.into_handler(),
|
||||
AdminHandlerCommand::Http(config) => config.into_handler(),
|
||||
|
||||
Reference in New Issue
Block a user