flnet 0.7.2

Network setup and communication
Documentation
use crate::{
    config::{NodeConfig, NodeInfo},
    network::{NetReply, NetworkMessage},
};
use flmodules::{
    broker::{Broker, BrokerError, Subsystem, SubsystemHandler, Translate},
    nodeids::U256,
};

pub struct NetworkBrokerSimul {
    nsh_broker: Broker<NSHubMessage>,
}

impl NetworkBrokerSimul {
    pub async fn new() -> Result<Self, BrokerError> {
        let nsh_broker = NSHub::new().await?;
        Ok(Self { nsh_broker })
    }

    pub async fn new_node(&mut self) -> Result<(NodeConfig, Broker<NetworkMessage>), BrokerError> {
        let nc = NodeConfig::new();
        let nc_id = nc.info.get_id();
        let mut nm_broker = Broker::new();

        nm_broker
            .link_bi(
                self.nsh_broker.clone(),
                Self::nsh_net(nc_id.clone()),
                Self::net_nsh(nc_id),
            )
            .await?;
        self.nsh_broker
            .emit_msg(NSHubMessage::NewClient(nc.info.clone()))?;

        Ok((nc, nm_broker))
    }

    fn nsh_net(our_id: U256) -> Translate<NSHubMessage, NetworkMessage> {
        Box::new(move |msg| {
            if let NSHubMessage::ToClient(dst, net_msg) = msg {
                if dst == our_id {
                    return Some(net_msg);
                }
            }
            None
        })
    }

    fn net_nsh(our_id: U256) -> Translate<NetworkMessage, NSHubMessage> {
        Box::new(move |msg| Some(NSHubMessage::FromClient(our_id, msg)))
    }
}

#[derive(Clone, Debug, PartialEq)]
enum NSHubMessage {
    FromClient(U256, NetworkMessage),
    ToClient(U256, NetworkMessage),
    NewClient(NodeInfo),
}

struct NSHub {
    nodes: Vec<NodeInfo>,
}

impl NSHub {
    async fn new() -> Result<Broker<NSHubMessage>, BrokerError> {
        let mut b = Broker::new();
        b.add_subsystem(Subsystem::Handler(Box::new(Self { nodes: vec![] })))
            .await?;
        Ok(b)
    }

    fn net_msg(&self, id: U256, net_msg: NetworkMessage) -> Vec<NSHubMessage> {
        if let NetworkMessage::Call(msg) = net_msg {
            match msg {
                crate::network::NetCall::SendNodeMessage(id_dst, msg_node) => {
                    vec![NSHubMessage::ToClient(
                        id_dst,
                        NetworkMessage::Reply(NetReply::RcvNodeMessage(id, msg_node)),
                    )]
                }
                crate::network::NetCall::SendWSUpdateListRequest => {
                    vec![NSHubMessage::ToClient(
                        id,
                        NetworkMessage::Reply(NetReply::RcvWSUpdateList(self.nodes.clone())),
                    )]
                }
                _ => {
                    vec![]
                }
            }
        } else {
            vec![]
        }
    }
}

#[cfg_attr(feature = "nosend", async_trait(?Send))]
#[cfg_attr(not(feature = "nosend"), async_trait::async_trait)]
impl SubsystemHandler<NSHubMessage> for NSHub {
    async fn messages(&mut self, msgs: Vec<NSHubMessage>) -> Vec<NSHubMessage> {
        let mut out = vec![];

        for msg in msgs {
            match msg {
                NSHubMessage::FromClient(id, net_msg) => {
                    out.append(&mut self.net_msg(id, net_msg));
                }
                NSHubMessage::NewClient(info) => {
                    self.nodes.push(info);
                }
                _ => {}
            }
        }

        out.into_iter()
            .inspect(|msg| log::trace!("Sending message {:?}", msg))
            .map(|msg| msg)
            .collect()
    }
}