1
- use std:: { path:: PathBuf , str :: FromStr } ;
1
+ use std:: path:: PathBuf ;
2
2
3
3
use anyhow:: Result ;
4
4
use iroh:: { protocol:: Router , Endpoint } ;
5
5
use iroh_blobs:: {
6
6
net_protocol:: Blobs ,
7
- rpc:: client:: blobs:: { ReadAtLen , WrapOption } ,
7
+ rpc:: client:: blobs:: WrapOption ,
8
+ store:: { ExportFormat , ExportMode } ,
8
9
ticket:: BlobTicket ,
9
10
util:: SetTagOption ,
10
11
} ;
@@ -19,41 +20,53 @@ async fn main() -> Result<()> {
19
20
20
21
// Now we build a router that accepts blobs connections & routes them
21
22
// to the blobs protocol.
22
- let node = Router :: builder ( endpoint)
23
+ let router = Router :: builder ( endpoint)
23
24
. accept ( iroh_blobs:: ALPN , blobs. clone ( ) )
24
25
. spawn ( )
25
26
. await ?;
26
27
27
- let blobs = blobs. client ( ) ;
28
+ // We use a blobs client to interact with the blobs protocol we're running locally:
29
+ let blobs_client = blobs. client ( ) ;
28
30
29
- let args = std :: env :: args ( ) . collect :: < Vec < _ > > ( ) ;
30
- match & args. iter ( ) . map ( String :: as_str ) . collect :: < Vec < _ > > ( ) [ .. ] {
31
- [ _cmd , "send" , path ] => {
32
- let abs_path = PathBuf :: from_str ( path ) ? . canonicalize ( ) ? ;
31
+ // Grab all passed in arguments, the first one is the binary itself, so we skip it.
32
+ let args: Vec < String > = std :: env :: args ( ) . skip ( 1 ) . collect ( ) ;
33
+ // Convert to &str, so we can pattern-match easily:
34
+ let arg_refs : Vec < & str > = args . iter ( ) . map ( String :: as_str ) . collect ( ) ;
33
35
34
- println ! ( "Analyzing file." ) ;
36
+ match arg_refs. as_slice ( ) {
37
+ [ "send" , filename] => {
38
+ let filename: PathBuf = filename. parse ( ) ?;
39
+ let abs_path = std:: path:: absolute ( & filename) ?;
35
40
36
- let blob = blobs
37
- . add_from_path ( abs_path, true , SetTagOption :: Auto , WrapOption :: NoWrap )
41
+ println ! ( "Hashing file." ) ;
42
+
43
+ // keep the file in place and link it, instead of copying it into the in-memory blobs database
44
+ let in_place = true ;
45
+ let blob = blobs_client
46
+ . add_from_path ( abs_path, in_place, SetTagOption :: Auto , WrapOption :: NoWrap )
38
47
. await ?
39
48
. finish ( )
40
49
. await ?;
41
50
42
- let node_id = node . endpoint ( ) . node_id ( ) ;
51
+ let node_id = router . endpoint ( ) . node_id ( ) ;
43
52
let ticket = BlobTicket :: new ( node_id. into ( ) , blob. hash , blob. format ) ?;
44
53
45
- println ! ( "File analyzed. Fetch this file by running:" ) ;
46
- println ! ( "cargo run --example transfer -- receive {ticket} {path}" ) ;
54
+ println ! ( "File hashed. Fetch this file by running:" ) ;
55
+ println ! (
56
+ "cargo run --example transfer -- receive {ticket} {}" ,
57
+ filename. display( )
58
+ ) ;
47
59
48
60
tokio:: signal:: ctrl_c ( ) . await ?;
49
61
}
50
- [ _cmd, "receive" , ticket, path] => {
51
- let path_buf = PathBuf :: from_str ( path) ?;
52
- let ticket = BlobTicket :: from_str ( ticket) ?;
62
+ [ "receive" , ticket, filename] => {
63
+ let filename: PathBuf = filename. parse ( ) ?;
64
+ let abs_path = std:: path:: absolute ( filename) ?;
65
+ let ticket: BlobTicket = ticket. parse ( ) ?;
53
66
54
67
println ! ( "Starting download." ) ;
55
68
56
- blobs
69
+ blobs_client
57
70
. download ( ticket. hash ( ) , ticket. node_addr ( ) . clone ( ) )
58
71
. await ?
59
72
. finish ( )
@@ -62,14 +75,21 @@ async fn main() -> Result<()> {
62
75
println ! ( "Finished download." ) ;
63
76
println ! ( "Copying to destination." ) ;
64
77
65
- let mut file = tokio:: fs:: File :: create ( path_buf) . await ?;
66
- let mut reader = blobs. read_at ( ticket. hash ( ) , 0 , ReadAtLen :: All ) . await ?;
67
- tokio:: io:: copy ( & mut reader, & mut file) . await ?;
78
+ blobs_client
79
+ . export (
80
+ ticket. hash ( ) ,
81
+ abs_path,
82
+ ExportFormat :: Blob ,
83
+ ExportMode :: Copy ,
84
+ )
85
+ . await ?
86
+ . finish ( )
87
+ . await ?;
68
88
69
89
println ! ( "Finished copying." ) ;
70
90
}
71
91
_ => {
72
- println ! ( "Couldn't parse command line arguments. " ) ;
92
+ println ! ( "Couldn't parse command line arguments: {args:?} " ) ;
73
93
println ! ( "Usage:" ) ;
74
94
println ! ( " # to send:" ) ;
75
95
println ! ( " cargo run --example transfer -- send [FILE]" ) ;
@@ -82,7 +102,7 @@ async fn main() -> Result<()> {
82
102
83
103
// Gracefully shut down the node
84
104
println ! ( "Shutting down." ) ;
85
- node . shutdown ( ) . await ?;
105
+ router . shutdown ( ) . await ?;
86
106
87
107
Ok ( ( ) )
88
108
}
0 commit comments