adbkit
Version:
A pure Node.js client for the Android Debug Bridge.
122 lines (103 loc) • 3.59 kB
JavaScript
var EventEmitter, Packet, PacketReader,
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
hasProp = {}.hasOwnProperty;
EventEmitter = require('events').EventEmitter;
Packet = require('./packet');
PacketReader = (function(superClass) {
extend(PacketReader, superClass);
function PacketReader(stream) {
this.stream = stream;
PacketReader.__super__.constructor.call(this);
this.inBody = false;
this.buffer = null;
this.packet = null;
this.stream.on('readable', this._tryRead.bind(this));
this.stream.on('error', (function(_this) {
return function(err) {
return _this.emit('error', err);
};
})(this));
this.stream.on('end', (function(_this) {
return function() {
return _this.emit('end');
};
})(this));
setImmediate(this._tryRead.bind(this));
}
PacketReader.prototype._tryRead = function() {
var header;
while (this._appendChunk()) {
while (this.buffer) {
if (this.inBody) {
if (!(this.buffer.length >= this.packet.length)) {
break;
}
this.packet.data = this._consume(this.packet.length);
if (!this.packet.verifyChecksum()) {
this.emit('error', new PacketReader.ChecksumError(this.packet));
return;
}
this.emit('packet', this.packet);
this.inBody = false;
} else {
if (!(this.buffer.length >= 24)) {
break;
}
header = this._consume(24);
this.packet = new Packet(header.readUInt32LE(0), header.readUInt32LE(4), header.readUInt32LE(8), header.readUInt32LE(12), header.readUInt32LE(16), header.readUInt32LE(20), new Buffer(0));
if (!this.packet.verifyMagic()) {
this.emit('error', new PacketReader.MagicError(this.packet));
return;
}
if (this.packet.length === 0) {
this.emit('packet', this.packet);
} else {
this.inBody = true;
}
}
}
}
};
PacketReader.prototype._appendChunk = function() {
var chunk;
if (chunk = this.stream.read()) {
if (this.buffer) {
return this.buffer = Buffer.concat([this.buffer, chunk], this.buffer.length + chunk.length);
} else {
return this.buffer = chunk;
}
} else {
return null;
}
};
PacketReader.prototype._consume = function(length) {
var chunk;
chunk = this.buffer.slice(0, length);
this.buffer = length === this.buffer.length ? null : this.buffer.slice(length);
return chunk;
};
return PacketReader;
})(EventEmitter);
PacketReader.ChecksumError = (function(superClass) {
extend(ChecksumError, superClass);
function ChecksumError(packet) {
this.packet = packet;
Error.call(this);
this.name = 'ChecksumError';
this.message = "Checksum mismatch";
Error.captureStackTrace(this, PacketReader.ChecksumError);
}
return ChecksumError;
})(Error);
PacketReader.MagicError = (function(superClass) {
extend(MagicError, superClass);
function MagicError(packet) {
this.packet = packet;
Error.call(this);
this.name = 'MagicError';
this.message = "Magic value mismatch";
Error.captureStackTrace(this, PacketReader.MagicError);
}
return MagicError;
})(Error);
module.exports = PacketReader;