UNPKG

adbkit

Version:

A pure Node.js client for the Android Debug Bridge.

204 lines (176 loc) 5.83 kB
var EventEmitter, Packet, Parser, Promise, Protocol, Service, debug, 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; Promise = require('bluebird'); debug = require('debug')('adb:tcpusb:service'); Parser = require('../parser'); Protocol = require('../protocol'); Packet = require('./packet'); Service = (function(superClass) { extend(Service, superClass); function Service(client, serial, localId1, remoteId, socket) { this.client = client; this.serial = serial; this.localId = localId1; this.remoteId = remoteId; this.socket = socket; Service.__super__.constructor.call(this); this.opened = false; this.ended = false; this.transport = null; this.needAck = false; } Service.prototype.end = function() { var err, localId; if (this.transport) { this.transport.end(); } if (this.ended) { return this; } debug('O:A_CLSE'); localId = this.opened ? this.localId : 0; try { this.socket.write(Packet.assemble(Packet.A_CLSE, localId, this.remoteId, null)); } catch (_error) { err = _error; } this.transport = null; this.ended = true; this.emit('end'); return this; }; Service.prototype.handle = function(packet) { return Promise["try"]((function(_this) { return function() { switch (packet.command) { case Packet.A_OPEN: return _this._handleOpenPacket(packet); case Packet.A_OKAY: return _this._handleOkayPacket(packet); case Packet.A_WRTE: return _this._handleWritePacket(packet); case Packet.A_CLSE: return _this._handleClosePacket(packet); default: throw new Error("Unexpected packet " + packet.command); } }; })(this))["catch"]((function(_this) { return function(err) { _this.emit('error', err); return _this.end(); }; })(this)); }; Service.prototype._handleOpenPacket = function(packet) { debug('I:A_OPEN', packet); return this.client.transport(this.serial).then((function(_this) { return function(transport) { _this.transport = transport; if (_this.ended) { throw new LateTransportError(); } _this.transport.write(Protocol.encodeData(packet.data.slice(0, -1))); return _this.transport.parser.readAscii(4).then(function(reply) { switch (reply) { case Protocol.OKAY: debug('O:A_OKAY'); _this.socket.write(Packet.assemble(Packet.A_OKAY, _this.localId, _this.remoteId, null)); return _this.opened = true; case Protocol.FAIL: return _this.transport.parser.readError(); default: return _this.transport.parser.unexpected(reply, 'OKAY or FAIL'); } }); }; })(this)).then((function(_this) { return function() { return new Promise(function(resolve, reject) { _this.transport.socket.on('readable', function() { return _this._tryPush(); }).on('end', resolve).on('error', reject); return _this._tryPush(); }); }; })(this))["finally"]((function(_this) { return function() { return _this.end(); }; })(this)); }; Service.prototype._handleOkayPacket = function(packet) { debug('I:A_OKAY', packet); if (this.ended) { return; } if (!this.transport) { throw new Service.PrematurePacketError(packet); } this.needAck = false; return this._tryPush(); }; Service.prototype._handleWritePacket = function(packet) { debug('I:A_WRTE', packet); if (this.ended) { return; } if (!this.transport) { throw new Service.PrematurePacketError(packet); } if (packet.data) { this.transport.write(packet.data); } debug('O:A_OKAY'); return this.socket.write(Packet.assemble(Packet.A_OKAY, this.localId, this.remoteId, null)); }; Service.prototype._handleClosePacket = function(packet) { debug('I:A_CLSE', packet); if (this.ended) { return; } if (!this.transport) { throw new Service.PrematurePacketError(packet); } return this.end(); }; Service.prototype._tryPush = function() { var chunk; if (this.needAck || this.ended) { return; } if (chunk = this._readChunk(this.transport.socket)) { debug('O:A_WRTE'); this.socket.write(Packet.assemble(Packet.A_WRTE, this.localId, this.remoteId, chunk)); return this.needAck = true; } }; Service.prototype._readChunk = function(stream) { return stream.read(this.socket.maxPayload) || stream.read(); }; return Service; })(EventEmitter); Service.PrematurePacketError = (function(superClass) { extend(PrematurePacketError, superClass); function PrematurePacketError(packet1) { this.packet = packet1; Error.call(this); this.name = 'PrematurePacketError'; this.message = "Premature packet"; Error.captureStackTrace(this, Service.PrematurePacketError); } return PrematurePacketError; })(Error); Service.LateTransportError = (function(superClass) { extend(LateTransportError, superClass); function LateTransportError() { Error.call(this); this.name = 'LateTransportError'; this.message = "Late transport"; Error.captureStackTrace(this, Service.LateTransportError); } return LateTransportError; })(Error); module.exports = Service;