Skip to content
This repository has been archived by the owner on May 5, 2022. It is now read-only.

Commit

Permalink
feat: drop connection after too many packets
Browse files Browse the repository at this point in the history
Drop the connection after sending `2^31` packets over a single connection.

Fixes #21.
  • Loading branch information
sentientwaffle committed Oct 16, 2019
1 parent f5949ff commit 833a3f0
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 3 deletions.
18 changes: 15 additions & 3 deletions src/connection.ts
Expand Up @@ -918,7 +918,7 @@ export class Connection extends EventEmitter {
let amountToSend = Long.UZERO

// Set packet number to correlate response with request
const requestPacket = new Packet(this.nextPacketSequence++, IlpPacketType.Prepare)
const requestPacket = new Packet(this.getNextPacketSequence(), IlpPacketType.Prepare)

// TODO make sure these aren't too big
requestPacket.frames = this.queuedFrames
Expand Down Expand Up @@ -1107,6 +1107,7 @@ export class Connection extends EventEmitter {
}
}
}

/**
* (Internal) Send volly of test packests to find the exchange rate, its precision, and potential other amounts to try.
* @private
Expand Down Expand Up @@ -1229,7 +1230,7 @@ export class Connection extends EventEmitter {
*/
protected async sendTestPacket (amount: Long, timeout = DEFAULT_PACKET_TIMEOUT): Promise<Packet | IlpPacket.IlpReject | null> {
// Set packet number to correlate response with request
const requestPacket = new Packet(this.nextPacketSequence++, IlpPacketType.Prepare)
const requestPacket = new Packet(this.getNextPacketSequence(), IlpPacketType.Prepare)

this.log.trace('sending test packet %s for amount: %s. timeout: %d', requestPacket.sequence, amount, timeout)

Expand Down Expand Up @@ -1314,7 +1315,7 @@ export class Connection extends EventEmitter {
errorMessage = ''
}

const packet = new Packet(this.nextPacketSequence, IlpPacketType.Prepare, 0, [
const packet = new Packet(this.nextPacketSequence++, IlpPacketType.Prepare, 0, [
new ConnectionCloseFrame(errorCode, errorMessage)
])

Expand Down Expand Up @@ -1622,6 +1623,17 @@ export class Connection extends EventEmitter {
this._totalDelivered = result.sum
}
}

private getNextPacketSequence (): number {
const sequence = this.nextPacketSequence++
if (sequence >= 2 ** 31) {
// Destroy the connection when too many packets are sent (see https://github.com/interledger/rfcs/blob/master/0029-stream/0029-stream.md#513-maximum-number-of-packets-per-connection).
//
// Throwing here will abort the current send and `destroy()` the connection.
throw new ConnectionError('Connection exceeded maximum number of packets', ErrorCode.InternalError)
}
return sequence
}
}

function isFulfill (packet: IlpPacket.IlpFulfill | IlpPacket.IlpReject): packet is IlpPacket.IlpFulfill {
Expand Down
19 changes: 19 additions & 0 deletions test/connection.test.ts
Expand Up @@ -1631,4 +1631,23 @@ describe('Connection', function () {
assert.isFalse(this.serverConn['streams'].has(1))
})
})

describe('Maximum packet count handling', function () {
it('destroys the connection when 2^31 packets are sent', async function () {
const clientStream = this.clientConn.createStream()
const clientSpy = sinon.spy()
const serverSpy = sinon.spy()
this.clientConn.on('error', clientSpy)
this.serverConn.on('error', serverSpy)

this.clientConn['nextPacketSequence'] = 2 ** 31
clientStream.write('hello')
await new Promise(setImmediate)

assert.calledOnce(clientSpy)
assert.calledOnce(serverSpy)
assert.equal(clientSpy.args[0][0].message, 'Connection exceeded maximum number of packets')
assert.equal(serverSpy.args[0][0].message, 'Remote connection error. Code: InternalError, message: Connection exceeded maximum number of packets')
})
})
})

0 comments on commit 833a3f0

Please sign in to comment.