我正在寻找使用 mDNS、floodsub 和 kademlia DHT 编写网络行为。到目前为止,我已经让这些服务中的每一个都可以工作,但是还不能将这些服务的响应用于任何有意义的事情。
理想情况下,我能够将来自行为过程事件的数据(例如为 Kad DHT 实现的事件)传输到主 Swarmpoll
循环中。例如,在我的例子中,我引用了一个结构,该结构表示通过sled
数据库持久化到磁盘的图形。该结构的所有权存在于轮询 swarm 的方法中。收到a 后,我将如何更新此图表(例如添加条目)KademliaEvent
?
我尝试过的解决方案:
- 将我想要更新的数据结构的所有权转移到
ClientBehavior
结构中,这样我就可以self.my_data_structure.add(result);
从KademliaEvent
inject_event
方法 中获取#[derive(NetworkBehaviour)]
根本不喜欢这个Graph
只是一个结构,不会发出任何事件/实现NetworkBehaviour
- 创建一个
Context
结构体,derive
该结构体可用于在轮询方法和相应方法NetworkBehaviour
之间来回传递响应inject_event
#[derive(NetworkBehaviour)]
不适合Arc
s /Mutex
es
这是我的 NetworkBehavior 的样子:
/// A network behavior describing a client connected to a pub-sub compatible,
/// optionally mDNS-compatible network. Such a "behavior" may be implemented for
/// any libp2p transport, but any transport used with this behavior must implement
/// asynchronous reading & writing capabilities.
#[derive(NetworkBehaviour)]
pub struct ClientBehavior<TSubstream: AsyncRead + AsyncWrite + Send + Unpin + 'static> {
/// Some pubsub mechanism bound to the above transport
pub floodsub: Floodsub<TSubstream>,
/// Some mDNS service bound to the above transport
pub mdns: Mdns<TSubstream>,
/// Allow for the client to do some external discovery on the global network through a KAD DHT
pub kad_dht: Kademlia<TSubstream, MemoryStore>,
}
以及我的 KademliaNetworkBehaviourEventProceess
实现是什么样的:
impl<TSubstream: AsyncRead + AsyncWrite + Send + Unpin + 'static>
NetworkBehaviourEventProcess<KademliaEvent> for ClientBehavior<TSubstream>
{
fn inject_event(&mut self, event: KademliaEvent) {
// Some behavior logic, nothing special, really, just a bunch of matches
// NOTE: this is when I'd want to update the `Graph`, since KademliaEvent will contain data that I need to put in the `Graph` instance
}
}
以及我如何产生我Swarm
的和我的ClientBehavior
:
// Initialize a new behavior for a client that we will generate in the not-so-distant future with the given peerId, alongside
// an mDNS service handler as well as a floodsub instance targeted at the given peer
let mut behavior = ClientBehavior {
floodsub: Floodsub::new(self.peer_id.clone()),
mdns: Mdns::new().await?,
kad_dht: Kademlia::new(self.peer_id.clone(), store),
};
// Iterate through bootstrap addresses
for bootstrap_peer in bootstrap_addresses {
// NOTE: add_address is a method that isn't provided by #[derive(NetworkBehaviour)].
// It's just a helper method I wrote that adds the peer to the Floodsub & DHT views.
behavior.add_address(&bootstrap_peer.0, bootstrap_peer.1); // Add the bootstrap peer to the DHT
}
// Bootstrap the behavior's DHT
behavior.kad_dht.bootstrap();
// Note: here, `self` is a reference to a configuration struct holding a peer ID, and a keypair
let mut swarm = Swarm::new(
libp2p::build_tcp_ws_secio_mplex_yamux(self.keypair.clone())?,
behavior,
self.peer_id.clone(),
); // Initialize a swarm
以及我如何轮询群体:
// NOTE: Here, `self` has ownership of the aforementioned `Graph` instance. I'd like to update this
// instance from this block, or from the ClientBehavior itself--as long as I'm able to update it once a `KademliaEvent` is received.
// Try to get the address we'll listen on
if let Ok(addr) = format!("/ip4/0.0.0.0/tcp/{}", port).parse::<Multiaddr>() {
// Try to tell the swarm to listen on this address, return an error if this doesn't work
if let Err(e) = Swarm::listen_on(&mut swarm, addr.clone()) {
// Convert the addr err into an io error
let e: std::io::Error = io::ErrorKind::AddrNotAvailable.into();
// Return an error
return Err(e.into());
};
// Fetch the hash of the first transaction in the DAG from the network
swarm
.kad_dht
.get_record(&Key::new(&sync::ROOT_TRANSACTION_KEY), Quorum::Majority);
loop {
// Poll the swarm
match swarm.next_event().await {
// NOTE: Initially, I was under the impression that I would be able to intercept
// events from the ClientBehavior here. Yet, the below info! call is never reached.
// This remains the case in libp2p example code that I have experimented with.
SwarmEvent::Behaviour(e) => info!("idk: {:?}", e),
_ => debug!("Some other event; this is handled specifically in the actual codebase, but for this question, all I really care about is the above behavior event."),
};
}
}
我只需要实现NetworkBehaviour
自己吗?