aboutsummaryrefslogtreecommitdiffstats
path: root/mumd/src
diff options
context:
space:
mode:
Diffstat (limited to 'mumd/src')
-rw-r--r--mumd/src/command.rs23
-rw-r--r--mumd/src/network/tcp.rs33
-rw-r--r--mumd/src/state.rs45
3 files changed, 65 insertions, 36 deletions
diff --git a/mumd/src/command.rs b/mumd/src/command.rs
index 410751a..73ab3bd 100644
--- a/mumd/src/command.rs
+++ b/mumd/src/command.rs
@@ -32,16 +32,19 @@ pub async fn handle(
&mut connection_info_sender,
);
match event {
- ExecutionContext::TcpEventCallback(event, generator) => {
- tcp_event_queue.register_callback(
- event,
- Box::new(move |e| {
- let response = generator(e);
- for response in response {
- response_sender.send(response).unwrap();
- }
- }),
- );
+ ExecutionContext::TcpEventCallback(callbacks) => {
+ for (event, generator) in callbacks {
+ let response_sender = response_sender.clone();
+ tcp_event_queue.register_callback(
+ event,
+ Box::new(move |e| {
+ let response = generator(e);
+ for response in response {
+ response_sender.send(response).unwrap();
+ }
+ }),
+ );
+ }
}
ExecutionContext::TcpEventSubscriber(event, mut handler) => tcp_event_queue
.register_subscriber(
diff --git a/mumd/src/network/tcp.rs b/mumd/src/network/tcp.rs
index 5cc2bf7..1c7123f 100644
--- a/mumd/src/network/tcp.rs
+++ b/mumd/src/network/tcp.rs
@@ -35,17 +35,23 @@ type TcpReceiver =
pub(crate) type TcpEventCallback = Box<dyn FnOnce(TcpEventData)>;
pub(crate) type TcpEventSubscriber = Box<dyn FnMut(TcpEventData) -> bool>; //the bool indicates if it should be kept or not
-#[derive(Debug, Clone, Hash, Eq, PartialEq)]
+#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
+pub enum DisconnectedReason {
+ InvalidTls,
+ Other,
+}
+
+#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
pub enum TcpEvent {
Connected, //fires when the client has connected to a server
- Disconnected, //fires when the client has disconnected from a server
+ Disconnected(DisconnectedReason), //fires when the client has disconnected from a server
TextMessage, //fires when a text message comes in
}
#[derive(Clone)]
pub enum TcpEventData<'a> {
Connected(Result<&'a msgs::ServerSync, mumlib::Error>),
- Disconnected,
+ Disconnected(DisconnectedReason),
TextMessage(&'a msgs::TextMessage),
}
@@ -53,7 +59,7 @@ impl<'a> From<&TcpEventData<'a>> for TcpEvent {
fn from(t: &TcpEventData) -> Self {
match t {
TcpEventData::Connected(_) => TcpEvent::Connected,
- TcpEventData::Disconnected => TcpEvent::Disconnected,
+ TcpEventData::Disconnected(reason) => TcpEvent::Disconnected(*reason),
TcpEventData::TextMessage(_) => TcpEvent::TextMessage,
}
}
@@ -141,12 +147,25 @@ pub async fn handle(
}
return Err(TcpError::NoConnectionInfoReceived);
};
- let (mut sink, stream) = connect(
+ let connect_result = connect(
connection_info.socket_addr,
connection_info.hostname,
connection_info.accept_invalid_cert,
)
- .await?;
+ .await;
+
+ let (mut sink, stream) = match connect_result {
+ Ok(ok) => ok,
+ Err(TcpError::TlsConnectError(_)) => {
+ warn!("Invalid TLS");
+ state.read().unwrap().broadcast_phase(StatePhase::Disconnected);
+ event_queue.resolve(TcpEventData::Disconnected(DisconnectedReason::InvalidTls));
+ continue;
+ }
+ Err(e) => {
+ return Err(e);
+ }
+ };
// Handshake (omitting `Version` message for brevity)
let (username, password) = {
@@ -193,7 +212,7 @@ pub async fn handle(
.await
.unwrap_or(Ok(()))?;
- event_queue.resolve(TcpEventData::Disconnected);
+ event_queue.resolve(TcpEventData::Disconnected(DisconnectedReason::Other));
debug!("Fully disconnected TCP stream, waiting for new connection info");
}
diff --git a/mumd/src/state.rs b/mumd/src/state.rs
index 84583e0..e0e3ccd 100644
--- a/mumd/src/state.rs
+++ b/mumd/src/state.rs
@@ -2,7 +2,7 @@ pub mod channel;
pub mod server;
pub mod user;
-use crate::audio::{AudioInput, AudioOutput, NotificationEvents};
+use crate::{audio::{AudioInput, AudioOutput, NotificationEvents}, network::tcp::DisconnectedReason};
use crate::error::StateError;
use crate::network::tcp::{TcpEvent, TcpEventData};
use crate::network::{ConnectionInfo, VoiceStreamType};
@@ -26,8 +26,10 @@ use std::{
use tokio::sync::{mpsc, watch};
macro_rules! at {
- ($event:expr, $generator:expr) => {
- ExecutionContext::TcpEventCallback($event, Box::new($generator))
+ ( $( $event:expr => $generator:expr ),+ $(,)? ) => {
+ ExecutionContext::TcpEventCallback(vec![
+ $( ($event, Box::new($generator)), )*
+ ])
};
}
@@ -41,7 +43,7 @@ type Responses = Box<dyn Iterator<Item = mumlib::error::Result<Option<CommandRes
//TODO give me a better name
pub enum ExecutionContext {
- TcpEventCallback(TcpEvent, Box<dyn FnOnce(TcpEventData) -> Responses>),
+ TcpEventCallback(Vec<(TcpEvent, Box<dyn FnOnce(TcpEventData) -> Responses>)>),
TcpEventSubscriber(
TcpEvent,
Box<
@@ -555,22 +557,27 @@ pub fn handle_command(
accept_invalid_cert,
)))
.unwrap();
- at!(TcpEvent::Connected, |res| {
- //runs the closure when the client is connected
- if let TcpEventData::Connected(res) = res {
- Box::new(iter::once(res.map(|msg| {
- Some(CommandResponse::ServerConnect {
- welcome_message: if msg.has_welcome_text() {
- Some(msg.get_welcome_text().to_string())
- } else {
- None
- },
- })
- })))
- } else {
- unreachable!("callback should be provided with a TcpEventData::Connected");
+ at!(
+ TcpEvent::Connected => |res| {
+ //runs the closure when the client is connected
+ if let TcpEventData::Connected(res) = res {
+ Box::new(iter::once(res.map(|msg| {
+ Some(CommandResponse::ServerConnect {
+ welcome_message: if msg.has_welcome_text() {
+ Some(msg.get_welcome_text().to_string())
+ } else {
+ None
+ },
+ })
+ })))
+ } else {
+ unreachable!("callback should be provided with a TcpEventData::Connected");
+ }
+ },
+ TcpEvent::Disconnected(DisconnectedReason::InvalidTls) => |_| {
+ Box::new(iter::once(Ok(Some(CommandResponse::ServerCertReject))))
}
- })
+ )
}
Command::ServerDisconnect => {
if !matches!(*state.phase_receiver().borrow(), StatePhase::Connected(_)) {