tatami 0.1.2

A library for creating satellites and interacting with Tatami protocols.
Documentation
use std::fmt::Debug;

#[cfg(feature = "mdns")]
use libp2p::mdns::MdnsEvent;
use libp2p::{
	gossipsub::{GossipsubEvent, GossipsubMessage},
	kad::KademliaEvent,
	swarm::SwarmEvent,
};
#[cfg(feature = "mdns")]
use tracing::trace;
use tracing::{info, warn};

use crate::{
	satellite::{
		message::{Message, PeerMessage},
		TatamiEvent,
	},
	swarm::event::SatelliteSwamEvent,
	Satellite, TatamiError,
};

impl Satellite {
	/// The single function to parse and manage every Swarm event
	pub fn handle_swarm_event<T: Debug>(
		&mut self,
		event: SwarmEvent<SatelliteSwamEvent, T>,
	) -> Result<(), TatamiError> {
		match event {
			// Whenever a connection is established
			SwarmEvent::ConnectionEstablished { peer_id, .. } => {
				info!("Connection established with {}", peer_id);
				self.event_sender
					.send(TatamiEvent::ConnectionEstablished(peer_id))
					.or(Err(TatamiError::Breakdown))?;
			}
			// Whenever a connection is closed
			SwarmEvent::ConnectionClosed { peer_id, cause, .. } => {
				info!("Connection closed with {}", peer_id);
				warn!("Reason: {:#?}", cause);
				self.event_sender
					.send(TatamiEvent::ConnectionClosed(peer_id))
					.or(Err(TatamiError::Breakdown))?;
			}
			SwarmEvent::NewListenAddr { address, .. } => {
				info!("Now listening on {}", address);
				self.event_sender
					.send(TatamiEvent::NewListenAddress(address))
					.or(Err(TatamiError::Breakdown))?;
			}
			#[cfg(feature = "mdns")]
			SwarmEvent::Behaviour(SatelliteSwamEvent::Mdns(MdnsEvent::Discovered(discovered))) => {
				trace!("Discovered {:#?}", discovered);
				for (peer_id, multiaddr) in discovered {
					if self.config.mdns_config.auto_register {
						info!("Automatically registering {}", peer_id);
						self.add_address(&peer_id, multiaddr);
					}
				}
			}
			SwarmEvent::Behaviour(SatelliteSwamEvent::Kademlia(
				KademliaEvent::RoutingUpdated { peer, .. },
			)) => {
				info!("Satellite can see {}", peer);
				if self.config.auto_connect && !self.is_connected(&peer) {
					info!("Automatically dialling {}", peer);
					self.dial_peer(peer)?;
				}
			}
			SwarmEvent::Behaviour(SatelliteSwamEvent::GossipSub(GossipsubEvent::Message {
				message: GossipsubMessage { data, .. },
				..
			})) => {
				let message: Message =
					serde_json::from_slice(&data).or(Err(TatamiError::Generic))?;
				info!("Received message {:#?}", message);
				// Check the message
				if message.verify()? {
					let peer_message = PeerMessage {
						peer: message.source()?,
						payload: message.payload,
					};
					self.event_sender
						.send(TatamiEvent::MessageReceived(peer_message))
						.or(Err(TatamiError::Breakdown))?;
				}
			}
			// An undiagnosed event occurs
			_ => {
				info!("Undiagnosed Event: {:#?}", event);
				self.event_sender
					.send(TatamiEvent::UndiagnosedEvent)
					.or(Err(TatamiError::Breakdown))?;
			}
		}
		Ok(())
	}
}