every.channel/third_party/iroh-org/iroh-gossip/README.md
2026-02-15 16:17:27 -05:00

93 lines
3.7 KiB
Markdown

# iroh-gossip
This crate implements the `iroh-gossip` protocol.
It is based on *epidemic broadcast trees* to disseminate messages among a swarm of peers interested in a *topic*.
The implementation is based on the papers [HyParView](https://asc.di.fct.unl.pt/~jleitao/pdf/dsn07-leitao.pdf) and [PlumTree](https://asc.di.fct.unl.pt/~jleitao/pdf/srds07-leitao.pdf).
The crate is made up from two modules:
The `proto` module is the protocol implementation, as a state machine without any IO.
The `net` module implements networking logic for running `iroh-gossip` on `iroh` connections.
The `net` module is optional behind the `net` feature flag (enabled by default).
# Getting Started
The `iroh-gossip` protocol was designed to be used in conjunction with `iroh`. [Iroh](https://docs.rs/iroh) is a networking library for making direct connections, these connections are how gossip messages are sent.
Iroh provides a [`Router`](https://docs.rs/iroh/latest/iroh/protocol/struct.Router.html) that takes an [`Endpoint`](https://docs.rs/iroh/latest/iroh/endpoint/struct.Endpoint.html) and any protocols needed for the application. Similar to a router in webserver library, it runs a loop accepting incoming connections and routes them to the specific protocol handler, based on `ALPN`.
Here is a basic example of how to set up `iroh-gossip` with `iroh`:
```rust,no_run
use iroh::{protocol::Router, Endpoint, EndpointId};
use iroh_gossip::{api::Event, Gossip, TopicId};
use n0_error::{Result, StdResultExt};
use n0_future::StreamExt;
#[tokio::main]
async fn main() -> Result<()> {
// create an iroh endpoint that includes the standard discovery mechanisms
// we've built at number0
let endpoint = Endpoint::bind().await?;
// build gossip protocol
let gossip = Gossip::builder().spawn(endpoint.clone());
// setup router
let router = Router::builder(endpoint)
.accept(iroh_gossip::ALPN, gossip.clone())
.spawn();
// gossip swarms are centered around a shared "topic id", which is a 32 byte identifier
let topic_id = TopicId::from_bytes([23u8; 32]);
// and you need some bootstrap peers to join the swarm
let bootstrap_peers = bootstrap_peers();
// then, you can subscribe to the topic and join your initial peers
let (sender, mut receiver) = gossip
.subscribe(topic_id, bootstrap_peers)
.await?
.split();
// you might want to wait until you joined at least one other peer:
receiver.joined().await?;
// then, you can broadcast messages to all other peers!
sender.broadcast(b"hello world this is a gossip message".to_vec().into()).await?;
// and read messages from others!
while let Some(event) = receiver.next().await {
match event? {
Event::Received(message) => {
println!("received a message: {:?}", std::str::from_utf8(&message.content));
}
_ => {}
}
}
// clean shutdown makes sure that other peers are notified that you went offline
router.shutdown().await.std_context("shutdown router")?;
Ok(())
}
fn bootstrap_peers() -> Vec<EndpointId> {
// insert your bootstrap peers here, or get them from your environment
vec![]
}
```
# License
This project is licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
<http://www.apache.org/licenses/LICENSE-2.0>)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or
<http://opensource.org/licenses/MIT>)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this project by you, as defined in the Apache-2.0 license,
shall be dual licensed as above, without any additional terms or conditions.