From 71b21f12756e66a8ae1f6c0504ad17ba0ac2dd0e Mon Sep 17 00:00:00 2001 From: Crawford Comeaux Date: Tue, 23 Jun 2015 14:21:46 -0400 Subject: [PATCH] Added support for AMF0 packets Refactored read()'s core functionality into readData(); added readPacket(), readHeader(), and readMessage(); info object now has isPacket property. TODO: [ ] Test changes to read's docstrings [ ] Write tests for packet support --- lib/read.js | 90 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 84 insertions(+), 6 deletions(-) diff --git a/lib/read.js b/lib/read.js index 0841cd5..e6e2a37 100644 --- a/lib/read.js +++ b/lib/read.js @@ -14,22 +14,100 @@ var amf0Types = constants.amf0Types; module.exports = read; /** - * Reads an AMF object from the specified Buffer at the specified offset. + * Reads an AMF object or packet from the specified Buffer at the specified offset. * * @param {Buffer} buffer The Buffer instance to read from. - * @param {Object|Number} info "Options" object, or the byte offset to begin reading from. - * @return {Object|Array} The decoded AMF object. + * @param {Object|Number} [info={offset: 0, ispacket: false}] "Options" object, or the byte offset to begin reading from. + * @param {Number} [info.offset=0] byte offset to begin reading from. + * @param {boolean} [info.isPacket=false] flag specifying if buffer contains a packet or an object + * @return {Object|Array} The decoded AMF object or packet. * @api public */ function read (buffer, info) { if ('number' == typeof info) info = { offset: info }; - if (!info) info = {}; - if (null == info.offset) info.offset = 0; - + info = info || {} + info.offset = info.offset || 0; + info.isPacket = info.isPacket || false; // gets reset to 0 on each `read()` call info.byteLength = 0; + if (info.isPacket) { + return readPacket(buffer, info); + } else { + return readData(buffer, info); + } +} + +function readPacket (buffer, info) { + var packet = {}; + var headers = []; + var messages = []; + + var offset = info.offset; + packet.version = buffer.readUInt16BE(offset); + bytesUsed(info,2); + + var headerCount = buffer.readUInt16BE(info.offset); + bytesUsed(info,2); + + for (var i = 0, j = headerCount; i < j; i++) { + headers.push(readHeader(buffer, info)); + } + + var messageCount = buffer.readUInt16BE(info.offset); + bytesUsed(info,2); + + for (var i = 0, j = messageCount; i < j; i++) { + messages.push(readMessage(buffer,info)); + } + + // headerCount/messageCount aren't stored in the packet + // object since they're equal to the length of the arrays. + // But maybe that's something worth testing for? + + packet.headers = headers; + packet.messages = messages; + return packet; +} + +function readHeader (buffer, info) { + var headerName = readString(buffer,info); + // + var mustUnderstand = buffer.readUInt8(info.offset) != 0 ? true : false; + bytesUsed(info, 1); + var headerLength = buffer.readUInt32BE(info.offset); + bytesUsed(info,4); + + var header = { + name: headerName, + mustUnderstand: mustUnderstand, + length: headerLength, + // Header payload is just an AMF0 value-type + value: readData(buffer, info) + } + + return header; +} + +function readMessage (buffer, info) { + var targetURI = readString(buffer, info); + var responseURI = readString(buffer, info); + var messageLength = buffer.readUInt32BE(info.offset); + bytesUsed(info,4); + + var message = { + targetURI: targetURI, + responseURI: responseURI, + length: messageLength, + // Message payload is just an AMF0 value-type + value: readData(buffer, info) + } + + return message; +} + +function readData (buffer, info) { // read the "type" byte var type = buffer.readUInt8(info.offset); bytesUsed(info, 1);