libp2p/
builder.rs

1use std::marker::PhantomData;
2
3mod phase;
4mod select_security;
5
6/// Build a [`Swarm`](libp2p_swarm::Swarm) by combining an identity, a set of
7/// [`Transport`](libp2p_core::Transport)s and a
8/// [`NetworkBehaviour`](libp2p_swarm::NetworkBehaviour).
9///
10/// ```
11/// # use libp2p::{swarm::NetworkBehaviour, SwarmBuilder};
12/// # use libp2p::core::transport::dummy::DummyTransport;
13/// # use libp2p::core::muxing::StreamMuxerBox;
14/// # use libp2p::identity::PeerId;
15/// # use std::error::Error;
16/// #
17/// # #[cfg(all(
18/// #     not(target_arch = "wasm32"),
19/// #     feature = "tokio",
20/// #     feature = "tcp",
21/// #     feature = "tls",
22/// #     feature = "noise",
23/// #     feature = "quic",
24/// #     feature = "dns",
25/// #     feature = "relay",
26/// #     feature = "websocket",
27/// # ))]
28/// # async fn build_swarm() -> Result<(), Box<dyn Error>> {
29/// #     #[derive(NetworkBehaviour)]
30/// #     #[behaviour(prelude = "libp2p_swarm::derive_prelude")]
31/// #     struct MyBehaviour {
32/// #         relay: libp2p_relay::client::Behaviour,
33/// #     }
34///
35///  let swarm = SwarmBuilder::with_new_identity()
36///      .with_tokio()
37///      .with_tcp(
38///          Default::default(),
39///          (libp2p_tls::Config::new, libp2p_noise::Config::new),
40///          libp2p_yamux::Config::default,
41///      )?
42///      .with_quic()
43///      .with_other_transport(|_key| DummyTransport::<(PeerId, StreamMuxerBox)>::new())?
44///      .with_dns()?
45///      .with_websocket(
46///          (libp2p_tls::Config::new, libp2p_noise::Config::new),
47///          libp2p_yamux::Config::default,
48///      )
49///      .await?
50///      .with_relay_client(
51///          (libp2p_tls::Config::new, libp2p_noise::Config::new),
52///          libp2p_yamux::Config::default,
53///      )?
54///      .with_behaviour(|_key, relay| MyBehaviour { relay })?
55///      .build();
56/// #
57/// #     Ok(())
58/// # }
59/// ```
60pub struct SwarmBuilder<Provider, Phase> {
61    keypair: libp2p_identity::Keypair,
62    phantom: PhantomData<Provider>,
63    phase: Phase,
64}
65
66#[cfg(test)]
67mod tests {
68    use crate::SwarmBuilder;
69    use libp2p_core::{muxing::StreamMuxerBox, transport::dummy::DummyTransport};
70    use libp2p_identity::PeerId;
71    use libp2p_swarm::{NetworkBehaviour, Swarm};
72
73    #[test]
74    #[cfg(all(feature = "tokio", feature = "tcp", feature = "tls", feature = "noise"))]
75    fn tcp() {
76        let _ = SwarmBuilder::with_new_identity()
77            .with_tokio()
78            .with_tcp(
79                Default::default(),
80                libp2p_tls::Config::new,
81                libp2p_yamux::Config::default,
82            )
83            .unwrap()
84            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
85            .unwrap()
86            .build();
87    }
88
89    #[test]
90    #[cfg(all(
91        feature = "async-std",
92        feature = "tcp",
93        feature = "tls",
94        feature = "noise"
95    ))]
96    fn async_std_tcp() {
97        let _ = SwarmBuilder::with_new_identity()
98            .with_async_std()
99            .with_tcp(
100                Default::default(),
101                libp2p_tls::Config::new,
102                libp2p_yamux::Config::default,
103            )
104            .unwrap()
105            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
106            .unwrap()
107            .build();
108    }
109
110    #[test]
111    #[cfg(all(feature = "tokio", feature = "tcp", feature = "tls", feature = "mplex"))]
112    fn tcp_yamux_mplex() {
113        let _ = SwarmBuilder::with_new_identity()
114            .with_tokio()
115            .with_tcp(
116                Default::default(),
117                libp2p_tls::Config::new,
118                (
119                    libp2p_yamux::Config::default(),
120                    libp2p_mplex::MplexConfig::default(),
121                ),
122            )
123            .unwrap()
124            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
125            .unwrap()
126            .build();
127    }
128
129    #[test]
130    #[cfg(all(feature = "tokio", feature = "tcp", feature = "tls", feature = "noise"))]
131    fn tcp_tls_noise() {
132        let _ = SwarmBuilder::with_new_identity()
133            .with_tokio()
134            .with_tcp(
135                Default::default(),
136                (libp2p_tls::Config::new, libp2p_noise::Config::new),
137                (
138                    libp2p_yamux::Config::default,
139                    libp2p_mplex::MplexConfig::default,
140                ),
141            )
142            .unwrap()
143            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
144            .unwrap()
145            .build();
146    }
147
148    #[test]
149    #[cfg(all(
150        feature = "tokio",
151        feature = "tcp",
152        feature = "tls",
153        feature = "noise",
154        feature = "quic"
155    ))]
156    fn tcp_quic() {
157        let _ = SwarmBuilder::with_new_identity()
158            .with_tokio()
159            .with_tcp(
160                Default::default(),
161                (libp2p_tls::Config::new, libp2p_noise::Config::new),
162                libp2p_yamux::Config::default,
163            )
164            .unwrap()
165            .with_quic()
166            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
167            .unwrap()
168            .build();
169    }
170
171    #[test]
172    #[cfg(all(
173        feature = "tokio",
174        feature = "tcp",
175        feature = "tls",
176        feature = "noise",
177        feature = "relay"
178    ))]
179    fn tcp_relay() {
180        #[derive(libp2p_swarm::NetworkBehaviour)]
181        #[behaviour(prelude = "libp2p_swarm::derive_prelude")]
182        struct Behaviour {
183            dummy: libp2p_swarm::dummy::Behaviour,
184            relay: libp2p_relay::client::Behaviour,
185        }
186
187        let _ = SwarmBuilder::with_new_identity()
188            .with_tokio()
189            .with_tcp(
190                Default::default(),
191                libp2p_tls::Config::new,
192                libp2p_yamux::Config::default,
193            )
194            .unwrap()
195            .with_relay_client(libp2p_tls::Config::new, libp2p_yamux::Config::default)
196            .unwrap()
197            .with_behaviour(|_, relay| Behaviour {
198                dummy: libp2p_swarm::dummy::Behaviour,
199                relay,
200            })
201            .unwrap()
202            .build();
203    }
204
205    #[tokio::test]
206    #[cfg(all(
207        feature = "tokio",
208        feature = "tcp",
209        feature = "tls",
210        feature = "noise",
211        feature = "dns"
212    ))]
213    async fn tcp_dns() {
214        SwarmBuilder::with_new_identity()
215            .with_tokio()
216            .with_tcp(
217                Default::default(),
218                (libp2p_tls::Config::new, libp2p_noise::Config::new),
219                libp2p_yamux::Config::default,
220            )
221            .unwrap()
222            .with_dns()
223            .unwrap()
224            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
225            .unwrap()
226            .build();
227    }
228
229    /// Showcases how to provide custom transports unknown to the libp2p crate, e.g. WebRTC.
230    #[test]
231    #[cfg(feature = "tokio")]
232    fn other_transport() -> Result<(), Box<dyn std::error::Error>> {
233        let _ = SwarmBuilder::with_new_identity()
234            .with_tokio()
235            // Closure can either return a Transport directly.
236            .with_other_transport(|_| DummyTransport::<(PeerId, StreamMuxerBox)>::new())?
237            // Or a Result containing a Transport.
238            .with_other_transport(|_| {
239                if true {
240                    Ok(DummyTransport::<(PeerId, StreamMuxerBox)>::new())
241                } else {
242                    Err(Box::from("test"))
243                }
244            })?
245            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
246            .unwrap()
247            .build();
248
249        Ok(())
250    }
251
252    #[tokio::test]
253    #[cfg(all(
254        feature = "tokio",
255        feature = "tcp",
256        feature = "tls",
257        feature = "noise",
258        feature = "dns",
259        feature = "websocket",
260    ))]
261    async fn tcp_websocket() {
262        let _ = SwarmBuilder::with_new_identity()
263            .with_tokio()
264            .with_tcp(
265                Default::default(),
266                (libp2p_tls::Config::new, libp2p_noise::Config::new),
267                libp2p_yamux::Config::default,
268            )
269            .unwrap()
270            .with_websocket(
271                (libp2p_tls::Config::new, libp2p_noise::Config::new),
272                libp2p_yamux::Config::default,
273            )
274            .await
275            .unwrap()
276            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
277            .unwrap()
278            .build();
279    }
280
281    #[tokio::test]
282    #[cfg(all(
283        feature = "tokio",
284        feature = "tcp",
285        feature = "tls",
286        feature = "noise",
287        feature = "quic",
288        feature = "dns",
289        feature = "relay",
290        feature = "websocket",
291    ))]
292    async fn all() {
293        #[derive(NetworkBehaviour)]
294        #[behaviour(prelude = "libp2p_swarm::derive_prelude")]
295        struct MyBehaviour {
296            relay: libp2p_relay::client::Behaviour,
297        }
298
299        let (builder, _bandwidth_sinks) = SwarmBuilder::with_new_identity()
300            .with_tokio()
301            .with_tcp(
302                Default::default(),
303                libp2p_tls::Config::new,
304                libp2p_yamux::Config::default,
305            )
306            .unwrap()
307            .with_quic()
308            .with_dns()
309            .unwrap()
310            .with_websocket(libp2p_tls::Config::new, libp2p_yamux::Config::default)
311            .await
312            .unwrap()
313            .with_relay_client(libp2p_tls::Config::new, libp2p_yamux::Config::default)
314            .unwrap()
315            .with_bandwidth_logging();
316        let _: Swarm<MyBehaviour> = builder
317            .with_behaviour(|_key, relay| MyBehaviour { relay })
318            .unwrap()
319            .build();
320    }
321
322    #[test]
323    #[cfg(all(feature = "tokio", feature = "tcp", feature = "tls", feature = "yamux"))]
324    fn tcp_bandwidth_logging() -> Result<(), Box<dyn std::error::Error>> {
325        let (builder, _logging) = SwarmBuilder::with_new_identity()
326            .with_tokio()
327            .with_tcp(
328                Default::default(),
329                libp2p_tls::Config::new,
330                libp2p_yamux::Config::default,
331            )?
332            .with_bandwidth_logging();
333
334        builder
335            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
336            .unwrap()
337            .build();
338
339        Ok(())
340    }
341
342    #[test]
343    #[cfg(all(feature = "tokio", feature = "quic"))]
344    fn quic_bandwidth_logging() -> Result<(), Box<dyn std::error::Error>> {
345        let (builder, _logging) = SwarmBuilder::with_new_identity()
346            .with_tokio()
347            .with_quic()
348            .with_bandwidth_logging();
349
350        builder
351            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
352            .unwrap()
353            .build();
354
355        Ok(())
356    }
357
358    #[test]
359    #[cfg(feature = "tokio")]
360    fn other_transport_bandwidth_logging() -> Result<(), Box<dyn std::error::Error>> {
361        let (builder, _logging) = SwarmBuilder::with_new_identity()
362            .with_tokio()
363            .with_other_transport(|_| DummyTransport::<(PeerId, StreamMuxerBox)>::new())?
364            .with_bandwidth_logging();
365
366        builder
367            .with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
368            .unwrap()
369            .build();
370
371        Ok(())
372    }
373}