use hotshot_types::traits::signature_key::SignatureKey;
use libp2p::{
autonat,
gossipsub::{Behaviour as GossipBehaviour, Event as GossipEvent, IdentTopic},
identify::{Behaviour as IdentifyBehaviour, Event as IdentifyEvent},
kad::store::MemoryStore,
request_response::{OutboundRequestId, ResponseChannel},
Multiaddr,
};
use libp2p_identity::PeerId;
use libp2p_swarm_derive::NetworkBehaviour;
use tracing::{debug, error};
use super::{
behaviours::dht::store::{file_backed::FileBackedStore, validated::ValidatedStore},
cbor, NetworkEventInternal,
};
#[derive(NetworkBehaviour, derive_more::Debug)]
#[behaviour(to_swarm = "NetworkEventInternal")]
pub struct NetworkDef<K: SignatureKey + 'static> {
#[debug(skip)]
gossipsub: GossipBehaviour,
#[debug(skip)]
pub dht: libp2p::kad::Behaviour<FileBackedStore<ValidatedStore<MemoryStore, K>>>,
#[debug(skip)]
identify: IdentifyBehaviour,
#[debug(skip)]
pub direct_message: cbor::Behaviour<Vec<u8>, Vec<u8>>,
#[debug(skip)]
pub autonat: libp2p::autonat::Behaviour,
}
impl<K: SignatureKey + 'static> NetworkDef<K> {
#[must_use]
pub fn new(
gossipsub: GossipBehaviour,
dht: libp2p::kad::Behaviour<FileBackedStore<ValidatedStore<MemoryStore, K>>>,
identify: IdentifyBehaviour,
direct_message: super::cbor::Behaviour<Vec<u8>, Vec<u8>>,
autonat: autonat::Behaviour,
) -> NetworkDef<K> {
Self {
gossipsub,
dht,
identify,
direct_message,
autonat,
}
}
}
impl<K: SignatureKey + 'static> NetworkDef<K> {
pub fn add_address(&mut self, peer_id: &PeerId, address: Multiaddr) {
self.dht.add_address(peer_id, address);
}
}
impl<K: SignatureKey + 'static> NetworkDef<K> {
pub fn publish_gossip(&mut self, topic: IdentTopic, contents: Vec<u8>) {
if let Err(e) = self.gossipsub.publish(topic, contents) {
tracing::warn!("Failed to publish gossip message. Error: {:?}", e);
}
}
pub fn subscribe_gossip(&mut self, t: &str) {
if let Err(e) = self.gossipsub.subscribe(&IdentTopic::new(t)) {
error!("Failed to subscribe to topic {:?}. Error: {:?}", t, e);
}
}
pub fn unsubscribe_gossip(&mut self, t: &str) {
if let Err(e) = self.gossipsub.unsubscribe(&IdentTopic::new(t)) {
error!("Failed to unsubscribe from topic {:?}. Error: {:?}", t, e);
}
}
}
impl<K: SignatureKey + 'static> NetworkDef<K> {
pub fn add_direct_request(&mut self, peer_id: PeerId, data: Vec<u8>) -> OutboundRequestId {
self.direct_message.send_request(&peer_id, data)
}
pub fn add_direct_response(&mut self, chan: ResponseChannel<Vec<u8>>, msg: Vec<u8>) {
let _ = self.direct_message.send_response(chan, msg);
}
}
impl From<GossipEvent> for NetworkEventInternal {
fn from(event: GossipEvent) -> Self {
Self::GossipEvent(Box::new(event))
}
}
impl From<libp2p::kad::Event> for NetworkEventInternal {
fn from(event: libp2p::kad::Event) -> Self {
Self::DHTEvent(event)
}
}
impl From<IdentifyEvent> for NetworkEventInternal {
fn from(event: IdentifyEvent) -> Self {
Self::IdentifyEvent(Box::new(event))
}
}
impl From<libp2p::request_response::Event<Vec<u8>, Vec<u8>>> for NetworkEventInternal {
fn from(value: libp2p::request_response::Event<Vec<u8>, Vec<u8>>) -> Self {
Self::DMEvent(value)
}
}
impl From<libp2p::autonat::Event> for NetworkEventInternal {
fn from(event: libp2p::autonat::Event) -> Self {
Self::AutonatEvent(event)
}
}