11import { peerIdFromString } from '@libp2p/peer-id'
2- import { multiaddr } from '@multiformats/multiaddr '
3- import { debounce } from './utils.js '
2+ import { debounce } from '@libp2p/utils/debounce '
3+ import { multiaddr , protocols } from '@multiformats/multiaddr '
44import type { ComponentLogger , Libp2pEvents , Logger , TypedEventTarget , PeerId , PeerStore } from '@libp2p/interface'
5- import type { TransportManager } from '@libp2p/interface-internal'
5+ import type { AddressManager as AddressManagerInterface , TransportManager } from '@libp2p/interface-internal'
66import type { Multiaddr } from '@multiformats/multiaddr'
77
88export interface AddressManagerInit {
@@ -28,7 +28,7 @@ export interface AddressManagerInit {
2828 noAnnounce ?: string [ ]
2929}
3030
31- export interface DefaultAddressManagerComponents {
31+ export interface AddressManagerComponents {
3232 peerId : PeerId
3333 transportManager : TransportManager
3434 peerStore : PeerStore
@@ -69,29 +69,38 @@ function stripPeerId (ma: Multiaddr, peerId: PeerId): Multiaddr {
6969 return ma
7070}
7171
72- export class DefaultAddressManager {
72+ const CODEC_IP4 = 0x04
73+ const CODEC_IP6 = 0x29
74+ const CODEC_DNS4 = 0x36
75+ const CODEC_DNS6 = 0x37
76+
77+ export class AddressManager implements AddressManagerInterface {
7378 private readonly log : Logger
74- private readonly components : DefaultAddressManagerComponents
79+ private readonly components : AddressManagerComponents
7580 // this is an array to allow for duplicates, e.g. multiples of `/ip4/0.0.0.0/tcp/0`
7681 private readonly listen : string [ ]
7782 private readonly announce : Set < string >
7883 private readonly observed : Map < string , ObservedAddressMetadata >
7984 private readonly announceFilter : AddressFilter
85+ private readonly ipDomainMappings : Map < string , string >
86+
87+ private readonly where : Error
8088
8189 /**
8290 * Responsible for managing the peer addresses.
8391 * Peers can specify their listen and announce addresses.
8492 * The listen addresses will be used by the libp2p transports to listen for new connections,
8593 * while the announce addresses will be used for the peer addresses' to other peers in the network.
8694 */
87- constructor ( components : DefaultAddressManagerComponents , init : AddressManagerInit = { } ) {
95+ constructor ( components : AddressManagerComponents , init : AddressManagerInit = { } ) {
8896 const { listen = [ ] , announce = [ ] } = init
8997
9098 this . components = components
9199 this . log = components . logger . forComponent ( 'libp2p:address-manager' )
92100 this . listen = listen . map ( ma => ma . toString ( ) )
93101 this . announce = new Set ( announce . map ( ma => ma . toString ( ) ) )
94102 this . observed = new Map ( )
103+ this . ipDomainMappings = new Map ( )
95104 this . announceFilter = init . announceFilter ?? defaultAddressFilter
96105
97106 // this method gets called repeatedly on startup when transports start listening so
@@ -106,6 +115,8 @@ export class DefaultAddressManager {
106115 components . events . addEventListener ( 'transport:close' , ( ) => {
107116 this . _updatePeerStoreAddresses ( )
108117 } )
118+
119+ this . where = new Error ( 'where' )
109120 }
110121
111122 readonly [ Symbol . toStringTag ] = '@libp2p/address-manager'
@@ -200,37 +211,109 @@ export class DefaultAddressManager {
200211 }
201212
202213 getAddresses ( ) : Multiaddr [ ] {
203- let addrs = this . getAnnounceAddrs ( ) . map ( ma => ma . toString ( ) )
214+ let multiaddrs = this . getAnnounceAddrs ( )
204215
205- if ( addrs . length === 0 ) {
216+ if ( multiaddrs . length === 0 ) {
206217 // no configured announce addrs, add configured listen addresses
207- addrs = this . components . transportManager . getAddrs ( ) . map ( ma => ma . toString ( ) )
218+ multiaddrs = this . components . transportManager . getAddrs ( )
208219 }
209220
210221 // add observed addresses we are confident in
211- addrs = addrs . concat (
212- Array . from ( this . observed )
213- . filter ( ( [ ma , metadata ] ) => metadata . confident )
214- . map ( ( [ ma ] ) => ma )
215- )
222+ multiaddrs = multiaddrs
223+ . concat (
224+ Array . from ( this . observed )
225+ . filter ( ( [ ma , metadata ] ) => metadata . confident )
226+ . map ( ( [ ma ] ) => multiaddr ( ma ) )
227+ )
228+
229+ const mappedMultiaddrs : Multiaddr [ ] = [ ]
230+
231+ // add ip->domain mappings
232+ for ( const ma of multiaddrs ) {
233+ const tuples = [ ...ma . stringTuples ( ) ]
234+ let mappedIp = false
235+
236+ for ( const [ ip , domain ] of this . ipDomainMappings . entries ( ) ) {
237+ for ( let i = 0 ; i < tuples . length ; i ++ ) {
238+ if ( tuples [ i ] [ 1 ] !== ip ) {
239+ continue
240+ }
241+
242+ if ( tuples [ i ] [ 0 ] === CODEC_IP4 ) {
243+ tuples [ i ] [ 0 ] = CODEC_DNS4
244+ tuples [ i ] [ 1 ] = domain
245+ mappedIp = true
246+ }
247+
248+ if ( tuples [ i ] [ 0 ] === CODEC_IP6 ) {
249+ tuples [ i ] [ 0 ] = CODEC_DNS6
250+ tuples [ i ] [ 1 ] = domain
251+ mappedIp = true
252+ }
253+ }
254+ }
255+
256+ if ( mappedIp ) {
257+ mappedMultiaddrs . push (
258+ multiaddr ( `/${
259+ tuples . map ( tuple => {
260+ return [
261+ protocols ( tuple [ 0 ] ) . name ,
262+ tuple [ 1 ]
263+ ] . join ( '/' )
264+ } ) . join ( '/' )
265+ } `)
266+ )
267+ }
268+ }
269+
270+ multiaddrs = multiaddrs . concat ( mappedMultiaddrs )
216271
217272 // dedupe multiaddrs
218- const addrSet = new Set ( addrs )
273+ const addrSet = new Set < string > ( )
274+ multiaddrs = multiaddrs . filter ( ma => {
275+ const maStr = ma . toString ( )
276+
277+ if ( addrSet . has ( maStr ) ) {
278+ return false
279+ }
280+
281+ addrSet . add ( maStr )
282+
283+ return true
284+ } )
219285
220286 // Create advertising list
221- return this . announceFilter ( Array . from ( addrSet )
222- . map ( str => multiaddr ( str ) ) )
223- . map ( ma => {
224- // do not append our peer id to a path multiaddr as it will become invalid
225- if ( ma . protos ( ) . pop ( ) ?. path === true ) {
226- return ma
227- }
287+ return this . announceFilter (
288+ Array . from ( addrSet )
289+ . map ( str => {
290+ const ma = multiaddr ( str )
291+
292+ // do not append our peer id to a path multiaddr as it will become invalid
293+ if ( ma . protos ( ) . pop ( ) ?. path === true ) {
294+ return ma
295+ }
296+
297+ if ( ma . getPeerId ( ) === this . components . peerId . toString ( ) ) {
298+ return ma
299+ }
300+
301+ return ma . encapsulate ( `/p2p/${ this . components . peerId . toString ( ) } ` )
302+ } )
303+ )
304+ }
228305
229- if ( ma . getPeerId ( ) === this . components . peerId . toString ( ) ) {
230- return ma
231- }
306+ addDNSMapping ( domain : string , addresses : string [ ] ) : void {
307+ addresses . forEach ( ip => {
308+ this . ipDomainMappings . set ( ip , domain )
309+ } )
310+ }
232311
233- return ma . encapsulate ( `/p2p/${ this . components . peerId . toString ( ) } ` )
234- } )
312+ removeDNSMapping ( domain : string ) : void {
313+ for ( const [ key , value ] of this . ipDomainMappings . entries ( ) ) {
314+ if ( value === domain ) {
315+ this . ipDomainMappings . delete ( key )
316+ }
317+ }
235318 }
236319}
0 commit comments