Files
mize/src/server/proto.rs

457 lines
12 KiB
Rust

use derive_more::From;
use futures_util::stream::select_all::Iter;
use serde::de::Error;
use serde_json::json;
use serde::de::Visitor;
use serde::de;
use std::time::Duration;
//use std::panic::update_hook;
use std::vec;
use std::collections::HashMap;
use crate::server::itemstore;
use crate::server::Mutexes;
use crate::server::Peer;
use crate::error;
use crate::server::Client;
use std::sync::Arc;
use futures_util::stream::Collect;
use tokio::sync::{Mutex, mpsc};
use crate::server;
use crate::error::MizeError;
use crate::server::itemstore::Item;
use crate::server::proto;
use serde_json::Value as JsonValue;
use serde::{Serialize, Deserialize};
//###//===================================================
//all the structs and enums
#[derive(From, Debug, Clone)]
pub enum MizeMessage {
Json(JsonMessage),
Bin(BinMessage),
Pong(),
}
#[derive(Debug, Clone)]
pub struct BinMessage {
pub raw: Vec<u8>,
}
#[derive(From, Debug, Clone, Serialize, Deserialize)]
pub struct ErrMessage {
//pub cat: String,
pub err: MizeError,
}
//enum variant and a struct for every cmd a good idea???
#[derive(From, Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "cmd")]
pub enum JsonMessage {
#[serde(rename="err")]
ErrMsg(ErrMessage),
#[serde(rename="item.get")]
Get(GetItemMessage),
#[serde(rename="item.get-sub")]
GetSub(GetSubMessage),
#[serde(rename="item.give")]
Give(GiveItemMessage),
#[serde(rename="item.create")]
Create(CreateItemMessage),
#[serde(rename="item.created-id")]
CreatedId(CreatedIdMessage),
#[serde(rename="item.delete")]
Delete(DeleteItemMessage),
#[serde(rename="item.sub")]
Sub(SubItemMessage),
#[serde(rename="item.unsub")]
Unsub(UnsubItemMessage),
#[serde(rename="item.update-req")]
UpdateRequest(UpdateRequestMessage),
#[serde(rename="item.update")]
Update(UpdateMessage),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetItemMessage {
//pub cat: String,
//cmd: String,
#[serde(flatten)]
id: MizeId,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetSubMessage {
//pub cat: String,
//cmd: String,
#[serde(flatten)]
id: MizeId,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GiveItemMessage {
//pub cat: String,
//cmd: String,
#[serde(flatten)]
id: MizeId,
item: Item,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateItemMessage {
//pub cat: String,
//cmd: String,
item: Item,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreatedIdMessage {
//pub cat: String,
//cmd: String,
#[serde(flatten)]
id: MizeId,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeleteItemMessage {
//pub cat: String,
//cmd: String,
#[serde(flatten)]
id: MizeId,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SubItemMessage {
//pub cat: String,
//cmd: String,
#[serde(flatten)]
id: MizeId,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UnsubItemMessage {
//pub cat: String,
//cmd: String,
#[serde(flatten)]
id: MizeId,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdateRequestMessage {
//pub cat: String,
//cmd: String,
#[serde(flatten)]
id: MizeId,
#[serde(flatten)]
delta: Delta,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdateMessage {
//pub cat: String,
//cmd: String,
#[serde(flatten)]
id: MizeId,
#[serde(flatten)]
delta: Delta,
}
#[serde(from = "SerdeDelta")]
#[serde(into = "SerdeDelta")]
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
pub struct Delta {
pub delta: Vec<(Path, Option<JsonValue>)>,
}
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
pub struct SerdeDelta {
pub delta: Vec<SerdeDeltaEntry>,
}
impl From<SerdeDelta> for Delta {
fn from(serde: SerdeDelta) -> Delta {
let mut delta = Delta {delta: Vec::new()};
for SerdeDeltaEntry(path, json) in serde.delta {
delta.delta.push((path, json));
}
return delta;
}
}
impl From<Delta> for SerdeDelta {
fn from(delta: Delta) -> SerdeDelta {
let mut serde = SerdeDelta {delta: Vec::new()};
for (path, json) in delta.delta {
serde.delta.push(SerdeDeltaEntry(path, json));
}
return serde;
}
}
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
pub struct SerdeDeltaEntry (
pub Path,
#[serde(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub Option<JsonValue>,
);
pub type Path = Vec<String>;
pub type Update = Vec<(MizeId, Delta)>;
#[derive(Debug, Default, Clone, Serialize, Deserialize, Eq, Hash, PartialEq)]
pub struct MizeId {
#[serde(rename="id")]
main: String,
}
pub enum MizeIdKind<'a>{
Module{mod_name: &'a str, id: &'a str},
Upstream(&'a server::Peer),
Local(u64),
}
impl MizeId {
pub fn new(main: String) -> MizeId {
MizeId { main }
}
pub fn as_string(self) -> String {
self.main
}
pub fn new_local(local_part: &str) -> MizeId {
MizeId { main: local_part.to_owned() }
}
pub fn kind(&self) -> Result<MizeIdKind, MizeError> {
let first_char = match self.main.chars().nth(0) {
Some(ch) => ch,
None => {
return Err(MizeError::new(11).extra_msg("Couldn't get the first char from a MizeId"));
},
};
if (first_char == '#'){
let iter = self.main.chars();
//scip the #
let mod_name_end = iter.enumerate().find(|&r| r.1 == '#' || r.1 == '/').ok_or(MizeError::new(11))?;
let mod_name = &self.main[0..mod_name_end.0];
let id = &self.main[mod_name_end.0..];
return Ok(MizeIdKind::Module{ mod_name, id});
} else {
let id: u64 = match self.main.parse(){
Ok(num) => num,
Err(_) => {
return Err(MizeError::new(11).extra_msg("Couldn't parse a local id into an integer"))
},
};
return Ok(MizeIdKind::Local(id));
}
}
}
impl Delta {
pub fn new() -> Delta{
Delta { delta: Vec::new() }
}
pub fn append(&mut self, path: Vec<&str>, json: JsonValue){
let new_path: Vec<String> = path.into_iter().map(|e| e.to_owned()).collect();
self.delta.push((new_path, Some(json)));
}
}
//###//===================================================
//From trait implementations, to be able to treat everything as a MizeMessage that can be
impl From<GiveItemMessage> for MizeMessage {
fn from(give: GiveItemMessage) -> MizeMessage {
let two: JsonMessage = give.into();
return two.into();
}
}
impl From<MizeError> for MizeMessage {
fn from(err: MizeError) -> MizeMessage {
let hi: ErrMessage = err.into();
let two: JsonMessage = hi.into();
return two.into();
}
}
impl From<CreatedIdMessage> for MizeMessage {
fn from(give: CreatedIdMessage) -> MizeMessage {
let two: JsonMessage = give.into();
return two.into();
}
}
impl From<UpdateMessage> for MizeMessage {
fn from(give: UpdateMessage) -> MizeMessage {
let two: JsonMessage = give.into();
return two.into();
}
}
//###//===================================================
// functions
pub async fn handle_json_msg(msg: JsonMessage, origin: Peer, mutexes: Mutexes) -> Result<(), MizeError>{
match msg {
JsonMessage::Get(msg) => {
match msg.id.kind()? {
//MizeId::Module { mod_name, id } => {
//TODO: get type of module with mod_name .... and then either forward msg or call
//module_get_code
//},
MizeIdKind::Local(id) => {
let itemstore = mutexes.itemstore.lock().await;
let response = GiveItemMessage {
id: msg.id,
item: itemstore.get(id).await?,
};
origin.send(response).await;
},
_ => {return Err(MizeError::new(11).extra_msg("id type is not implemented"));},
};
return Ok(());
},
JsonMessage::GetSub(msg) => {
//sub to item
let mut subs = mutexes.subs.lock().await;
if let Some(mut vec_ids) = subs.get_mut(&msg.id) {
vec_ids.push(origin.clone());
} else {
subs.insert(msg.id.clone(), vec![origin.clone()]);
};
match msg.id.kind()? {
//MizeId::Module { mod_name, id } => {
//TODO: get type of module with mod_name .... and then either forward msg or call
//module_get_code
//},
MizeIdKind::Local(id) => {
let itemstore = mutexes.itemstore.lock().await;
let response = GiveItemMessage {
id: msg.id,
item: itemstore.get(id).await?,
};
origin.send(response).await;
},
_ => {return Err(MizeError::new(11).extra_msg("id types not implemented"));},
}
return Ok(());
}
JsonMessage::UpdateRequest(mut msg) => {
let update: Update = vec![(msg.id, msg.delta)];
handle_update(update, origin, mutexes.clone()).await?;
// let subs = mutexes.subs.lock().await;
// for (id, delta) in new_update {
//send that delta to every origin that is subbed the item
// let peers = match subs.get(&id) {
// Some(vec) => vec,
// None => continue,
// };
// let message = UpdateMessage{id, delta};
// for peer in peers {
//TODO: send should only take a reference
// peer.send(message.clone()).await
// }
// }
},
JsonMessage::Create(msg) => {
let itemstore = mutexes.itemstore.lock().await;
let id = itemstore.create(msg.item, mutexes.clone(), origin.clone()).await?;
let response = CreatedIdMessage {id: MizeId::new(format!("{}", id))};
origin.send(response).await;
return Ok(());
},
JsonMessage::Delete(msg) => {
match msg.id.kind()? {
MizeIdKind::Local(id) => {
let itemstore = mutexes.itemstore.lock().await;
itemstore.delete(id).await?;
return Ok(());
},
_ => {return Err(MizeError::new(11).extra_msg("deleteng non Local items not implemented yet"));}
}
},
_ => {
return Err(MizeError::new(11).extra_msg("ItemMessage cmd not handeld"));
},
};
return Ok(())
}
pub async fn handle_update(update: Update, origin: Peer, mutexes: Mutexes) -> Result<(), MizeError> {
mutexes.update_tx.send((update, origin)).await.map_err(|err| MizeError::new(11).extra_msg(format!("From SendError: {}", err)));
Ok(())
}
pub async fn update_thread(mut update_rx: mpsc::Receiver<(Update, Peer)>, mutexes: Mutexes) -> Result<(), MizeError> {
while let Some((update, origin)) = update_rx.recv().await {
println!("UPDATE: {:?}", update.iter().next().unwrap().0);
//TODO: run update code from modules and types
let itemstore = mutexes.itemstore.lock().await;
let subs = mutexes.subs.lock().await;
for (id, delta) in update {
//update the items in the itemstore
if let MizeIdKind::Local(id) = id.kind()? {
itemstore.update(id.clone(), delta.clone()).await?;
} else {
return Err(MizeError::new(11).extra_msg("updates to non local items are not handeld yet"));
}
//send a update msg to subbed clients
let peers = match subs.get(&id) {
Some(hi) => hi,
None => break,
};
let msg = UpdateMessage{id, delta};
for peer in peers {
peer.send(msg.clone()).await;
}
}
}
Ok(())
}