mqtt-packet
Advanced tools
Comparing version 6.5.0 to 6.6.0
@@ -40,4 +40,4 @@ /* Protocol - protocol constants */ | ||
/* Length */ | ||
protocol.LENGTH_MASK = 0x7F | ||
protocol.LENGTH_FIN_MASK = 0x80 | ||
protocol.VARBYTEINT_MASK = 0x7F | ||
protocol.VARBYTEINT_FIN_MASK = 0x80 | ||
@@ -44,0 +44,0 @@ /* Connack */ |
const max = 65536 | ||
const cache = {} | ||
// in node 6 Buffer.subarray returns a Uint8Array instead of a Buffer | ||
// later versions return a Buffer | ||
// alternative is Buffer.slice but that creates a new buffer | ||
// creating new buffers takes time | ||
// SubOk is only false on node < 8 | ||
const SubOk = Buffer.isBuffer(Buffer.from([1, 2]).subarray(0, 1)) | ||
function generateBuffer (i) { | ||
@@ -18,21 +25,7 @@ const buffer = Buffer.allocUnsafe(2) | ||
/** | ||
* calcVariableByteIntLength - calculate the variable byte integer | ||
* length field | ||
* | ||
* @api private | ||
*/ | ||
function calcVariableByteIntLength (length) { | ||
if (length >= 0 && length < 128) return 1 | ||
else if (length >= 128 && length < 16384) return 2 | ||
else if (length >= 16384 && length < 2097152) return 3 | ||
else if (length >= 2097152 && length < 268435456) return 4 | ||
else return 0 | ||
} | ||
function genBufVariableByteInt (num) { | ||
const maxLength = 4 // max 4 bytes | ||
let digit = 0 | ||
let pos = 0 | ||
const length = calcVariableByteIntLength(num) | ||
const buffer = Buffer.allocUnsafe(length) | ||
const buffer = Buffer.allocUnsafe(maxLength) | ||
@@ -45,8 +38,9 @@ do { | ||
buffer.writeUInt8(digit, pos++) | ||
} while (num > 0) | ||
} while (num > 0 && pos < maxLength) | ||
return { | ||
data: buffer, | ||
length | ||
if (num > 0) { | ||
pos = 0 | ||
} | ||
return SubOk ? buffer.subarray(0, pos) : buffer.slice(0, pos) | ||
} | ||
@@ -53,0 +47,0 @@ |
{ | ||
"name": "mqtt-packet", | ||
"version": "6.5.0", | ||
"version": "6.6.0", | ||
"description": "Parse and generate MQTT packets like a breeze", | ||
@@ -5,0 +5,0 @@ "main": "mqtt.js", |
@@ -75,2 +75,4 @@ const bl = require('bl') | ||
this._list.consume(result.bytes) | ||
} else { | ||
this._emitError(new Error('Invalid length')) | ||
} | ||
@@ -546,4 +548,4 @@ debug('_parseLength %d', result.value) | ||
let mul = 1 | ||
let length = 0 | ||
let result = true | ||
let value = 0 | ||
let result = false | ||
let current | ||
@@ -554,8 +556,10 @@ const padding = this._pos ? this._pos : 0 | ||
current = this._list.readUInt8(padding + bytes++) | ||
length += mul * (current & constants.LENGTH_MASK) | ||
value += mul * (current & constants.VARBYTEINT_MASK) | ||
mul *= 0x80 | ||
if ((current & constants.LENGTH_FIN_MASK) === 0) break | ||
if ((current & constants.VARBYTEINT_FIN_MASK) === 0) { | ||
result = true | ||
break | ||
} | ||
if (this._list.length <= bytes) { | ||
result = false | ||
break | ||
@@ -572,4 +576,4 @@ } | ||
bytes, | ||
value: length | ||
} : length | ||
value | ||
} : value | ||
: false | ||
@@ -576,0 +580,0 @@ |
522
test.js
@@ -72,2 +72,11 @@ const test = require('tape') | ||
// the API allows to pass strings as buffers to writeToStream and generate | ||
// parsing them back will result in a string so only generate and compare to buffer | ||
function testGenerateOnly (name, object, buffer, opts) { | ||
test(name, t => { | ||
t.equal(mqtt.generate(object, opts).toString('hex'), buffer.toString('hex')) | ||
t.end() | ||
}) | ||
} | ||
function testParseError (expected, fixture, opts) { | ||
@@ -88,7 +97,8 @@ test(expected, t => { | ||
parser.parse(fixture) | ||
t.end() | ||
}) | ||
} | ||
function testGenerateError (expected, fixture, opts) { | ||
test(expected, t => { | ||
function testGenerateError (expected, fixture, opts, name) { | ||
test(name || expected, t => { | ||
t.plan(1) | ||
@@ -101,5 +111,15 @@ | ||
} | ||
t.end() | ||
}) | ||
} | ||
function testGenerateErrorMultipleCmds (cmds, expected, fixture, opts) { | ||
cmds.forEach(cmd => { | ||
const obj = Object.assign({}, fixture) | ||
obj.cmd = cmd | ||
testGenerateError(expected, obj, opts, `${expected} on ${cmd}`) | ||
} | ||
) | ||
} | ||
function testParseGenerateDefaults (name, object, buffer, opts) { | ||
@@ -120,2 +140,3 @@ test(`${name} parse`, t => { | ||
t.equal(parser.parse(fixture), 0, 'remaining bytes') | ||
t.end() | ||
}) | ||
@@ -141,5 +162,15 @@ | ||
t.false(result, 'result should be false') | ||
t.end() | ||
}) | ||
} | ||
test('cacheNumbers get/set/unset', t => { | ||
t.true(mqtt.writeToStream.cacheNumbers, 'initial state of cacheNumbers is enabled') | ||
mqtt.writeToStream.cacheNumbers = false | ||
t.false(mqtt.writeToStream.cacheNumbers, 'cacheNumbers can be disabled') | ||
mqtt.writeToStream.cacheNumbers = true | ||
t.true(mqtt.writeToStream.cacheNumbers, 'cacheNumbers can be enabled') | ||
t.end() | ||
}) | ||
test('disabled numbers cache', t => { | ||
@@ -179,2 +210,9 @@ const stream = WS() | ||
testGenerateError('Unknown command', {}) | ||
testParseError('Not supported', Buffer.from([0, 1, 0]), {}) | ||
testParseError('Invalid length', Buffer.from( | ||
[16, 255, 255, 255, 255] | ||
), {}) | ||
testParseGenerate('minimal connect', { | ||
@@ -202,3 +240,3 @@ cmd: 'connect', | ||
testParseGenerate('connect MQTT 5.0', { | ||
testGenerateOnly('minimal connect with clientId as Buffer', { | ||
cmd: 'connect', | ||
@@ -208,2 +246,24 @@ retain: false, | ||
dup: false, | ||
length: 18, | ||
protocolId: 'MQIsdp', | ||
protocolVersion: 3, | ||
clean: false, | ||
keepalive: 30, | ||
clientId: Buffer.from('test') | ||
}, Buffer.from([ | ||
16, 18, // Header | ||
0, 6, // Protocol ID length | ||
77, 81, 73, 115, 100, 112, // Protocol ID | ||
3, // Protocol version | ||
0, // Connect flags | ||
0, 30, // Keepalive | ||
0, 4, // Client ID length | ||
116, 101, 115, 116 // Client ID | ||
])) | ||
testParseGenerate('connect MQTT 5', { | ||
cmd: 'connect', | ||
retain: false, | ||
qos: 0, | ||
dup: false, | ||
length: 125, | ||
@@ -278,3 +338,3 @@ protocolId: 'MQTT', | ||
testParseGenerate('connect MQTT 5.0 with will properties but w/o will payload', { | ||
testParseGenerate('connect MQTT 5 with will properties but with empty will payload', { | ||
cmd: 'connect', | ||
@@ -352,3 +412,3 @@ retain: false, | ||
testParseGenerate('connect MQTT 5.0 w/o will properties', { | ||
testParseGenerate('connect MQTT 5 w/o will properties', { | ||
cmd: 'connect', | ||
@@ -687,46 +747,40 @@ retain: false, | ||
test('connect all strings generate', t => { | ||
const message = { | ||
cmd: 'connect', | ||
retain: false, | ||
qos: 0, | ||
dup: false, | ||
length: 54, | ||
protocolId: 'MQIsdp', | ||
protocolVersion: 3, | ||
will: { | ||
retain: true, | ||
qos: 2, | ||
topic: 'topic', | ||
payload: 'payload' | ||
}, | ||
clean: true, | ||
keepalive: 30, | ||
clientId: 'test', | ||
username: 'username', | ||
password: 'password' | ||
} | ||
const expected = Buffer.from([ | ||
16, 54, // Header | ||
0, 6, // Protocol ID length | ||
77, 81, 73, 115, 100, 112, // Protocol ID | ||
3, // Protocol version | ||
246, // Connect flags | ||
0, 30, // Keepalive | ||
0, 4, // Client ID length | ||
116, 101, 115, 116, // Client ID | ||
0, 5, // Will topic length | ||
116, 111, 112, 105, 99, // Will topic | ||
0, 7, // Will payload length | ||
112, 97, 121, 108, 111, 97, 100, // Will payload | ||
0, 8, // Username length | ||
117, 115, 101, 114, 110, 97, 109, 101, // Username | ||
0, 8, // Password length | ||
112, 97, 115, 115, 119, 111, 114, 100 // Password | ||
]) | ||
testGenerateOnly('connect all strings generate', { | ||
cmd: 'connect', | ||
retain: false, | ||
qos: 0, | ||
dup: false, | ||
length: 54, | ||
protocolId: 'MQIsdp', | ||
protocolVersion: 3, | ||
will: { | ||
retain: true, | ||
qos: 2, | ||
topic: 'topic', | ||
payload: 'payload' | ||
}, | ||
clean: true, | ||
keepalive: 30, | ||
clientId: 'test', | ||
username: 'username', | ||
password: 'password' | ||
}, Buffer.from([ | ||
16, 54, // Header | ||
0, 6, // Protocol ID length | ||
77, 81, 73, 115, 100, 112, // Protocol ID | ||
3, // Protocol version | ||
246, // Connect flags | ||
0, 30, // Keepalive | ||
0, 4, // Client ID length | ||
116, 101, 115, 116, // Client ID | ||
0, 5, // Will topic length | ||
116, 111, 112, 105, 99, // Will topic | ||
0, 7, // Will payload length | ||
112, 97, 121, 108, 111, 97, 100, // Will payload | ||
0, 8, // Username length | ||
117, 115, 101, 114, 110, 97, 109, 101, // Username | ||
0, 8, // Password length | ||
112, 97, 115, 115, 119, 111, 114, 100 // Password | ||
])) | ||
t.equal(mqtt.generate(message).toString('hex'), expected.toString('hex')) | ||
t.end() | ||
}) | ||
testParseError('Cannot parse protocolId', Buffer.from([ | ||
@@ -738,2 +792,88 @@ 16, 4, | ||
// missing protocol version on connect | ||
testParseError('Packet too short', Buffer.from([ | ||
16, 8, // Header | ||
0, 6, // Protocol ID length | ||
77, 81, 73, 115, 100, 112 // Protocol ID | ||
])) | ||
// missing keepalive on connect | ||
testParseError('Packet too short', Buffer.from([ | ||
16, 10, // Header | ||
0, 6, // Protocol ID length | ||
77, 81, 73, 115, 100, 112, // Protocol ID | ||
3, // Protocol version | ||
246 // Connect flags | ||
])) | ||
// missing clientid on connect | ||
testParseError('Packet too short', Buffer.from([ | ||
16, 10, // Header | ||
0, 6, // Protocol ID length | ||
77, 81, 73, 115, 100, 112, // Protocol ID | ||
3, // Protocol version | ||
246, // Connect flags | ||
0, 30 // Keepalive | ||
])) | ||
// missing will topic on connect | ||
testParseError('Cannot parse will topic', Buffer.from([ | ||
16, 16, // Header | ||
0, 6, // Protocol ID length | ||
77, 81, 73, 115, 100, 112, // Protocol ID | ||
3, // Protocol version | ||
246, // Connect flags | ||
0, 30, // Keepalive | ||
0, 2, // Will topic length | ||
0, 0 // Will topic | ||
])) | ||
// missing will payload on connect | ||
testParseError('Cannot parse will payload', Buffer.from([ | ||
16, 23, // Header | ||
0, 6, // Protocol ID length | ||
77, 81, 73, 115, 100, 112, // Protocol ID | ||
3, // Protocol version | ||
246, // Connect flags | ||
0, 30, // Keepalive | ||
0, 5, // Will topic length | ||
116, 111, 112, 105, 99, // Will topic | ||
0, 2, // Will payload length | ||
0, 0 // Will payload | ||
])) | ||
// missing username on connect | ||
testParseError('Cannot parse username', Buffer.from([ | ||
16, 32, // Header | ||
0, 6, // Protocol ID length | ||
77, 81, 73, 115, 100, 112, // Protocol ID | ||
3, // Protocol version | ||
246, // Connect flags | ||
0, 30, // Keepalive | ||
0, 5, // Will topic length | ||
116, 111, 112, 105, 99, // Will topic | ||
0, 7, // Will payload length | ||
112, 97, 121, 108, 111, 97, 100, // Will payload | ||
0, 2, // Username length | ||
0, 0 // Username | ||
])) | ||
// missing password on connect | ||
testParseError('Cannot parse password', Buffer.from([ | ||
16, 42, // Header | ||
0, 6, // Protocol ID length | ||
77, 81, 73, 115, 100, 112, // Protocol ID | ||
3, // Protocol version | ||
246, // Connect flags | ||
0, 30, // Keepalive | ||
0, 5, // Will topic length | ||
116, 111, 112, 105, 99, // Will topic | ||
0, 7, // Will payload length | ||
112, 97, 121, 108, 111, 97, 100, // Will payload | ||
0, 8, // Username length | ||
117, 115, 101, 114, 110, 97, 109, 101, // Username | ||
0, 2, // Password length | ||
0, 0 // Password | ||
])) | ||
testParseGenerate('connack with return code 0', { | ||
@@ -751,3 +891,3 @@ cmd: 'connack', | ||
testParseGenerate('connack MQTT5 with properties', { | ||
testParseGenerate('connack MQTT 5 with properties', { | ||
cmd: 'connack', | ||
@@ -803,3 +943,3 @@ retain: false, | ||
testParseGenerate('connack MQTT5 with properties and doubled user properties', { | ||
testParseGenerate('connack MQTT 5 with properties and doubled user properties', { | ||
cmd: 'connack', | ||
@@ -880,2 +1020,12 @@ retain: false, | ||
testGenerateError('Invalid return code', { | ||
cmd: 'connack', | ||
retain: false, | ||
qos: 0, | ||
dup: false, | ||
length: 2, | ||
sessionPresent: false, | ||
returnCode: '5' // returncode must be a number | ||
}) | ||
testParseGenerate('minimal publish', { | ||
@@ -896,3 +1046,3 @@ cmd: 'publish', | ||
testParseGenerate('publish MQTT5 properties', { | ||
testParseGenerate('publish MQTT 5 properties', { | ||
cmd: 'publish', | ||
@@ -902,3 +1052,3 @@ retain: true, | ||
dup: true, | ||
length: 60, | ||
length: 86, | ||
topic: 'test', | ||
@@ -914,3 +1064,3 @@ payload: Buffer.from('test'), | ||
userProperties: { | ||
test: 'test' | ||
test: ['test', 'test', 'test'] | ||
}, | ||
@@ -921,7 +1071,7 @@ subscriptionIdentifier: 120, | ||
}, Buffer.from([ | ||
61, 60, // Header | ||
61, 86, // Header | ||
0, 4, // Topic length | ||
116, 101, 115, 116, // Topic (test) | ||
0, 10, // Message ID | ||
47, // properties length | ||
73, // properties length | ||
1, 1, // payloadFormatIndicator | ||
@@ -933,2 +1083,4 @@ 2, 0, 0, 16, 225, // message expiry interval | ||
38, 0, 4, 116, 101, 115, 116, 0, 4, 116, 101, 115, 116, // userProperties | ||
38, 0, 4, 116, 101, 115, 116, 0, 4, 116, 101, 115, 116, // userProperties | ||
38, 0, 4, 116, 101, 115, 116, 0, 4, 116, 101, 115, 116, // userProperties | ||
11, 120, // subscriptionIdentifier | ||
@@ -939,3 +1091,3 @@ 3, 0, 4, 116, 101, 115, 116, // content type | ||
testParseGenerate('publish MQTT5 with multiple same properties', { | ||
testParseGenerate('publish MQTT 5 with multiple same properties', { | ||
cmd: 'publish', | ||
@@ -945,3 +1097,3 @@ retain: true, | ||
dup: true, | ||
length: 62, | ||
length: 64, | ||
topic: 'test', | ||
@@ -959,11 +1111,11 @@ payload: Buffer.from('test'), | ||
}, | ||
subscriptionIdentifier: [120, 121], | ||
subscriptionIdentifier: [120, 121, 122], | ||
contentType: 'test' | ||
} | ||
}, Buffer.from([ | ||
61, 62, // Header | ||
61, 64, // Header | ||
0, 4, // Topic length | ||
116, 101, 115, 116, // Topic (test) | ||
0, 10, // Message ID | ||
49, // properties length | ||
51, // properties length | ||
1, 1, // payloadFormatIndicator | ||
@@ -977,2 +1129,3 @@ 2, 0, 0, 16, 225, // message expiry interval | ||
11, 121, // subscriptionIdentifier | ||
11, 122, // subscriptionIdentifier | ||
3, 0, 4, 116, 101, 115, 116, // content type | ||
@@ -982,3 +1135,29 @@ 116, 101, 115, 116 // Payload (test) | ||
;(() => { | ||
testParseGenerate('publish MQTT 5 properties with 0-4 byte varbyte', { | ||
cmd: 'publish', | ||
retain: true, | ||
qos: 2, | ||
dup: true, | ||
length: 27, | ||
topic: 'test', | ||
payload: Buffer.from('test'), | ||
messageId: 10, | ||
properties: { | ||
payloadFormatIndicator: false, | ||
subscriptionIdentifier: [128, 16384, 2097152] // this tests the varbyte handling | ||
} | ||
}, Buffer.from([ | ||
61, 27, // Header | ||
0, 4, // Topic length | ||
116, 101, 115, 116, // Topic (test) | ||
0, 10, // Message ID | ||
14, // properties length | ||
1, 0, // payloadFormatIndicator | ||
11, 128, 1, // subscriptionIdentifier | ||
11, 128, 128, 1, // subscriptionIdentifier | ||
11, 128, 128, 128, 1, // subscriptionIdentifier | ||
116, 101, 115, 116 // Payload (test) | ||
]), { protocolVersion: 5 }) | ||
; (() => { | ||
const buffer = Buffer.alloc(2048) | ||
@@ -1099,2 +1278,17 @@ testParseGenerate('2KB publish packet', { | ||
testGenerateError('Invalid subscriptionIdentifier: 268435456', { | ||
cmd: 'publish', | ||
retain: true, | ||
qos: 2, | ||
dup: true, | ||
length: 27, | ||
topic: 'test', | ||
payload: Buffer.from('test'), | ||
messageId: 10, | ||
properties: { | ||
payloadFormatIndicator: false, | ||
subscriptionIdentifier: 268435456 | ||
} | ||
}, { protocolVersion: 5 }, 'MQTT 5.0 var byte integer >24 bits throws error') | ||
testParseGenerate('puback', { | ||
@@ -1112,3 +1306,3 @@ cmd: 'puback', | ||
testParseGenerate('puback with reason and no MQTT5 properties', { | ||
testParseGenerate('puback with reason and no MQTT 5 properties', { | ||
cmd: 'puback', | ||
@@ -1127,3 +1321,3 @@ retain: false, | ||
testParseGenerate('puback MQTT5 properties', { | ||
testParseGenerate('puback MQTT 5 properties', { | ||
cmd: 'puback', | ||
@@ -1163,3 +1357,3 @@ retain: false, | ||
testParseGenerate('pubrec MQTT5 properties', { | ||
testParseGenerate('pubrec MQTT 5 properties', { | ||
cmd: 'pubrec', | ||
@@ -1234,3 +1428,3 @@ retain: false, | ||
testParseGenerate('pubcomp MQTT5 properties', { | ||
testParseGenerate('pubcomp MQTT 5 properties', { | ||
cmd: 'pubcomp', | ||
@@ -1419,3 +1613,3 @@ retain: false, | ||
testParseGenerate('suback MQTT5', { | ||
testParseGenerate('suback MQTT 5', { | ||
cmd: 'suback', | ||
@@ -1463,2 +1657,22 @@ retain: false, | ||
testGenerateError('Invalid unsubscriptions', { | ||
cmd: 'unsubscribe', | ||
retain: false, | ||
qos: 1, | ||
dup: true, | ||
length: 5, | ||
unsubscriptions: 5, | ||
messageId: 7 | ||
}, {}, 'unsubscribe with unsubscriptions not an array') | ||
testGenerateError('Invalid unsubscriptions', { | ||
cmd: 'unsubscribe', | ||
retain: false, | ||
qos: 1, | ||
dup: true, | ||
length: 5, | ||
unsubscriptions: [1, 2], | ||
messageId: 7 | ||
}, {}, 'unsubscribe with unsubscriptions as an object') | ||
testParseGenerate('unsubscribe MQTT 5', { | ||
@@ -1606,4 +1820,2 @@ cmd: 'unsubscribe', | ||
testGenerateError('Unknown command', {}) | ||
testGenerateError('Invalid protocolId', { | ||
@@ -1630,2 +1842,23 @@ cmd: 'connect', | ||
testGenerateError('Invalid protocol version', { | ||
cmd: 'connect', | ||
retain: false, | ||
qos: 0, | ||
dup: false, | ||
length: 54, | ||
protocolId: 'MQIsdp', | ||
protocolVersion: 1, | ||
will: { | ||
retain: true, | ||
qos: 2, | ||
topic: 'topic', | ||
payload: 'payload' | ||
}, | ||
clean: true, | ||
keepalive: 30, | ||
clientId: 'test', | ||
username: 'username', | ||
password: 'password' | ||
}) | ||
testGenerateError('clientId must be supplied before 3.1.1', { | ||
@@ -1944,3 +2177,3 @@ cmd: 'connect', | ||
// CONNECT Packets that contain an unsupported protocol version | ||
// Flag (i.e. not `3` or `4`) should cause an error | ||
// Flag (i.e. not `3` or `4` or '5') should cause an error | ||
testParseError('Invalid protocol version', Buffer.from([ | ||
@@ -2015,2 +2248,68 @@ 16, 18, | ||
testWriteToStreamError('Invalid command', { | ||
cmd: 'invalid' | ||
}) | ||
testWriteToStreamError('Invalid protocolId', { | ||
cmd: 'connect', | ||
protocolId: {} | ||
}) | ||
test('userProperties null prototype', t => { | ||
t.plan(3) | ||
const packet = mqtt.generate({ | ||
cmd: 'connect', | ||
retain: false, | ||
qos: 0, | ||
dup: false, | ||
length: 125, | ||
protocolId: 'MQTT', | ||
protocolVersion: 5, | ||
will: { | ||
retain: true, | ||
qos: 2, | ||
properties: { | ||
willDelayInterval: 1234, | ||
payloadFormatIndicator: false, | ||
messageExpiryInterval: 4321, | ||
contentType: 'test', | ||
responseTopic: 'topic', | ||
correlationData: Buffer.from([1, 2, 3, 4]), | ||
userProperties: { | ||
test: 'test' | ||
} | ||
}, | ||
topic: 'topic', | ||
payload: Buffer.from([4, 3, 2, 1]) | ||
}, | ||
clean: true, | ||
keepalive: 30, | ||
properties: { | ||
sessionExpiryInterval: 1234, | ||
receiveMaximum: 432, | ||
maximumPacketSize: 100, | ||
topicAliasMaximum: 456, | ||
requestResponseInformation: true, | ||
requestProblemInformation: true, | ||
userProperties: { | ||
test: 'test' | ||
}, | ||
authenticationMethod: 'test', | ||
authenticationData: Buffer.from([1, 2, 3, 4]) | ||
}, | ||
clientId: 'test' | ||
}) | ||
const parser = mqtt.parser() | ||
parser.on('packet', packet => { | ||
t.equal(packet.cmd, 'connect') | ||
t.equal(Object.getPrototypeOf(packet.properties.userProperties), null) | ||
t.equal(Object.getPrototypeOf(packet.will.properties.userProperties), null) | ||
}) | ||
parser.parse(packet) | ||
}) | ||
test('stops parsing after first error', t => { | ||
@@ -2089,72 +2388,15 @@ t.plan(4) | ||
testWriteToStreamError('Invalid protocolId', { | ||
cmd: 'connect', | ||
protocolId: {} | ||
}) | ||
testWriteToStreamError('Invalid topic', { | ||
cmd: 'publish', | ||
topic: {} | ||
}) | ||
testWriteToStreamError('Invalid messageId', { | ||
cmd: 'subscribe', | ||
mid: {} | ||
}) | ||
test('userProperties null prototype', t => { | ||
t.plan(3) | ||
const packet = mqtt.generate({ | ||
cmd: 'connect', | ||
retain: false, | ||
qos: 0, | ||
dup: false, | ||
length: 125, | ||
protocolId: 'MQTT', | ||
protocolVersion: 5, | ||
will: { | ||
retain: true, | ||
qos: 2, | ||
properties: { | ||
willDelayInterval: 1234, | ||
payloadFormatIndicator: false, | ||
messageExpiryInterval: 4321, | ||
contentType: 'test', | ||
responseTopic: 'topic', | ||
correlationData: Buffer.from([1, 2, 3, 4]), | ||
userProperties: { | ||
test: 'test' | ||
} | ||
}, | ||
topic: 'topic', | ||
payload: Buffer.from([4, 3, 2, 1]) | ||
}, | ||
clean: true, | ||
keepalive: 30, | ||
properties: { | ||
sessionExpiryInterval: 1234, | ||
receiveMaximum: 432, | ||
maximumPacketSize: 100, | ||
topicAliasMaximum: 456, | ||
requestResponseInformation: true, | ||
requestProblemInformation: true, | ||
userProperties: { | ||
test: 'test' | ||
}, | ||
authenticationMethod: 'test', | ||
authenticationData: Buffer.from([1, 2, 3, 4]) | ||
}, | ||
clientId: 'test' | ||
}) | ||
const parser = mqtt.parser() | ||
parser.on('packet', packet => { | ||
t.equal(packet.cmd, 'connect') | ||
t.equal(Object.getPrototypeOf(packet.properties.userProperties), null) | ||
t.equal(Object.getPrototypeOf(packet.will.properties.userProperties), null) | ||
}) | ||
parser.parse(packet) | ||
}) | ||
testGenerateErrorMultipleCmds([ | ||
'publish', | ||
'puback', | ||
'pubrec', | ||
'pubrel', | ||
'subscribe', | ||
'suback', | ||
'unsubscribe', | ||
'unsuback' | ||
], 'Invalid messageId', { | ||
qos: 1, // required for publish | ||
topic: 'test', // required for publish | ||
messageId: 'a' | ||
}, {}) |
@@ -786,3 +786,3 @@ const protocol = require('./constants') | ||
if (!buffer) { | ||
buffer = genBufVariableByteInt(num).data | ||
buffer = genBufVariableByteInt(num) | ||
if (num < 16384) varByteIntCache[num] = buffer | ||
@@ -926,7 +926,8 @@ } | ||
case 'var': { | ||
if (typeof value !== 'number' || value < 0 || value > 0xffffffff) { | ||
// var byte integer is max 24 bits packed in 32 bits | ||
if (typeof value !== 'number' || value < 0 || value > 0x0fffffff) { | ||
stream.emit('error', new Error(`Invalid ${name}: ${value}`)) | ||
return false | ||
} | ||
length += 1 + genBufVariableByteInt(value).length | ||
length += 1 + Buffer.byteLength(genBufVariableByteInt(value)) | ||
break | ||
@@ -988,3 +989,3 @@ } | ||
} | ||
const propertiesLengthLength = genBufVariableByteInt(propertiesLength).length | ||
const propertiesLengthLength = Buffer.byteLength(genBufVariableByteInt(propertiesLength)) | ||
@@ -991,0 +992,0 @@ return { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
139245
4427