common/peer/
peer_builder.rs1use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
2use std::sync::Arc;
3
4use iroh::discovery::pkarr::dht::DhtDiscovery;
5use iroh::Endpoint;
6
7pub use super::blobs_store::BlobsStore;
8
9use crate::bucket_log::BucketLogProvider;
10use crate::crypto::SecretKey;
11
12use super::peer_inner::Peer;
13use super::sync::SyncProvider;
14
15pub struct NeedsSyncProvider;
17
18pub struct ReadyToBuild;
20
21#[derive(Clone)]
25pub struct PeerBuilder<L: BucketLogProvider, State = ReadyToBuild> {
26 socket_address: Option<SocketAddr>,
29 secret_key: Option<SecretKey>,
31 blobs_store: Option<BlobsStore>,
33 log_provider: Option<L>,
34 sync_provider: Option<Arc<dyn SyncProvider<L>>>,
36 _state: std::marker::PhantomData<State>,
38}
39
40impl<L: BucketLogProvider, State> PeerBuilder<L, State> {
42 pub fn socket_address(mut self, socket_addr: SocketAddr) -> Self {
43 self.socket_address = Some(socket_addr);
44 self
45 }
46
47 pub fn secret_key(mut self, secret_key: SecretKey) -> Self {
48 self.secret_key = Some(secret_key);
49 self
50 }
51
52 pub fn blobs_store(mut self, blobs: BlobsStore) -> Self {
53 self.blobs_store = Some(blobs);
54 self
55 }
56
57 pub fn log_provider(mut self, log_provider: L) -> Self {
58 self.log_provider = Some(log_provider);
59 self
60 }
61}
62
63impl<L: BucketLogProvider> Default for PeerBuilder<L, NeedsSyncProvider> {
65 fn default() -> Self {
66 Self::new()
67 }
68}
69
70impl<L: BucketLogProvider> PeerBuilder<L, NeedsSyncProvider> {
71 pub fn new() -> Self {
75 PeerBuilder {
76 socket_address: None,
77 secret_key: None,
78 blobs_store: None,
79 log_provider: None,
80 sync_provider: None,
81 _state: std::marker::PhantomData,
82 }
83 }
84
85 pub fn with_sync_provider(
89 mut self,
90 provider: Arc<dyn SyncProvider<L>>,
91 ) -> PeerBuilder<L, ReadyToBuild> {
92 self.sync_provider = Some(provider);
93
94 PeerBuilder {
95 socket_address: self.socket_address,
96 secret_key: self.secret_key,
97 blobs_store: self.blobs_store,
98 log_provider: self.log_provider,
99 sync_provider: self.sync_provider,
100 _state: std::marker::PhantomData,
101 }
102 }
103}
104
105impl<L: BucketLogProvider> PeerBuilder<L, ReadyToBuild> {
107 pub async fn build(self) -> Peer<L> {
108 let socket_addr = self
110 .socket_address
111 .unwrap_or_else(|| SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0));
112 let secret_key = self.secret_key.unwrap_or_else(SecretKey::generate);
114
115 let blobs_store = match self.blobs_store {
117 Some(blobs) => blobs,
118 None => BlobsStore::memory().await.unwrap(),
119 };
120
121 let mainline_discovery = DhtDiscovery::builder()
123 .secret_key(secret_key.0.clone())
124 .build()
125 .expect("failed to build mainline discovery");
126
127 let addr = SocketAddrV4::new(
129 socket_addr
130 .ip()
131 .to_string()
132 .parse::<Ipv4Addr>()
133 .expect("failed to parse IP address"),
134 socket_addr.port(),
135 );
136
137 let endpoint = Endpoint::builder()
139 .secret_key(secret_key.0.clone())
140 .discovery(mainline_discovery)
141 .bind_addr_v4(addr)
142 .bind()
143 .await
144 .expect("failed to bind ephemeral endpoint");
145
146 let log_provider = self.log_provider.expect("log_provider is required");
148
149 let sync_provider = self.sync_provider.expect("sync_provider must be set");
150
151 Peer::new(
152 log_provider,
153 socket_addr,
154 blobs_store,
155 secret_key,
156 endpoint,
157 sync_provider,
158 )
159 }
160}