added bootstrapper actor
This commit is contained in:
parent
dd8faef275
commit
2eaa05f1be
|
|
@ -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()
|
||||
}
|
||||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
Loading…
Reference in New Issue