iroh_net/
lib.rs

1//! Peer-to-peer QUIC connections.
2//!
3//! <div class="warning">
4//!
5//! The `iroh-net` crate has been renamed to `iroh`.  Please use the
6//! `iroh` crate instead.
7//!
8//! </div>
9//!
10//! iroh-net is a library to establish direct connectivity between peers.  It exposes an
11//! interface to [QUIC] connections and streams to the user, while implementing direct
12//! connectivity using [hole punching] complemented by relay servers under the hood.
13//!
14//! An iroh-net node is created and controlled by the [`Endpoint`], e.g. connecting to
15//! another node:
16//!
17//! ```no_run
18//! # use iroh_net::{Endpoint, NodeAddr};
19//! # async fn wrapper() -> testresult::TestResult {
20//! let addr: NodeAddr = todo!();
21//! let ep = Endpoint::builder().bind().await?;
22//! let conn = ep.connect(addr, b"my-alpn").await?;
23//! let mut send_stream = conn.open_uni().await?;
24//! send_stream.write_all(b"msg").await?;
25//! # Ok(())
26//! # }
27//! ```
28//!
29//! The other node can accept incoming connections using the [`Endpoint`] as well:
30//!
31//! ```no_run
32//! # use iroh_net::{Endpoint, NodeAddr};
33//! # async fn wrapper() -> testresult::TestResult {
34//! let ep = Endpoint::builder()
35//!     .alpns(vec![b"my-alpn".to_vec()])
36//!     .bind()
37//!     .await?;
38//! let conn = ep.accept().await.ok_or("err")?.await?;
39//! let mut recv_stream = conn.accept_uni().await?;
40//! let mut buf = [0u8; 3];
41//! recv_stream.read_exact(&mut buf).await?;
42//! # Ok(())
43//! # }
44//! ```
45//!
46//! Of course you can also use [bi-directional streams] or any other features from QUIC.
47//!
48//! For more elaborate examples, see [below](#examples) or the examples directory in
49//! the source repository.
50//!
51//!
52//! # Connection Establishment
53//!
54//! An iroh-net connection between two iroh-net nodes is usually established with the help
55//! of a Relay server.  When creating the [`Endpoint`] it connects to the closest Relay
56//! server and designates this as the *home relay*.  When other nodes want to connect they
57//! first establish connection via this home relay.  As soon as connection between the two
58//! nodes is established they will attempt to create a direct connection, using [hole
59//! punching] if needed.  Once the direct connection is established the relay server is no
60//! longer involved in the connection.
61//!
62//! If one of the iroh-net nodes can be reached directly, connectivity can also be
63//! established without involving a Relay server.  This is done by using the node's
64//! listening addresses in the connection establishement instead of the [`RelayUrl`] which
65//! is used to identify a Relay server.  Of course it is also possible to use both a
66//! [`RelayUrl`] and direct addresses at the same time to connect.
67//!
68//!
69//! # Encryption
70//!
71//! The connection is encrypted using TLS, like standard QUIC connections.  Unlike standard
72//! QUIC there is no client, server or server TLS key and certificate chain.  Instead each iroh-net node has a
73//! unique [`SecretKey`] used to authenticate and encrypt the connection.  When an iroh-net
74//! node connects, it uses the corresponding [`PublicKey`] to ensure the connection is only
75//! established with the intended peer.
76//!
77//! Since the [`PublicKey`] is also used to identify the iroh-net node it is also known as
78//! the [`NodeId`].  As encryption is an integral part of TLS as used in QUIC this
79//! [`NodeId`] is always a required parameter to establish a connection.
80//!
81//! When accepting connections the peer's [`NodeId`] is authenticated.  However it is up to
82//! the application to decide if a particular peer is allowed to connect or not.
83//!
84//!
85//! # Relay Servers
86//!
87//! Relay servers exist to ensure all iroh-net nodes are always reachable.  They accept
88//! **encrypted** traffic for iroh-net nodes which are connected to them, forwarding it to
89//! the correct destination based on the [`NodeId`] only.  Since nodes only send encrypted
90//! traffic, the Relay servers can not decode any traffic for other iroh-net nodes and only
91//! forward it.
92//!
93//! The connections to the Relay server are initiated as normal HTTP 1.1 connections using
94//! TLS.  Once connected the transport is upgraded to a plain TCP connection using a custom
95//! protocol.  All further data is then sent using this custom relaying protocol.  Usually
96//! soon after the connection is established via the Relay it will migrate to a direct
97//! connection.  However if this is not possible the connection will keep flowing over the
98//! relay server as a fallback.
99//!
100//! Additionally to providing reliable connectivity between iroh-net nodes, Relay servers
101//! provide some functions to assist in [hole punching].  They have various services to help
102//! nodes understand their own network situation.  This includes offering a [STUN] server,
103//! but also a few HTTP extra endpoints as well as responding to ICMP echo requests.
104//!
105//! By default the [number 0] relay servers are used, see [`RelayMode::Default`].
106//!
107//!
108//! # Connections and Streams
109//!
110//! An iroh-net node is managed using the [`Endpoint`] and this is used to create or accept
111//! connections to other nodes.  To establish a connection to an iroh-net node you need to
112//! know three pieces of information:
113//!
114//! - The [`NodeId`] of the peer to connect to.
115//! - Some addressing information:
116//!   - Usually the [`RelayUrl`] identifying the Relay server.
117//!   - Sometimes, or usually additionally, any direct addresses which might be known.
118//! - The QUIC/TLS Application-Layer Protocol Negotiation, or [ALPN], name to use.
119//!
120//! The ALPN is used by both sides to agree on which application-specific protocol will be
121//! used over the resulting QUIC connection.  These can be protocols like `h3` used for
122//! [HTTP/3][HTTP3], but more commonly will be a custom identifier for the application.
123//!
124//! Once connected the API exposes QUIC streams.  These are very cheap to create so can be
125//! created at any time and can be used to create very many short-lived stream as well as
126//! long-lived streams.  There are two stream types to choose from:
127//!
128//! - **Uni-directional** which only allows the peer which initiated the stream to send
129//!   data.
130//!
131//! - **Bi-directional** which allows both peers to send and receive data.  However, the
132//!   initiator of this stream has to send data before the peer will be aware of this
133//!   stream.
134//!
135//! Additionally to being extremely light-weight, streams can be interleaved and will not
136//! block each other.  Allowing many streams to co-exist, regardless of how long they last.
137//!
138//! <div class="warning">
139//!
140//! To keep streams cheap, they are lazily created on the network: only once a sender starts
141//! sending data on the stream will the receiver become aware of a stream.  This means only
142//! calling [`Connection::open_bi`] is not sufficient for the corresponding call to
143//! [`Connection::accept_bi`] to return.  The sender **must** send data on the stream before
144//! the receiver's [`Connection::accept_bi`] call will return.
145//!
146//! </div>
147//!
148//! ## Node Discovery
149//!
150//! The need to know the [`RelayUrl`] *or* some direct addresses in addition to the
151//! [`NodeId`] to connect to an iroh-net node can be an obstacle.  To address this the
152//! [`endpoint::Builder`] allows to configure a [`discovery`] service.
153//!
154//! The [`DnsDiscovery`] service is a discovery service which will publish the [`RelayUrl`]
155//! and direct addresses to a service publishing those as DNS records.  To connect it looks
156//! up the [`NodeId`] in the DNS system to find the addressing details.  This enables
157//! connecting using only the [`NodeId`] which is often more convenient and resilient.
158//!
159//! See [the discovery module] for more details.
160//!
161//!
162//! # Examples
163//!
164//! The central struct is the [`Endpoint`], which allows you to connect to other nodes:
165//!
166//! ```no_run
167//! use anyhow::Result;
168//! use iroh_net::{Endpoint, NodeAddr};
169//!
170//! async fn connect(addr: NodeAddr) -> Result<()> {
171//!     // The Endpoint is the central object that manages an iroh-net node.
172//!     let ep = Endpoint::builder().bind().await?;
173//!
174//!     // Establish a QUIC connection, open a bi-directional stream, exchange messages.
175//!     let conn = ep.connect(addr, b"hello-world").await?;
176//!     let (mut send_stream, mut recv_stream) = conn.open_bi().await?;
177//!     send_stream.write_all(b"hello").await?;
178//!     send_stream.finish()?;
179//!     let _msg = recv_stream.read_to_end(10).await?;
180//!
181//!     // Gracefully close the connection and endpoint.
182//!     conn.close(1u8.into(), b"done");
183//!     ep.close(0u8.into(), b"ep closing").await?;
184//!     println!("Client closed");
185//!     Ok(())
186//! }
187//! ```
188//!
189//! Every [`Endpoint`] can also accept connections:
190//!
191//! ```no_run
192//! use anyhow::{Context, Result};
193//! use futures_lite::StreamExt;
194//! use iroh_net::ticket::NodeTicket;
195//! use iroh_net::{Endpoint, NodeAddr};
196//!
197//! async fn accept() -> Result<()> {
198//!     // To accept connections at least one ALPN must be configured.
199//!     let ep = Endpoint::builder()
200//!         .alpns(vec![b"hello-world".to_vec()])
201//!         .bind()
202//!         .await?;
203//!
204//!     // Accept a QUIC connection, accept a bi-directional stream, exchange messages.
205//!     let conn = ep.accept().await.context("no incoming connection")?.await?;
206//!     let (mut send_stream, mut recv_stream) = conn.accept_bi().await?;
207//!     let _msg = recv_stream.read_to_end(10).await?;
208//!     send_stream.write_all(b"world").await?;
209//!     send_stream.finish()?;
210//!
211//!     // Wait for the client to close the connection and gracefully close the endpoint.
212//!     conn.closed().await;
213//!     ep.close(0u8.into(), b"ep closing").await?;
214//!     Ok(())
215//! }
216//! ```
217//!
218//! Please see the examples directory for more nuanced examples.
219//!
220//!
221//! [QUIC]: https://quickwg.org
222//! [bi-directional streams]: crate::endpoint::Connection::open_bi
223//! [`NodeTicket`]: crate::ticket::NodeTicket
224//! [hole punching]: https://en.wikipedia.org/wiki/Hole_punching_(networking)
225//! [socket addresses]: https://doc.rust-lang.org/stable/std/net/enum.SocketAddr.html
226//! [STUN]: https://en.wikipedia.org/wiki/STUN
227//! [ALPN]: https://en.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation
228//! [HTTP3]: https://en.wikipedia.org/wiki/HTTP/3
229//! [`SecretKey`]: crate::key::SecretKey
230//! [`PublicKey`]: crate::key::PublicKey
231//! [`RelayUrl`]: crate::relay::RelayUrl
232//! [`discovery`]: crate::endpoint::Builder::discovery
233//! [`DnsDiscovery`]: crate::discovery::dns::DnsDiscovery
234//! [number 0]: https://n0.computer
235//! [`RelayMode::Default`]: crate::relay::RelayMode::Default
236//! [the discovery module]: crate::discovery
237//! [`Connection::open_bi`]: crate::endpoint::Connection::open_bi
238//! [`Connection::accept_bi`]: crate::endpoint::Connection::accept_bi
239
240#![deprecated(
241    note = "This crate has been renamed from 'iroh-net' to 'iroh', please use the new crate"
242)]
243#![allow(deprecated)]
244#![recursion_limit = "256"]
245#![deny(missing_docs, rustdoc::broken_intra_doc_links)]
246#![cfg_attr(iroh_docsrs, feature(doc_cfg))]
247
248pub mod defaults;
249pub mod dialer;
250mod disco;
251pub mod discovery;
252pub mod dns;
253pub mod endpoint;
254mod magicsock;
255pub mod metrics;
256pub mod netcheck;
257pub mod ping;
258pub mod relay;
259pub mod stun;
260pub mod ticket;
261pub mod tls;
262pub(crate) mod util;
263
264pub use endpoint::{AddrInfo, Endpoint, NodeAddr};
265pub use iroh_base::{key, key::NodeId};
266
267#[cfg(any(test, feature = "test-utils"))]
268#[cfg_attr(iroh_docsrs, doc(cfg(any(test, feature = "test-utils"))))]
269pub mod test_utils;