libp2p
Version:
JavaScript implementation of libp2p, a modular peer to peer network stack
146 lines • 5.87 kB
JavaScript
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