// Package socket implements iroh's "magic socket": a single net.PacketConn, // driven by quic-go, that multiplexes datagrams across several transports // (direct UDP, relay, custom). Because quic-go addresses paths with net.Addr, // each non-IP path is represented by a synthetic IPv6 Unique Local Address (RFC // 4193) from a private range. These mapped addresses are an internal indirection // only — they are never sent on the wire — but the byte scheme matches the Rust // implementation (iroh/src/socket/mapped_addrs.rs) for cross-referencing.
package socket import ( ) // The mapped-address scheme. See iroh/src/socket/mapped_addrs.rs. const ( // addrPrefixL is the first byte of every Unique Local Address (RFC 4193). addrPrefixL = 0xfd // mappedPort is the fixed dummy port for all mapped socket addresses; the // port plays no role in addressing. mappedPort = 12345 ) // addrGlobalID is n0's 40-bit ULA global id (bytes 1..6). var addrGlobalID = [5]byte{0x15, 0x07, 0x0a, 0x51, 0x0b} // Subnet ids (bytes 6..8) distinguish the mapped-address kinds. var ( subnetEndpointID = [2]byte{0x00, 0x00} // fd15:70a:510b::/64 subnetRelay = [2]byte{0x00, 0x01} // fd15:70a:510b:1::/64 subnetCustom = [2]byte{0x00, 0x03} // fd15:70a:510b:3::/64 ) // Per-kind counters; the low 8 bytes of each mapped address. They start at 1, // matching the Rust AtomicU64::new(1) (the first Add(1) yields 1). var ( endpointIDCounter atomic.Uint64 relayCounter atomic.Uint64 customCounter atomic.Uint64 ) // mappedAddr builds a mapped IPv6 address for the given subnet and counter. func mappedAddr( [2]byte, uint64) netip.Addr { var [16]byte [0] = addrPrefixL copy([1:6], addrGlobalID[:]) copy([6:8], [:]) binary.BigEndian.PutUint64([8:16], ) return netip.AddrFrom16() } // hasMappedPrefix reports whether addr is in n0's mapped ULA range with the // given subnet id. func hasMappedPrefix( netip.Addr, [2]byte) bool { if !.Is6() || .Is4In6() { return false } := .As16() return [0] == addrPrefixL && [1] == addrGlobalID[0] && [2] == addrGlobalID[1] && [3] == addrGlobalID[2] && [4] == addrGlobalID[3] && [5] == addrGlobalID[4] && [6] == [0] && [7] == [1] } // EndpointIDMappedAddr addresses a remote endpoint via any/all of its paths. It // is used for the initial connection, before a path is selected: the socket // duplicates datagrams sent here onto every candidate path. type EndpointIDMappedAddr struct{ a netip.Addr } // RelayMappedAddr addresses a remote endpoint via a specific relay path // (an (EndpointID, RelayURL) pair). type RelayMappedAddr struct{ a netip.Addr } // CustomMappedAddr addresses a remote endpoint via a custom transport path. type CustomMappedAddr struct{ a netip.Addr } // NewEndpointIDMappedAddr allocates a fresh endpoint-id mapped address. func () EndpointIDMappedAddr { return EndpointIDMappedAddr{mappedAddr(subnetEndpointID, endpointIDCounter.Add(1))} } // NewRelayMappedAddr allocates a fresh relay mapped address. func () RelayMappedAddr { return RelayMappedAddr{mappedAddr(subnetRelay, relayCounter.Add(1))} } // RelayMappedAddrFromAddr wraps an existing relay mapped IPv6 address. It is // used to reverse-look-up the (relay, endpoint) pair an address maps to via // [Socket.LookupRelay]; it does not allocate a new mapping. func ( netip.Addr) RelayMappedAddr { return RelayMappedAddr{a: } } // NewCustomMappedAddr allocates a fresh custom mapped address. func () CustomMappedAddr { return CustomMappedAddr{mappedAddr(subnetCustom, customCounter.Add(1))} } // Addr returns the underlying IPv6 address. func ( EndpointIDMappedAddr) () netip.Addr { return .a } // EndpointIDMappedAddrFromAddr wraps an existing endpoint-id mapped IPv6 // address. It is used to reverse-look-up the endpoint id via // [Socket.LookupEndpointID]. func ( netip.Addr) EndpointIDMappedAddr { return EndpointIDMappedAddr{a: } } // Addr returns the underlying IPv6 address. func ( RelayMappedAddr) () netip.Addr { return .a } // Addr returns the underlying IPv6 address. func ( CustomMappedAddr) () netip.Addr { return .a } // CustomMappedAddrFromAddr wraps an existing custom mapped IPv6 address. It is // used to reverse-look-up the custom address via [Socket.LookupCustom]. func ( netip.Addr) CustomMappedAddr { return CustomMappedAddr{a: } } // AddrPort returns the mapped address with the fixed dummy port, suitable for // handing to quic-go as a path's net.Addr. func ( EndpointIDMappedAddr) () netip.AddrPort { return mappedAddrPort(.a) } // AddrPort returns the mapped address with the fixed dummy port. func ( RelayMappedAddr) () netip.AddrPort { return mappedAddrPort(.a) } // AddrPort returns the mapped address with the fixed dummy port. func ( CustomMappedAddr) () netip.AddrPort { return mappedAddrPort(.a) } func mappedAddrPort( netip.Addr) netip.AddrPort { return netip.AddrPortFrom(, mappedPort) } // MappedKind classifies a netip.Addr as one of the mapped kinds or a real IP. type MappedKind int const ( // KindIP is a real (non-mapped) IP address. KindIP MappedKind = iota // KindEndpointID is an EndpointIDMappedAddr. KindEndpointID // KindRelay is a RelayMappedAddr. KindRelay // KindCustom is a CustomMappedAddr. KindCustom ) // Classify reports which mapped kind addr belongs to, or KindIP if it is a real // address. The order matches the Rust MultipathMappedAddr::from conversion. func ( netip.Addr) MappedKind { switch { case hasMappedPrefix(, subnetEndpointID): return KindEndpointID case hasMappedPrefix(, subnetRelay): return KindRelay case hasMappedPrefix(, subnetCustom): return KindCustom default: return KindIP } } // AddrMap is a bidirectional map between a key K and a mapped address of value // type V, generating a new mapped address on first lookup of a key. It is the // Go analog of the Rust AddrMap. type AddrMap[ comparable, comparable] struct { gen func() addrOf func() netip.Addr mu sync.Mutex fwd map[] rev map[netip.Addr] } // NewAddrMap returns an AddrMap whose missing keys are filled with gen(), keyed // in reverse by addrOf(value). func [ comparable, comparable]( func() , func() netip.Addr) *AddrMap[, ] { return &AddrMap[, ]{ gen: , addrOf: , fwd: make(map[]), rev: make(map[netip.Addr]), } } // Get returns the mapped address for key, generating and recording one if it // does not yet exist. func ( *AddrMap[, ]) ( ) { .mu.Lock() defer .mu.Unlock() if , := .fwd[]; { return } := .gen() .fwd[] = .rev[.addrOf()] = return } // Lookup returns the key that maps to addr, if any. func ( *AddrMap[, ]) ( netip.Addr) (, bool) { .mu.Lock() defer .mu.Unlock() , := .rev[] return , } // Remove deletes the mapping for key, if any. The next Get of the same key // generates a fresh mapped address. func ( *AddrMap[, ]) ( ) { .mu.Lock() defer .mu.Unlock() , := .fwd[] if ! { return } delete(.fwd, ) delete(.rev, .addrOf()) } // Len returns the number of mappings. Intended for tests and metrics. func ( *AddrMap[, ]) () int { .mu.Lock() defer .mu.Unlock() return len(.fwd) }