implemented GetInfo for actix server
This commit is contained in:
parent
7871e8d6a6
commit
63181ec9b5
|
|
@ -1,63 +1,63 @@
|
||||||
use futures::lock::Mutex;
|
// use futures::lock::Mutex;
|
||||||
use serverlib::plugin::WeakPluginInterface;
|
// use serverlib::plugin::WeakPluginInterface;
|
||||||
use std::sync::Mutex as StdMutex;
|
// use std::sync::Mutex as StdMutex;
|
||||||
use std::thread::sleep;
|
// use std::thread::sleep;
|
||||||
use std::time::Duration;
|
// use std::time::Duration;
|
||||||
|
|
||||||
use serverlib::plugin::IPlugin;
|
// use serverlib::plugin::IPlugin;
|
||||||
use serverlib::plugin::PluginDetails;
|
// use serverlib::plugin::PluginDetails;
|
||||||
|
|
||||||
#[derive(Debug)]
|
// #[derive(Debug)]
|
||||||
pub struct ExamplePlugin {
|
// pub struct ExamplePlugin {
|
||||||
number: Mutex<u8>,
|
// number: Mutex<u8>,
|
||||||
interface: StdMutex<Option<WeakPluginInterface>>,
|
// interface: StdMutex<Option<WeakPluginInterface>>,
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl Default for ExamplePlugin {
|
// impl Default for ExamplePlugin {
|
||||||
fn default() -> Self {
|
// fn default() -> Self {
|
||||||
ExamplePlugin {
|
// ExamplePlugin {
|
||||||
number: Mutex::new(0),
|
// number: Mutex::new(0),
|
||||||
interface: StdMutex::default(),
|
// interface: StdMutex::default(),
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
// #[async_trait::async_trait]
|
||||||
impl IPlugin for ExamplePlugin {
|
// impl IPlugin for ExamplePlugin {
|
||||||
fn details(&self) -> PluginDetails {
|
// fn details(&self) -> PluginDetails {
|
||||||
PluginDetails {
|
// PluginDetails {
|
||||||
display_name: "ExamplePlugin",
|
// display_name: "ExamplePlugin",
|
||||||
id: "io.github.michael-bailey.ExamplePlugin",
|
// id: "io.github.michael-bailey.ExamplePlugin",
|
||||||
version: "0.0.1",
|
// version: "0.0.1",
|
||||||
contacts: vec!["bailey-michael1@outlook.com"],
|
// contacts: vec!["bailey-michael1@outlook.com"],
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn set_interface(&self, interface: WeakPluginInterface) {
|
// fn set_interface(&self, interface: WeakPluginInterface) {
|
||||||
if let Ok(mut lock) = self.interface.lock() {
|
// if let Ok(mut lock) = self.interface.lock() {
|
||||||
*lock = Some(interface);
|
// *lock = Some(interface);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
async fn event(&self) {
|
// async fn event(&self) {
|
||||||
println!("Not Implemented");
|
// println!("Not Implemented");
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn init(&self) {
|
// fn init(&self) {
|
||||||
println!("[ExamplePlugin]: example init")
|
// println!("[ExamplePlugin]: example init")
|
||||||
}
|
// }
|
||||||
|
|
||||||
async fn run(&self) {
|
// async fn run(&self) {
|
||||||
println!("Example!!!");
|
// println!("Example!!!");
|
||||||
sleep(Duration::new(1, 0));
|
// sleep(Duration::new(1, 0));
|
||||||
let mut a = self.number.lock().await;
|
// let mut a = self.number.lock().await;
|
||||||
*a = a.overflowing_add(1).0;
|
// *a = a.overflowing_add(1).0;
|
||||||
println!("[ExamplePlugin]: example run {}", *a);
|
// println!("[ExamplePlugin]: example run {}", *a);
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn deinit(&self) {
|
// fn deinit(&self) {
|
||||||
if let Some(mut lock) = self.number.try_lock() {
|
// if let Some(mut lock) = self.number.try_lock() {
|
||||||
*lock = 0;
|
// *lock = 0;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@ mod example;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use serverlib::plugin::Plugin;
|
// use serverlib::plugin::Plugin;
|
||||||
|
|
||||||
use crate::example::ExamplePlugin;
|
// use crate::example::ExamplePlugin;
|
||||||
use serverlib::plugin::plugin::Plugin;
|
// use serverlib::plugin::plugin::Plugin;
|
||||||
use std::sync::Arc;
|
// use std::sync::Arc;
|
||||||
|
|
||||||
#[no_mangle]
|
// #[no_mangle]
|
||||||
pub extern "C" fn get_plugin() -> Plugin {
|
// pub extern "C" fn get_plugin() -> Plugin {
|
||||||
Arc::new(ExamplePlugin::default())
|
// Arc::new(ExamplePlugin::default())
|
||||||
}
|
// }
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,89 @@
|
||||||
mod network;
|
mod network;
|
||||||
pub(crate) mod prelude;
|
pub(crate) mod prelude;
|
||||||
|
|
||||||
use network::NetworkManager;
|
use crate::network::ConnectionMessage;
|
||||||
use network::NetworkMessage::Ping;
|
use crate::network::NetworkOutput;
|
||||||
use network::NetworkResponse::Pong;
|
use actix::clock::sleep;
|
||||||
|
use actix::fut::wrap_future;
|
||||||
|
use actix::Actor;
|
||||||
|
use actix::ActorFutureExt;
|
||||||
|
use actix::Addr;
|
||||||
|
use actix::AsyncContext;
|
||||||
|
use actix::Context;
|
||||||
|
use actix::Handler;
|
||||||
|
use foundation::messages::network::NetworkSockOut;
|
||||||
|
use network::{NetworkManager, NetworkMessage};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
/// This struct is the main actor of teh server.
|
||||||
|
/// all other actors are ran through here.
|
||||||
|
struct Server {
|
||||||
|
network_manager: Option<Addr<NetworkManager>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Server {
|
||||||
|
pub(crate) fn new() -> Addr<Self> {
|
||||||
|
Server {
|
||||||
|
network_manager: None,
|
||||||
|
}
|
||||||
|
.start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Actor for Server {
|
||||||
|
type Context = Context<Self>;
|
||||||
|
|
||||||
|
fn started(&mut self, ctx: &mut Self::Context) {
|
||||||
|
self
|
||||||
|
.network_manager
|
||||||
|
.replace(NetworkManager::new(ctx.address().recipient()));
|
||||||
|
|
||||||
|
if let Some(net_mgr) = self.network_manager.as_ref() {
|
||||||
|
net_mgr.do_send(NetworkMessage::StartListening);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Handler<NetworkOutput> for Server {
|
||||||
|
type Result = ();
|
||||||
|
fn handle(
|
||||||
|
&mut self,
|
||||||
|
msg: NetworkOutput,
|
||||||
|
ctx: &mut Self::Context,
|
||||||
|
) -> Self::Result {
|
||||||
|
use ConnectionMessage::{CloseConnection, SendData};
|
||||||
|
use NetworkOutput::{InfoRequested, NewClient};
|
||||||
|
use NetworkSockOut::GotInfo;
|
||||||
|
println!("server received message");
|
||||||
|
match msg {
|
||||||
|
// This uses promise like funcionality to queue
|
||||||
|
// a set of async operations,
|
||||||
|
// so they occur in the right order
|
||||||
|
InfoRequested(sender) => {
|
||||||
|
let fut = wrap_future(
|
||||||
|
sender.send(SendData(
|
||||||
|
serde_json::to_string(&GotInfo {
|
||||||
|
server_name: "String".to_owned(),
|
||||||
|
server_owner: "String".to_owned(),
|
||||||
|
})
|
||||||
|
.expect("Failed to serialise"),
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
// equivalent to using .then() in js
|
||||||
|
.map(move |out, act: &mut Self, ctx| {
|
||||||
|
sender.do_send(CloseConnection);
|
||||||
|
});
|
||||||
|
ctx.spawn(fut);
|
||||||
|
}
|
||||||
|
NewClient(_, _) => todo!(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[actix::main()]
|
#[actix::main()]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let network = NetworkManager::new();
|
let server = Server::new();
|
||||||
|
loop {
|
||||||
let pong = network.send(Ping).await;
|
sleep(Duration::from_millis(500)).await;
|
||||||
if let Ok(Pong) = pong {
|
|
||||||
println!("received pong");
|
|
||||||
} else {
|
|
||||||
println!("error occurred")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
/// # connection.rs
|
|
||||||
/// An actor that handles a TcpStream.
|
|
||||||
use crate::prelude::ObservableMessage;
|
use crate::prelude::ObservableMessage;
|
||||||
use actix::fut::wrap_future;
|
use actix::fut::wrap_future;
|
||||||
use actix::Actor;
|
use actix::Actor;
|
||||||
|
use actix::ActorContext;
|
||||||
use actix::Addr;
|
use actix::Addr;
|
||||||
use actix::AsyncContext;
|
use actix::AsyncContext;
|
||||||
use actix::Context;
|
use actix::Context;
|
||||||
|
|
@ -10,17 +9,27 @@ use actix::Handler;
|
||||||
use actix::Message;
|
use actix::Message;
|
||||||
use actix::Recipient;
|
use actix::Recipient;
|
||||||
use actix::SpawnHandle;
|
use actix::SpawnHandle;
|
||||||
|
use futures::future::join_all;
|
||||||
|
use futures::Future;
|
||||||
|
use futures::FutureExt;
|
||||||
|
use serde::Serialize;
|
||||||
|
use std::io::Write;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::sync::Arc;
|
||||||
use tokio::io::split;
|
use tokio::io::split;
|
||||||
use tokio::io::AsyncBufReadExt;
|
use tokio::io::AsyncBufReadExt;
|
||||||
|
use tokio::io::AsyncWriteExt;
|
||||||
use tokio::io::BufReader;
|
use tokio::io::BufReader;
|
||||||
use tokio::io::ReadHalf;
|
use tokio::io::ReadHalf;
|
||||||
use tokio::io::WriteHalf;
|
use tokio::io::WriteHalf;
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
|
/// This is a message that can be sent to the Connection.
|
||||||
#[derive(Message)]
|
#[derive(Message)]
|
||||||
#[rtype(result = "()")]
|
#[rtype(result = "()")]
|
||||||
enum ConnectionMessage {
|
pub(crate) enum ConnectionMessage {
|
||||||
SendData(String),
|
SendData(String),
|
||||||
CloseConnection,
|
CloseConnection,
|
||||||
}
|
}
|
||||||
|
|
@ -28,8 +37,8 @@ enum ConnectionMessage {
|
||||||
#[derive(Message)]
|
#[derive(Message)]
|
||||||
#[rtype(result = "()")]
|
#[rtype(result = "()")]
|
||||||
pub(crate) enum ConnectionOuput {
|
pub(crate) enum ConnectionOuput {
|
||||||
RecvData(String),
|
RecvData(Addr<Connection>, SocketAddr, String),
|
||||||
NoMessage,
|
ConnectionClosed(Addr<Connection>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Message)]
|
#[derive(Message)]
|
||||||
|
|
@ -49,7 +58,7 @@ enum SelfMessage {
|
||||||
/// - loop_future: the future holding the receiving loop.
|
/// - loop_future: the future holding the receiving loop.
|
||||||
pub(crate) struct Connection {
|
pub(crate) struct Connection {
|
||||||
read_half: Option<ReadHalf<TcpStream>>,
|
read_half: Option<ReadHalf<TcpStream>>,
|
||||||
write_half: WriteHalf<TcpStream>,
|
write_half: Arc<Mutex<WriteHalf<TcpStream>>>,
|
||||||
address: SocketAddr,
|
address: SocketAddr,
|
||||||
observers: Vec<Recipient<ConnectionOuput>>,
|
observers: Vec<Recipient<ConnectionOuput>>,
|
||||||
loop_future: Option<SpawnHandle>,
|
loop_future: Option<SpawnHandle>,
|
||||||
|
|
@ -63,7 +72,7 @@ impl Connection {
|
||||||
let (read_half, write_half) = split(stream);
|
let (read_half, write_half) = split(stream);
|
||||||
Connection {
|
Connection {
|
||||||
read_half: Some(read_half),
|
read_half: Some(read_half),
|
||||||
write_half,
|
write_half: Arc::new(Mutex::new(write_half)),
|
||||||
address,
|
address,
|
||||||
observers: Vec::new(),
|
observers: Vec::new(),
|
||||||
loop_future: None,
|
loop_future: None,
|
||||||
|
|
@ -128,12 +137,21 @@ impl Handler<ConnectionMessage> for Connection {
|
||||||
fn handle(
|
fn handle(
|
||||||
&mut self,
|
&mut self,
|
||||||
msg: ConnectionMessage,
|
msg: ConnectionMessage,
|
||||||
_ctx: &mut Self::Context,
|
ctx: &mut Self::Context,
|
||||||
) -> Self::Result {
|
) -> Self::Result {
|
||||||
use ConnectionMessage::{CloseConnection, SendData};
|
use ConnectionMessage::{CloseConnection, SendData};
|
||||||
|
let writer = self.write_half.clone();
|
||||||
|
|
||||||
match msg {
|
match msg {
|
||||||
SendData(d) => {}
|
SendData(d) => {
|
||||||
CloseConnection => {}
|
ctx.spawn(wrap_future(async move {
|
||||||
|
let mut lock = writer.lock().await;
|
||||||
|
let mut buffer = Vec::new();
|
||||||
|
writeln!(&mut buffer, "{}", d.as_str());
|
||||||
|
lock.write_all(&buffer).await;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
CloseConnection => ctx.stop(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -143,15 +161,31 @@ impl Handler<SelfMessage> for Connection {
|
||||||
fn handle(
|
fn handle(
|
||||||
&mut self,
|
&mut self,
|
||||||
msg: SelfMessage,
|
msg: SelfMessage,
|
||||||
_ctx: &mut Self::Context,
|
ctx: &mut Self::Context,
|
||||||
) -> Self::Result {
|
) -> Self::Result {
|
||||||
use ConnectionOuput::RecvData;
|
use ConnectionOuput::RecvData;
|
||||||
use SelfMessage::UpdateObserversWithData;
|
use SelfMessage::UpdateObserversWithData;
|
||||||
match msg {
|
match msg {
|
||||||
UpdateObserversWithData(data) => {
|
UpdateObserversWithData(data) => {
|
||||||
for o in self.observers.clone() {
|
let send = ctx.address();
|
||||||
o.do_send(RecvData(data.clone()));
|
let addr = self.address.clone();
|
||||||
}
|
// this is a mess
|
||||||
|
let futs: Vec<Pin<Box<dyn Future<Output = ()> + Send>>> = self
|
||||||
|
.observers
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.map(|r| {
|
||||||
|
let send = send.clone();
|
||||||
|
let data = data.clone();
|
||||||
|
async move {
|
||||||
|
let _ = r.send(RecvData(send, addr, data)).await;
|
||||||
|
}
|
||||||
|
.boxed()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let _ = ctx.spawn(wrap_future(async {
|
||||||
|
join_all(futs).await;
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,139 @@
|
||||||
|
use crate::network::connection::ConnectionOuput;
|
||||||
|
use crate::network::Connection;
|
||||||
|
use crate::prelude::ObservableMessage;
|
||||||
|
use actix::fut::wrap_future;
|
||||||
|
use actix::Actor;
|
||||||
|
use actix::ActorContext;
|
||||||
|
use actix::Addr;
|
||||||
|
use actix::AsyncContext;
|
||||||
|
use actix::Context;
|
||||||
|
use actix::Handler;
|
||||||
|
use actix::Message;
|
||||||
|
use actix::Recipient;
|
||||||
|
use foundation::messages::network::{NetworkSockIn, NetworkSockOut};
|
||||||
|
use foundation::ClientDetails;
|
||||||
|
use serde_json::{from_str, to_string};
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
enum ConnectionPhase {
|
||||||
|
Started,
|
||||||
|
Requested,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Message)]
|
||||||
|
#[rtype(result = "()")]
|
||||||
|
pub(crate) enum InitiatorOutput {
|
||||||
|
InfoRequest(Addr<Connection>),
|
||||||
|
ClientRequest(Addr<Connection>, ClientDetails),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # ConnectionInitiator
|
||||||
|
/// Handles the initiatin of a new connection.
|
||||||
|
///
|
||||||
|
/// This will do one of two things:
|
||||||
|
/// - Create a new client and send it to the network manager.
|
||||||
|
/// - Request the eserver info and send it to the connection.
|
||||||
|
pub(crate) struct ConnectionInitiator {
|
||||||
|
delegate: Recipient<InitiatorOutput>,
|
||||||
|
connection: Addr<Connection>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConnectionInitiator {
|
||||||
|
pub(crate) fn new(
|
||||||
|
delegate: Recipient<InitiatorOutput>,
|
||||||
|
connection: Addr<Connection>,
|
||||||
|
) -> Addr<Self> {
|
||||||
|
ConnectionInitiator {
|
||||||
|
connection,
|
||||||
|
delegate,
|
||||||
|
}
|
||||||
|
.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_request(
|
||||||
|
&mut self,
|
||||||
|
sender: Addr<Connection>,
|
||||||
|
ctx: &mut <Self as Actor>::Context,
|
||||||
|
address: SocketAddr,
|
||||||
|
data: String,
|
||||||
|
) {
|
||||||
|
use InitiatorOutput::{ClientRequest, InfoRequest};
|
||||||
|
use NetworkSockIn::{Connect, Info};
|
||||||
|
use NetworkSockOut::{Connecting, GotInfo};
|
||||||
|
use ObservableMessage::Unsubscribe;
|
||||||
|
|
||||||
|
let msg = from_str::<NetworkSockIn>(data.as_str())
|
||||||
|
.expect("error deserialising incomming message");
|
||||||
|
|
||||||
|
match msg {
|
||||||
|
Info => self
|
||||||
|
.delegate
|
||||||
|
.do_send(InfoRequest(sender))
|
||||||
|
.expect("Failed to send info request Message"),
|
||||||
|
Connect {
|
||||||
|
uuid,
|
||||||
|
username,
|
||||||
|
address,
|
||||||
|
} => self
|
||||||
|
.delegate
|
||||||
|
.do_send(ClientRequest(
|
||||||
|
sender,
|
||||||
|
ClientDetails {
|
||||||
|
uuid,
|
||||||
|
username,
|
||||||
|
address,
|
||||||
|
public_key: None,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
.expect("Failed to send connect request"),
|
||||||
|
};
|
||||||
|
ctx.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Actor for ConnectionInitiator {
|
||||||
|
type Context = Context<Self>;
|
||||||
|
|
||||||
|
/// on start initiate the protocol.
|
||||||
|
/// also add self as a subscriber to the connection.
|
||||||
|
fn started(&mut self, ctx: &mut Self::Context) {
|
||||||
|
use super::ConnectionMessage::SendData;
|
||||||
|
use NetworkSockOut::Request;
|
||||||
|
use ObservableMessage::Subscribe;
|
||||||
|
|
||||||
|
self
|
||||||
|
.connection
|
||||||
|
.do_send(Subscribe(ctx.address().recipient()));
|
||||||
|
|
||||||
|
self
|
||||||
|
.connection
|
||||||
|
.do_send(SendData(to_string(&Request).unwrap()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// once stopped remove self from the connection subscribers
|
||||||
|
fn stopped(&mut self, ctx: &mut Self::Context) {
|
||||||
|
use ObservableMessage::Unsubscribe;
|
||||||
|
self
|
||||||
|
.connection
|
||||||
|
.do_send(Unsubscribe(ctx.address().recipient()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Handler<ConnectionOuput> for ConnectionInitiator {
|
||||||
|
type Result = ();
|
||||||
|
fn handle(
|
||||||
|
&mut self,
|
||||||
|
msg: ConnectionOuput,
|
||||||
|
ctx: &mut Self::Context,
|
||||||
|
) -> Self::Result {
|
||||||
|
use ConnectionOuput::{ConnectionClosed, RecvData};
|
||||||
|
use ConnectionPhase::Requested;
|
||||||
|
match msg {
|
||||||
|
RecvData(sender, addr, data) => {
|
||||||
|
self.handle_request(sender, ctx, addr, data)
|
||||||
|
}
|
||||||
|
ConnectionClosed(_) => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/// # listener.rs
|
|
||||||
/// An actor for listening for new connections from the network
|
|
||||||
use crate::network::connection::Connection;
|
use crate::network::connection::Connection;
|
||||||
|
use crate::network::ConnectionInitiator;
|
||||||
|
use crate::network::InitiatorOutput;
|
||||||
use actix::fut::wrap_future;
|
use actix::fut::wrap_future;
|
||||||
use actix::Actor;
|
use actix::Actor;
|
||||||
use actix::Addr;
|
use actix::Addr;
|
||||||
|
|
@ -12,7 +12,6 @@ use actix::Recipient;
|
||||||
use actix::SpawnHandle;
|
use actix::SpawnHandle;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::net::ToSocketAddrs;
|
use std::net::ToSocketAddrs;
|
||||||
use std::sync::Arc;
|
|
||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
|
|
@ -26,46 +25,51 @@ pub(super) enum ListenerMessage {
|
||||||
#[derive(Message)]
|
#[derive(Message)]
|
||||||
#[rtype(result = "()")]
|
#[rtype(result = "()")]
|
||||||
pub(super) enum ListenerOutput {
|
pub(super) enum ListenerOutput {
|
||||||
Started,
|
|
||||||
StartFailed,
|
|
||||||
NewConnection(Addr<Connection>),
|
NewConnection(Addr<Connection>),
|
||||||
NoConnection,
|
InfoRequest(Addr<Connection>),
|
||||||
Error,
|
|
||||||
Stopped,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) struct NetworkListener {
|
pub(super) struct NetworkListener {
|
||||||
address: SocketAddr,
|
address: SocketAddr,
|
||||||
// delegate: Arc<RwLock<Recipient<ListenerOutput>>>,
|
delegate: Recipient<ListenerOutput>,
|
||||||
looper: Option<SpawnHandle>,
|
looper: Option<SpawnHandle>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NetworkListener {
|
impl NetworkListener {
|
||||||
pub(crate) fn new<T: ToSocketAddrs>(
|
pub(crate) fn new<T: ToSocketAddrs>(
|
||||||
address: T,
|
address: T,
|
||||||
// delegate: Recipient<ListenerOutput>,
|
delegate: Recipient<ListenerOutput>,
|
||||||
) -> Addr<NetworkListener> {
|
) -> Addr<NetworkListener> {
|
||||||
NetworkListener {
|
NetworkListener {
|
||||||
address: address
|
address: address
|
||||||
.to_socket_addrs()
|
.to_socket_addrs()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.collect::<Vec<SocketAddr>>()[0],
|
.collect::<Vec<SocketAddr>>()[0],
|
||||||
// delegate: Arc::new(RwLock::new(delegate)),
|
delegate,
|
||||||
looper: None,
|
looper: None,
|
||||||
}
|
}
|
||||||
.start()
|
.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// called when the actor is to start listening
|
||||||
fn start_listening(&mut self, ctx: &mut <Self as Actor>::Context) {
|
fn start_listening(&mut self, ctx: &mut <Self as Actor>::Context) {
|
||||||
|
println!("Network listener started listening");
|
||||||
let addr = self.address.clone();
|
let addr = self.address.clone();
|
||||||
|
let self_addr = ctx.address();
|
||||||
let loop_future = ctx.spawn(wrap_future(async move {
|
let loop_future = ctx.spawn(wrap_future(async move {
|
||||||
let listener = TcpListener::bind(addr).await.unwrap();
|
let listener = TcpListener::bind(addr).await.unwrap();
|
||||||
while let Ok((stream, addr)) = listener.accept().await {
|
while let Ok((stream, addr)) = listener.accept().await {
|
||||||
|
println!("new tcp connection");
|
||||||
let conn = Connection::new(stream, addr);
|
let conn = Connection::new(stream, addr);
|
||||||
|
let connection_initiator =
|
||||||
|
ConnectionInitiator::new(self_addr.clone().recipient(), conn);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// called when the actor is to stop listening
|
||||||
fn stop_listening(&mut self, ctx: &mut <Self as Actor>::Context) {
|
fn stop_listening(&mut self, ctx: &mut <Self as Actor>::Context) {
|
||||||
|
println!("Network listener stopped listening");
|
||||||
if let Some(fut) = self.looper.take() {
|
if let Some(fut) = self.looper.take() {
|
||||||
ctx.cancel_future(fut);
|
ctx.cancel_future(fut);
|
||||||
}
|
}
|
||||||
|
|
@ -75,7 +79,9 @@ impl NetworkListener {
|
||||||
impl Actor for NetworkListener {
|
impl Actor for NetworkListener {
|
||||||
type Context = Context<Self>;
|
type Context = Context<Self>;
|
||||||
|
|
||||||
fn started(&mut self, ctx: &mut Self::Context) {}
|
fn started(&mut self, ctx: &mut Self::Context) {
|
||||||
|
println!("Network listener started");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Handler<ListenerMessage> for NetworkListener {
|
impl Handler<ListenerMessage> for NetworkListener {
|
||||||
|
|
@ -92,3 +98,21 @@ impl Handler<ListenerMessage> for NetworkListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Handler<InitiatorOutput> for NetworkListener {
|
||||||
|
type Result = ();
|
||||||
|
fn handle(
|
||||||
|
&mut self,
|
||||||
|
msg: InitiatorOutput,
|
||||||
|
ctx: &mut Self::Context,
|
||||||
|
) -> Self::Result {
|
||||||
|
use InitiatorOutput::{ClientRequest, InfoRequest};
|
||||||
|
match msg {
|
||||||
|
ClientRequest(addr, client_details) => {}
|
||||||
|
InfoRequest(addr) => {
|
||||||
|
println!("Got Info request");
|
||||||
|
self.delegate.do_send(ListenerOutput::InfoRequest(addr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
mod connection;
|
mod connection;
|
||||||
|
mod connection_initiator;
|
||||||
mod listener;
|
mod listener;
|
||||||
mod network_manager;
|
mod network_manager;
|
||||||
|
|
||||||
use connection::Connection;
|
pub(crate) use connection::{Connection, ConnectionMessage, ConnectionOuput};
|
||||||
use listener::{ListenerMessage, NetworkListener};
|
pub(crate) use connection_initiator::{ConnectionInitiator, InitiatorOutput};
|
||||||
pub(crate) use network_manager::{NetworkManager, NetworkMessage, NetworkResponse};
|
use listener::{ListenerMessage, ListenerOutput, NetworkListener};
|
||||||
|
pub(crate) use network_manager::{
|
||||||
|
NetworkManager, NetworkMessage, NetworkOutput,
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,82 +1,120 @@
|
||||||
|
use crate::network::connection::ConnectionOuput;
|
||||||
|
use crate::network::listener::ListenerOutput;
|
||||||
|
use crate::network::Connection;
|
||||||
use crate::network::ListenerMessage;
|
use crate::network::ListenerMessage;
|
||||||
use crate::network::NetworkListener;
|
use crate::network::NetworkListener;
|
||||||
|
use crate::prelude::ObservableMessage;
|
||||||
|
use actix::fut::wrap_future;
|
||||||
use actix::Actor;
|
use actix::Actor;
|
||||||
|
|
||||||
use actix::Addr;
|
use actix::Addr;
|
||||||
use actix::AsyncContext;
|
use actix::AsyncContext;
|
||||||
use actix::Context;
|
use actix::Context;
|
||||||
use actix::Handler;
|
use actix::Handler;
|
||||||
use actix::Message;
|
use actix::Message;
|
||||||
use actix::MessageResponse;
|
use actix::Recipient;
|
||||||
use actix::SpawnHandle;
|
use foundation::ClientDetails;
|
||||||
use std::time::Duration;
|
|
||||||
use tokio::net::TcpListener;
|
|
||||||
|
|
||||||
#[derive(Message)]
|
#[derive(Message, Debug, Ord, PartialOrd, Eq, PartialEq)]
|
||||||
#[rtype(result = "NetworkResponse")]
|
#[rtype(result = "()")]
|
||||||
pub(crate) enum NetworkMessage {
|
pub(crate) enum NetworkMessage {
|
||||||
StartListening,
|
StartListening,
|
||||||
StopListening,
|
StopListening,
|
||||||
Ping,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(MessageResponse, Debug, Ord, PartialOrd, Eq, PartialEq)]
|
#[derive(Message)]
|
||||||
pub(crate) enum NetworkResponse {
|
#[rtype(result = "()")]
|
||||||
Listening,
|
pub(crate) enum NetworkOutput {
|
||||||
NotListening,
|
NewClient(Addr<Connection>, ClientDetails),
|
||||||
Pong,
|
InfoRequested(Addr<Connection>),
|
||||||
None,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct NetworkManager {
|
pub(crate) struct NetworkManager {
|
||||||
listener_addr: Addr<NetworkListener>,
|
listener_addr: Option<Addr<NetworkListener>>,
|
||||||
|
delegate: Recipient<NetworkOutput>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NetworkManager {
|
impl NetworkManager {
|
||||||
pub(crate) fn new() -> Addr<NetworkManager> {
|
pub(crate) fn new(
|
||||||
|
delegate: Recipient<NetworkOutput>,
|
||||||
|
) -> Addr<NetworkManager> {
|
||||||
NetworkManager {
|
NetworkManager {
|
||||||
listener_addr: NetworkListener::new("0.0.0.0:5600"),
|
listener_addr: None,
|
||||||
|
delegate,
|
||||||
}
|
}
|
||||||
.start()
|
.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_listener(
|
fn start_listener(&mut self, _ctx: &mut <Self as actix::Actor>::Context) {
|
||||||
&mut self,
|
use ListenerMessage::StartListening;
|
||||||
_ctx: &mut <Self as actix::Actor>::Context,
|
if let Some(addr) = self.listener_addr.as_ref() {
|
||||||
) -> NetworkResponse {
|
addr.do_send(StartListening);
|
||||||
NetworkResponse::Listening
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stop_listener(
|
fn stop_listener(&mut self, _ctx: &mut <Self as actix::Actor>::Context) {
|
||||||
&mut self,
|
|
||||||
_ctx: &mut <Self as actix::Actor>::Context,
|
|
||||||
) -> NetworkResponse {
|
|
||||||
use ListenerMessage::StopListening;
|
use ListenerMessage::StopListening;
|
||||||
use NetworkResponse::NotListening;
|
if let Some(addr) = self.listener_addr.as_ref() {
|
||||||
self.listener_addr.do_send(StopListening);
|
addr.do_send(StopListening);
|
||||||
NotListening
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_connection(
|
||||||
|
&mut self,
|
||||||
|
ctx: &mut <Self as Actor>::Context,
|
||||||
|
connection: Addr<Connection>,
|
||||||
|
) {
|
||||||
|
println!("Got new connection");
|
||||||
|
let delegate = self.delegate.clone();
|
||||||
|
ctx.spawn(wrap_future(async move {
|
||||||
|
// delegate.send(NewConnection(recipient))
|
||||||
|
// delegate.send().await;
|
||||||
|
// delegate.send().await;
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Actor for NetworkManager {
|
impl Actor for NetworkManager {
|
||||||
type Context = Context<Self>;
|
type Context = Context<Self>;
|
||||||
|
|
||||||
fn started(&mut self, _ctx: &mut Self::Context) {}
|
fn started(&mut self, ctx: &mut Self::Context) {
|
||||||
|
println!("started network manager");
|
||||||
|
let recipient = ctx.address().recipient();
|
||||||
|
self
|
||||||
|
.listener_addr
|
||||||
|
.replace(NetworkListener::new("0.0.0.0:5600", recipient));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Handler<NetworkMessage> for NetworkManager {
|
impl Handler<NetworkMessage> for NetworkManager {
|
||||||
type Result = NetworkResponse;
|
type Result = ();
|
||||||
fn handle(
|
fn handle(
|
||||||
&mut self,
|
&mut self,
|
||||||
msg: NetworkMessage,
|
msg: NetworkMessage,
|
||||||
ctx: &mut <Self as actix::Actor>::Context,
|
ctx: &mut <Self as actix::Actor>::Context,
|
||||||
) -> <Self as Handler<NetworkMessage>>::Result {
|
) -> <Self as Handler<NetworkMessage>>::Result {
|
||||||
use NetworkMessage::{Ping, StartListening, StopListening};
|
use NetworkMessage::{StartListening, StopListening};
|
||||||
use NetworkResponse::{None, Pong};
|
|
||||||
match msg {
|
match msg {
|
||||||
StartListening => self.start_listener(ctx),
|
StartListening => self.start_listener(ctx),
|
||||||
StopListening => None,
|
StopListening => self.stop_listener(ctx),
|
||||||
Ping => Pong,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Handler<ListenerOutput> for NetworkManager {
|
||||||
|
type Result = ();
|
||||||
|
fn handle(
|
||||||
|
&mut self,
|
||||||
|
msg: ListenerOutput,
|
||||||
|
ctx: &mut Self::Context,
|
||||||
|
) -> Self::Result {
|
||||||
|
use ListenerOutput::{InfoRequest, NewConnection};
|
||||||
|
match msg {
|
||||||
|
NewConnection(connection) => self.new_connection(ctx, connection),
|
||||||
|
InfoRequest(connection) => self
|
||||||
|
.delegate
|
||||||
|
.do_send(NetworkOutput::InfoRequested(connection))
|
||||||
|
.expect("failed to send message"),
|
||||||
|
_ => todo!(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue