UNPKG

libp2p

Version:

JavaScript implementation of libp2p, a modular peer to peer network stack

146 lines 5.87 kB
import { isIPv4 } from '@chainsafe/is-ip'; import { trackedMap } from '@libp2p/utils/tracked-map'; import { multiaddr, protocols } from '@multiformats/multiaddr'; export const defaultValues = { maxObservedAddresses: 10 }; const CODEC_IP4 = 0x04; const CODEC_IP6 = 0x29; const CODEC_TCP = 0x06; const CODEC_UDP = 0x0111; export class IPMappings { log; mappings; constructor(components, init = {}) { this.log = components.logger.forComponent('libp2p:address-manager:ip-mappings'); this.mappings = trackedMap({ name: 'libp2p_address_manager_ip_mappings', metrics: components.metrics }); } has(ma) { const tuples = ma.stringTuples(); for (const mappings of this.mappings.values()) { for (const mapping of mappings) { if (mapping.externalIp === tuples[0][1]) { return true; } } } return false; } add(internalIp, internalPort, externalIp, externalPort = internalPort, protocol = 'tcp') { const key = `${internalIp}-${internalPort}-${protocol}`; const mappings = this.mappings.get(key) ?? []; const mapping = { internalIp, internalPort, externalIp, externalPort, externalFamily: isIPv4(externalIp) ? 4 : 6, protocol, verified: false, expires: 0 }; mappings.push(mapping); this.mappings.set(key, mappings); } remove(ma) { const tuples = ma.stringTuples(); const host = tuples[0][1] ?? ''; const protocol = tuples[1][0] === CODEC_TCP ? 'tcp' : 'udp'; const port = parseInt(tuples[1][1] ?? '0'); let wasConfident = false; for (const [key, mappings] of this.mappings.entries()) { for (let i = 0; i < mappings.length; i++) { const mapping = mappings[i]; if (mapping.externalIp === host && mapping.externalPort === port && mapping.protocol === protocol) { this.log('removing %s:%s to %s:%s %s IP mapping', mapping.externalIp, mapping.externalPort, host, port, protocol); wasConfident = wasConfident || mapping.verified; mappings.splice(i, 1); i--; } } if (mappings.length === 0) { this.mappings.delete(key); } } return wasConfident; } getAll(addresses) { const ipMappedAddresses = []; for (const { multiaddr: ma } of addresses) { const tuples = ma.stringTuples(); let tuple; // see if the internal host/port/protocol tuple has been mapped externally if ((tuples[0][0] === CODEC_IP4 || tuples[0][0] === CODEC_IP6) && tuples[1][0] === CODEC_TCP) { tuple = `${tuples[0][1]}-${tuples[1][1]}-tcp`; } else if ((tuples[0][0] === CODEC_IP4 || tuples[0][0] === CODEC_IP6) && tuples[1][0] === CODEC_UDP) { tuple = `${tuples[0][1]}-${tuples[1][1]}-udp`; } if (tuple == null) { continue; } const mappings = this.mappings.get(tuple); if (mappings == null) { continue; } for (const mapping of mappings) { tuples[0][0] = mapping.externalFamily === 4 ? CODEC_IP4 : CODEC_IP6; tuples[0][1] = mapping.externalIp; tuples[1][1] = `${mapping.externalPort}`; ipMappedAddresses.push({ multiaddr: multiaddr(`/${tuples.map(tuple => { return [ protocols(tuple[0]).name, tuple[1] ].join('/'); }).join('/')}`), verified: mapping.verified, type: 'ip-mapping', expires: mapping.expires, lastVerified: mapping.lastVerified }); } } return ipMappedAddresses; } confirm(ma, ttl) { const tuples = ma.stringTuples(); const host = tuples[0][1]; let startingConfidence = false; for (const mappings of this.mappings.values()) { for (const mapping of mappings) { if (mapping.externalIp === host) { this.log('marking %s to %s IP mapping as verified', mapping.internalIp, mapping.externalIp); startingConfidence = mapping.verified; mapping.verified = true; mapping.expires = Date.now() + ttl; mapping.lastVerified = Date.now(); } } } return startingConfidence; } unconfirm(ma, ttl) { const tuples = ma.stringTuples(); const host = tuples[0][1] ?? ''; const protocol = tuples[1][0] === CODEC_TCP ? 'tcp' : 'udp'; const port = parseInt(tuples[1][1] ?? '0'); let wasConfident = false; for (const mappings of this.mappings.values()) { for (let i = 0; i < mappings.length; i++) { const mapping = mappings[i]; if (mapping.externalIp === host && mapping.externalPort === port && mapping.protocol === protocol) { this.log('removing verification of %s:%s to %s:%s %s IP mapping', mapping.externalIp, mapping.externalPort, host, port, protocol); wasConfident = wasConfident || mapping.verified; mapping.verified = false; mapping.expires = Date.now() + ttl; } } } return wasConfident; } } //# sourceMappingURL=ip-mappings.js.map