added bootstrapper actor

This commit is contained in:
michael-bailey 2022-09-03 08:02:38 +01:00
parent dd8faef275
commit 2eaa05f1be
9 changed files with 244 additions and 61 deletions

View File

@ -0,0 +1,42 @@
use clap::{App, Arg, ArgMatches, value_parser};
pub(crate) fn get_args() -> ArgMatches {
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")
)
.arg(
Arg::new("config file")
.short('c')
.long("config_file")
.takes_value(true)
.help("overrides the default config file location")
)
.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()
}

View File

@ -0,0 +1,95 @@
use crate::bootstrapper::builder::Builder;
use crate::config_manager::ConfigManagerDataMessage::SoftSetValue;
use crate::config_manager::{ConfigManager, ConfigValue};
use crate::Server;
use actix::fut::wrap_future;
use actix::{
Actor, ActorFutureExt, ActorStreamExt, ActorTryFutureExt, Addr,
AsyncContext, Context,
};
use clap::ArgMatches;
use std::fs::OpenOptions;
use tokio::fs::File;
/// # Bootstrapper
/// This class acts as the init daemon of the server.
/// it creates the necessary actors required by the server before it inits.
/// it handles things like fetching configurations and uses them in server creation.
/// It takes the args passed into the program and overrides the corresponding fields in the config manager
pub struct Bootstrapper {
args: ArgMatches,
server: Option<Addr<Server>>,
}
impl Bootstrapper {
pub fn create() -> Builder {
Builder::new()
}
}
impl Actor for Bootstrapper {
type Context = Context<Self>;
fn started(&mut self, ctx: &mut Self::Context) {
let config_file = self
.args
.get_one::<String>("config file")
.map(|v| v.clone());
let port = self.args.get_one::<u16>("port").map(|v| *v);
let name = self
.args
.get_one::<String>("server name")
.map(|v| v.clone());
let owner = self
.args
.get_one::<String>("server owner")
.map(|v| v.clone());
let fut = wrap_future(async move {
let config_manager = ConfigManager::shared(config_file);
if let Some(port) = port {
config_manager
.send(SoftSetValue(
"server.port".into(),
ConfigValue::Number(port.into()),
))
.await;
}
if let Some(name) = name {
let _ = config_manager
.send(SoftSetValue(
"server.name".into(),
ConfigValue::String(name),
))
.await;
}
if let Some(owner) = owner {
let _ = config_manager
.send(SoftSetValue(
"server.owner".into(),
ConfigValue::String(owner),
))
.await;
}
config_manager
})
.map(|val, obj: &mut Bootstrapper, _ctx| {
obj.server = Server::create(val).build().into();
});
ctx.spawn(fut);
}
}
impl From<Builder> for Bootstrapper {
fn from(b: Builder) -> Self {
Self {
args: b.args,
server: None,
}
}
}

View File

@ -0,0 +1,33 @@
use std::fs::OpenOptions;
use actix::{Actor, Addr};
use clap::ArgMatches;
use tokio::fs::File;
use crate::bootstrapper::bootstrapper::Bootstrapper;
use super::get_args;
pub struct Builder {
pub(super) args: ArgMatches,
}
impl Builder {
pub(super) fn new() -> Self {
Self {
args: get_args(),
}
}
pub fn file(mut self, path: String) -> Self {
let file = OpenOptions::new()
.create(true)
.write(true)
.read(true)
.open(path)
.ok().map(|val| File::from(val));
self
}
pub fn build(self) -> Addr<Bootstrapper> {
Bootstrapper::from(self).start()
}
}

View File

View File

@ -0,0 +1,7 @@
mod bootstrapper;
mod builder;
mod messages;
mod arg_fetcher;
pub(crate) use arg_fetcher::get_args;
pub(crate) use bootstrapper::Bootstrapper;

View File

@ -30,7 +30,7 @@ pub(crate) struct ConfigManager {
}
impl ConfigManager {
pub fn new(file: Option<String>) -> Addr<Self> {
pub fn shared(file: Option<String>) -> Addr<Self> {
INIT.call_once(|| {
// Since this access is inside a call_once, before any other accesses, it is safe
unsafe {
@ -70,7 +70,7 @@ impl ConfigManager {
}
impl ConfigManager {
pub(crate) fn get_value(
pub fn get_value(
&self,
val_path: String,
) -> Result<ConfigValue, &'static str> {
@ -95,6 +95,52 @@ impl ConfigManager {
}
Ok(current_node.clone())
}
// this doesn't work for now
pub fn set_value(&self, val_path: String) -> Result<(), &'static str> {
use ConfigValue::{Array, Dict};
let path: Vec<String> = val_path.split('.').map(|v| v.into()).collect();
let mut current_node: &ConfigValue = &self.root;
let mut next_node: Option<&ConfigValue> = None;
// check that the current
for i in path {
match current_node {
Dict(v) => {
if v.contains_key(&i) {
next_node = v.get(&i);
} else {
return Err("invalid path");
}
}
Array(v) => {
if let Ok(index) = i.parse::<usize>() {
if v.len() > index {
next_node = v.get(index)
} else {
return Err("invalid path");
}
}
}
_ => return Err("invalid path"),
}
match next_node {
Some(a @ Dict(_) | a @ Array(_)) => {
current_node = a;
continue;
}
_ => return Err("invalid path"),
}
}
if let Dict(v) = current_node {
} else if let Dict(v) = current_node {
}
Ok(())
}
}
impl Actor for ConfigManager {

View File

@ -10,65 +10,21 @@ pub(crate) mod prelude;
pub(crate) mod rhai;
pub(crate) mod lua;
pub(crate) mod scripting;
pub(crate) mod bootstrapper;
pub(crate) mod config_manager;
use std::env::args;
use actix::Actor;
use server::Server;
use tokio::time::{sleep, Duration};
use clap::{App, Arg, value_parser};
use openssl::version::version;
use crate::bootstrapper::{Bootstrapper, get_args};
#[actix::main()]
async fn main() {
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();
let init = Bootstrapper::create()
.build();
loop {
sleep(Duration::from_millis(1000)).await;
}

View File

@ -1,33 +1,36 @@
use actix::{Actor, Addr};
use crate::config_manager::ConfigManager;
use super::*;
pub struct ServerBuilder {
pub(super) config: Addr<ConfigManager>,
pub(super) name: Option<String>,
pub(super) port: Option<u16>,
pub(super) owner: Option<String>,
}
impl<'rhai> ServerBuilder {
pub(super) fn new() -> Self {
pub(super) fn new(config_manager: Addr<ConfigManager>) -> Self {
Self {
config: config_manager,
name: None,
port: None,
owner: None,
}
}
pub fn port(mut self, port: u16) -> Self {
self.port = Some(port);
pub fn port(mut self, port: Option<u16>) -> Self {
self.port = port;
self
}
pub fn name(mut self, name: String) -> Self {
self.name = Some(name);
pub fn name(mut self, name: Option<String>) -> Self {
self.name = name;
self
}
pub fn owner(mut self, owner: String) -> Self {
self.owner = Some(owner);
pub fn owner(mut self, owner: Option<String>) -> Self {
self.owner = owner;
self
}

View File

@ -10,6 +10,7 @@ use foundation::messages::network::NetworkSockOut::GotInfo;
use crate::client_management::{ClientManager, ClientManagerOutput};
use crate::client_management::client::Client;
use crate::client_management::ClientManagerMessage::AddClient;
use crate::config_manager::ConfigManager;
use crate::lua::LuaManager;
use crate::rhai::RhaiManager;
use crate::network::{Connection, NetworkManager, NetworkMessage, NetworkOutput};
@ -29,8 +30,8 @@ pub struct Server {
}
impl Server {
pub fn create() -> builder::ServerBuilder {
ServerBuilder::new()
pub(crate) fn create(config_manager: Addr<ConfigManager>) -> builder::ServerBuilder {
ServerBuilder::new(config_manager)
}
pub(crate) fn client_request(