UNPKG

domotz-remote-pawn

Version:

Domotz Agent

190 lines (172 loc) 5.55 kB
"use strict"; var util = require ("util"); var packets = require ("../packets"); var opcodes = require ("../opcodes"); var errors = require ("../errors"); var Request = require ("../request"); var knownExtensions = require ("../known-extensions"); var IncomingRequest = module.exports = function (args){ Request.call (this, args.helper._rinfo.address, args.helper._rinfo.port, args.globalOptions.retries, args.globalOptions.extensions.timeout); this._isRRQ = !args.reader; this._globalOptions = args.globalOptions; this._maxDataLength = 4; this._file = args.message.file; this._size = args.size || null; this._requestUserExtensions = args.message.userExtensions; this._responseUserExtensions = null; this._oackSent = false; this._firstPacket = true; this._requestExtensions = args.message.extensions; this._responseExtensions = null; var me = this; this._initSocket (args.helper._socket, function (message){ if (me._firstPacket){ me._firstPacket = false; me._requestTimer.reset (); } me._onMessage (message); }); //The socket is still not bound to an address and port because no packet has //been still sent, so the stats cannot be emitted yet (the call to address() //fails) //The socket must be manually bound this._socket.bind (0, null, function (){ if (me._requestExtensions === null){ //The client doesn't send extensions, it's probably that it doesn't //rollover automatically (old client), so we can abort the transfer //prematurely //Check the size (65535x512) if (me._isRRQ && me._size > 33553920){ return me._sendErrorAndClose (errors.EFBIG); } me._onReady (me._createStats (512, 1), 0); if (!me._isRRQ){ //The ACK of the block 0 is retransmitted from the reader me._sendAck (0); } }else{ //Send OACK me._sendOackMessage (me._requestExtensions); } }); }; util.inherits (IncomingRequest, Request); IncomingRequest.prototype.continueRequest = function (size){ this._setSize (size); if (this._requestExtensions === null){ this.onContinue (); }else{ if( this._responseExtensions.tsize !== undefined){ this._responseExtensions.tsize = size; } //Set the user extensions for (var p in this._responseUserExtensions){ //Ignore invalid extensions if (knownExtensions[p]) continue; if (this._requestUserExtensions[p] === undefined) continue; this._responseExtensions[p] = this._responseUserExtensions[p]; } this._sendAndRetransmit (packets.oack.serialize (this._responseExtensions)); } }; IncomingRequest.prototype._createStats = function (blockSize, windowSize){ //Save max data length this._maxDataLength += blockSize; var address = this._socket.address (); return { blockSize: blockSize, windowSize: windowSize, size: this._size, userExtensions: this._requestUserExtensions, retries: this._globalOptions.retries, timeout: this._timeout, localAddress: address.address, localPort: address.port, remoteAddress: this._address, remotePort: this._port, }; }; IncomingRequest.prototype._onMessage = function (buffer){ var op = buffer.readUInt16BE (0); if (op === opcodes.DATA){ if (!this._isRRQ){ if (buffer.length < 4 || buffer.length > this._maxDataLength){ return this._sendErrorAndClose (errors.EBADMSG); } try{ this._onData (packets.data.deserialize (buffer)); }catch (error){ this._sendErrorAndClose (error); } }else{ this._sendErrorAndClose (errors.EBADOP); } }else if (op === opcodes.ACK){ if (this._isRRQ){ if (buffer.length !== 4){ return this._sendErrorAndClose (errors.EBADMSG); } if (this._oackSent){ this._oackSent = false; if (buffer.readUInt16BE (2) !== 0){ this._sendErrorAndClose (errors.EBADMSG); }else{ this.onContinue (); } }else{ try{ this._onAck (packets.ack.deserialize (buffer)); }catch (error){ this._sendErrorAndClose (error); } } }else{ this._sendErrorAndClose (errors.EBADOP); } }else if (op === opcodes.ERROR){ if (buffer.length < 4) return this._closeWithError (errors.EBADMSG); try{ this._close (new Error (packets.error.deserialize (buffer).message)); }catch (error){ return this._closeWithError (error); } }else{ this._sendErrorAndClose (errors.EBADOP); } }; IncomingRequest.prototype._sendOackMessage = function (extensions){ var ext = {}; if (extensions.blksize !== undefined){ var blksize = this._globalOptions.extensions.blksize; ext.blksize = extensions.blksize > blksize ? blksize : extensions.blksize; } if (extensions.windowsize !== undefined){ var windowsize = this._globalOptions.extensions.windowsize; ext.windowsize = extensions.windowsize > windowsize ? windowsize : extensions.windowsize; } if (extensions.tsize !== undefined){ if (!this._isRRQ) this._size = extensions.tsize; ext.tsize = extensions.tsize; //ext.tsize is set later, when the request continues (RRQ) } if (extensions.rollover !== undefined){ ext.rollover = 0; } this._oackSent = true; var me = this; var ready = function (){ me._onReady (me._createStats (ext.blksize || 512, ext.windowsize || 1), 0, true); }; if (this._isRRQ){ //Save the extensions this._responseExtensions = ext; ready (); }else{ ready (); this._sendAndRetransmit (packets.oack.serialize (ext)); } };