pub struct Endpoint { /* private fields */ }Expand description
Controls an iroh endpoint, establishing connections with other endpoints.
This is the main API interface to create connections to, and accept connections from other iroh endpoints. The connections are peer-to-peer and encrypted, a Relay server is used to make the connections reliable. See the [crate docs] for a more detailed overview of iroh.
It is recommended to only create a single instance per application. This ensures all the connections made share the same peer-to-peer connections to other iroh endpoints, while still remaining independent connections. This will result in more optimal network behaviour.
The endpoint is created using the Builder, which can be created using
Endpoint::builder.
Once an endpoint exists, new connections are typically created using the
Endpoint::connect and Endpoint::accept methods. Once established, the
Connection gives access to most QUIC features. Individual streams to send data to
the peer are created using the Connection::open_bi, Connection::accept_bi,
Connection::open_uni and Connection::open_bi functions.
Note that due to the light-weight properties of streams a stream will only be accepted once the initiating peer has sent some data on it.
Implementations§
Source§impl Endpoint
impl Endpoint
Sourcepub fn empty_builder() -> Builder
pub fn empty_builder() -> Builder
Returns the builder for an Endpoint, with an empty configuration.
See Builder::empty for details.
Sourcepub fn set_alpns(&self, alpns: Vec<Vec<u8>>)
pub fn set_alpns(&self, alpns: Vec<Vec<u8>>)
Sets the list of accepted ALPN protocols.
This will only affect new incoming connections. Note that this overrides the current list of ALPNs.
If the endpoint is closed, this method will log a warning and ignore the request to set new ALPNs.
Sourcepub async fn insert_relay(
&self,
relay: RelayUrl,
config: Arc<RelayConfig>,
) -> Option<Arc<RelayConfig>>
pub async fn insert_relay( &self, relay: RelayUrl, config: Arc<RelayConfig>, ) -> Option<Arc<RelayConfig>>
Sourcepub async fn remove_relay(&self, relay: &RelayUrl) -> Option<Arc<RelayConfig>>
pub async fn remove_relay(&self, relay: &RelayUrl) -> Option<Arc<RelayConfig>>
Sourcepub async fn connect(
&self,
endpoint_addr: impl Into<EndpointAddr>,
alpn: &[u8],
) -> Result<Connection, ConnectError>
pub async fn connect( &self, endpoint_addr: impl Into<EndpointAddr>, alpn: &[u8], ) -> Result<Connection, ConnectError>
Connects to a remote Endpoint.
A value that can be converted into an EndpointAddr is required. This can be either an
EndpointAddr or an EndpointId.
The EndpointAddr must contain the EndpointId to dial and may also contain a RelayUrl
and direct addresses. If direct addresses are provided, they will be used to try and
establish a direct connection without involving a relay server.
If neither a RelayUrl or direct addresses are configured in the EndpointAddr it
may still be possible a connection can be established. This depends on which, if any,
crate::address_lookup::AddressLookups were configured using Builder::address_lookup. The Address Lookup
service will also be used if the remote endpoint is not reachable on the provided direct
addresses and there is no RelayUrl.
If addresses or relay servers are neither provided nor can be discovered, the connection attempt will fail with an error.
The alpn, or application-level protocol identifier, is also required. The remote
endpoint must support this alpn, otherwise the connection attempt will fail with
an error.
Sourcepub async fn connect_with_opts(
&self,
endpoint_addr: impl Into<EndpointAddr>,
alpn: &[u8],
options: ConnectOptions,
) -> Result<Connecting, ConnectWithOptsError>
pub async fn connect_with_opts( &self, endpoint_addr: impl Into<EndpointAddr>, alpn: &[u8], options: ConnectOptions, ) -> Result<Connecting, ConnectWithOptsError>
Starts a connection attempt with a remote Endpoint.
Like Endpoint::connect (see also its docs for general details), but allows for a more
advanced connection setup with more customization in two aspects:
- The returned future resolves to a
Connecting, which can be further processed into aConnectionby awaiting, or alternatively allows connecting with 0-RTT viaConnecting::into_0rtt. Note: Please read the documentation forinto_0rttcarefully to assess security concerns. - The
QuicTransportConfigfor the connection can be modified via the providedConnectOptions. Note: Please be aware that changing transport config settings may have adverse effects on establishing and maintaining direct connections. Carefully test settings you use and consider this currently as still rather experimental.
Sourcepub fn accept(&self) -> Accept<'_>
pub fn accept(&self) -> Accept<'_>
Accepts an incoming connection on the endpoint.
Only connections with the ALPNs configured in Builder::alpns will be accepted.
If multiple ALPNs have been configured the ALPN can be inspected before accepting
the connection using Connecting::alpn.
The returned future will yield None if the endpoint is closed by calling
Endpoint::close.
Sourcepub fn secret_key(&self) -> &SecretKey
pub fn secret_key(&self) -> &SecretKey
Returns the secret_key of this endpoint.
Sourcepub fn id(&self) -> PublicKey
pub fn id(&self) -> PublicKey
Returns the endpoint id of this endpoint.
This ID is the unique addressing information of this endpoint and other peers must know it to be able to connect to this endpoint.
Sourcepub fn addr(&self) -> EndpointAddr
pub fn addr(&self) -> EndpointAddr
Returns the current EndpointAddr.
As long as the endpoint was able to bind to a network interface, some
local addresses will be available.
The state of other fields depends on the state of networking and connectivity.
Use the Endpoint::online method to ensure that the endpoint is considered
“online” (has contacted a relay server) before calling this method, if you want
to ensure that the EndpointAddr will contain enough information to allow this endpoint
to be dialable by a remote endpoint over the internet.
You can use the Endpoint::watch_addr method to get updates when the EndpointAddr
changes.
Sourcepub fn watch_addr(&self) -> impl Watcher<Value = EndpointAddr> + use<>
pub fn watch_addr(&self) -> impl Watcher<Value = EndpointAddr> + use<>
Returns a Watcher for the current EndpointAddr for this endpoint.
The observed EndpointAddr will have the current RelayUrl and direct addresses.
use iroh::{Endpoint, Watcher, endpoint::presets};
let endpoint = Endpoint::builder(presets::N0)
.alpns(vec![b"my-alpn".to_vec()])
.bind()
.await?;
let endpoint_addr = endpoint.watch_addr().get();The Endpoint::online method can be used as a convenience method to
understand if the endpoint has ever been considered “online”. But after
that initial call to Endpoint::online, to understand if your
endpoint is no longer able to be connected to by endpoints outside
of the private or local network, watch for changes in it’s EndpointAddr.
If there are no addrsin the EndpointAddr, you may not be dialable by other endpoints
on the internet.
The EndpointAddr will change as:
- network conditions change
- the endpoint connects to a relay server
- the endpoint changes its preferred relay server
- more addresses are discovered for this endpoint
§Closing behavior
The returned watcher only becomes disconnected once the last clone of the Endpoint
is dropped. Closing the endpoint does not disconnect the watcher. Thus, a stream created
via Watcher::stream only terminates once the endpoint is fully dropped. To stop a task
that loops over a watcher stream once the endpoint stops, combine with Self::closed:
let endpoint = Endpoint::bind(presets::N0).await?;
// We want to watch address changes in a different task, and stop our task
// once the endpoint stops.
let mut addr_stream = endpoint.watch_addr().stream();
let endpoint_closed = endpoint.closed();
tokio::spawn(endpoint_closed.run_until(async move {
while let Some(addr) = addr_stream.next().await {
info!("our address changed: {addr:?}");
}
info!("endpoint closed");
}));
// Do fancy things, then close the endpoint.
// Our task above will stop even if there are still clones of `Endpoint` alive somewhere.
endpoint.close().await;Sourcepub async fn online(&self)
pub async fn online(&self)
A convenience method that waits for the endpoint to be considered “online”.
This currently means at least one relay server was connected, and at least one local IP address is available. Even if no relays are configured, this will still wait for a relay connection.
Once this has been resolved the first time, this will always immediately resolve.
This has no timeout, so if that is needed, you need to wrap it in a
timeout. We recommend using a timeout close to
crate::NET_REPORT_TIMEOUTs, so you can be sure that at least one
crate::NetReport has been attempted.
To understand if the endpoint has gone back “offline”,
you must use the Endpoint::watch_addr method, to
get information on the current relay and direct address information.
In the common case where the endpoint’s configured relay servers are
only accessible via a wide area network (WAN) connection, this method
will await indefinitely when the endpoint has no WAN connection. If you’re
writing an app that’s designed to work without a WAN connection, defer
any calls to online as long as possible, or avoid calling online
entirely.
The online method does not interact with crate::address_lookup::AddressLookup
services, which means that any Address Lookup that relies on a WAN
connection is independent of the endpoint’s online status.
§Examples
use iroh::Endpoint;
#[tokio::main]
async fn main() {
// After this await returns, the endpoint is bound to a local socket.
// It can be dialed, but almost certainly hasn't finished picking a
// relay.
let endpoint = Endpoint::bind().await;
// After this await returns we have a connection to at least one relay
// and holepunching should work as expected.
endpoint.online().await;
}Sourcepub fn bound_sockets(&self) -> Vec<SocketAddr>
pub fn bound_sockets(&self) -> Vec<SocketAddr>
Returns the local socket addresses on which the underlying sockets are bound.
The Endpoint always binds on an IPv4 address and also tries to bind on an IPv6
address if available.
Sourcepub fn dns_resolver(&self) -> Result<&DnsResolver, EndpointError>
pub fn dns_resolver(&self) -> Result<&DnsResolver, EndpointError>
Sourcepub fn tls_config(&self) -> &ClientConfig
pub fn tls_config(&self) -> &ClientConfig
Returns the rustls::ClientConfig used by the endpoint for connecting to external services.
This might be useful for address lookup services or other functions that want to use the same trust anchors as iroh does for verifying the validity of TLS certificates presented by external services.
Note that this TLS config is unrelated to how iroh validates the authenticity of iroh connections itself.
The config is based on the trust anchors set via Builder::ca_roots_config.
Sourcepub fn address_lookup(&self) -> Result<&ConcurrentAddressLookup, EndpointError>
pub fn address_lookup(&self) -> Result<&ConcurrentAddressLookup, EndpointError>
Returns the Address Lookup service, if configured.
§Errors
Returns a EndpointError::Closed error if the endpoint is closed.
Sourcepub async fn remote_info(&self, endpoint_id: PublicKey) -> Option<RemoteInfo>
pub async fn remote_info(&self, endpoint_id: PublicKey) -> Option<RemoteInfo>
Returns addressing information about a recently used remote endpoint.
The returned RemoteInfo contains a list of all transport addresses for the remote
that we know about. This is a snapshot in time and not a watcher.
Returns None if the endpoint doesn’t have information about the remote or if the endpoint is closed.
When remote endpoints are no longer used, our endpoint will keep information around
for a little while, and then drop it. Afterwards, this will return None.
Sourcepub async fn network_change(&self)
pub async fn network_change(&self)
Notifies the system of potential network changes.
On many systems iroh is able to detect network changes by itself, however some systems like android do not expose this functionality to native code. Android does however provide this functionality to Java code. This function allows for notifying iroh of any potential network changes like this.
Even when the network did not change, or iroh was already able to detect the network change itself, there is no harm in calling this function.
If the endpoint is closed, this method will log a warning and ignore the request.
Sourcepub fn set_user_data_for_address_lookup(&self, user_data: Option<UserData>)
pub fn set_user_data_for_address_lookup(&self, user_data: Option<UserData>)
Sets the initial user-defined data to be published in Address Lookups for this endpoint.
If the user-defined data passed to this function is different to the previous one, the endpoint will republish its endpoint info to the configured Address Lookups.
See also Builder::user_data_for_address_lookup for setting an initial value when
building the endpoint.
If the endpoint is closed, this method will log a warning and ignore the request.
Sourcepub async fn close(&self)
pub async fn close(&self)
Closes the QUIC endpoint and the socket.
This will close any remaining open Connections with an error code
of 0 and an empty reason. Though it is best practice to close those
explicitly before with a custom error code and reason.
It will then make a best effort to wait for all close notifications to be acknowledged by the peers, re-transmitting them if needed. This ensures the peers are aware of the closed connections instead of having to wait for a timeout on the connection. Once all connections are closed or timed out, the future finishes.
The maximum time-out that this future will wait for depends on QUIC transport configurations of non-drained connections at the time of calling, and their current estimates of round trip time. With default parameters and a conservative estimate of round trip time, this call’s future should take 3 seconds to resolve in cases of bad connectivity or failed connections. In the usual case, this call’s future should return much more quickly.
It is highly recommended you do wait for this close call to finish, if possible. Not doing so will make connections that were still open while closing the endpoint time out on the remote end. Thus remote ends will assume connections to have failed even if all application data was transmitted successfully.
Note: Someone used to closing TCP sockets might wonder why it is necessary to wait for timeouts when closing QUIC endpoints, while they don’t have to do this for TCP sockets. This is due to QUIC and its acknowledgments being implemented in user-land, while TCP sockets usually get closed and drained by the operating system in the kernel during the “Time-Wait” period of the TCP socket.
Be aware however that the underlying UDP sockets are only closed once all clones of
the the respective Endpoint are dropped.
Sourcepub fn closed(&self) -> EndpointClosed
pub fn closed(&self) -> EndpointClosed
Returns a future that resolves once the endpoint closes.
The returned future does not contain a clone or reference to the Endpoint,
so keeping the returned future alive does not prevent the endpoint from being dropped.
To run a task and stop it once the endpoint closes, you can use
EndpointClosed::run_until:
let endpoint = Endpoint::bind(presets::N0).await?;
tokio::spawn(endpoint.closed().run_until(async move {
// the future will be aborted once the endpoint closes.
}));Sourcepub fn create_server_config_builder(
&self,
alpns: Vec<Vec<u8>>,
) -> ServerConfigBuilder
pub fn create_server_config_builder( &self, alpns: Vec<Vec<u8>>, ) -> ServerConfigBuilder
Create a ServerConfigBuilder for this endpoint that includes the given alpns.
Use the ServerConfigBuilder to customize the ServerConfig connection configuration
for a connection accepted using the Incoming::accept_with method.