From 82f433054536e4f423263e16847c524ee2069066 Mon Sep 17 00:00:00 2001 From: Titouan Rigoudy Date: Tue, 16 Nov 2021 17:41:56 +0100 Subject: [PATCH] Start handling peer connect request. --- client/src/context.rs | 2 + client/src/control/request.rs | 4 +- client/src/dispatcher.rs | 13 +-- client/src/handlers/mod.rs | 2 + .../handlers/peer_connect_request_handler.rs | 81 +++++++++++++++++++ client/src/main.rs | 1 + client/src/peer.rs | 70 ++++++++++++++++ proto/src/peer/worker.rs | 31 ------- 8 files changed, 166 insertions(+), 38 deletions(-) create mode 100644 client/src/handlers/peer_connect_request_handler.rs create mode 100644 client/src/peer.rs diff --git a/client/src/context.rs b/client/src/context.rs index 508e926..6d5c657 100644 --- a/client/src/context.rs +++ b/client/src/context.rs @@ -8,6 +8,7 @@ use tokio::sync::mpsc::{channel, Receiver, Sender}; use crate::clock::SimulatedSystemClock; use crate::clock::SystemClock; use crate::control::Response as ControlResponse; +use crate::peer::PeerMap; use crate::room::RoomMap; use crate::user::UserMap; use crate::Config; @@ -17,6 +18,7 @@ use crate::Config; pub struct State { pub rooms: RoomMap, pub users: UserMap, + pub peers: PeerMap, } /// Holds process-wide context for message handlers to execute against. diff --git a/client/src/control/request.rs b/client/src/control/request.rs index c8b1ded..f0799b8 100644 --- a/client/src/control/request.rs +++ b/client/src/control/request.rs @@ -4,9 +4,11 @@ use serde::{Deserialize, Serialize}; /// controller client to the client. #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum Request { + /// The controller wants to connect to a peer. Contains the peer name. + PeerConnectRequest(String), /// The controller wants to join a room. Contains the room name. RoomJoinRequest(String), - /// The controller wants to leave a rom. Contains the room name. + /// The controller wants to leave a room. Contains the room name. RoomLeaveRequest(String), /// The controller wants to know what the login status is. LoginStatusRequest, diff --git a/client/src/dispatcher.rs b/client/src/dispatcher.rs index c804e42..9c1ebdb 100644 --- a/client/src/dispatcher.rs +++ b/client/src/dispatcher.rs @@ -7,12 +7,7 @@ use solstice_proto::server::ServerResponse; use crate::context::Context; use crate::control::Request as ControlRequest; -use crate::handlers::{ - LoginStatusRequestHandler, PrivilegedUsersResponseHandler, - RoomJoinRequestHandler, RoomJoinResponseHandler, RoomListRequestHandler, - RoomListResponseHandler, RoomMessageRequestHandler, - RoomMessageResponseHandler, UserListRequestHandler, -}; +use crate::handlers::*; use crate::message_handler::MessageHandler; /// The type of messages dispatched by a dispatcher. @@ -110,6 +105,12 @@ impl Dispatcher { warn!("Unhandled server response: {:?}", response); None } + Message::ControlRequest(ControlRequest::PeerConnectRequest(request)) => { + Some(Box::new(DispatchedMessage { + message: request, + handler: PeerConnectRequestHandler::default(), + })) + } Message::ControlRequest(ControlRequest::RoomListRequest) => { Some(Box::new(DispatchedMessage { message: (), diff --git a/client/src/handlers/mod.rs b/client/src/handlers/mod.rs index ccf2873..aa6dbc6 100644 --- a/client/src/handlers/mod.rs +++ b/client/src/handlers/mod.rs @@ -1,4 +1,5 @@ mod login_status_request_handler; +mod peer_connect_request_handler; mod privileged_users_response_handler; mod room_join_request_handler; mod room_join_response_handler; @@ -9,6 +10,7 @@ mod room_message_response_handler; mod user_list_request_handler; pub use login_status_request_handler::LoginStatusRequestHandler; +pub use peer_connect_request_handler::PeerConnectRequestHandler; pub use privileged_users_response_handler::PrivilegedUsersResponseHandler; pub use room_join_request_handler::RoomJoinRequestHandler; pub use room_join_response_handler::RoomJoinResponseHandler; diff --git a/client/src/handlers/peer_connect_request_handler.rs b/client/src/handlers/peer_connect_request_handler.rs new file mode 100644 index 0000000..1175dbd --- /dev/null +++ b/client/src/handlers/peer_connect_request_handler.rs @@ -0,0 +1,81 @@ +use anyhow::{bail, Context as AnyhowContext}; +use solstice_proto::server::{PeerAddressRequest, ServerRequest}; + +use crate::context::Context; +use crate::message_handler::MessageHandler; +use crate::peer::PeerState; + +#[derive(Debug, Default)] +pub struct PeerConnectRequestHandler; + +impl MessageHandler for PeerConnectRequestHandler { + type Message = String; + + fn run( + self, + context: &mut Context, + user_name: &String, + ) -> anyhow::Result<()> { + let peer = match context.state.peers.peers.get_mut(user_name) { + Some(peer) => peer, + None => { + // Address is not even known, we need to ask for it first. + context + .state + .peers + .peers + .insert(user_name.clone(), PeerState::FetchingAddress); + + let request = ServerRequest::PeerAddressRequest(PeerAddressRequest { + user_name: user_name.clone(), + }); + context + .server_request_tx + .blocking_send(request) + .context("sending peer address request")?; + + return Ok(()); + } + }; + + bail!("Unimplemented. Peer = {:?}", peer); + } + + fn name() -> String { + "PeerConnectRequestHandler".to_string() + } +} + +#[cfg(test)] +mod tests { + use solstice_proto::server::{PeerAddressRequest, ServerRequest}; + + use crate::context::ContextBundle; + use crate::message_handler::MessageHandler; + use crate::peer::PeerState; + + use super::PeerConnectRequestHandler; + + #[test] + fn run_unknown_peer() { + let mut bundle = ContextBundle::default(); + + PeerConnectRequestHandler::default() + .run(&mut bundle.context, &"aisha".to_string()) + .unwrap(); + + match bundle.context.state.peers.peers.get("aisha") { + Some(PeerState::FetchingAddress) => (), + None => panic!("Missing state"), + } + + drop(bundle.context.server_request_tx); + match bundle.server_request_rx.blocking_recv() { + Some(ServerRequest::PeerAddressRequest(PeerAddressRequest { + user_name, + })) => assert_eq!(user_name, "aisha"), + Some(request) => panic!("Unexpected server request: {:?}", request), + None => panic!("Expected server request, got none"), + } + } +} diff --git a/client/src/main.rs b/client/src/main.rs index 2b9d7dd..3aae563 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -16,6 +16,7 @@ mod dispatcher; mod handlers; mod login; mod message_handler; +mod peer; mod room; #[cfg(test)] mod testing; diff --git a/client/src/peer.rs b/client/src/peer.rs new file mode 100644 index 0000000..bf88e54 --- /dev/null +++ b/client/src/peer.rs @@ -0,0 +1,70 @@ +//! This module provides abstractions for interacting with a set of peers. + +use std::collections::HashMap; + +// Peer states: +// +// - closed +// - opening +// - open +// - waiting for pierce firewall +// - cannot connect +// +// Transitions: +// +// - closed: +// -> fetching ip: +// request IP from server +// -> open: +// accept connection +// receive peerinit +// - fetching ip: +// -> opening: +// receive IP from server +// request connection +// - opening: +// -> open: +// connect +// send peerinit +// -> waiting for pierce firewall: +// connect failed, or send peerinit failed +// send connecttopeer to server +// - open: +// -> closed: +// connection closed +// - waiting for pierce firewall: +// -> open: +// accept connection +// receive pierce firewall +// -> cannot connect: +// receive cannot connect +// + +/// The current state of a peer connection. +#[derive(Debug)] +pub enum PeerState { + FetchingAddress, + /* + Opening { + address: SocketAddr, + }, + Waiting { + address: SocketAddr, + token: u32, + }, + Failed { + address: SocketAddr, + token: u32, + }, + // TODO: Handle cannot connect logic, add `Failed` state. + Open { + address: SocketAddr, + message_tx: Sender, + } + */ +} + +#[derive(Debug, Default)] +pub struct PeerMap { + pub peers: HashMap, +} diff --git a/proto/src/peer/worker.rs b/proto/src/peer/worker.rs index db54c91..7e19656 100644 --- a/proto/src/peer/worker.rs +++ b/proto/src/peer/worker.rs @@ -9,37 +9,6 @@ use tokio::net::{TcpListener, TcpStream}; use crate::core::{FrameReader, FrameWriter, Worker}; use crate::peer::{InitialMessage, Message}; -// Peer states: -// -// - closed -// - open -// - waiting for pierce firewall -// - cannot connect -// -// Transitions: -// -// - closed: -// -> open: -// connect -// send peerinit -// -> waiting for pierce firewall: -// connect failed, or send peerinit failed -// send connecttopeer to server -// -> open: -// accept connection -// receive peerinit -// - open: -// -> closed: -// connection closed -// - waiting for pierce firewall: -// -> open: -// accept connection -// receive pierce firewall -// ???send peer init??? -// -> cannot connect: -// receive cannot connect -// - /// A peer to connect to. #[derive(Debug)] pub struct PeerConnection {