iroh_blobs/net_protocol.rs
1//! Adaptation of `iroh-blobs` as an [`iroh`] [`ProtocolHandler`].
2//!
3//! This is the easiest way to share data from a [`crate::api::Store`] over iroh connections.
4//!
5//! # Example
6//!
7//! ```rust
8//! # async fn example() -> anyhow::Result<()> {
9//! use iroh::{protocol::Router, Endpoint};
10//! use iroh_blobs::{store, ticket::BlobTicket, BlobsProtocol};
11//!
12//! // create a store
13//! let store = store::fs::FsStore::load("blobs").await?;
14//!
15//! // add some data
16//! let t = store.add_slice(b"hello world").await?;
17//!
18//! // create an iroh endpoint
19//! let endpoint = Endpoint::builder().discovery_n0().bind().await?;
20//! endpoint.online().await;
21//! let addr = endpoint.node_addr();
22//!
23//! // create a blobs protocol handler
24//! let blobs = BlobsProtocol::new(&store, None);
25//!
26//! // create a router and add the blobs protocol handler
27//! let router = Router::builder(endpoint)
28//! .accept(iroh_blobs::ALPN, blobs)
29//! .spawn();
30//!
31//! // this data is now globally available using the ticket
32//! let ticket = BlobTicket::new(addr, t.hash, t.format);
33//! println!("ticket: {}", ticket);
34//!
35//! // wait for control-c to exit
36//! tokio::signal::ctrl_c().await?;
37//! # Ok(())
38//! # }
39//! ```
40
41use std::{fmt::Debug, ops::Deref, sync::Arc};
42
43use iroh::{
44 endpoint::Connection,
45 protocol::{AcceptError, ProtocolHandler},
46};
47use tracing::error;
48
49use crate::{api::Store, provider::events::EventSender};
50
51#[derive(Debug)]
52pub(crate) struct BlobsInner {
53 store: Store,
54 events: EventSender,
55}
56
57/// A protocol handler for the blobs protocol.
58#[derive(Debug, Clone)]
59pub struct BlobsProtocol {
60 inner: Arc<BlobsInner>,
61}
62
63impl Deref for BlobsProtocol {
64 type Target = Store;
65
66 fn deref(&self) -> &Self::Target {
67 &self.inner.store
68 }
69}
70
71impl BlobsProtocol {
72 pub fn new(store: &Store, events: Option<EventSender>) -> Self {
73 Self {
74 inner: Arc::new(BlobsInner {
75 store: store.clone(),
76 events: events.unwrap_or(EventSender::DEFAULT),
77 }),
78 }
79 }
80
81 pub fn store(&self) -> &Store {
82 &self.inner.store
83 }
84}
85
86impl ProtocolHandler for BlobsProtocol {
87 async fn accept(&self, conn: Connection) -> std::result::Result<(), AcceptError> {
88 let store = self.store().clone();
89 let events = self.inner.events.clone();
90 crate::provider::handle_connection(conn, store, events).await;
91 Ok(())
92 }
93
94 async fn shutdown(&self) {
95 if let Err(cause) = self.store().shutdown().await {
96 error!("error shutting down store: {:?}", cause);
97 }
98 }
99}