libp2p/
builder.rs

1use std::marker::PhantomData;
2
3mod phase;
4mod select_muxer;
5mod select_security;
6
7#[cfg(all(not(target_arch = "wasm32"), feature = "websocket"))]
8pub use phase::WebsocketError;
9pub use phase::{BehaviourError, TransportError};
10
11/// Build a [`Swarm`](libp2p_swarm::Swarm) by combining an identity, a set of
12/// [`Transport`](libp2p_core::Transport)s and a
13/// [`NetworkBehaviour`](libp2p_swarm::NetworkBehaviour).
14///
15/// ```
16/// # use libp2p::{swarm::NetworkBehaviour, SwarmBuilder};
17/// # use libp2p::core::transport::dummy::DummyTransport;
18/// # use libp2p::core::muxing::StreamMuxerBox;
19/// # use libp2p::identity::PeerId;
20/// # use std::error::Error;
21/// #
22/// # #[cfg(all(
23/// #     not(target_arch = "wasm32"),
24/// #     feature = "tokio",
25/// #     feature = "tcp",
26/// #     feature = "tls",
27/// #     feature = "noise",
28/// #     feature = "quic",
29/// #     feature = "dns",
30/// #     feature = "relay",
31/// #     feature = "websocket",
32/// # ))]
33/// # async fn build_swarm() -> Result<(), Box<dyn Error>> {
34/// #     #[derive(NetworkBehaviour)]
35/// #     #[behaviour(prelude = "libp2p_swarm::derive_prelude")]
36/// #     struct MyBehaviour {
37/// #         relay: libp2p_relay::client::Behaviour,
38/// #     }
39///
40/// let swarm = SwarmBuilder::with_new_identity()
41///     .with_tokio()
42///     .with_tcp(
43///         Default::default(),
44///         (libp2p_tls::Config::new, libp2p_noise::Config::new),
45///         libp2p_yamux::Config::default,
46///     )?
47///     .with_quic()
48///     .with_other_transport(|_key| DummyTransport::<(PeerId, StreamMuxerBox)>::new())?
49///     .with_dns()?
50///     .with_websocket(
51///         (libp2p_tls::Config::new, libp2p_noise::Config::new),
52///         libp2p_yamux::Config::default,
53///     )
54///     .await?
55///     .with_relay_client(
56///         (libp2p_tls::Config::new, libp2p_noise::Config::new),
57///         libp2p_yamux::Config::default,
58///     )?
59///     .with_behaviour(|_key, relay| MyBehaviour { relay })?
60///     .with_swarm_config(|cfg| {
61///         // Edit cfg here.
62///         cfg
63///     })
64///     .build();
65/// #
66/// #     Ok(())
67/// # }
68/// ```
69pub struct SwarmBuilder<Provider, Phase> {
70    keypair: libp2p_identity::Keypair,
71    phantom: PhantomData<Provider>,
72    phase: Phase,
73}
74
75#[cfg(test)]
76mod tests {
77    use libp2p_core::{muxing::StreamMuxerBox, transport::dummy::DummyTransport};
78    use libp2p_identity::PeerId;
79    use libp2p_swarm::NetworkBehaviour;
80
81    use crate::SwarmBuilder;
82
83    #[test]
84    #[cfg(all(
85        feature = "tokio",
86        feature = "tcp",
87        feature = "tls",
88        feature = "noise",
89        feature = "yamux",
90    ))]
91    fn tcp() {
92        let _ = SwarmBuilder::with_new_identity()
93            .with_tokio()
94            .with_tcp(
95                Default::default(),
96                libp2p_tls::Config::new,
97                libp2p_yamux::Config::default,
98            )
99            .unwrap()
100            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
101            .unwrap()
102            .build();
103    }
104
105    #[test]
106    #[cfg(all(feature = "tokio", feature = "quic"))]
107    fn quic() {
108        let _ = SwarmBuilder::with_new_identity()
109            .with_tokio()
110            .with_quic()
111            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
112            .unwrap()
113            .build();
114    }
115
116    #[test]
117    #[cfg(all(feature = "tokio", feature = "quic"))]
118    fn quic_config() {
119        let _ = SwarmBuilder::with_new_identity()
120            .with_tokio()
121            .with_quic_config(|config| config)
122            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
123            .unwrap()
124            .build();
125    }
126
127    #[test]
128    #[cfg(all(feature = "tokio", feature = "tcp", feature = "tls", feature = "yamux"))]
129    fn tcp_yamux_mplex() {
130        let _ = SwarmBuilder::with_new_identity()
131            .with_tokio()
132            .with_tcp(
133                Default::default(),
134                libp2p_tls::Config::new,
135                (libp2p_yamux::Config::default, libp2p_mplex::Config::default),
136            )
137            .unwrap()
138            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
139            .unwrap()
140            .build();
141    }
142
143    #[test]
144    #[cfg(all(
145        feature = "tokio",
146        feature = "tcp",
147        feature = "tls",
148        feature = "noise",
149        feature = "yamux"
150    ))]
151    fn tcp_tls_noise() {
152        let _ = SwarmBuilder::with_new_identity()
153            .with_tokio()
154            .with_tcp(
155                Default::default(),
156                (libp2p_tls::Config::new, libp2p_noise::Config::new),
157                (libp2p_yamux::Config::default, libp2p_mplex::Config::default),
158            )
159            .unwrap()
160            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
161            .unwrap()
162            .build();
163    }
164
165    #[test]
166    #[cfg(all(
167        feature = "tokio",
168        feature = "tcp",
169        feature = "tls",
170        feature = "noise",
171        feature = "yamux",
172        feature = "quic"
173    ))]
174    fn tcp_quic() {
175        let _ = SwarmBuilder::with_new_identity()
176            .with_tokio()
177            .with_tcp(
178                Default::default(),
179                (libp2p_tls::Config::new, libp2p_noise::Config::new),
180                libp2p_yamux::Config::default,
181            )
182            .unwrap()
183            .with_quic()
184            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
185            .unwrap()
186            .build();
187    }
188
189    #[test]
190    #[cfg(all(
191        feature = "tokio",
192        feature = "tcp",
193        feature = "tls",
194        feature = "noise",
195        feature = "yamux",
196        feature = "quic"
197    ))]
198    fn tcp_quic_config() {
199        let _ = SwarmBuilder::with_new_identity()
200            .with_tokio()
201            .with_tcp(
202                Default::default(),
203                (libp2p_tls::Config::new, libp2p_noise::Config::new),
204                libp2p_yamux::Config::default,
205            )
206            .unwrap()
207            .with_quic_config(|config| config)
208            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
209            .unwrap()
210            .build();
211    }
212
213    #[test]
214    #[cfg(all(
215        feature = "tokio",
216        feature = "tcp",
217        feature = "tls",
218        feature = "noise",
219        feature = "yamux",
220        feature = "relay"
221    ))]
222    fn tcp_relay() {
223        #[derive(libp2p_swarm::NetworkBehaviour)]
224        #[behaviour(prelude = "libp2p_swarm::derive_prelude")]
225        struct Behaviour {
226            dummy: libp2p_swarm::dummy::Behaviour,
227            relay: libp2p_relay::client::Behaviour,
228        }
229
230        let _ = SwarmBuilder::with_new_identity()
231            .with_tokio()
232            .with_tcp(
233                Default::default(),
234                libp2p_tls::Config::new,
235                libp2p_yamux::Config::default,
236            )
237            .unwrap()
238            .with_relay_client(libp2p_tls::Config::new, libp2p_yamux::Config::default)
239            .unwrap()
240            .with_behaviour(|_, relay| Behaviour {
241                dummy: libp2p_swarm::dummy::Behaviour,
242                relay,
243            })
244            .unwrap()
245            .build();
246    }
247
248    #[tokio::test]
249    #[cfg(all(
250        feature = "tokio",
251        feature = "tcp",
252        feature = "tls",
253        feature = "noise",
254        feature = "yamux",
255        feature = "dns"
256    ))]
257    async fn tcp_dns() {
258        SwarmBuilder::with_new_identity()
259            .with_tokio()
260            .with_tcp(
261                Default::default(),
262                (libp2p_tls::Config::new, libp2p_noise::Config::new),
263                libp2p_yamux::Config::default,
264            )
265            .unwrap()
266            .with_dns()
267            .unwrap()
268            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
269            .unwrap()
270            .build();
271    }
272
273    #[tokio::test]
274    #[cfg(all(
275        feature = "tokio",
276        feature = "tcp",
277        feature = "noise",
278        feature = "yamux",
279        feature = "dns"
280    ))]
281    async fn tcp_dns_config() {
282        SwarmBuilder::with_new_identity()
283            .with_tokio()
284            .with_tcp(
285                Default::default(),
286                (libp2p_tls::Config::new, libp2p_noise::Config::new),
287                libp2p_yamux::Config::default,
288            )
289            .unwrap()
290            .with_dns_config(
291                libp2p_dns::ResolverConfig::default(),
292                libp2p_dns::ResolverOpts::default(),
293            )
294            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
295            .unwrap()
296            .build();
297    }
298
299    #[tokio::test]
300    #[cfg(all(feature = "tokio", feature = "quic", feature = "dns"))]
301    async fn quic_dns_config() {
302        SwarmBuilder::with_new_identity()
303            .with_tokio()
304            .with_quic()
305            .with_dns_config(
306                libp2p_dns::ResolverConfig::default(),
307                libp2p_dns::ResolverOpts::default(),
308            )
309            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
310            .unwrap()
311            .build();
312    }
313
314    #[tokio::test]
315    #[cfg(all(
316        feature = "tokio",
317        feature = "tcp",
318        feature = "noise",
319        feature = "yamux",
320        feature = "quic",
321        feature = "dns"
322    ))]
323    async fn tcp_quic_dns_config() {
324        SwarmBuilder::with_new_identity()
325            .with_tokio()
326            .with_tcp(
327                Default::default(),
328                (libp2p_tls::Config::new, libp2p_noise::Config::new),
329                libp2p_yamux::Config::default,
330            )
331            .unwrap()
332            .with_quic()
333            .with_dns_config(
334                libp2p_dns::ResolverConfig::default(),
335                libp2p_dns::ResolverOpts::default(),
336            )
337            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
338            .unwrap()
339            .build();
340    }
341
342    /// Showcases how to provide custom transports unknown to the libp2p crate, e.g. WebRTC.
343    #[test]
344    #[cfg(feature = "tokio")]
345    fn other_transport() -> Result<(), Box<dyn std::error::Error>> {
346        let _ = SwarmBuilder::with_new_identity()
347            .with_tokio()
348            // Closure can either return a Transport directly.
349            .with_other_transport(|_| DummyTransport::<(PeerId, StreamMuxerBox)>::new())?
350            // Or a Result containing a Transport.
351            .with_other_transport(|_| {
352                if true {
353                    Ok(DummyTransport::<(PeerId, StreamMuxerBox)>::new())
354                } else {
355                    Err(Box::from("test"))
356                }
357            })?
358            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
359            .unwrap()
360            .build();
361
362        Ok(())
363    }
364
365    #[tokio::test]
366    #[cfg(all(
367        feature = "tokio",
368        feature = "tcp",
369        feature = "tls",
370        feature = "noise",
371        feature = "yamux",
372        feature = "dns",
373        feature = "websocket",
374    ))]
375    async fn tcp_websocket() {
376        let _ = SwarmBuilder::with_new_identity()
377            .with_tokio()
378            .with_tcp(
379                Default::default(),
380                (libp2p_tls::Config::new, libp2p_noise::Config::new),
381                libp2p_yamux::Config::default,
382            )
383            .unwrap()
384            .with_websocket(
385                (libp2p_tls::Config::new, libp2p_noise::Config::new),
386                libp2p_yamux::Config::default,
387            )
388            .await
389            .unwrap()
390            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
391            .unwrap()
392            .build();
393    }
394
395    #[tokio::test]
396    #[cfg(all(
397        feature = "tokio",
398        feature = "tcp",
399        feature = "tls",
400        feature = "noise",
401        feature = "yamux",
402        feature = "quic",
403        feature = "dns",
404        feature = "relay",
405        feature = "websocket",
406        feature = "metrics",
407    ))]
408    async fn all() {
409        #[derive(NetworkBehaviour)]
410        #[behaviour(prelude = "libp2p_swarm::derive_prelude")]
411        struct MyBehaviour {
412            relay: libp2p_relay::client::Behaviour,
413        }
414
415        let _ = SwarmBuilder::with_new_identity()
416            .with_tokio()
417            .with_tcp(
418                Default::default(),
419                libp2p_tls::Config::new,
420                libp2p_yamux::Config::default,
421            )
422            .unwrap()
423            .with_quic()
424            .with_dns()
425            .unwrap()
426            .with_websocket(libp2p_tls::Config::new, libp2p_yamux::Config::default)
427            .await
428            .unwrap()
429            .with_relay_client(libp2p_tls::Config::new, libp2p_yamux::Config::default)
430            .unwrap()
431            .with_bandwidth_metrics(&mut libp2p_metrics::Registry::default())
432            .with_behaviour(|_key, relay| MyBehaviour { relay })
433            .unwrap()
434            .build();
435    }
436
437    #[test]
438    #[cfg(all(feature = "tokio", feature = "tcp", feature = "tls", feature = "yamux"))]
439    fn tcp_bandwidth_metrics() -> Result<(), Box<dyn std::error::Error>> {
440        let _ = SwarmBuilder::with_new_identity()
441            .with_tokio()
442            .with_tcp(
443                Default::default(),
444                libp2p_tls::Config::new,
445                libp2p_yamux::Config::default,
446            )?
447            .with_bandwidth_metrics(&mut libp2p_metrics::Registry::default())
448            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
449            .unwrap()
450            .build();
451
452        Ok(())
453    }
454
455    #[test]
456    #[cfg(all(feature = "tokio", feature = "quic"))]
457    fn quic_bandwidth_metrics() {
458        let _ = SwarmBuilder::with_new_identity()
459            .with_tokio()
460            .with_quic()
461            .with_bandwidth_metrics(&mut libp2p_metrics::Registry::default())
462            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
463            .unwrap()
464            .build();
465    }
466
467    #[test]
468    #[cfg(feature = "tokio")]
469    fn other_transport_bandwidth_metrics() -> Result<(), Box<dyn std::error::Error>> {
470        let _ = SwarmBuilder::with_new_identity()
471            .with_tokio()
472            .with_other_transport(|_| DummyTransport::<(PeerId, StreamMuxerBox)>::new())?
473            .with_bandwidth_metrics(&mut libp2p_metrics::Registry::default())
474            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
475            .unwrap()
476            .build();
477
478        Ok(())
479    }
480}