Merge pull request #14 from diasdavid/close-timeout

fix: destroy hanging connections after timeout
This commit is contained in:
David Dias 2016-06-01 01:09:40 +01:00
commit 073e14553b
2 changed files with 53 additions and 2 deletions

View File

@ -12,6 +12,7 @@ const contains = require('lodash.contains')
exports = module.exports = TCP exports = module.exports = TCP
const IPFS_CODE = 421 const IPFS_CODE = 421
const CLOSE_TIMEOUT = 300
function TCP () { function TCP () {
if (!(this instanceof TCP)) { if (!(this instanceof TCP)) {
@ -56,6 +57,17 @@ function TCP () {
} }
handler(conn) handler(conn)
}) })
listener.__connections = {}
listener.on('connection', (conn) => {
const key = `${conn.remoteAddress}:${conn.remotePort}`
listener.__connections[key] = conn
conn.on('close', () => {
delete listener.__connections[key]
})
})
listener.listen(m.toOptions(), () => { listener.listen(m.toOptions(), () => {
// Node.js likes to convert addr to IPv6 (when 0.0.0.0 for e.g) // Node.js likes to convert addr to IPv6 (when 0.0.0.0 for e.g)
const address = listener.address() const address = listener.address()
@ -86,13 +98,21 @@ function TCP () {
} }
this.close = (callback) => { this.close = (callback) => {
log('closing')
if (listeners.length === 0) { if (listeners.length === 0) {
log('Called close with no active listeners') log('Called close with no active listeners')
return callback() return callback()
} }
parallel(listeners.map((listener) => { parallel(listeners.map((listener) => (cb) => {
return (cb) => listener.close(cb) setTimeout(() => {
Object.keys(listener.__connections).forEach((key) => {
log('destroying %s', key)
listener.__connections[key].destroy()
})
}, CLOSE_TIMEOUT)
listener.close(cb)
}), callback) }), callback)
} }

View File

@ -148,4 +148,35 @@ describe('libp2p-tcp', function () {
expect(valid[0]).to.deep.equal(mh1) expect(valid[0]).to.deep.equal(mh1)
done() done()
}) })
it('destroys after timeout', (done) => {
const server = new TCPlibp2p()
const mh = multiaddr('/ip4/127.0.0.1/tcp/9090')
server.createListener(mh, (conn) => {
const i = setInterval(() => {
conn.read()
conn.write('hi\n')
}, 100)
i.unref()
}, () => {
let connected = 0
const connectHandler = () => {
connected++
if (connected === 10) {
setTimeout(() => {
server.close(done)
}, 1)
}
}
const errorHandler = () => {}
for (let i = 0; i < 10; i++) {
const client = net.connect(9090)
client.on('connect', connectHandler)
// just ignore the resets
client.on('error', errorHandler)
}
})
})
}) })