Skip to main content

Endpoint

Struct Endpoint 

Source
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

Source

pub fn builder(preset: impl Preset) -> Builder

Returns the builder for an Endpoint, with the given Preset configuration.

Source

pub fn empty_builder() -> Builder

Returns the builder for an Endpoint, with an empty configuration.

See Builder::empty for details.

Source

pub async fn bind(preset: impl Preset) -> Result<Endpoint, BindError>

Constructs a default Endpoint using the provided Preset and binds it immediately.

Source

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.

Source

pub async fn insert_relay( &self, relay: RelayUrl, config: Arc<RelayConfig>, ) -> Option<Arc<RelayConfig>>

Adds the provided configuration to the RelayMap.

Replacing and returning any existing configuration for RelayUrl.

Will also return None if the endpoint is closed.

Source

pub async fn remove_relay(&self, relay: &RelayUrl) -> Option<Arc<RelayConfig>>

Removes the configuration from the RelayMap for the provided RelayUrl.

Returns any existing configuration if it exists. Will also return None if the endpoint is closed.

Source

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.

Source

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:

  1. The returned future resolves to a Connecting, which can be further processed into a Connection by awaiting, or alternatively allows connecting with 0-RTT via Connecting::into_0rtt. Note: Please read the documentation for into_0rtt carefully to assess security concerns.
  2. The QuicTransportConfig for the connection can be modified via the provided ConnectOptions. 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.
Source

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.

Source

pub fn secret_key(&self) -> &SecretKey

Returns the secret_key of this endpoint.

Source

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.

Source

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.

Source

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;
Source

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;
}
Source

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.

Source

pub fn dns_resolver(&self) -> Result<&DnsResolver, EndpointError>

Returns the DNS resolver used in this Endpoint.

§Errors

Returns an EndpointError::Closed error if the endpoint is closed.

See Builder::dns_resolver.

Source

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.

Source

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.

See Builder::address_lookup.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn is_closed(&self) -> bool

Check if this endpoint is still alive, or already closed.

Source

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.
}));
Source

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.

Trait Implementations§

Source§

impl Clone for Endpoint

Source§

fn clone(&self) -> Endpoint

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Endpoint

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more