Skip to content

Commit 4db6033

Browse files
committed
docs: Update the transfer example to iroh 0.90
1 parent 845e37c commit 4db6033

File tree

1 file changed

+113
-0
lines changed

1 file changed

+113
-0
lines changed

examples/transfer.rs

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
use std::path::PathBuf;
2+
3+
use anyhow::Result;
4+
use iroh::{protocol::Router, Endpoint};
5+
use iroh_blobs::{
6+
api::blobs::{AddPathOptions, ExportMode, ExportOptions, ImportMode},
7+
net_protocol::Blobs,
8+
store::mem::MemStore,
9+
ticket::BlobTicket,
10+
BlobFormat,
11+
};
12+
13+
#[tokio::main]
14+
async fn main() -> Result<()> {
15+
// Create an endpoint, it allows creating and accepting
16+
// connections in the iroh p2p world
17+
let endpoint = Endpoint::builder().discovery_n0().bind().await?;
18+
// We initialize an in-memory backing store for iroh-blobs
19+
let store = MemStore::new();
20+
// Then we initialize a struct that can accept blobs requests over iroh connections
21+
let blobs = Blobs::new(&store, endpoint.clone(), None);
22+
23+
// Grab all passed in arguments, the first one is the binary itself, so we skip it.
24+
let args: Vec<String> = std::env::args().skip(1).collect();
25+
// Convert to &str, so we can pattern-match easily:
26+
let arg_refs: Vec<&str> = args.iter().map(String::as_str).collect();
27+
28+
match arg_refs.as_slice() {
29+
["send", filename] => {
30+
// For sending files we build a router that accepts blobs connections & routes them
31+
// to the blobs protocol.
32+
let router = Router::builder(endpoint)
33+
.accept(iroh_blobs::ALPN, blobs)
34+
.spawn();
35+
36+
let filename: PathBuf = filename.parse()?;
37+
let abs_path = std::path::absolute(&filename)?;
38+
39+
println!("Hashing file.");
40+
41+
// When we import a blob, we get back a tag that refers to said blob in the store
42+
// and allows us to control when/if it gets garbage-collected
43+
let tag = store
44+
.blobs()
45+
.add_path_with_opts(AddPathOptions {
46+
path: abs_path,
47+
format: BlobFormat::Raw,
48+
mode: ImportMode::TryReference,
49+
})
50+
.await?;
51+
52+
let node_id = router.endpoint().node_id();
53+
let ticket = BlobTicket::new(node_id.into(), tag.hash, tag.format);
54+
55+
println!("File hashed. Fetch this file by running:");
56+
println!(
57+
"cargo run --example transfer -- receive {ticket} {}",
58+
filename.display()
59+
);
60+
61+
tokio::signal::ctrl_c().await?;
62+
63+
// Gracefully shut down the node
64+
println!("Shutting down.");
65+
router.shutdown().await?;
66+
}
67+
["receive", ticket, filename] => {
68+
// For receiving files, we create a "downloader" that allows us to fetch files
69+
// from other nodes via iroh connections
70+
let downloader = store.downloader(&endpoint);
71+
72+
let filename: PathBuf = filename.parse()?;
73+
let abs_path = std::path::absolute(filename)?;
74+
let ticket: BlobTicket = ticket.parse()?;
75+
76+
println!("Starting download.");
77+
78+
downloader
79+
.download(ticket.hash(), Some(ticket.node_addr().node_id))
80+
.await?;
81+
82+
println!("Finished download.");
83+
println!("Copying to destination.");
84+
85+
store
86+
.blobs()
87+
.export_with_opts(ExportOptions {
88+
hash: ticket.hash(),
89+
mode: ExportMode::TryReference,
90+
target: abs_path,
91+
})
92+
.await?;
93+
94+
println!("Finished copying.");
95+
96+
// Gracefully shut down the node
97+
println!("Shutting down.");
98+
endpoint.close().await;
99+
}
100+
_ => {
101+
println!("Couldn't parse command line arguments: {args:?}");
102+
println!("Usage:");
103+
println!(" # to send:");
104+
println!(" cargo run --example transfer -- send [FILE]");
105+
println!(" # this will print a ticket.");
106+
println!();
107+
println!(" # to receive:");
108+
println!(" cargo run --example transfer -- receive [TICKET] [FILE]");
109+
}
110+
}
111+
112+
Ok(())
113+
}

0 commit comments

Comments
 (0)