#![allow(non_snake_case)]
use crate::{
dht::{
dht_event::{DhtEvent, PeerHoldRequestData},
dht_trait::Dht,
rrdht::RrDht,
},
p2p::p2p_protocol::P2pProtocol,
transport::{
error::TransportResult,
memory_mock::transport_memory::TransportMemory,
protocol::{TransportCommand, TransportEvent},
transport_trait::Transport,
TransportId, TransportIdRef,
},
transport_space::TransportSpace,
transport_wss::TransportWss,
};
use lib3h_protocol::{AddressRef, DidWork, Lib3hResult};
pub struct P2pGateway<T: Transport, D: Dht> {
transport: T,
dht: D,
advertise: String,
}
impl P2pGateway<TransportMemory, RrDht> {
pub fn new_with_memory(name: &str) -> Self {
let mut gateway = P2pGateway {
transport: TransportMemory::new(),
dht: RrDht::new(),
advertise: String::new(),
};
let binding = gateway
.bind(name)
.expect("TransportMemory.bind() failed. url/name might not be unique?");
gateway.advertise = binding;
gateway
}
}
impl P2pGateway<TransportWss<std::net::TcpStream>, RrDht> {
pub fn new_with_wss() -> Self {
P2pGateway {
transport: TransportWss::with_std_tcp_stream(),
dht: RrDht::new(),
advertise: String::new(),
}
}
}
impl P2pGateway<TransportSpace, RrDht> {
pub fn new_with_space() -> Self {
P2pGateway {
transport: TransportSpace::new(),
dht: RrDht::new(),
advertise: String::new(),
}
}
}
impl<T: Transport, D: Dht> P2pGateway<T, D> {
pub fn id(&self) -> String {
"FIXME_ID".to_string()
}
pub fn advertise(&self) -> String {
self.advertise.clone()
}
}
impl<T: Transport, D: Dht> Dht for P2pGateway<T, D> {
fn get_peer(&self, peer_address: &str) -> Option<PeerHoldRequestData> {
self.dht.get_peer(peer_address)
}
fn fetch_peer(&self, peer_address: &str) -> Option<PeerHoldRequestData> {
self.dht.fetch_peer(peer_address)
}
fn drop_peer(&self, peer_address: &str) -> Lib3hResult<()> {
self.dht.drop_peer(peer_address)
}
fn get_data(&self, data_address: &AddressRef) -> Lib3hResult<Vec<u8>> {
self.dht.get_data(data_address)
}
fn fetch_data(&self, data_address: &AddressRef) -> Lib3hResult<Vec<u8>> {
self.dht.fetch_data(data_address)
}
fn post(&mut self, evt: DhtEvent) -> Lib3hResult<()> {
self.dht.post(evt)
}
fn process(&mut self) -> Lib3hResult<(DidWork, Vec<DhtEvent>)> {
self.dht.process()
}
fn this_peer(&self) -> Lib3hResult<()> {
self.dht.this_peer()
}
}
impl<T: Transport, D: Dht> Transport for P2pGateway<T, D> {
fn connect(&mut self, uri: &str) -> TransportResult<TransportId> {
self.transport.connect(&uri)
}
fn close(&mut self, id: &TransportIdRef) -> TransportResult<()> {
self.transport.close(id)
}
fn close_all(&mut self) -> TransportResult<()> {
self.transport.close_all()
}
fn send(&mut self, id_list: &[&TransportIdRef], payload: &[u8]) -> TransportResult<()> {
self.transport.send(id_list, payload)
}
fn send_all(&mut self, payload: &[u8]) -> TransportResult<()> {
self.transport.send_all(payload)
}
fn bind(&mut self, url: &str) -> TransportResult<String> {
self.transport.bind(url)
}
fn post(&mut self, command: TransportCommand) -> TransportResult<()> {
self.transport.post(command)
}
fn process(&mut self) -> TransportResult<(DidWork, Vec<TransportEvent>)> {
self.transport.process()
}
fn transport_id_list(&self) -> TransportResult<Vec<TransportId>> {
self.transport.transport_id_list()
}
}
impl<T: Transport, D: Dht> P2pGateway<T, D> {
pub fn do_process(&mut self) -> Lib3hResult<(DidWork, Vec<P2pProtocol>)> {
let mut outbox = Vec::new();
let (did_work, event_list) = self.transport.process()?;
if did_work {
for evt in event_list {
let mut p2p_output = self.serve_TransportEvent(&evt)?;
outbox.append(&mut p2p_output);
}
}
let (did_work, dht_event_list) = self.dht.process()?;
if did_work {
for evt in dht_event_list {
let (did_work, mut p2p_output) = self.serve_DhtEvent(evt)?;
if did_work {
outbox.append(&mut p2p_output);
}
}
}
Ok((did_work, outbox))
}
}
impl<T: Transport, D: Dht> P2pGateway<T, D> {
fn serve_TransportEvent(&mut self, evt: &TransportEvent) -> Lib3hResult<Vec<P2pProtocol>> {
println!("(log.d) >>> '(TransportGateway)' recv: {:?}", evt);
let mut outbox: Vec<P2pProtocol> = Vec::new();
match evt {
TransportEvent::TransportError(id, e) => {
println!(
"(log.e) Connection Error for {}: {}\n Closing connection.",
id, e
);
self.transport.close(id)?;
}
TransportEvent::ConnectResult(id) => {
println!("(log.i) Connection opened: {}", id);
}
TransportEvent::Closed(id) => {
println!("(log.w) Connection closed: {}", id);
self.transport.close(id)?;
}
TransportEvent::Received(id, msg) => {
println!("(log.d) Received message from: {}", id);
let p2p_msg = match P2pProtocol::deserialize(msg) {
Err(e) => {
println!("(log.e) Payload failed to deserialize: {:?}", msg);
return Err(e);
}
Ok(obj) => obj,
};
outbox = self.serve_P2pProtocol(&p2p_msg)?;
}
};
Ok(outbox)
}
fn serve_P2pProtocol(&mut self, p2p_msg: &P2pProtocol) -> Lib3hResult<Vec<P2pProtocol>> {
let outbox = Vec::new();
match p2p_msg {
P2pProtocol::Gossip => {
}
P2pProtocol::DirectMessage => {
}
P2pProtocol::FetchData => {
}
P2pProtocol::FetchDataResponse => {
}
};
Ok(outbox)
}
fn serve_DhtEvent(&mut self, evt: DhtEvent) -> Lib3hResult<(DidWork, Vec<P2pProtocol>)> {
let outbox = Vec::new();
let did_work = false;
match evt {
DhtEvent::RemoteGossipBundle(_data) => {
}
DhtEvent::GossipTo(_data) => {
}
DhtEvent::UnreliableGossipTo(_data) => {
}
DhtEvent::PeerHoldRequest(_data) => {
}
DhtEvent::PeerTimedOut(_peer_address) => {
}
DhtEvent::DataHoldRequest(_data) => {
}
DhtEvent::DataFetch(_data) => {
}
DhtEvent::DataFetchResponse(_data) => {
}
DhtEvent::DataPrune(_peer_address) => {
}
}
Ok((did_work, outbox))
}
}