Skip to content

Commit f7635b0

Browse files
committed
wip
1 parent ecaefb0 commit f7635b0

File tree

3 files changed

+128
-0
lines changed

3 files changed

+128
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
test/repo-tests*
55
**/bundle.js
66
**/.nyc_output
7+
**/.vscode/
78

89
# Logs
910
logs

src/mappers/index.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
'use strict'
2+
const debug = require('debug')
3+
4+
class BaseMapper {
5+
constructor (name) {
6+
this.name = name
7+
this.mappings = {}
8+
9+
this.log = debug(`nat-puncher:${name}`)
10+
this.log.err = debug(`nat-puncher:${name}:error`)
11+
}
12+
13+
newMapping (port) {
14+
return {
15+
routerIp: null,
16+
internalIp: null,
17+
internalPort: port,
18+
externalIp: null, // Only provided by PCP, undefined for other protocols
19+
externalPort: null, // The actual external port of the mapping, -1 on failure
20+
ttl: null, // The actual (response) lifetime of the mapping
21+
protocol: this.name, // The protocol used to make the mapping ('natPmp', 'pcp', 'upnp')
22+
nonce: null, // Only for PCP; the nonce field for deletion
23+
errInfo: null // Error message if failure; currently used only for UPnP
24+
}
25+
}
26+
27+
addMapping (intPort, extPort, ttl, callback) {
28+
// If lifetime is zero, we want to refresh every 24 hours
29+
ttl = !ttl ? 24 * 60 * 60 : ttl
30+
31+
this._addPortMapping(intPort,
32+
extPort,
33+
ttl,
34+
(err, mapping) => {
35+
if (err) {
36+
this.log.err(err)
37+
return callback(err)
38+
}
39+
this.mappings[`${mapping.externalIp}:${mapping.externalPort}`] = mapping
40+
callback(null, mapping)
41+
})
42+
}
43+
44+
_addPortMapping (intPort, extPort, lifetime, cb) {
45+
cb(new Error('Not implemented!'))
46+
}
47+
48+
deleteMapping (mapping, callback) {
49+
this._removePortMapping(mapping.internalPort,
50+
mapping.externalPort,
51+
(err) => {
52+
if (err) {
53+
return callback(err)
54+
}
55+
56+
// delete the mappings
57+
delete this.mappings[`${mapping.externalIp}:${mapping.externalPort}`]
58+
callback()
59+
})
60+
}
61+
62+
_removePortMapping (intPort, extPort, callback) {
63+
callback(new Error('Not implemented!'))
64+
}
65+
}
66+
67+
module.exports = BaseMapper

test/manager.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/* eslint-env mocha */
2+
'use strict'
3+
4+
const chai = require('chai')
5+
chai.use(require('dirty-chai'))
6+
chai.use(require('chai-checkmark'))
7+
8+
const Manager = require('../src')
9+
const Mapper = require('../src/mappers')
10+
11+
const expect = chai.expect
12+
13+
describe('NAT manager', () => {
14+
it('should create mappings', (done) => {
15+
class Mapper1 extends Mapper {
16+
constructor () {
17+
super('mapper1')
18+
}
19+
20+
_addPortMapping (intPort, extPort, lifetime, cb) {
21+
cb(null, this.newMapping(intPort))
22+
}
23+
}
24+
25+
const manager = new Manager([
26+
new Mapper1()
27+
])
28+
29+
manager.addMapping(55555, 55555, 0, (err, mapping) => {
30+
expect(err).to.not.exist()
31+
expect(mapping).to.exist()
32+
expect(mapping.internalPort).to.eql(55555)
33+
done()
34+
})
35+
})
36+
37+
it('should try mappings in order', (done) => {
38+
let fail = true
39+
40+
class Mapper1 extends Mapper {
41+
_addPortMapping (intPort, extPort, lifetime, cb) {
42+
cb(fail ? new Error('fail') : null, this.newMapping(intPort))
43+
fail = false
44+
}
45+
}
46+
47+
const manager = new Manager([
48+
new Mapper1('1'),
49+
new Mapper1('2')
50+
])
51+
52+
manager.addMapping(55555, 55555, 0, (err, mapping) => {
53+
expect(err).to.not.exist()
54+
expect(mapping).to.exist()
55+
expect(mapping.protocol).to.eql('2')
56+
expect(mapping.internalPort).to.eql(55555)
57+
done()
58+
})
59+
})
60+
})

0 commit comments

Comments
 (0)