merge develop into master #20
|
|
@ -19,7 +19,7 @@ name = "server"
|
|||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
clap = "2.33.3"
|
||||
clap = "3.2.5"
|
||||
uuid = {version = "0.8", features = ["serde", "v4"]}
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
|
|
@ -33,6 +33,7 @@ async-trait = "0.1.52"
|
|||
actix = "0.13"
|
||||
mlua = { version = "0.7.3", features=["lua54", "async", "serde", "macros"] }
|
||||
libloading = "0.7"
|
||||
toml = "0.4.2"
|
||||
aquamarine = "0.1.11"
|
||||
tokio-stream = "0.1.9"
|
||||
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ use crate::{
|
|||
ConnectionOuput,
|
||||
},
|
||||
prelude::{
|
||||
ObservableMessage,
|
||||
ObservableMessage::{Subscribe, Unsubscribe},
|
||||
messages::ObservableMessage,
|
||||
messages::ObservableMessage::{Subscribe, Unsubscribe},
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -165,7 +165,7 @@ impl Actor for Client {
|
|||
use ConnectionMessage::SendData;
|
||||
println!("[Client] started");
|
||||
self.connection
|
||||
.do_send(Subscribe(ctx.address().recipient()));
|
||||
.do_send::<ObservableMessage<ConnectionOuput>>(Subscribe(ctx.address().recipient()));
|
||||
self.connection.do_send(SendData(
|
||||
to_string::<ClientStreamOut>(&Connected).unwrap(),
|
||||
));
|
||||
|
|
@ -175,7 +175,7 @@ impl Actor for Client {
|
|||
use ClientStreamOut::Disconnected;
|
||||
use ConnectionMessage::SendData;
|
||||
self.connection
|
||||
.do_send(Unsubscribe(ctx.address().recipient()));
|
||||
.do_send::<ObservableMessage<ConnectionOuput>>(Unsubscribe(ctx.address().recipient()));
|
||||
self.connection.do_send(SendData(
|
||||
to_string::<ClientStreamOut>(&Disconnected).unwrap(),
|
||||
));
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ use crate::{
|
|||
Client,
|
||||
},
|
||||
network::NetworkOutput,
|
||||
prelude::ObservableMessage,
|
||||
prelude::messages::ObservableMessage,
|
||||
};
|
||||
|
||||
#[derive(Message)]
|
||||
|
|
@ -165,7 +165,7 @@ impl ClientManager {
|
|||
addr: Addr<Client>,
|
||||
) {
|
||||
println!("[ClientManager] adding client");
|
||||
use crate::prelude::ObservableMessage::Subscribe;
|
||||
use crate::prelude::messages::ObservableMessage::Subscribe;
|
||||
let recp = ctx.address().recipient::<ClientObservableMessage>();
|
||||
addr.do_send(Subscribe(recp));
|
||||
self.clients.insert(uuid, addr);
|
||||
|
|
@ -173,7 +173,7 @@ impl ClientManager {
|
|||
|
||||
fn remove_client(&mut self, ctx: &mut Context<ClientManager>, uuid: Uuid) {
|
||||
println!("[ClientManager] removing client");
|
||||
use crate::prelude::ObservableMessage::Unsubscribe;
|
||||
use crate::prelude::messages::ObservableMessage::Unsubscribe;
|
||||
let recp = ctx.address().recipient::<ClientObservableMessage>();
|
||||
if let Some(addr) = self.clients.remove(&uuid) {
|
||||
addr.do_send(Unsubscribe(recp));
|
||||
|
|
|
|||
|
|
@ -8,12 +8,64 @@ pub(crate) mod client_management;
|
|||
pub(crate) mod network;
|
||||
pub(crate) mod prelude;
|
||||
|
||||
use std::env::args;
|
||||
use server::Server;
|
||||
use tokio::time::{sleep, Duration};
|
||||
use clap::{App, Arg, value_parser};
|
||||
use openssl::version::version;
|
||||
|
||||
#[actix::main()]
|
||||
async fn main() {
|
||||
let _server = Server::new();
|
||||
|
||||
let args = App::new("Rust Chat Server")
|
||||
.author("Michael Bailey & Mitchel Hardie")
|
||||
.version("0.1.0")
|
||||
.about("A chat server written in rust, with a custom json protocol, based on serde and actix")
|
||||
.arg(
|
||||
Arg::new("port")
|
||||
.short('p')
|
||||
.long("port")
|
||||
.takes_value(true)
|
||||
.value_parser(value_parser!(u16))
|
||||
.default_value("5600")
|
||||
.help("overrides the default port")
|
||||
)
|
||||
.arg(
|
||||
Arg::new("server name")
|
||||
.short('n')
|
||||
.long("name")
|
||||
.takes_value(true)
|
||||
.help("overrides the default port of the server")
|
||||
)
|
||||
.arg(
|
||||
Arg::new("server owner")
|
||||
.short('o')
|
||||
.long("owner")
|
||||
.takes_value(true)
|
||||
.help("overrides the owner of the server")
|
||||
)
|
||||
.after_help("This is a chat server made to test out writing a full application in rust \
|
||||
It has evolved over time to use different frameworks\
|
||||
It is currently using actix")
|
||||
.get_matches();
|
||||
|
||||
let mut server_builder = Server::create();
|
||||
|
||||
if let Some(port) = args.get_one::<u16>("port") {
|
||||
server_builder = server_builder.port(*port);
|
||||
println!("got port number {:?}", port);
|
||||
}
|
||||
if let Some(name) = args.get_one::<String>("server name") {
|
||||
server_builder = server_builder.name(name.clone());
|
||||
println!("got server name number {:?}", name)
|
||||
}
|
||||
if let Some(owner) = args.get_one::<String>("server owner") {
|
||||
server_builder = server_builder.owner(owner.clone());
|
||||
println!("got server owner number {:?}", owner)
|
||||
}
|
||||
|
||||
let _server = server_builder.build();
|
||||
|
||||
loop {
|
||||
sleep(Duration::from_millis(1000)).await;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ use tokio::{
|
|||
sync::Mutex,
|
||||
};
|
||||
|
||||
use crate::prelude::ObservableMessage;
|
||||
use crate::prelude::messages::ObservableMessage;
|
||||
|
||||
/// This is a message that can be sent to the Connection.
|
||||
#[derive(Message)]
|
||||
|
|
@ -22,7 +22,7 @@ use serde_json::{from_str, to_string};
|
|||
|
||||
use crate::{
|
||||
network::{connection::ConnectionOuput, Connection, ConnectionMessage},
|
||||
prelude::ObservableMessage,
|
||||
prelude::messages::ObservableMessage,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
|
|
@ -37,6 +37,6 @@ pub(crate) use connection_initiator::{ConnectionInitiator, InitiatorOutput};
|
|||
use listener::{ListenerMessage, ListenerOutput, NetworkListener};
|
||||
pub(crate) use network_manager::{
|
||||
NetworkManager,
|
||||
NetworkMessage,
|
||||
NetworkOutput,
|
||||
NetworkMessage
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
use actix::{Actor, Addr, WeakRecipient};
|
||||
use crate::network::network_manager::messages::NetworkOutput;
|
||||
use crate::network::NetworkManager;
|
||||
|
||||
pub struct Builder {
|
||||
pub(super) port: Option<u16>,
|
||||
pub(super) delegate: WeakRecipient<NetworkOutput>,
|
||||
}
|
||||
|
||||
impl Builder {
|
||||
pub(super) fn new(delegate: WeakRecipient<NetworkOutput>) -> Self {
|
||||
Self {
|
||||
port: None,
|
||||
delegate,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn port(mut self, port: u16) -> Self {
|
||||
self.port = Some(port);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> Addr<NetworkManager> {
|
||||
NetworkManager::from(self).start()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct Config {
|
||||
pub(super) port: u16,
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
use actix::Addr;
|
||||
use foundation::ClientDetails;
|
||||
use crate::network::Connection;
|
||||
use actix::Message;
|
||||
|
||||
#[derive(Message, Debug, Ord, PartialOrd, Eq, PartialEq)]
|
||||
#[rtype(result = "()")]
|
||||
pub enum NetworkMessage {
|
||||
StartListening,
|
||||
StopListening,
|
||||
}
|
||||
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub enum NetworkOutput {
|
||||
NewClient(Addr<Connection>, ClientDetails),
|
||||
InfoRequested(Addr<Connection>),
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
//! # network_manager
|
||||
//! This module contains the network manager actor
|
||||
//! it's role involves handling new oncomming network connections
|
||||
|
||||
mod builder;
|
||||
mod messages;
|
||||
mod network_manager;
|
||||
mod config;
|
||||
|
||||
use config::*;
|
||||
pub(crate) use network_manager::{NetworkManager};
|
||||
pub(crate) use builder::*;
|
||||
pub(crate) use messages::{NetworkMessage,NetworkOutput};
|
||||
|
|
@ -1,43 +1,14 @@
|
|||
//! # network_manager
|
||||
//! This module contains the network manager actor
|
||||
//! it's role involves handling new oncomming network connections
|
||||
|
||||
use actix::{
|
||||
Actor,
|
||||
Addr,
|
||||
AsyncContext,
|
||||
Context,
|
||||
Handler,
|
||||
Message,
|
||||
WeakRecipient,
|
||||
};
|
||||
use actix::{Actor, Addr, AsyncContext, Context, Handler, WeakRecipient};
|
||||
use foundation::ClientDetails;
|
||||
|
||||
use crate::network::{
|
||||
listener::ListenerOutput,
|
||||
Connection,
|
||||
ConnectionInitiator,
|
||||
InitiatorOutput,
|
||||
InitiatorOutput::ClientRequest,
|
||||
ListenerMessage,
|
||||
NetworkListener,
|
||||
};
|
||||
|
||||
#[derive(Message, Debug, Ord, PartialOrd, Eq, PartialEq)]
|
||||
#[rtype(result = "()")]
|
||||
pub enum NetworkMessage {
|
||||
StartListening,
|
||||
StopListening,
|
||||
}
|
||||
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub enum NetworkOutput {
|
||||
NewClient(Addr<Connection>, ClientDetails),
|
||||
InfoRequested(Addr<Connection>),
|
||||
}
|
||||
use crate::network::{Connection, ConnectionInitiator, InitiatorOutput};
|
||||
use crate::network::listener::{ListenerMessage, ListenerOutput};
|
||||
use crate::network::listener::NetworkListener;
|
||||
use crate::network::network_manager::Builder;
|
||||
use crate::network::network_manager::config::Config;
|
||||
use crate::network::network_manager::messages::{NetworkMessage, NetworkOutput};
|
||||
|
||||
pub struct NetworkManager {
|
||||
config: Config,
|
||||
listener_addr: Option<Addr<NetworkListener>>,
|
||||
delegate: WeakRecipient<NetworkOutput>,
|
||||
initiators: Vec<Addr<ConnectionInitiator>>,
|
||||
|
|
@ -46,11 +17,18 @@ pub struct NetworkManager {
|
|||
impl NetworkManager {
|
||||
pub fn new(delegate: WeakRecipient<NetworkOutput>) -> Addr<NetworkManager> {
|
||||
NetworkManager {
|
||||
config: Config {
|
||||
port: 5600
|
||||
},
|
||||
listener_addr: None,
|
||||
delegate,
|
||||
initiators: Vec::new(),
|
||||
}
|
||||
.start()
|
||||
.start()
|
||||
}
|
||||
|
||||
pub fn create(delegate: WeakRecipient<NetworkOutput>) -> Builder {
|
||||
Builder::new(delegate)
|
||||
}
|
||||
|
||||
fn start_listener(&mut self, _ctx: &mut <Self as actix::Actor>::Context) {
|
||||
|
|
@ -135,10 +113,10 @@ impl Actor for NetworkManager {
|
|||
type Context = Context<Self>;
|
||||
|
||||
fn started(&mut self, ctx: &mut Self::Context) {
|
||||
println!("started network manager");
|
||||
println!("[NetworkManager] started with config {:?}", self.config);
|
||||
let recipient = ctx.address().recipient();
|
||||
self.listener_addr
|
||||
.replace(NetworkListener::new("0.0.0.0:5600", recipient));
|
||||
.replace(NetworkListener::new(format!("0.0.0.0:{}", self.config.port), recipient));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -187,3 +165,17 @@ impl Handler<InitiatorOutput> for NetworkManager {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Builder> for NetworkManager {
|
||||
fn from(builder: Builder) -> Self {
|
||||
Self {
|
||||
config: Config {
|
||||
port: builder.port.unwrap_or_else(|| 5600),
|
||||
},
|
||||
listener_addr: None,
|
||||
delegate: builder.delegate,
|
||||
|
||||
initiators: Vec::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
use actix::{Actor, Addr};
|
||||
use super::*;
|
||||
|
||||
pub struct ServerBuilder {
|
||||
pub(super) name: Option<String>,
|
||||
pub(super) port: Option<u16>,
|
||||
pub(super) owner: Option<String>,
|
||||
}
|
||||
|
||||
impl ServerBuilder {
|
||||
pub(super) fn new() -> Self {
|
||||
Self {
|
||||
name: None,
|
||||
port: None,
|
||||
owner: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn port(mut self, port: u16) -> Self {
|
||||
self.port = Some(port);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn name(mut self, name: String) -> Self {
|
||||
self.name = Some(name);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn owner(mut self, owner: String) -> Self {
|
||||
self.owner = Some(owner);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> Addr<Server> {
|
||||
Server::from(self).start()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
/// Configuration for the server
|
||||
pub(super) struct ServerConfig {
|
||||
pub(super) port: u16,
|
||||
pub(super) name: String,
|
||||
pub(super) owner: String,
|
||||
}
|
||||
|
||||
impl Default for ServerConfig {
|
||||
fn default() -> Self {
|
||||
ServerConfig {
|
||||
owner: "john_smith@example.com".to_string(),
|
||||
name: "default server name".to_string(),
|
||||
port: 5600,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
//! # actix_server
|
||||
//! this holds the server actor
|
||||
//! the server acts as teh main actor
|
||||
//! and supervisor to the actor system.
|
||||
|
||||
mod server;
|
||||
mod config;
|
||||
mod builder;
|
||||
|
||||
use config::ServerConfig;
|
||||
pub use server::Server;
|
||||
pub(crate) use builder::ServerBuilder;
|
||||
|
|
@ -1,39 +1,19 @@
|
|||
//! # actix_server
|
||||
//! this holds the server actor
|
||||
//! the server acts as teh main actor
|
||||
//! and supervisor to the actor system.
|
||||
|
||||
use actix::{
|
||||
fut::wrap_future,
|
||||
Actor,
|
||||
ActorFutureExt,
|
||||
Addr,
|
||||
AsyncContext,
|
||||
Context,
|
||||
Handler,
|
||||
};
|
||||
use foundation::{messages::network::NetworkSockOut, ClientDetails};
|
||||
|
||||
use crate::{
|
||||
client_management::{
|
||||
Client,
|
||||
ClientManager,
|
||||
ClientManagerMessage,
|
||||
ClientManagerOutput,
|
||||
},
|
||||
network::{
|
||||
Connection,
|
||||
ConnectionInitiator,
|
||||
ConnectionMessage,
|
||||
NetworkManager,
|
||||
NetworkMessage,
|
||||
NetworkOutput,
|
||||
},
|
||||
};
|
||||
use actix::{Actor, ActorFutureExt, Addr, AsyncContext, Context, ContextFutureSpawner, Handler};
|
||||
use actix::fut::wrap_future;
|
||||
use foundation::ClientDetails;
|
||||
use foundation::messages::network::NetworkSockOut::GotInfo;
|
||||
use crate::client_management::{Client, ClientManager, ClientManagerOutput};
|
||||
use crate::client_management::ClientManagerMessage::AddClient;
|
||||
use crate::network::{Connection, NetworkManager, NetworkMessage, NetworkOutput};
|
||||
use crate::network::ConnectionMessage::{CloseConnection, SendData};
|
||||
use crate::network::NetworkOutput::{InfoRequested, NewClient};
|
||||
use crate::server::{builder, ServerBuilder};
|
||||
use crate::server::config::ServerConfig;
|
||||
|
||||
/// This struct is the main actor of the server.
|
||||
/// all other actors are ran through here.
|
||||
pub struct Server {
|
||||
config: ServerConfig,
|
||||
network_manager: Option<Addr<NetworkManager>>,
|
||||
client_management: Option<Addr<ClientManager>>,
|
||||
}
|
||||
|
|
@ -41,10 +21,15 @@ pub struct Server {
|
|||
impl Server {
|
||||
pub(crate) fn new() -> Addr<Self> {
|
||||
Server {
|
||||
config: Default::default(),
|
||||
network_manager: None,
|
||||
client_management: None,
|
||||
}
|
||||
.start()
|
||||
.start()
|
||||
}
|
||||
|
||||
pub fn create() -> builder::ServerBuilder {
|
||||
ServerBuilder::new()
|
||||
}
|
||||
|
||||
pub(crate) fn client_request(
|
||||
|
|
@ -53,7 +38,6 @@ impl Server {
|
|||
addr: Addr<Connection>,
|
||||
details: ClientDetails,
|
||||
) {
|
||||
use ClientManagerMessage::AddClient;
|
||||
if let Some(mgr) = self.client_management.as_ref() {
|
||||
let client = Client::new(addr, details.clone());
|
||||
mgr.do_send(AddClient(details.uuid, client));
|
||||
|
|
@ -65,21 +49,19 @@ impl Server {
|
|||
ctx: &mut <Self as Actor>::Context,
|
||||
sender: Addr<Connection>,
|
||||
) {
|
||||
use ConnectionMessage::{CloseConnection, SendData};
|
||||
use NetworkSockOut::GotInfo;
|
||||
let fut = wrap_future(
|
||||
sender.send(SendData(
|
||||
serde_json::to_string(&GotInfo {
|
||||
server_name: "String".to_owned(),
|
||||
server_owner: "String".to_owned(),
|
||||
server_name: self.config.name.clone(),
|
||||
server_owner: self.config.owner.clone(),
|
||||
})
|
||||
.expect("Failed to serialise"),
|
||||
.expect("Failed to serialise"),
|
||||
)),
|
||||
)
|
||||
// equivalent to using .then() in js
|
||||
.map(move |_out, _act: &mut Self, _ctx| {
|
||||
sender.do_send(CloseConnection);
|
||||
});
|
||||
// equivalent to using .then() in js
|
||||
.map(move |_out, _act: &mut Self, _ctx| {
|
||||
sender.do_send(CloseConnection);
|
||||
});
|
||||
ctx.spawn(fut);
|
||||
}
|
||||
}
|
||||
|
|
@ -88,13 +70,15 @@ impl Actor for Server {
|
|||
type Context = Context<Self>;
|
||||
|
||||
fn started(&mut self, ctx: &mut Self::Context) {
|
||||
let addr = ctx.address();
|
||||
let addr = ctx.address().downgrade();
|
||||
|
||||
self.network_manager
|
||||
.replace(NetworkManager::new(addr.clone().recipient().downgrade()));
|
||||
let nm = NetworkManager::create(addr.clone().recipient())
|
||||
.port(self.config.port)
|
||||
.build();
|
||||
self.network_manager.replace(nm);
|
||||
|
||||
self.client_management.replace(ClientManager::new(
|
||||
addr.clone().recipient::<ClientManagerOutput>().downgrade(),
|
||||
addr.clone().recipient(),
|
||||
));
|
||||
|
||||
if let Some(net_mgr) = self.network_manager.as_ref() {
|
||||
|
|
@ -110,9 +94,6 @@ impl Handler<NetworkOutput> for Server {
|
|||
msg: NetworkOutput,
|
||||
ctx: &mut Self::Context,
|
||||
) -> Self::Result {
|
||||
use ConnectionMessage::{CloseConnection, SendData};
|
||||
use NetworkOutput::{InfoRequested, NewClient};
|
||||
use NetworkSockOut::GotInfo;
|
||||
println!("[ServerActor] received message");
|
||||
match msg {
|
||||
// This uses promise like funcionality to queue
|
||||
|
|
@ -136,3 +117,17 @@ impl Handler<ClientManagerOutput> for Server {
|
|||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<builder::ServerBuilder> for Server {
|
||||
fn from(builder: ServerBuilder) -> Self {
|
||||
Server {
|
||||
config: ServerConfig {
|
||||
port: builder.port.unwrap_or(5600),
|
||||
name: builder.name.unwrap_or_else(|| "Default Name".to_string()),
|
||||
owner: builder.owner.unwrap_or_else(|| "Default owner".to_string()),
|
||||
},
|
||||
network_manager: None,
|
||||
client_management: None
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue