libp2p/
builder.rs

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