Skip to content

Commit

Permalink
Removed encoding option
Browse files Browse the repository at this point in the history
By the spec, the only thing that is a Buffer are password and payload.
Everything else must be utf-8.
  • Loading branch information
mcollina committed Jan 9, 2015
1 parent dd70dab commit 6443f19
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 73 deletions.
24 changes: 13 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
mqtt-packet   [![Build Status](https://travis-ci.org/mqttjs/mqtt-packet.png)](https://travis-ci.org/mqttjs/mqtt-packet)
===========

Encode and Decode MQTT packets the node way.
Encode and Decode MQTT 3.1.1 packets the node way.

* <a href="#install">Install</a>
* <a href="#examples">Examples</a>
Expand Down Expand Up @@ -35,7 +35,7 @@ var mqtt = require('mqtt-packet')
, dup: false
, length: 10
, topic: 'test'
, payload: 'test'
, payload: 'test' // can also be a Buffer
}

console.log(mqtt.generate(object))
Expand Down Expand Up @@ -70,7 +70,7 @@ parser.on('packet', function(packet) {
// , dup: false
// , length: 10
// , topic: 'test'
// , payload: 'test'
// , payload: <Buffer 74 65 73 74>
// }
})

Expand All @@ -97,7 +97,7 @@ The object must be one of the ones specified by the [packets](#packets)
section. Throws an `Error` if a packet cannot be generated.
<a name="parser">
### mqtt.parser(opts)
### mqtt.parser()
Returns a new `Parser` object. `Parser` inherits from `EventEmitter` and
will emit:
Expand All @@ -106,10 +106,6 @@ will emit:
[packets](#packets)
* `error`, if an error happens
The only allowed option is `{ encoding: 'binary' }` which will block the
automatic parsing of all the strings in the package. Instead, the
strings will remain 'raw', i.e. a `Buffer`.
<a name="parse">
#### Parser.parse(buffer)
Expand All @@ -133,17 +129,20 @@ and that you can input to `generate`.
, clientId: 'my-device'
, keepalive: 0 // seconds, 0 is the default, can be any positive number
, username: 'matteo'
, password: 'collina'
, password: new Buffer('collina') // passwords are buffers
, will: {
topic: 'mydevice/status'
, payload: 'dead'
, payload: new Buffer('dead') // payloads are buffers
}
}
```
The only mandatory argument is `clientId`, as `generate` will throw if
missing.
If `password` or `will.payload` are passed as strings, they will
automatically be converted into a `Buffer`.
### Connack
```js
Expand Down Expand Up @@ -219,7 +218,7 @@ All properties are mandatory.
, qos: 2
, dup: false
, topic: 'test'
, payload: 'test'
, payload: new Buffer('test')
, retain: false
}
```
Expand All @@ -228,6 +227,9 @@ Only the `topic` and properties are mandatory
Both `topic` and `payload` can be `Buffer` objects instead of strings.
`messageId` is mandatory for `qos > 0`.
If `payload` is passed to `generate(packet)` as a string, it will be
automatically converted into a `Buffer`.
### Puback
```js
Expand Down
4 changes: 2 additions & 2 deletions generate.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ function connect(opts) {
}

// Payload
if (will.payload) {
if (will.payload.length) {
if (will.payload && will.payload) {
if (will.payload.length >= 0) {
if ('string' === typeof will.payload) {
length += Buffer.byteLength(will.payload) + 2
} else {
Expand Down
41 changes: 21 additions & 20 deletions parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,13 @@ var bl = require('bl')
, EE = require('events').EventEmitter
, constants = require('./constants')

function Parser(opts) {
function Parser() {
if (!(this instanceof Parser)) {
return new Parser(opts)
return new Parser()
}

opts = opts || {}

this._list = bl()
this._newPacket()
this.encoding = opts.encoding || "utf8"

this._states = [
'_parseHeader'
Expand Down Expand Up @@ -210,7 +207,7 @@ Parser.prototype._parseConnect = function () {
packet.will.topic = topic

// Parse will payload
payload = this._parseString()
payload = this._parseBuffer()
if (payload === null)
return this.emit('error', new Error('cannot parse will payload'))
packet.will.payload = payload
Expand All @@ -226,7 +223,7 @@ Parser.prototype._parseConnect = function () {

// Parse password
if(flags.password) {
password = this._parseString()
password = this._parseBuffer()
if(password === null)
return this.emit('error', new Error('cannot parse username'))
packet.password = password
Expand Down Expand Up @@ -255,13 +252,7 @@ Parser.prototype._parsePublish = function () {
if (!this._parseMessageId()) { return }
}

// Parse the payload
/* No checks - whatever remains in the packet is the payload */
if (this.encoding !== 'binary') {
packet.payload = this._list.toString(this.encoding, this._pos, packet.length)
} else {
packet.payload = this._list.slice(this._pos, packet.length)
}
packet.payload = this._list.slice(this._pos, packet.length)
}

Parser.prototype._parseSubscribe = function() {
Expand Down Expand Up @@ -341,18 +332,28 @@ Parser.prototype._parseMessageId = function() {
return true
}

Parser.prototype._parseString = function () {
Parser.prototype._parseString = function(maybeBuffer) {
var length = this._parseNum()
, result

if(length === -1 || length + this._pos > this._list.length)
return null

if (this.encoding !== 'binary') {
result = this._list.toString(this.encoding || 'utf8', this._pos, this._pos + length)
} else {
result = this._list.slice(this._pos, this._pos + length)
}
result = this._list.toString('utf8', this._pos, this._pos + length)

this._pos += length

return result
}

Parser.prototype._parseBuffer = function() {
var length = this._parseNum()
, result

if(length === -1 || length + this._pos > this._list.length)
return null

result = this._list.slice(this._pos, this._pos + length)

this._pos += length

Expand Down
117 changes: 77 additions & 40 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,13 +130,13 @@ testParseGenerate('empty will payload', {
retain: true
, qos: 2
, topic: 'topic'
, payload: ''
, payload: new Buffer(0)
}
, clean: true
, keepalive: 30
, clientId: 'test'
, username: 'username'
, password: 'password'
, password: new Buffer('password')
}, new Buffer([
16, 47, // Header
0, 6, // Protocol id length
Expand Down Expand Up @@ -168,13 +168,13 @@ testParseGenerate('maximal connect', {
retain: true
, qos: 2
, topic: 'topic'
, payload: 'payload'
, payload: new Buffer('payload')
}
, clean: true
, keepalive: 30
, clientId: 'test'
, username: 'username'
, password: 'password'
, password: new Buffer('password')
}, new Buffer([
16, 54, // Header
0, 6, // Protocol id length
Expand All @@ -194,34 +194,48 @@ testParseGenerate('maximal connect', {
112, 97, 115, 115, 119, 111, 114, 100 //password
]))

testParseGenerate('binary username/password', {
cmd: 'connect'
, retain: false
, qos: 0
, dup: false
, length: 28
, protocolId: new Buffer([77, 81, 73, 115, 100, 112])
, protocolVersion: 3
, clean: false
, keepalive: 30
, clientId: new Buffer([116, 101, 115, 116])
, username: new Buffer([12, 13, 14])
, password: new Buffer([15, 16, 17])
}, new Buffer([
16, 28, // Header
0, 6, // Protocol id length
77, 81, 73, 115, 100, 112, // Protocol id
3, // Protocol version
0x80 | 0x40, // Connect flags
0, 30, // Keepalive
0, 4, //Client id length
116, 101, 115, 116, // Client id
0, 3, // username length
12, 13, 14, // username
0, 3, // password length
15, 16, 17 //password
]), {
encoding: 'binary'
test('connect all strings generate', function(t) {
var 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'
}
, expected = new Buffer([
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 protocol id', new Buffer([
Expand Down Expand Up @@ -259,7 +273,7 @@ testParseGenerate('minimal publish', {
, dup: false
, length: 10
, topic: 'test'
, payload: 'test'
, payload: new Buffer('test')
}, new Buffer([
48, 10, // Header
0, 4, // Topic length
Expand All @@ -275,13 +289,13 @@ testParseGenerate('minimal publish', {
, qos: 0
, dup: false
, length: 2054
, topic: new Buffer('test')
, topic: 'test'
, payload: buffer
}, Buffer.concat([new Buffer([
48, 134, 16, // Header
0, 4, // Topic length
116, 101, 115, 116, // Topic (test)
]), buffer]), { encoding: 'binary' })
]), buffer]))
})()

;(function() {
Expand All @@ -292,13 +306,13 @@ testParseGenerate('minimal publish', {
, qos: 0
, dup: false
, length: 6 + 2 * 1024 * 1024
, topic: new Buffer('test')
, topic: 'test'
, payload: buffer
}, Buffer.concat([new Buffer([
48, 134, 128, 128, 1, // Header
0, 4, // Topic length
116, 101, 115, 116, // Topic (test)
]), buffer]), { encoding: 'binary' })
]), buffer]))
})()

testParseGenerate('maximal publish', {
Expand All @@ -309,7 +323,7 @@ testParseGenerate('maximal publish', {
, dup: true
, topic: 'test'
, messageId: 10
, payload: 'test'
, payload: new Buffer('test')
}, new Buffer([
61, 12, // Header
0, 4, // Topic length
Expand All @@ -318,14 +332,37 @@ testParseGenerate('maximal publish', {
116, 101, 115, 116 // Payload
]))

test('publish all strings generate', function(t) {
var message = {
cmd:'publish'
, retain: true
, qos: 2
, length: 12
, dup: true
, topic: 'test'
, messageId: 10
, payload: new Buffer('test')
}
, expected = new Buffer([
61, 12, // Header
0, 4, // Topic length
116, 101, 115, 116, // Topic
0, 10, // Message id
116, 101, 115, 116 // Payload
])

t.equal(mqtt.generate(message).toString('hex'), expected.toString('hex'))
t.end()
})

testParseGenerate('empty publish', {
cmd: 'publish'
, retain: false
, qos: 0
, dup: false
, length: 6
, topic: 'test'
, payload: ''
, payload: new Buffer(0)
}, new Buffer([
48, 6, // Header
0, 4, // Topic length
Expand All @@ -346,7 +383,7 @@ test('splitted publish parse', function(t) {
, dup: false
, length: 10
, topic: 'test'
, payload: 'test'
, payload: new Buffer('test')
};

parser.on('packet', function(packet) {
Expand Down

0 comments on commit 6443f19

Please sign in to comment.