|
|
@ -1,38 +1,18 @@ |
|
|
//! This module defines the central message dispatcher to the client process.
|
|
|
|
|
|
|
|
|
|
|
|
use std::fmt::Debug;
|
|
|
|
|
|
|
|
|
//! This module defines the central event dispatcher to the client process.
|
|
|
|
|
|
|
|
|
use log::{error, warn};
|
|
|
use log::{error, warn};
|
|
|
use solstice_proto::server::ServerResponse;
|
|
|
use solstice_proto::server::ServerResponse;
|
|
|
|
|
|
|
|
|
use crate::context::Context;
|
|
|
use crate::context::Context;
|
|
|
use crate::control::Request as ControlRequest;
|
|
|
use crate::control::Request as ControlRequest;
|
|
|
|
|
|
use crate::event::{Event, EventHandler};
|
|
|
use crate::handlers::*;
|
|
|
use crate::handlers::*;
|
|
|
use crate::message_handler::MessageHandler;
|
|
|
use crate::message_handler::MessageHandler;
|
|
|
use crate::room::{HandleRoomEvent, RoomEvent, RoomEventHandler};
|
|
|
|
|
|
|
|
|
|
|
|
/// The type of messages dispatched by a dispatcher.
|
|
|
|
|
|
#[derive(Debug, Eq, PartialEq)]
|
|
|
|
|
|
pub enum Message {
|
|
|
|
|
|
ControlRequest(ControlRequest),
|
|
|
|
|
|
ServerResponse(ServerResponse),
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl From<ServerResponse> for Message {
|
|
|
|
|
|
fn from(response: ServerResponse) -> Self {
|
|
|
|
|
|
Self::ServerResponse(response)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl From<ControlRequest> for Message {
|
|
|
|
|
|
fn from(request: ControlRequest) -> Self {
|
|
|
|
|
|
Self::ControlRequest(request)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
use crate::room::{RoomEvent, RoomEventHandler};
|
|
|
|
|
|
|
|
|
/// Subsystem event handlers to which the `Dispatcher` dispatches events.
|
|
|
/// Subsystem event handlers to which the `Dispatcher` dispatches events.
|
|
|
pub trait DispatcherHandlers {
|
|
|
pub trait DispatcherHandlers {
|
|
|
type RoomEventHandler: HandleRoomEvent;
|
|
|
|
|
|
|
|
|
type RoomEventHandler: EventHandler<Event = RoomEvent>;
|
|
|
fn room_event_handler(&mut self) -> &mut Self::RoomEventHandler;
|
|
|
fn room_event_handler(&mut self) -> &mut Self::RoomEventHandler;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -51,14 +31,14 @@ impl DispatcherHandlers for DefaultDispatcherHandlers { |
|
|
|
|
|
|
|
|
/// Parts that make up a `Dispatcher`.
|
|
|
/// Parts that make up a `Dispatcher`.
|
|
|
pub struct DispatcherParts<H> {
|
|
|
pub struct DispatcherParts<H> {
|
|
|
/// The global context against which messages are handled.
|
|
|
|
|
|
|
|
|
/// The global context against which events are handled.
|
|
|
pub context: Context,
|
|
|
pub context: Context,
|
|
|
|
|
|
|
|
|
/// Subsystem event handlers. Injected for testability.
|
|
|
/// Subsystem event handlers. Injected for testability.
|
|
|
pub handlers: H,
|
|
|
pub handlers: H,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
/// The `Dispatcher` is in charge of mapping messages to their handlers.
|
|
|
|
|
|
|
|
|
/// The `Dispatcher` is in charge of mapping events to their handlers.
|
|
|
pub struct Dispatcher<H> {
|
|
|
pub struct Dispatcher<H> {
|
|
|
pub context: Context,
|
|
|
pub context: Context,
|
|
|
pub handlers: H,
|
|
|
pub handlers: H,
|
|
|
@ -81,79 +61,68 @@ impl<H: DispatcherHandlers> Dispatcher<H> { |
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
fn dispatch_internal(&mut self, message: Message) -> anyhow::Result<()> {
|
|
|
|
|
|
match message {
|
|
|
|
|
|
Message::ServerResponse(ServerResponse::PeerAddressResponse(
|
|
|
|
|
|
response,
|
|
|
|
|
|
)) => {
|
|
|
|
|
|
|
|
|
fn dispatch_internal(&mut self, event: Event) -> anyhow::Result<()> {
|
|
|
|
|
|
match event {
|
|
|
|
|
|
Event::ServerResponse(ServerResponse::PeerAddressResponse(response)) => {
|
|
|
PeerAddressResponseHandler::default().run(&mut self.context, &response)
|
|
|
PeerAddressResponseHandler::default().run(&mut self.context, &response)
|
|
|
}
|
|
|
}
|
|
|
Message::ServerResponse(ServerResponse::PrivilegedUsersResponse(
|
|
|
|
|
|
|
|
|
Event::ServerResponse(ServerResponse::PrivilegedUsersResponse(
|
|
|
response,
|
|
|
response,
|
|
|
)) => PrivilegedUsersResponseHandler::default()
|
|
|
)) => PrivilegedUsersResponseHandler::default()
|
|
|
.run(&mut self.context, &response),
|
|
|
.run(&mut self.context, &response),
|
|
|
Message::ServerResponse(ServerResponse::RoomJoinResponse(response)) => {
|
|
|
|
|
|
self
|
|
|
|
|
|
.handlers
|
|
|
|
|
|
.room_event_handler()
|
|
|
|
|
|
.handle(&mut self.context, RoomEvent::JoinResponse(response))
|
|
|
|
|
|
}
|
|
|
|
|
|
Message::ServerResponse(ServerResponse::RoomMessageResponse(
|
|
|
|
|
|
response,
|
|
|
|
|
|
)) => self
|
|
|
|
|
|
|
|
|
Event::ServerResponse(ServerResponse::RoomJoinResponse(response)) => self
|
|
|
.handlers
|
|
|
.handlers
|
|
|
.room_event_handler()
|
|
|
.room_event_handler()
|
|
|
.handle(&mut self.context, RoomEvent::MessageResponse(response)),
|
|
|
|
|
|
Message::ServerResponse(ServerResponse::RoomListResponse(response)) => {
|
|
|
|
|
|
|
|
|
.handle(&mut self.context, RoomEvent::JoinResponse(response)),
|
|
|
|
|
|
Event::ServerResponse(ServerResponse::RoomMessageResponse(response)) => {
|
|
|
self
|
|
|
self
|
|
|
.handlers
|
|
|
.handlers
|
|
|
.room_event_handler()
|
|
|
.room_event_handler()
|
|
|
.handle(&mut self.context, RoomEvent::ListResponse(response))
|
|
|
|
|
|
|
|
|
.handle(&mut self.context, RoomEvent::MessageResponse(response))
|
|
|
}
|
|
|
}
|
|
|
Message::ServerResponse(response) => {
|
|
|
|
|
|
|
|
|
Event::ServerResponse(ServerResponse::RoomListResponse(response)) => self
|
|
|
|
|
|
.handlers
|
|
|
|
|
|
.room_event_handler()
|
|
|
|
|
|
.handle(&mut self.context, RoomEvent::ListResponse(response)),
|
|
|
|
|
|
Event::ServerResponse(response) => {
|
|
|
warn!("Unhandled server response: {:?}", response);
|
|
|
warn!("Unhandled server response: {:?}", response);
|
|
|
Ok(())
|
|
|
Ok(())
|
|
|
}
|
|
|
}
|
|
|
Message::ControlRequest(ControlRequest::LoginStatusRequest) => {
|
|
|
|
|
|
|
|
|
Event::ControlRequest(ControlRequest::LoginStatusRequest) => {
|
|
|
LoginStatusRequestHandler::default().run(&mut self.context, &())
|
|
|
LoginStatusRequestHandler::default().run(&mut self.context, &())
|
|
|
}
|
|
|
}
|
|
|
Message::ControlRequest(ControlRequest::PeerConnectRequest(request)) => {
|
|
|
|
|
|
|
|
|
Event::ControlRequest(ControlRequest::PeerConnectRequest(request)) => {
|
|
|
PeerConnectRequestHandler::default().run(&mut self.context, &request)
|
|
|
PeerConnectRequestHandler::default().run(&mut self.context, &request)
|
|
|
}
|
|
|
}
|
|
|
Message::ControlRequest(ControlRequest::RoomListRequest) => self
|
|
|
|
|
|
|
|
|
Event::ControlRequest(ControlRequest::RoomListRequest) => self
|
|
|
.handlers
|
|
|
.handlers
|
|
|
.room_event_handler()
|
|
|
.room_event_handler()
|
|
|
.handle(&mut self.context, RoomEvent::ListRequest),
|
|
|
.handle(&mut self.context, RoomEvent::ListRequest),
|
|
|
Message::ControlRequest(ControlRequest::RoomMessageRequest(request)) => {
|
|
|
|
|
|
|
|
|
Event::ControlRequest(ControlRequest::RoomMessageRequest(request)) => {
|
|
|
self
|
|
|
self
|
|
|
.handlers
|
|
|
.handlers
|
|
|
.room_event_handler()
|
|
|
.room_event_handler()
|
|
|
.handle(&mut self.context, RoomEvent::MessageRequest(request))
|
|
|
.handle(&mut self.context, RoomEvent::MessageRequest(request))
|
|
|
}
|
|
|
}
|
|
|
Message::ControlRequest(ControlRequest::RoomJoinRequest(room_name)) => {
|
|
|
|
|
|
self
|
|
|
|
|
|
.handlers
|
|
|
|
|
|
.room_event_handler()
|
|
|
|
|
|
.handle(&mut self.context, RoomEvent::JoinRequest(room_name))
|
|
|
|
|
|
}
|
|
|
|
|
|
Message::ControlRequest(ControlRequest::UserListRequest) => {
|
|
|
|
|
|
|
|
|
Event::ControlRequest(ControlRequest::RoomJoinRequest(room_name)) => self
|
|
|
|
|
|
.handlers
|
|
|
|
|
|
.room_event_handler()
|
|
|
|
|
|
.handle(&mut self.context, RoomEvent::JoinRequest(room_name)),
|
|
|
|
|
|
Event::ControlRequest(ControlRequest::UserListRequest) => {
|
|
|
UserListRequestHandler::default().run(&mut self.context, &())
|
|
|
UserListRequestHandler::default().run(&mut self.context, &())
|
|
|
}
|
|
|
}
|
|
|
Message::ControlRequest(request) => {
|
|
|
|
|
|
|
|
|
Event::ControlRequest(request) => {
|
|
|
warn!("Unhandled control request: {:?}", request);
|
|
|
warn!("Unhandled control request: {:?}", request);
|
|
|
Ok(())
|
|
|
Ok(())
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
/// Dispatches the given message to the appropriate subsystem handler.
|
|
|
|
|
|
pub fn dispatch(&mut self, message: Message) {
|
|
|
|
|
|
let debug_message = format!("{:?}", &message);
|
|
|
|
|
|
if let Err(error) = self.dispatch_internal(message) {
|
|
|
|
|
|
error!(
|
|
|
|
|
|
"Error handling message: {:?}\nMessage: {}",
|
|
|
|
|
|
error, debug_message
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
/// Dispatches the given event to the appropriate subsystem handler.
|
|
|
|
|
|
pub fn dispatch(&mut self, event: Event) {
|
|
|
|
|
|
let debug_event = format!("{:?}", &event);
|
|
|
|
|
|
if let Err(error) = self.dispatch_internal(event) {
|
|
|
|
|
|
error!("Error handling event: {:?}\nEvent: {}", error, debug_event);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@ -166,7 +135,7 @@ mod tests { |
|
|
|
|
|
|
|
|
use crate::context::ContextBundle;
|
|
|
use crate::context::ContextBundle;
|
|
|
use crate::control;
|
|
|
use crate::control;
|
|
|
use crate::dispatcher::Message;
|
|
|
|
|
|
|
|
|
use crate::dispatcher::Event;
|
|
|
use crate::room::testing::FakeRoomEventHandler;
|
|
|
use crate::room::testing::FakeRoomEventHandler;
|
|
|
|
|
|
|
|
|
use super::*;
|
|
|
use super::*;
|
|
|
@ -190,9 +159,9 @@ mod tests { |
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
/// Dispatches `message` to fake handlers using a new `Dispatcher` and
|
|
|
|
|
|
|
|
|
/// Dispatches `event` to fake handlers using a new `Dispatcher` and
|
|
|
/// `Context`, then returns the handlers for inspection.
|
|
|
/// `Context`, then returns the handlers for inspection.
|
|
|
fn dispatch(message: Message) -> FakeDispatcherHandlers {
|
|
|
|
|
|
|
|
|
fn dispatch(event: Event) -> FakeDispatcherHandlers {
|
|
|
let bundle = ContextBundle::default();
|
|
|
let bundle = ContextBundle::default();
|
|
|
|
|
|
|
|
|
let mut dispatcher = Dispatcher::from_parts(DispatcherParts {
|
|
|
let mut dispatcher = Dispatcher::from_parts(DispatcherParts {
|
|
|
@ -200,7 +169,7 @@ mod tests { |
|
|
handlers: FakeDispatcherHandlers::default(),
|
|
|
handlers: FakeDispatcherHandlers::default(),
|
|
|
});
|
|
|
});
|
|
|
|
|
|
|
|
|
dispatcher.dispatch(message);
|
|
|
|
|
|
|
|
|
dispatcher.dispatch(event);
|
|
|
|
|
|
|
|
|
dispatcher.into_parts().handlers
|
|
|
dispatcher.into_parts().handlers
|
|
|
}
|
|
|
}
|
|
|
@ -211,7 +180,7 @@ mod tests { |
|
|
reason: "bleep bloop".to_string(),
|
|
|
reason: "bleep bloop".to_string(),
|
|
|
};
|
|
|
};
|
|
|
|
|
|
|
|
|
let handlers = dispatch(Message::ServerResponse(response.into()));
|
|
|
|
|
|
|
|
|
let handlers = dispatch(Event::ServerResponse(response.into()));
|
|
|
|
|
|
|
|
|
assert!(!handlers.has_events());
|
|
|
assert!(!handlers.has_events());
|
|
|
}
|
|
|
}
|
|
|
@ -220,7 +189,7 @@ mod tests { |
|
|
fn dispatches_login_status_request() {
|
|
|
fn dispatches_login_status_request() {
|
|
|
let request = control::Request::LoginStatusRequest;
|
|
|
let request = control::Request::LoginStatusRequest;
|
|
|
|
|
|
|
|
|
let _handlers = dispatch(Message::ControlRequest(request));
|
|
|
|
|
|
|
|
|
let _handlers = dispatch(Event::ControlRequest(request));
|
|
|
|
|
|
|
|
|
// TODO: Check that event is dispatched to a new login event handler.
|
|
|
// TODO: Check that event is dispatched to a new login event handler.
|
|
|
}
|
|
|
}
|
|
|
@ -233,7 +202,7 @@ mod tests { |
|
|
port: 1234,
|
|
|
port: 1234,
|
|
|
};
|
|
|
};
|
|
|
|
|
|
|
|
|
let _handlers = dispatch(Message::ServerResponse(response.into()));
|
|
|
|
|
|
|
|
|
let _handlers = dispatch(Event::ServerResponse(response.into()));
|
|
|
|
|
|
|
|
|
// TODO: Check that event is dispatched to a new peer event handler.
|
|
|
// TODO: Check that event is dispatched to a new peer event handler.
|
|
|
}
|
|
|
}
|
|
|
@ -242,7 +211,7 @@ mod tests { |
|
|
fn dispatches_peer_connect_request() {
|
|
|
fn dispatches_peer_connect_request() {
|
|
|
let request = control::Request::PeerConnectRequest("shruti".to_string());
|
|
|
let request = control::Request::PeerConnectRequest("shruti".to_string());
|
|
|
|
|
|
|
|
|
let _handlers = dispatch(Message::ControlRequest(request));
|
|
|
|
|
|
|
|
|
let _handlers = dispatch(Event::ControlRequest(request));
|
|
|
|
|
|
|
|
|
// TODO: Check that event is dispatched to a new peer event handler.
|
|
|
// TODO: Check that event is dispatched to a new peer event handler.
|
|
|
}
|
|
|
}
|
|
|
@ -253,7 +222,7 @@ mod tests { |
|
|
users: vec!["foo".to_string(), "bar".to_string(), "baz".to_string()],
|
|
|
users: vec!["foo".to_string(), "bar".to_string(), "baz".to_string()],
|
|
|
};
|
|
|
};
|
|
|
|
|
|
|
|
|
let _handlers = dispatch(Message::ServerResponse(response.into()));
|
|
|
|
|
|
|
|
|
let _handlers = dispatch(Event::ServerResponse(response.into()));
|
|
|
|
|
|
|
|
|
// TODO: Check that event is dispatched to a new user event handler.
|
|
|
// TODO: Check that event is dispatched to a new user event handler.
|
|
|
}
|
|
|
}
|
|
|
@ -262,7 +231,7 @@ mod tests { |
|
|
fn dispatches_room_join_request() {
|
|
|
fn dispatches_room_join_request() {
|
|
|
let request = control::Request::RoomJoinRequest("bleep".to_string());
|
|
|
let request = control::Request::RoomJoinRequest("bleep".to_string());
|
|
|
|
|
|
|
|
|
let handlers = dispatch(Message::ControlRequest(request.into()));
|
|
|
|
|
|
|
|
|
let handlers = dispatch(Event::ControlRequest(request.into()));
|
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
assert_eq!(
|
|
|
handlers.room_event_handler.events,
|
|
|
handlers.room_event_handler.events,
|
|
|
@ -279,7 +248,7 @@ mod tests { |
|
|
users: Vec::new(),
|
|
|
users: Vec::new(),
|
|
|
};
|
|
|
};
|
|
|
|
|
|
|
|
|
let handlers = dispatch(Message::ServerResponse(response.clone().into()));
|
|
|
|
|
|
|
|
|
let handlers = dispatch(Event::ServerResponse(response.clone().into()));
|
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
assert_eq!(
|
|
|
handlers.room_event_handler.events,
|
|
|
handlers.room_event_handler.events,
|
|
|
@ -306,7 +275,7 @@ mod tests { |
|
|
operated_private_room_names: Vec::new(),
|
|
|
operated_private_room_names: Vec::new(),
|
|
|
};
|
|
|
};
|
|
|
|
|
|
|
|
|
let handlers = dispatch(Message::ServerResponse(response.clone().into()));
|
|
|
|
|
|
|
|
|
let handlers = dispatch(Event::ServerResponse(response.clone().into()));
|
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
assert_eq!(
|
|
|
handlers.room_event_handler.events,
|
|
|
handlers.room_event_handler.events,
|
|
|
@ -321,7 +290,7 @@ mod tests { |
|
|
message: "yo!".to_string(),
|
|
|
message: "yo!".to_string(),
|
|
|
};
|
|
|
};
|
|
|
|
|
|
|
|
|
let handlers = dispatch(Message::ControlRequest(request.clone().into()));
|
|
|
|
|
|
|
|
|
let handlers = dispatch(Event::ControlRequest(request.clone().into()));
|
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
assert_eq!(
|
|
|
handlers.room_event_handler.events,
|
|
|
handlers.room_event_handler.events,
|
|
|
@ -337,7 +306,7 @@ mod tests { |
|
|
message: "yo!".to_string(),
|
|
|
message: "yo!".to_string(),
|
|
|
};
|
|
|
};
|
|
|
|
|
|
|
|
|
let handlers = dispatch(Message::ServerResponse(response.clone().into()));
|
|
|
|
|
|
|
|
|
let handlers = dispatch(Event::ServerResponse(response.clone().into()));
|
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
assert_eq!(
|
|
|
handlers.room_event_handler.events,
|
|
|
handlers.room_event_handler.events,
|
|
|
|