Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
2f7a856
feat(iroh): allow IP transports to bind to multiple interfaces
dignifiedquire Nov 22, 2025
87a9989
fix: restructure ip transports
dignifiedquire Nov 22, 2025
16144e7
cleanup structure
dignifiedquire Nov 22, 2025
4058319
cleanup code some more
dignifiedquire Nov 22, 2025
102fbf8
fixup address mapping
Frando Nov 22, 2025
dc59321
example: expand transfer.rs example to support explicit interface binds
Frando Nov 22, 2025
4b4cff8
cleanup
dignifiedquire Nov 22, 2025
f7b507c
wip: user transport
dignifiedquire Nov 22, 2025
f2eb4da
expand basic types
dignifiedquire Nov 22, 2025
cdcc4ef
add ability to set a user transport
dignifiedquire Nov 22, 2025
0c860df
- Add example for custom transport
rklaehn Nov 22, 2025
acac97a
WIP wire up test transport
rklaehn Nov 23, 2025
12f0dba
More logging
rklaehn Nov 23, 2025
c09e121
WIP introduce UserMappedAddr
rklaehn Nov 23, 2025
3cdd3d8
feat(iroh): allow IP transports to bind to multiple interfaces
dignifiedquire Nov 22, 2025
2f3a08c
fix: restructure ip transports
dignifiedquire Nov 22, 2025
618ef1c
cleanup structure
dignifiedquire Nov 22, 2025
50d667d
cleanup code some more
dignifiedquire Nov 22, 2025
a50c350
fixup address mapping
Frando Nov 22, 2025
3ad0132
example: expand transfer.rs example to support explicit interface binds
Frando Nov 22, 2025
479652f
cleanup
dignifiedquire Nov 22, 2025
fc21176
Some println cleanup, and finished custom-transports example
rklaehn Nov 27, 2025
7412e2a
Merge branch 'feat-multipath' into feat-user-transport
rklaehn Nov 27, 2025
b0dbab6
Don't use discovery - just pass addr directly
rklaehn Nov 27, 2025
5eea792
Fix custom transports after merge
rklaehn Nov 27, 2025
6b62974
Merge branch 'feat-bind-interfaces' into feat-user-transport
rklaehn Nov 27, 2025
a38c55a
remove hex dep
rklaehn Nov 27, 2025
e6b3aab
remove debug println!
rklaehn Nov 27, 2025
739d8e1
clippy
rklaehn Nov 27, 2025
ba11e9b
Merge branch 'feat-bind-interfaces' into feat-user-transport
dignifiedquire Nov 28, 2025
12956c5
Merge branch 'feat-bind-interfaces' into feat-user-transport
rklaehn Dec 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 108 additions & 1 deletion iroh-base/src/endpoint_addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
//!
//! The primary way of addressing an endpoint is by using the [`EndpointAddr`].

use std::{collections::BTreeSet, net::SocketAddr};
use std::{collections::BTreeSet, fmt, net::SocketAddr};

use data_encoding::HEXLOWER;
use serde::{Deserialize, Serialize};

use crate::{EndpointId, PublicKey, RelayUrl};
Expand Down Expand Up @@ -52,6 +53,105 @@ pub enum TransportAddr {
Relay(RelayUrl),
/// IP based addresses
Ip(SocketAddr),
/// todo
User(UserAddr),
}

/// TODO
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct UserAddr {
/// id
id: u64,
/// data
data: UserAddrBytes,
}

#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
enum UserAddrBytes {
Inline { size: u8, data: [u8; 30] },
Heap(Box<[u8]>),
}

impl fmt::Debug for UserAddrBytes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if !f.alternate() {
write!(f, "[{}]", HEXLOWER.encode(self.as_bytes()))
} else {
let bytes = self.as_bytes();
match self {
Self::Inline { .. } => write!(f, "Inline[{}]", HEXLOWER.encode(bytes)),
Self::Heap(_) => write!(f, "Heap[{}]", HEXLOWER.encode(bytes)),
}
}
}
}

impl From<(u64, &[u8])> for UserAddr {
fn from((id, data): (u64, &[u8])) -> Self {
Self::from_parts(id, data)
}
}

impl UserAddrBytes {
pub fn len(&self) -> usize {
match self {
Self::Inline { size, .. } => *size as usize,
Self::Heap(data) => data.len(),
}
}

pub fn as_bytes(&self) -> &[u8] {
match self {
Self::Inline { size, data } => &data[..*size as usize],
Self::Heap(data) => data,
}
}

pub fn copy_from_slice(data: &[u8]) -> Self {
if data.len() <= 30 {
let mut inline = [0u8; 30];
inline[..data.len()].copy_from_slice(data);
Self::Inline {
size: data.len() as u8,
data: inline,
}
} else {
Self::Heap(data.to_vec().into_boxed_slice())
}
}
}

impl UserAddr {
/// Creates a new [`UserAddr`] from its parts.
pub fn from_parts(id: u64, data: &[u8]) -> Self {
Self {
id,
data: UserAddrBytes::copy_from_slice(data),
}
}

/// Id to distinguish different user address types
pub fn id(&self) -> u64 {
self.id
}

/// Data associated with this user address
pub fn data(&self) -> &[u8] {
self.data.as_bytes()
}

/// Convert to byte representation
pub fn as_vec(&self) -> Vec<u8> {
let mut out = Vec::with_capacity(8 + self.data.len());
out[..8].copy_from_slice(&self.id().to_le_bytes());
out[8..].copy_from_slice(self.data());
out
}

/// Parse from bytes
pub fn from_bytes(_data: &[u8]) -> Result<Self, &'static str> {
todo!()
}
}

impl TransportAddr {
Expand All @@ -64,6 +164,11 @@ impl TransportAddr {
pub fn is_ip(&self) -> bool {
matches!(self, Self::Ip(_))
}

/// TODO
pub fn is_user(&self) -> bool {
matches!(self, Self::User(_))
}
}

impl EndpointAddr {
Expand Down Expand Up @@ -147,6 +252,8 @@ mod tests {
Relay(RelayUrl),
/// IP based addresses
Ip(SocketAddr),
/// User addrs
User(UserAddr),
/// New addr type for testing
Cool(u16),
}
Expand Down
2 changes: 1 addition & 1 deletion iroh-base/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ mod key;
mod relay_url;

#[cfg(feature = "key")]
pub use self::endpoint_addr::{EndpointAddr, TransportAddr};
pub use self::endpoint_addr::{EndpointAddr, TransportAddr, UserAddr};
#[cfg(feature = "key")]
pub use self::key::{EndpointId, KeyParsingError, PublicKey, SecretKey, Signature, SignatureError};
#[cfg(feature = "relay")]
Expand Down
4 changes: 4 additions & 0 deletions iroh/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@ required-features = []
name = "connect"
required-features = []

[[example]]
name = "custom-transport"
required-features = []

[[example]]
name = "listen-unreliable"
required-features = []
Expand Down
Loading
Loading