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