UNPKG

@homebridge/dbus-native

Version:

D-bus protocol implementation in native javascript

119 lines (108 loc) 3.7 kB
const Buffer = require('safe-buffer').Buffer; const marshall = require('./marshall'); const constants = require('./constants'); const DBusBuffer = require('./dbus-buffer'); const headerSignature = require('./header-signature.json'); module.exports.unmarshalMessages = function messageParser( stream, onMessage, opts ) { var state = 0; // 0: header, 1: fields + body var header, fieldsAndBody; var fieldsLength, fieldsLengthPadded; var fieldsAndBodyLength = 0; var bodyLength = 0; stream.on('readable', function () { while (1) { if (state === 0) { header = stream.read(16); if (!header) break; state = 1; fieldsLength = header.readUInt32LE(12); fieldsLengthPadded = ((fieldsLength + 7) >> 3) << 3; bodyLength = header.readUInt32LE(4); fieldsAndBodyLength = fieldsLengthPadded + bodyLength; } else { fieldsAndBody = stream.read(fieldsAndBodyLength); if (!fieldsAndBody) break; state = 0; var messageBuffer = new DBusBuffer(fieldsAndBody, undefined, opts); var unmarshalledHeader = messageBuffer.readArray( headerSignature[0].child[0], fieldsLength ); messageBuffer.align(3); var headerName; var message = {}; message.serial = header.readUInt32LE(8); for (var i = 0; i < unmarshalledHeader.length; ++i) { headerName = constants.headerTypeName[unmarshalledHeader[i][0]]; message[headerName] = unmarshalledHeader[i][1][1][0]; } message.type = header[1]; message.flags = header[2]; if (bodyLength > 0 && message.signature) { message.body = messageBuffer.read(message.signature); } onMessage(message); } } }); }; // given buffer which contains entire message deserialise it // TODO: factor out common code module.exports.unmarshall = function unmarshall(buff, opts) { var msgBuf = new DBusBuffer(buff, undefined, opts); var headers = msgBuf.read('yyyyuua(yv)'); var message = {}; for (var i = 0; i < headers[6].length; ++i) { var headerName = constants.headerTypeName[headers[6][i][0]]; message[headerName] = headers[6][i][1][1][0]; } message.type = headers[1]; message.flags = headers[2]; message.serial = headers[5]; msgBuf.align(3); message.body = msgBuf.read(message.signature); return message; }; module.exports.marshall = function marshallMessage(message) { if (!message.serial) throw new Error('Missing or invalid serial'); var flags = message.flags || 0; var type = message.type || constants.messageType.methodCall; var bodyLength = 0; var bodyBuff; if (message.signature && message.body) { bodyBuff = marshall(message.signature, message.body); bodyLength = bodyBuff.length; } var header = [ constants.endianness.le, type, flags, constants.protocolVersion, bodyLength, message.serial ]; var headerBuff = marshall('yyyyuu', header); var fields = []; constants.headerTypeName.forEach(function (fieldName) { var fieldVal = message[fieldName]; if (fieldVal) { fields.push([ constants.headerTypeId[fieldName], [constants.fieldSignature[fieldName], fieldVal] ]); } }); var fieldsBuff = marshall('a(yv)', [fields], 12); var headerLenAligned = ((headerBuff.length + fieldsBuff.length + 7) >> 3) << 3; var messageLen = headerLenAligned + bodyLength; var messageBuff = Buffer.alloc(messageLen); headerBuff.copy(messageBuff); fieldsBuff.copy(messageBuff, headerBuff.length); if (bodyLength > 0) bodyBuff.copy(messageBuff, headerLenAligned); return messageBuff; };