@achingbrain/nat-port-mapper
Version:
Port mapping with UPnP and NAT-PMP
72 lines • 3.21 kB
JavaScript
import { DEFAULT_AUTO_REFRESH, DEFAULT_PORT_MAPPING_TTL, DEVICE_WAN_IP_CONNECTION_2 } from './constants.js';
import { InternetGatewayService } from './internet-gateway-service.js';
import { findNamespacedKey } from './utils.js';
const AddPinholeProtocols = {
TCP: '6',
UDP: '17'
};
export class InternetGatewayService6 extends InternetGatewayService {
async mapPort(localPort, localHost, options = {}) {
const mapping = {
remoteHost: options.remoteHost ?? '',
internalClient: localHost,
externalPort: `${options.externalPort ?? ''}`,
protocol: AddPinholeProtocols[options.protocol?.toUpperCase() === 'UDP' ? 'UDP' : 'TCP'] ?? '6',
description: options.description ?? this.options.description ?? '@achingbrain/nat-port-mapper',
ttl: Math.max(Math.round((options.ttl ?? this.options.ttl ?? DEFAULT_PORT_MAPPING_TTL) / 1000), 3600),
uniqueId: 0
};
this.log('creating mapping for local port %d to %j', localPort, mapping);
const gateway = await this.getGateway(options);
const response = await gateway.run(DEVICE_WAN_IP_CONNECTION_2, 'AddPinhole', [
['RemoteHost', mapping.remoteHost],
['RemotePort', mapping.externalPort],
['InternalClient', localHost],
['InternalPort', localPort],
['Protocol', mapping.protocol],
['LeaseTime', mapping.ttl]
], options);
const key = findNamespacedKey('AddPinholeResponse', response);
if (options.autoRefresh ?? this.options.autoRefresh ?? DEFAULT_AUTO_REFRESH) {
this.configureRefresh(localPort, mapping, options);
}
this.addMapping(localPort, {
...mapping,
uniqueId: Number(response[key].UniqueID)
});
return localPort;
}
async refreshPort(localPort, options) {
const mappings = this.mappings.get(localPort) ?? [];
for (const mapping of mappings) {
try {
const gateway = await this.getGateway(options);
await gateway.run(DEVICE_WAN_IP_CONNECTION_2, 'UpdatePinhole', [
['UniqueID', mapping.uniqueId],
['NewLeaseTime', mapping.ttl]
], options);
}
catch (err) {
this.log.error('could not refresh port %d mapping - %e', localPort, err);
}
this.configureRefresh(localPort, mapping, options);
}
}
async unmap(localPort, options) {
const mappings = this.mappings.get(localPort) ?? [];
for (const mapping of mappings) {
try {
clearTimeout(mapping.refreshTimeout);
const gateway = await this.getGateway(options);
await gateway.run(DEVICE_WAN_IP_CONNECTION_2, 'DeletePinhole', [
['UniqueID', mapping.uniqueId]
], options);
}
catch (err) {
this.log.error('could not unmap port %d - %e', localPort, err);
}
}
this.mappings.delete(localPort);
}
}
//# sourceMappingURL=internet-gateway-service-6.js.map