#![allow(non_snake_case)]
use crate::transport::memory_mock::transport_memory::TransportMemory;
use std::collections::{HashMap, VecDeque};
use lib3h_protocol::{
data_types::*, network_engine::NetworkEngine, protocol_client::Lib3hClientProtocol,
protocol_server::Lib3hServerProtocol, Address, DidWork, Lib3hResult,
};
use crate::{
dht::{
dht_event::{DhtEvent, PeerHoldRequestData},
dht_trait::Dht,
rrdht::RrDht,
},
p2p::{p2p_gateway::P2pGateway, p2p_protocol::P2pProtocol},
transport::transport_trait::Transport,
transport_space::TransportSpace,
transport_wss::TransportWss,
};
pub type PlayerId = (Address, Address);
#[derive(Debug, Clone, PartialEq)]
pub struct RealEngineConfig {
pub socket_type: String,
pub bootstrap_nodes: Vec<String>,
pub work_dir: String,
pub log_level: char,
}
pub struct RealEngine<T: Transport> {
_config: RealEngineConfig,
inbox: VecDeque<Lib3hClientProtocol>,
name: String,
transport_gateway: P2pGateway<T, RrDht>,
space_gateway_map: HashMap<PlayerId, P2pGateway<TransportSpace, RrDht>>,
}
impl RealEngine<TransportWss<std::net::TcpStream>> {
pub fn new(config: RealEngineConfig, name: &str) -> Lib3hResult<Self> {
Ok(RealEngine {
_config: config,
inbox: VecDeque::new(),
name: name.to_string(),
transport_gateway: P2pGateway::new_with_wss(),
space_gateway_map: HashMap::new(),
})
}
}
impl RealEngine<TransportMemory> {
pub fn new_mock(config: RealEngineConfig, name: &str) -> Lib3hResult<Self> {
Ok(RealEngine {
_config: config,
inbox: VecDeque::new(),
name: name.to_string(),
transport_gateway: P2pGateway::new_with_memory(name),
space_gateway_map: HashMap::new(),
})
}
}
impl<T: Transport> NetworkEngine for RealEngine<T> {
fn run(&self) -> Lib3hResult<()> {
Ok(())
}
fn stop(&self) -> Lib3hResult<()> {
Ok(())
}
fn terminate(&self) -> Lib3hResult<()> {
Ok(())
}
fn advertise(&self) -> String {
self.transport_gateway.advertise()
}
fn post(&mut self, client_msg: Lib3hClientProtocol) -> Lib3hResult<()> {
self.inbox.push_back(client_msg);
Ok(())
}
fn process(&mut self) -> Lib3hResult<(DidWork, Vec<Lib3hServerProtocol>)> {
let (did_work, mut outbox) = self.process_inbox()?;
let _ = self.process_transport_gateway()?;
let p2p_output = self.process_space_gateways()?;
let mut output = self.process_p2p(&p2p_output)?;
outbox.append(&mut output);
Ok((did_work, outbox))
}
}
impl<T: Transport> RealEngine<T> {
fn process_inbox(&mut self) -> Lib3hResult<(DidWork, Vec<Lib3hServerProtocol>)> {
let mut outbox = Vec::new();
let mut did_work = false;
loop {
let client_msg = match self.inbox.pop_front() {
None => break,
Some(msg) => msg,
};
let (success, mut output) = self.serve_Lib3hProtocol(client_msg)?;
if success {
did_work = success;
}
outbox.append(&mut output);
}
Ok((did_work, outbox))
}
fn process_transport_gateway(&mut self) -> Lib3hResult<DidWork> {
let (did_work, p2p_list) = self.transport_gateway.do_process()?;
if !did_work {
return Ok(false);
}
for p2p_msg in p2p_list {
self.serve_P2pProtocol(&p2p_msg)?;
}
Ok(true)
}
fn process_space_gateways(&mut self) -> Lib3hResult<Vec<P2pProtocol>> {
let mut output = Vec::new();
for (_space_address, space_gateway) in self.space_gateway_map.iter_mut() {
let (did_work, mut p2p_list) = space_gateway.do_process()?;
if did_work {
output.append(&mut p2p_list);
}
}
Ok(output)
}
fn process_p2p(&mut self, input: &Vec<P2pProtocol>) -> Lib3hResult<Vec<Lib3hServerProtocol>> {
let mut output = Vec::new();
for p2p_msg in input {
let mut evt_output = self.serve_P2pProtocol(p2p_msg)?;
output.append(&mut evt_output);
}
Ok(output)
}
fn serve_P2pProtocol(
&mut self,
p2p_msg: &P2pProtocol,
) -> Lib3hResult<Vec<Lib3hServerProtocol>> {
let outbox = Vec::new();
match p2p_msg {
P2pProtocol::Gossip => {
}
P2pProtocol::DirectMessage => {
}
P2pProtocol::FetchData => {
}
P2pProtocol::FetchDataResponse => {
}
};
Ok(outbox)
}
fn serve_Lib3hProtocol(
&mut self,
client_msg: Lib3hClientProtocol,
) -> Lib3hResult<(DidWork, Vec<Lib3hServerProtocol>)> {
println!("[d] >>>> '{}' recv: {:?}", self.name.clone(), client_msg);
let mut outbox = Vec::new();
let did_work = true;
match client_msg {
Lib3hClientProtocol::SuccessResult(_msg) => {
}
Lib3hClientProtocol::FailureResult(_msg) => {
}
Lib3hClientProtocol::Connect(msg) => {
self.transport_gateway.connect(&msg.peer_transport)?;
}
Lib3hClientProtocol::JoinSpace(msg) => {
let output = self.serve_JoinSpace(&msg)?;
outbox.push(output);
}
Lib3hClientProtocol::LeaveSpace(_msg) => {
}
Lib3hClientProtocol::SendDirectMessage(_msg) => {
}
Lib3hClientProtocol::HandleSendDirectMessageResult(_msg) => {
}
Lib3hClientProtocol::FetchEntry(_msg) => {
}
Lib3hClientProtocol::HandleFetchEntryResult(_msg) => {
}
Lib3hClientProtocol::PublishEntry(_msg) => {
}
Lib3hClientProtocol::HandleGetPublishingEntryListResult(_msg) => {
}
Lib3hClientProtocol::HandleGetHoldingEntryListResult(_msg) => {
}
}
Ok((did_work, outbox))
}
fn serve_JoinSpace(&mut self, join_msg: &SpaceData) -> Lib3hResult<Lib3hServerProtocol> {
let player_id = (join_msg.space_address.clone(), join_msg.agent_id.clone());
let mut res = ResultData {
request_id: join_msg.request_id.clone(),
space_address: join_msg.space_address.clone(),
to_agent_id: join_msg.agent_id.clone(),
result_info: vec![],
};
if self.space_gateway_map.contains_key(&player_id) {
res.result_info = "Already tracked".to_string().into_bytes();
return Ok(Lib3hServerProtocol::FailureResult(res));
}
self.space_gateway_map
.insert(player_id.clone(), P2pGateway::new_with_space());
let space_gateway = self.space_gateway_map.get_mut(&player_id).unwrap();
Dht::post(
space_gateway,
DhtEvent::PeerHoldRequest(PeerHoldRequestData {
peer_address: "FIXME".to_string(), transport: self.transport_gateway.id(),
timestamp: 42,
}),
)?;
Ok(Lib3hServerProtocol::SuccessResult(res))
}
}