@@ -78,6 +78,13 @@ const CODEC_IP4 = 0x04
7878const CODEC_IP6 = 0x29
7979const CODEC_DNS4 = 0x36
8080const CODEC_DNS6 = 0x37
81+ const CODEC_TCP = 0x06
82+ const CODEC_UDP = 0x0111
83+
84+ interface PublicAddressMapping {
85+ externalIp : string
86+ externalPort : number
87+ }
8188
8289export class AddressManager implements AddressManagerInterface {
8390 private readonly log : Logger
@@ -89,6 +96,7 @@ export class AddressManager implements AddressManagerInterface {
8996 private readonly observed : Map < string , ObservedAddressMetadata >
9097 private readonly announceFilter : AddressFilter
9198 private readonly ipDomainMappings : Map < string , string >
99+ private readonly publicAddressMappings : Map < string , PublicAddressMapping [ ] >
92100
93101 /**
94102 * Responsible for managing the peer addresses.
@@ -106,6 +114,7 @@ export class AddressManager implements AddressManagerInterface {
106114 this . appendAnnounce = new Set ( appendAnnounce . map ( ma => ma . toString ( ) ) )
107115 this . observed = new Map ( )
108116 this . ipDomainMappings = new Map ( )
117+ this . publicAddressMappings = new Map ( )
109118 this . announceFilter = init . announceFilter ?? defaultAddressFilter
110119
111120 // this method gets called repeatedly on startup when transports start listening so
@@ -239,11 +248,51 @@ export class AddressManager implements AddressManagerInterface {
239248 . map ( ( [ ma ] ) => multiaddr ( ma ) )
240249 )
241250
242- const mappedMultiaddrs : Multiaddr [ ] = [ ]
251+ // add public addresses
252+ const ipMappedMultiaddrs : Multiaddr [ ] = [ ]
253+ multiaddrs . forEach ( ma => {
254+ const tuples = ma . stringTuples ( )
255+ let tuple : string | undefined
256+
257+ // see if the internal host/port/protocol tuple has been mapped externally
258+ if ( ( tuples [ 0 ] [ 0 ] === CODEC_IP4 || tuples [ 0 ] [ 0 ] === CODEC_IP6 ) && tuples [ 1 ] [ 0 ] === CODEC_TCP ) {
259+ tuple = `${ tuples [ 0 ] [ 1 ] } -${ tuples [ 1 ] [ 1 ] } -tcp`
260+ } else if ( ( tuples [ 0 ] [ 0 ] === CODEC_IP4 || tuples [ 0 ] [ 0 ] === CODEC_IP6 ) && tuples [ 1 ] [ 0 ] === CODEC_UDP ) {
261+ tuple = `${ tuples [ 0 ] [ 1 ] } -${ tuples [ 1 ] [ 1 ] } -udp`
262+ }
263+
264+ if ( tuple == null ) {
265+ return
266+ }
267+
268+ const mappings = this . publicAddressMappings . get ( tuple )
269+
270+ if ( mappings == null ) {
271+ return
272+ }
273+
274+ mappings . forEach ( mapping => {
275+ tuples [ 0 ] [ 1 ] = mapping . externalIp
276+ tuples [ 1 ] [ 1 ] = `${ mapping . externalPort } `
277+
278+ ipMappedMultiaddrs . push (
279+ multiaddr ( `/${
280+ tuples . map ( tuple => {
281+ return [
282+ protocols ( tuple [ 0 ] ) . name ,
283+ tuple [ 1 ]
284+ ] . join ( '/' )
285+ } ) . join ( '/' )
286+ } `)
287+ )
288+ } )
289+ } )
290+ multiaddrs = multiaddrs . concat ( ipMappedMultiaddrs )
243291
244292 // add ip->domain mappings
293+ const dnsMappedMultiaddrs : Multiaddr [ ] = [ ]
245294 for ( const ma of multiaddrs ) {
246- const tuples = [ ... ma . stringTuples ( ) ]
295+ const tuples = ma . stringTuples ( )
247296 let mappedIp = false
248297
249298 for ( const [ ip , domain ] of this . ipDomainMappings . entries ( ) ) {
@@ -267,7 +316,7 @@ export class AddressManager implements AddressManagerInterface {
267316 }
268317
269318 if ( mappedIp ) {
270- mappedMultiaddrs . push (
319+ dnsMappedMultiaddrs . push (
271320 multiaddr ( `/${
272321 tuples . map ( tuple => {
273322 return [
@@ -279,8 +328,7 @@ export class AddressManager implements AddressManagerInterface {
279328 )
280329 }
281330 }
282-
283- multiaddrs = multiaddrs . concat ( mappedMultiaddrs )
331+ multiaddrs = multiaddrs . concat ( dnsMappedMultiaddrs )
284332
285333 // dedupe multiaddrs
286334 const addrSet = new Set < string > ( )
@@ -318,15 +366,41 @@ export class AddressManager implements AddressManagerInterface {
318366
319367 addDNSMapping ( domain : string , addresses : string [ ] ) : void {
320368 addresses . forEach ( ip => {
369+ this . log ( 'add DNS mapping %s to %s' , ip , domain )
321370 this . ipDomainMappings . set ( ip , domain )
322371 } )
323372 }
324373
325374 removeDNSMapping ( domain : string ) : void {
326375 for ( const [ key , value ] of this . ipDomainMappings . entries ( ) ) {
327376 if ( value === domain ) {
377+ this . log ( 'remove DNS mapping for %s' , domain )
328378 this . ipDomainMappings . delete ( key )
329379 }
330380 }
331381 }
382+
383+ addPublicAddressMapping ( internalIp : string , internalPort : number , externalIp : string , externalPort : number = internalPort , protocol : 'tcp' | 'udp' = 'tcp' ) : void {
384+ const key = `${ internalIp } -${ internalPort } -${ protocol } `
385+ const mappings = this . publicAddressMappings . get ( key ) ?? [ ]
386+ mappings . push ( {
387+ externalIp,
388+ externalPort
389+ } )
390+
391+ this . publicAddressMappings . set ( key , mappings )
392+ }
393+
394+ removePublicAddressMapping ( internalIp : string , internalPort : number , externalIp : string , externalPort : number = internalPort , protocol : 'tcp' | 'udp' = 'tcp' ) : void {
395+ const key = `${ internalIp } -${ internalPort } -${ protocol } `
396+ const mappings = ( this . publicAddressMappings . get ( key ) ?? [ ] ) . filter ( mapping => {
397+ return mapping . externalIp !== externalIp && mapping . externalPort !== externalPort
398+ } )
399+
400+ if ( mappings . length === 0 ) {
401+ this . publicAddressMappings . delete ( key )
402+ } else {
403+ this . publicAddressMappings . set ( key , mappings )
404+ }
405+ }
332406}
0 commit comments