Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

xadb

Package Overview
Dependencies
Maintainers
1
Versions
18
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

xadb - npm Package Compare versions

Comparing version 0.3.7 to 0.3.8

2

app.js

@@ -19,2 +19,4 @@ "use strict";

console.log(listDevicesWithPaths);
let Properties = yield client.getProperties(listDevicesWithPaths[0].id);
console.log(Properties);
});

@@ -21,0 +23,0 @@ }

@@ -13,2 +13,4 @@ //测试

console.log(listDevicesWithPaths);
let Properties = await client.getProperties(listDevicesWithPaths[0].id);
console.log(Properties);
// return client

@@ -15,0 +17,0 @@ // .listDevicesWithPaths()

2

package.json
{
"name": "xadb",
"version": "0.3.7",
"version": "0.3.8",
"main": "./index",

@@ -5,0 +5,0 @@ "scripts": {

@@ -6,5 +6,5 @@ /* eslint-disable

// Fix any style issues and re-enable lint.
const Promise = require('bluebird')
const forge = require('node-forge')
const { BigInteger } = forge.jsbn
const Promise = require('bluebird');
const forge = require('node-forge');
const {BigInteger} = forge.jsbn;

@@ -26,80 +26,82 @@ /*

*/
var Auth = (function() {
let RE = undefined
let readPublicKeyFromStruct = undefined
Auth = class Auth {
static initClass() {
// coffeelint: disable=max_line_length
RE = /^((?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?)\0? (.*)\s*$/
// coffeelint: enable=max_line_length
readPublicKeyFromStruct = function(struct, comment) {
if (!struct.length) { throw new Error('Invalid public key') }
// Keep track of what we've read already
let offset = 0
// Get len
const len = struct.readUInt32LE(offset) * 4
offset += 4
if (struct.length !== (4 + 4 + len + len + 4)) {
throw new Error('Invalid public key')
var Auth = (function () {
let RE = undefined;
let readPublicKeyFromStruct = undefined;
Auth = class Auth {
static initClass() {
// coffeelint: disable=max_line_length
RE = /^((?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?)\0? (.*)\s*$/;
// coffeelint: enable=max_line_length
readPublicKeyFromStruct = function (struct, comment) {
if (!struct.length) {
throw new Error('Invalid public key')
}
// Keep track of what we've read already
let offset = 0;
// Get len
const len = struct.readUInt32LE(offset) * 4;
offset += 4;
if (struct.length !== (4 + 4 + len + len + 4)) {
throw new Error('Invalid public key')
}
// Skip n0inv, we don't need it
offset += 4;
// Get n
const n = Buffer.alloc(len);
struct.copy(n, 0, offset, offset + len);
[].reverse.call(n);
offset += len;
// Skip rr, we don't need it
offset += len;
// Get e
const e = struct.readUInt32LE(offset);
if ((e !== 3) && (e !== 65537)) {
throw new Error(`Invalid exponent ${e}, only 3 and 65537 are supported`)
}
// Restore the public key
const key = forge.pki.setRsaPublicKey(
new BigInteger(n.toString('hex'), 16),
new BigInteger(e.toString(), 10)
);
// It will be difficult to retrieve the fingerprint later as it's based
// on the complete struct data, so let's just extend the key with it.
const md = forge.md.md5.create();
md.update(struct.toString('binary'));
key.fingerprint = md.digest().toHex().match(/../g).join(':');
// Expose comment for the same reason
key.comment = comment;
return key
}
}
// Skip n0inv, we don't need it
offset += 4
// Get n
const n = Buffer.alloc(len)
struct.copy(n, 0, offset, offset + len);
[].reverse.call(n)
offset += len
// Skip rr, we don't need it
offset += len
// Get e
const e = struct.readUInt32LE(offset)
if ((e !== 3) && (e !== 65537)) {
throw new Error(`Invalid exponent ${e}, only 3 and 65537 are supported`)
}
// Restore the public key
const key = forge.pki.setRsaPublicKey(
new BigInteger(n.toString('hex'), 16),
new BigInteger(e.toString(), 10)
)
// It will be difficult to retrieve the fingerprint later as it's based
// on the complete struct data, so let's just extend the key with it.
const md = forge.md.md5.create()
md.update(struct.toString('binary'))
key.fingerprint = md.digest().toHex().match(/../g).join(':')
// Expose comment for the same reason
key.comment = comment
return key
}
}
static parsePublicKey(buffer) {
return new Promise(function(resolve, reject) {
let match
if (match = RE.exec(buffer)) {
const struct = Buffer.from(match[1], 'base64')
const comment = match[2]
return resolve(readPublicKeyFromStruct(struct, comment))
} else {
return reject(new Error('Unrecognizable public key format'))
static parsePublicKey(buffer) {
return new Promise(function (resolve, reject) {
let match;
if (match = RE.exec(buffer)) {
const struct = Buffer.from(match[1], 'base64');
const comment = match[2];
return resolve(readPublicKeyFromStruct(struct, comment))
} else {
return reject(new Error('Unrecognizable public key format'))
}
})
}
})
}
}
Auth.initClass()
return Auth
})()
};
Auth.initClass();
return Auth
})();
module.exports = Auth
module.exports = Auth;

@@ -11,4 +11,4 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
const connection_1 = require("./connection");
const debug = require('debug')('adb:client');
const Connection = require('./connection');
const Sync = require('./sync');

@@ -76,3 +76,3 @@ const Parser = require('./parser');

let conn = yield new Promise((resolve, reject) => {
let my_conn = new connection_1.Connection(this.options)
let my_conn = new Connection(this.options)
.on('error', (err => reject(err))).on('connect', (() => resolve(my_conn))).connect();

@@ -79,0 +79,0 @@ });

@@ -1,6 +0,5 @@

import {Connection} from "./connection";
const debug = require('debug')('adb:client');
const Connection = require('./connection');
const Sync = require('./sync');

@@ -7,0 +6,0 @@ const Parser = require('./parser');

// TODO: This file was created by bulk-decaffeinate.
// Sanity-check the conversion and remove this comment.
const Command = require('../../command')
const Protocol = require('../../protocol')
const Command = require('../../command');
const Protocol = require('../../protocol');
class HostDevicesWithPathsCommand extends Command {
execute() {
this._send('host:devices-l')
return this.parser.readAscii(4)
.then(reply => {
switch (reply) {
case Protocol.OKAY:
return this._readDevices()
case Protocol.FAIL:
return this.parser.readError()
default:
return this.parser.unexpected(reply, 'OKAY or FAIL')
}
})
}
execute() {
this._send('host:devices-l');
return this.parser.readAscii(4)
.then(reply => {
switch (reply) {
case Protocol.OKAY:
return this._readDevices();
case Protocol.FAIL:
return this.parser.readError();
default:
return this.parser.unexpected(reply, 'OKAY or FAIL')
}
})
}
_readDevices() {
return this.parser.readValue()
.then(value => {
return this._parseDevices(value)
})
}
_readDevices() {
return this.parser.readValue()
.then(value => {
return this._parseDevices(value)
})
}
_parseDevices(value) {
const devices = []
if (!value.length) { return devices }
for (let line of value.toString('ascii').split('\n')) {
if (line) {
// For some reason, the columns are separated by spaces instead of tabs
const [id, type, path] = Array.from(line.split(/\s+/))
devices.push({id, type, path})
}
_parseDevices(value) {
const devices = [];
if (!value.length) {
return devices
}
for (let line of value.toString('ascii').split('\n')) {
if (line) {
let array = Array.from(line.split(/\s+/));
let [id, type, path, transport_id] = Array.from(line.split(/\s+/));
for (let i = 0; i < array.length; i++) {
let strs = array[i].split(':');
if (strs[0] == 'transport_id') {
transport_id = strs[1];
}
}
devices.push({id, type, path, transport_id})
}
}
return devices
}
return devices
}
}
module.exports = HostDevicesWithPathsCommand
module.exports = HostDevicesWithPathsCommand;

@@ -1,77 +0,82 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Net = require("net");
const events_1 = require("events");
const child_process_1 = require("child_process");
const debug = require("debug");
const parser_1 = require("./parser");
const dump = require('./dump');
class Connection extends events_1.EventEmitter {
constructor(options) {
super();
this.options = options;
this.socket = null;
this.parser = null;
this.triedStarting = false;
// TODO: This file was created by bulk-decaffeinate.
// Sanity-check the conversion and remove this comment.
const Net = require('net')
const debug = require('debug')('adb:connection')
const {EventEmitter} = require('events')
const {execFile} = require('child_process')
const Parser = require('./parser')
const dump = require('./dump')
class Connection extends EventEmitter {
constructor(options) {
super()
this.options = options
this.socket = null
this.parser = null
this.triedStarting = false
}
connect() {
this.socket = Net.connect(this.options)
this.socket.setNoDelay(true)
this.parser = new Parser(this.socket)
this.socket.on('connect', () => {
return this.emit('connect')
})
this.socket.on('end', () => {
return this.emit('end')
})
this.socket.on('drain', () => {
return this.emit('drain')
})
this.socket.on('timeout', () => {
return this.emit('timeout')
})
this.socket.on('error', err => {
return this._handleError(err)
})
this.socket.on('close', hadError => {
return this.emit('close', hadError)
})
return this
}
end() {
this.socket.end()
return this
}
write(data, callback) {
this.socket.write(dump(data), callback)
return this
}
startServer(callback) {
debug(`Starting ADB server via '${this.options.bin} start-server'`)
return this._exec(['start-server'], {}, callback)
}
_exec(args, options, callback) {
debug(`CLI: ${this.options.bin} ${args.join(' ')}`)
execFile(this.options.bin, args, options, callback)
return this
}
_handleError(err) {
if ((err.code === 'ECONNREFUSED') && !this.triedStarting) {
debug('Connection was refused, let\'s try starting the server once')
this.triedStarting = true
this.startServer(err => {
if (err) { return this._handleError(err) }
return this.connect()
})
} else {
debug(`Connection had an error: ${err.message}`)
this.emit('error', err)
this.end()
}
connect() {
this.socket = Net.connect(this.options);
this.socket.setNoDelay(true);
this.parser = new parser_1.Parser(this.socket);
this.socket.on('connect', () => {
return this.emit('connect');
});
this.socket.on('end', () => {
return this.emit('end');
});
this.socket.on('drain', () => {
return this.emit('drain');
});
this.socket.on('timeout', () => {
return this.emit('timeout');
});
this.socket.on('error', err => {
return this._handleError(err);
});
this.socket.on('close', hadError => {
return this.emit('close', hadError);
});
return this;
}
end() {
this.socket.end();
return this;
}
write(data, callback) {
this.socket.write(dump(data), callback);
return this;
}
startServer(callback) {
debug(`Starting ADB server via '${this.options.bin} start-server'`);
return this._exec(['start-server'], {}, callback);
}
_exec(args, options, callback) {
debug(`CLI: ${this.options.bin} ${args.join(' ')}`);
child_process_1.execFile(this.options.bin, args, options, callback);
return this;
}
_handleError(err) {
if ((err.code === 'ECONNREFUSED') && !this.triedStarting) {
debug('Connection was refused, let\'s try starting the server once');
this.triedStarting = true;
this.startServer(err => {
if (err) {
return this._handleError(err);
}
return this.connect();
});
}
else {
debug(`Connection had an error: ${err.message}`);
this.emit('error', err);
this.end();
}
}
}
}
exports.Connection = Connection;
//# sourceMappingURL=connection.js.map
module.exports = Connection
// TODO: This file was created by bulk-decaffeinate.
// Sanity-check the conversion and remove this comment.
const Assert = require('assert')
const Stream = require('stream')
const Assert = require('assert');
const Stream = require('stream');
class RgbTransform extends Stream.Transform {
constructor(meta, options) {
super(options)
this.meta = meta
this._buffer = Buffer.from('')
Assert.ok(((this.meta.bpp === 24) || (this.meta.bpp === 32)),
'Only 24-bit and 32-bit raw images with 8-bits per color are supported')
this._r_pos = this.meta.red_offset / 8
this._g_pos = this.meta.green_offset / 8
this._b_pos = this.meta.blue_offset / 8
this._a_pos = this.meta.alpha_offset / 8
this._pixel_bytes = this.meta.bpp / 8
}
constructor(meta, options) {
super(options);
this.meta = meta;
this._buffer = Buffer.from('');
Assert.ok(((this.meta.bpp === 24) || (this.meta.bpp === 32)),
'Only 24-bit and 32-bit raw images with 8-bits per color are supported');
this._r_pos = this.meta.red_offset / 8;
this._g_pos = this.meta.green_offset / 8;
this._b_pos = this.meta.blue_offset / 8;
this._a_pos = this.meta.alpha_offset / 8;
this._pixel_bytes = this.meta.bpp / 8
}
_transform(chunk, encoding, done) {
if (this._buffer.length) {
this._buffer = Buffer.concat([this._buffer, chunk], this._buffer.length + chunk.length)
} else {
this._buffer = chunk
_transform(chunk, encoding, done) {
if (this._buffer.length) {
this._buffer = Buffer.concat([this._buffer, chunk], this._buffer.length + chunk.length)
} else {
this._buffer = chunk
}
let sourceCursor = 0;
let targetCursor = 0;
const target = this._pixel_bytes === 3
? this._buffer
: Buffer.alloc(Math.max(4, (chunk.length / this._pixel_bytes) * 3));
while ((this._buffer.length - sourceCursor) >= this._pixel_bytes) {
const r = this._buffer[sourceCursor + this._r_pos];
const g = this._buffer[sourceCursor + this._g_pos];
const b = this._buffer[sourceCursor + this._b_pos];
target[targetCursor + 0] = r;
target[targetCursor + 1] = g;
target[targetCursor + 2] = b;
sourceCursor += this._pixel_bytes;
targetCursor += 3
}
if (targetCursor) {
this.push(target.slice(0, targetCursor));
this._buffer = this._buffer.slice(sourceCursor)
}
done()
}
let sourceCursor = 0
let targetCursor = 0
const target = this._pixel_bytes === 3
? this._buffer
: Buffer.alloc(Math.max(4, (chunk.length / this._pixel_bytes) * 3))
while ((this._buffer.length - sourceCursor) >= this._pixel_bytes) {
const r = this._buffer[sourceCursor + this._r_pos]
const g = this._buffer[sourceCursor + this._g_pos]
const b = this._buffer[sourceCursor + this._b_pos]
target[targetCursor + 0] = r
target[targetCursor + 1] = g
target[targetCursor + 2] = b
sourceCursor += this._pixel_bytes
targetCursor += 3
}
if (targetCursor) {
this.push(target.slice(0, targetCursor))
this._buffer = this._buffer.slice(sourceCursor)
}
done()
}
}
module.exports = RgbTransform
module.exports = RgbTransform;

@@ -1,152 +0,193 @@

"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const Protocol = require("./protocol");
/* eslint-disable
no-cond-assign,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
const Promise = require('bluebird');
const Protocol = require('./protocol');
class Parser {
constructor(stream) {
this.stream = stream;
this.ended = false;
this.ended = false
}
end() {
return __awaiter(this, void 0, void 0, function* () {
let work = yield new Promise((resolve, reject) => {
if (this.ended) {
return resolve(true);
}
const tryRead = () => {
while (this.stream.read()) {
}
};
this.stream.on('readable', tryRead);
this.stream.on('error', (err => reject(err)));
this.stream.on('end', (() => {
this.ended = true;
return resolve(true);
}));
this.stream.read(0);
this.stream.end();
});
this.stream.removeAllListeners();
return work;
});
let endListener, errorListener;
if (this.ended) {
return Promise.resolve(true)
}
const resolver = Promise.defer();
const tryRead = () => {
while (this.stream.read()) {
}
};
this.stream.on('readable', tryRead);
this.stream.on('error', (errorListener = err => resolver.reject(err))
);
this.stream.on('end', (endListener = () => {
this.ended = true;
return resolver.resolve(true)
})
);
this.stream.read(0);
this.stream.end();
return resolver.promise.cancellable().finally(() => {
this.stream.removeListener('readable', tryRead);
this.stream.removeListener('error', errorListener);
return this.stream.removeListener('end', endListener)
})
}
raw() {
return this.stream;
return this.stream
}
readAll() {
return __awaiter(this, void 0, void 0, function* () {
let work = yield new Promise((resolve, reject) => {
let all = Buffer.alloc(0);
const tryRead = () => {
let chunk;
while ((chunk = this.stream.read())) {
all = Buffer.concat([all, chunk]);
}
if (this.ended) {
return resolve(all);
}
};
this.stream.on('readable', tryRead);
this.stream.on('error', (err => reject(err)));
this.stream.on('end', (() => {
this.ended = true;
return resolve(all);
}));
tryRead();
});
this.stream.removeAllListeners();
return work;
});
let endListener, errorListener;
let all = Buffer.alloc(0);
const resolver = Promise.defer();
const tryRead = () => {
let chunk;
while ((chunk = this.stream.read())) {
all = Buffer.concat([all, chunk])
}
if (this.ended) {
return resolver.resolve(all)
}
};
this.stream.on('readable', tryRead);
this.stream.on('error', (errorListener = err => resolver.reject(err))
);
this.stream.on('end', (endListener = () => {
this.ended = true;
return resolver.resolve(all)
})
);
tryRead();
return resolver.promise.cancellable().finally(() => {
this.stream.removeListener('readable', tryRead);
this.stream.removeListener('error', errorListener);
return this.stream.removeListener('end', endListener)
})
}
readAscii(howMany) {
return this.readBytes(howMany)
.then(chunk => chunk.toString('ascii'));
.then(chunk => chunk.toString('ascii'))
}
readBytes(howMany) {
return __awaiter(this, void 0, void 0, function* () {
let work = yield new Promise((resolve, reject) => {
const tryRead = () => {
if (howMany) {
let chunk;
if (chunk = this.stream.read(howMany)) {
howMany -= chunk.length;
if (howMany === 0) {
return resolve(chunk);
}
}
if (this.ended) {
return reject(new Parser.PrematureEOFError(howMany));
}
const resolver = Promise.defer();
const tryRead = () => {
if (howMany) {
let chunk;
if (chunk = this.stream.read(howMany)) {
// If the stream ends while still having unread bytes, the read call
// will ignore the limit and just return what it's got.
howMany -= chunk.length;
if (howMany === 0) {
return resolver.resolve(chunk)
}
else {
return resolve(Buffer.alloc(0));
}
};
const endListener = () => {
this.ended = true;
return reject(new Parser.PrematureEOFError(howMany));
};
const errorListener = err => reject(err);
this.stream.on('readable', tryRead);
this.stream.on('error', errorListener);
this.stream.on('end', endListener);
tryRead();
});
this.stream.removeAllListeners();
return work;
});
}
if (this.ended) {
return resolver.reject(new Parser.PrematureEOFError(howMany))
}
} else {
return resolver.resolve(Buffer.alloc(0))
}
};
const endListener = () => {
this.ended = true;
return resolver.reject(new Parser.PrematureEOFError(howMany))
};
const errorListener = err => resolver.reject(err);
this.stream.on('readable', tryRead);
this.stream.on('error', errorListener);
this.stream.on('end', endListener);
tryRead();
return resolver.promise.cancellable().finally(() => {
this.stream.removeListener('readable', tryRead);
this.stream.removeListener('error', errorListener);
return this.stream.removeListener('end', endListener)
})
}
readByteFlow(howMany, targetStream) {
return __awaiter(this, void 0, void 0, function* () {
let work = yield new Promise((resolve, reject) => {
const tryRead = () => {
if (howMany) {
let chunk;
while ((chunk = this.stream.read(howMany) || this.stream.read())) {
howMany -= chunk.length;
targetStream.write(chunk);
if (howMany === 0) {
return resolve();
}
}
if (this.ended) {
return reject(new Parser.PrematureEOFError(howMany));
}
const resolver = Promise.defer();
const tryRead = () => {
if (howMany) {
// Try to get the exact amount we need first. If unsuccessful, take
// whatever is available, which will be less than the needed amount.
let chunk;
while ((chunk = this.stream.read(howMany) || this.stream.read())) {
howMany -= chunk.length;
targetStream.write(chunk);
if (howMany === 0) {
return resolver.resolve()
}
else {
return resolve();
}
};
const endListener = () => {
this.ended = true;
return reject(new Parser.PrematureEOFError(howMany));
};
const errorListener = err => reject(err);
this.stream.on('readable', tryRead);
this.stream.on('error', errorListener);
this.stream.on('end', endListener);
tryRead();
});
this.stream.removeAllListeners();
return work;
});
}
if (this.ended) {
return resolver.reject(new Parser.PrematureEOFError(howMany))
}
} else {
return resolver.resolve()
}
};
const endListener = () => {
this.ended = true;
return resolver.reject(new Parser.PrematureEOFError(howMany))
};
const errorListener = err => resolver.reject(err);
this.stream.on('readable', tryRead);
this.stream.on('error', errorListener);
this.stream.on('end', endListener);
tryRead();
return resolver.promise.cancellable().finally(() => {
this.stream.removeListener('readable', tryRead);
this.stream.removeListener('error', errorListener);
return this.stream.removeListener('end', endListener)
})
}
readError() {
return this.readValue()
.then(value => Promise.reject(new Parser.FailError(value.toString())));
.then(value => Promise.reject(new Parser.FailError(value.toString())))
}
readValue() {
return this.readAscii(4)
.then(value => {
const length = Protocol.decodeLength(value);
return this.readBytes(length);
});
const length = Protocol.decodeLength(value);
return this.readBytes(length)
})
}
readUntil(code) {

@@ -157,52 +198,54 @@ let skipped = Buffer.alloc(0);

.then(function (chunk) {
if (chunk[0] === code) {
return skipped;
}
else {
skipped = Buffer.concat([skipped, chunk]);
return read();
}
});
if (chunk[0] === code) {
return skipped
} else {
skipped = Buffer.concat([skipped, chunk]);
return read()
}
})
};
return read();
return read()
}
searchLine(re) {
return this.readLine()
.then(line => {
let match;
if ((match = re.exec(line))) {
return match;
}
else {
return this.searchLine(re);
}
});
let match;
if ((match = re.exec(line))) {
return match
} else {
return this.searchLine(re)
}
})
}
readLine() {
return this.readUntil(0x0a)
return this.readUntil(0x0a) // '\n'
.then(function (line) {
if (line[line.length - 1] === 0x0d) {
return line.slice(0, -1);
}
else {
return line;
}
});
if (line[line.length - 1] === 0x0d) { // '\r'
return line.slice(0, -1)
} else {
return line
}
})
}
unexpected(data, expected) {
return Promise.reject(new Parser.UnexpectedDataError(data, expected));
return Promise.reject(new Parser.UnexpectedDataError(data, expected))
}
}
Parser.FailError = class FailError extends Error {
constructor(message) {
super();
super(); // TODO check sanity
Error.call(this);
this.name = 'FailError';
this.message = `Failure: '${message}'`;
Error.captureStackTrace(this, Parser.FailError);
Error.captureStackTrace(this, Parser.FailError)
}
};
Parser.PrematureEOFError = class PrematureEOFError extends Error {
constructor(howManyMissing) {
super();
super(); // TODO check sanity
Error.call(this);

@@ -213,8 +256,9 @@ this.name = 'PrematureEOFError';

this.missingBytes = howManyMissing;
Error.captureStackTrace(this, Parser.PrematureEOFError);
Error.captureStackTrace(this, Parser.PrematureEOFError)
}
};
Parser.UnexpectedDataError = class UnexpectedDataError extends Error {
constructor(unexpected, expected) {
super();
super(); // TODO check sanity
Error.call(this);

@@ -225,6 +269,6 @@ this.name = 'UnexpectedDataError';

this.expected = expected;
Error.captureStackTrace(this, Parser.UnexpectedDataError);
Error.captureStackTrace(this, Parser.UnexpectedDataError)
}
};
exports.Parser = Parser;
//# sourceMappingURL=parser.js.map
module.exports = Parser;

@@ -23,3 +23,3 @@ class Protocol {

if (!Buffer.isBuffer(data)) {
data = Buffer.from(data);
data = Buffer.from(data)
}

@@ -26,0 +26,0 @@ return Buffer.concat([Buffer.from(Protocol.encodeLength(data.length)), data])

@@ -1,273 +0,328 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Fs = require('fs');
const Path = require('path');
const Promise = require('bluebird');
const { EventEmitter } = require('events');
const debug = require('debug')('adb:sync');
const Parser = require('./parser');
const Protocol = require('./protocol');
const Stats = require('./sync/stats');
const Entry = require('./sync/entry');
const PushTransfer = require('./sync/pushtransfer');
const PullTransfer = require('./sync/pulltransfer');
class Sync extends EventEmitter {
constructor(connection) {
super();
this.DEFAULT_CHMOD = 0o644;
this.DATA_MAX_LENGTH = 65536;
this.connection = connection;
this.parser = this.connection.parser;
/* eslint-disable
no-cond-assign,
no-unused-vars,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
const Fs = require('fs')
const Path = require('path')
const Promise = require('bluebird')
const {EventEmitter} = require('events')
const debug = require('debug')('adb:sync')
const Parser = require('./parser')
const Protocol = require('./protocol')
const Stats = require('./sync/stats')
const Entry = require('./sync/entry')
const PushTransfer = require('./sync/pushtransfer')
const PullTransfer = require('./sync/pulltransfer')
var Sync = (function() {
let TEMP_PATH = undefined
let DEFAULT_CHMOD = undefined
let DATA_MAX_LENGTH = undefined
Sync = class Sync extends EventEmitter {
static initClass() {
TEMP_PATH = '/data/local/tmp'
DEFAULT_CHMOD = 0o644
DATA_MAX_LENGTH = 65536
}
static temp(path) {
return `${Sync.TEMP_PATH}/${Path.basename(path)}`;
return `${TEMP_PATH}/${Path.basename(path)}`
}
constructor(connection) {
super()
this.connection = connection
this.parser = this.connection.parser
}
stat(path, callback) {
this._sendCommandWithArg(Protocol.STAT, path);
this._sendCommandWithArg(Protocol.STAT, path)
return this.parser.readAscii(4)
.then(reply => {
switch (reply) {
case Protocol.STAT:
return this.parser.readBytes(12)
.then(stat => {
const mode = stat.readUInt32LE(0)
const size = stat.readUInt32LE(4)
const mtime = stat.readUInt32LE(8)
if (mode === 0) {
return this._enoent(path)
} else {
return new Stats(mode, size, mtime)
}
})
case Protocol.FAIL:
return this._readError()
default:
return this.parser.unexpected(reply, 'STAT or FAIL')
}
}).nodeify(callback)
}
readdir(path, callback) {
const files = []
var readNext = () => {
return this.parser.readAscii(4)
.then(reply => {
.then(reply => {
switch (reply) {
case Protocol.STAT:
return this.parser.readBytes(12)
.then(stat => {
const mode = stat.readUInt32LE(0);
const size = stat.readUInt32LE(4);
const mtime = stat.readUInt32LE(8);
if (mode === 0) {
return this._enoent(path);
}
else {
return new Stats(mode, size, mtime);
}
});
case Protocol.FAIL:
return this._readError();
default:
return this.parser.unexpected(reply, 'STAT or FAIL');
case Protocol.DENT:
return this.parser.readBytes(16)
.then(stat => {
const mode = stat.readUInt32LE(0)
const size = stat.readUInt32LE(4)
const mtime = stat.readUInt32LE(8)
const namelen = stat.readUInt32LE(12)
return this.parser.readBytes(namelen)
.then(function(name) {
name = name.toString()
// Skip '.' and '..' to match Node's fs.readdir().
if ((name !== '.') && (name !== '..')) {
files.push(new Entry(name, mode, size, mtime))
}
return readNext()
})
})
case Protocol.DONE:
return this.parser.readBytes(16)
.then(zero => files)
case Protocol.FAIL:
return this._readError()
default:
return this.parser.unexpected(reply, 'DENT, DONE or FAIL')
}
}).nodeify(callback);
})
}
this._sendCommandWithArg(Protocol.LIST, path)
return readNext()
.nodeify(callback)
}
readdir(path, callback) {
const files = [];
var readNext = () => {
return this.parser.readAscii(4)
.then(reply => {
switch (reply) {
case Protocol.DENT:
return this.parser.readBytes(16)
.then(stat => {
const mode = stat.readUInt32LE(0);
const size = stat.readUInt32LE(4);
const mtime = stat.readUInt32LE(8);
const namelen = stat.readUInt32LE(12);
return this.parser.readBytes(namelen)
.then(function (name) {
name = name.toString();
if ((name !== '.') && (name !== '..')) {
files.push(new Entry(name, mode, size, mtime));
}
return readNext();
});
});
case Protocol.DONE:
return this.parser.readBytes(16)
.then(zero => files);
case Protocol.FAIL:
return this._readError();
default:
return this.parser.unexpected(reply, 'DENT, DONE or FAIL');
}
});
};
this._sendCommandWithArg(Protocol.LIST, path);
return readNext()
.nodeify(callback);
}
push(contents, path, mode) {
if (typeof contents === 'string') {
return this.pushFile(contents, path, mode);
}
else {
return this.pushStream(contents, path, mode);
}
if (typeof contents === 'string') {
return this.pushFile(contents, path, mode)
} else {
return this.pushStream(contents, path, mode)
}
}
pushFile(file, path, mode = this.DEFAULT_CHMOD) {
if (!mode) {
mode = this.DEFAULT_CHMOD;
}
return this.pushStream(Fs.createReadStream(file), path, mode);
pushFile(file, path, mode = DEFAULT_CHMOD) {
if (!mode) { mode = DEFAULT_CHMOD }
return this.pushStream(Fs.createReadStream(file), path, mode)
}
pushStream(stream, path, mode = this.DEFAULT_CHMOD) {
mode |= Stats.S_IFREG;
this._sendCommandWithArg(Protocol.SEND, `${path},${mode}`);
return this._writeData(stream, Math.floor(Date.now() / 1000));
pushStream(stream, path, mode = DEFAULT_CHMOD) {
mode |= Stats.S_IFREG
this._sendCommandWithArg(Protocol.SEND, `${path},${mode}`)
return this._writeData(stream, Math.floor(Date.now() / 1000))
}
pull(path) {
this._sendCommandWithArg(Protocol.RECV, `${path}`);
return this._readData();
this._sendCommandWithArg(Protocol.RECV, `${path}`)
return this._readData()
}
end() {
this.connection.end();
return this;
this.connection.end()
return this
}
tempFile(path) {
return Sync.temp(path);
return Sync.temp(path)
}
_writeData(stream, timeStamp) {
let writer;
const transfer = new PushTransfer;
const writeData = () => {
let endListener, errorListener, readableListener;
let resolver = Promise.defer();
writer = Promise.resolve()
.cancellable();
stream.on('end', (endListener = () => {
return writer.then(() => {
this._sendCommandWithLength(Protocol.DONE, timeStamp);
return resolver.resolve();
});
}));
const waitForDrain = () => {
let drainListener;
resolver = Promise.defer();
this.connection.on('drain', (drainListener = () => resolver.resolve()));
return resolver.promise.finally(() => {
return this.connection.removeListener('drain', drainListener);
});
};
const track = () => transfer.pop();
var writeNext = () => {
let chunk;
if (chunk = stream.read(this.DATA_MAX_LENGTH) || stream.read()) {
this._sendCommandWithLength(Protocol.DATA, chunk.length);
transfer.push(chunk.length);
if (this.connection.write(chunk, track)) {
return writeNext();
}
else {
return waitForDrain()
.then(writeNext);
}
}
else {
return Promise.resolve();
}
};
stream.on('readable', (readableListener = () => writer.then(writeNext)));
stream.on('error', (errorListener = err => resolver.reject(err)));
return resolver.promise.finally(function () {
stream.removeListener('end', endListener);
stream.removeListener('readable', readableListener);
stream.removeListener('error', errorListener);
return writer.cancel();
});
};
const readReply = () => {
return this.parser.readAscii(4)
.then(reply => {
switch (reply) {
case Protocol.OKAY:
return this.parser.readBytes(4)
.then(zero => true);
case Protocol.FAIL:
return this._readError();
default:
return this.parser.unexpected(reply, 'OKAY or FAIL');
}
});
};
writer = writeData()
.cancellable()
.catch(Promise.CancellationError, err => {
return this.connection.end();
}).catch(function (err) {
transfer.emit('error', err);
return reader.cancel();
});
var reader = readReply()
.cancellable()
.catch(Promise.CancellationError, err => true).catch(function (err) {
transfer.emit('error', err);
return writer.cancel();
}).finally(() => transfer.end());
transfer.on('cancel', function () {
writer.cancel();
return reader.cancel();
});
return transfer;
let writer
const transfer = new PushTransfer
const writeData = () => {
let endListener, errorListener, readableListener
let resolver = Promise.defer()
writer = Promise.resolve()
.cancellable()
stream.on('end', (endListener = () => {
return writer.then(() => {
this._sendCommandWithLength(Protocol.DONE, timeStamp)
return resolver.resolve()
})
})
)
const waitForDrain = () => {
let drainListener
resolver = Promise.defer()
this.connection.on('drain', (drainListener = () => resolver.resolve())
)
return resolver.promise.finally(() => {
return this.connection.removeListener('drain', drainListener)
})
}
const track = () => transfer.pop()
var writeNext = () => {
let chunk
if (chunk = stream.read(DATA_MAX_LENGTH) || stream.read()) {
this._sendCommandWithLength(Protocol.DATA, chunk.length)
transfer.push(chunk.length)
if (this.connection.write(chunk, track)) {
return writeNext()
} else {
return waitForDrain()
.then(writeNext)
}
} else {
return Promise.resolve()
}
}
stream.on('readable', (readableListener = () => writer.then(writeNext))
)
stream.on('error', (errorListener = err => resolver.reject(err))
)
return resolver.promise.finally(function() {
stream.removeListener('end', endListener)
stream.removeListener('readable', readableListener)
stream.removeListener('error', errorListener)
return writer.cancel()
})
}
const readReply = () => {
return this.parser.readAscii(4)
.then(reply => {
switch (reply) {
case Protocol.OKAY:
return this.parser.readBytes(4)
.then(zero => true)
case Protocol.FAIL:
return this._readError()
default:
return this.parser.unexpected(reply, 'OKAY or FAIL')
}
})
}
// While I can't think of a case that would break this double-Promise
// writer-reader arrangement right now, it's not immediately obvious
// that the code is correct and it may or may not have some failing
// edge cases. Refactor pending.
writer = writeData()
.cancellable()
.catch(Promise.CancellationError, err => {
return this.connection.end()
}).catch(function(err) {
transfer.emit('error', err)
return reader.cancel()
})
var reader = readReply()
.cancellable()
.catch(Promise.CancellationError, err => true).catch(function(err) {
transfer.emit('error', err)
return writer.cancel()}).finally(() => transfer.end())
transfer.on('cancel', function() {
writer.cancel()
return reader.cancel()
})
return transfer
}
_readData() {
let cancelListener;
const transfer = new PullTransfer;
var readNext = () => {
return this.parser.readAscii(4)
.cancellable()
.then(reply => {
switch (reply) {
case Protocol.DATA:
return this.parser.readBytes(4)
.then(lengthData => {
const length = lengthData.readUInt32LE(0);
return this.parser.readByteFlow(length, transfer)
.then(readNext);
});
case Protocol.DONE:
return this.parser.readBytes(4)
.then(zero => true);
case Protocol.FAIL:
return this._readError();
default:
return this.parser.unexpected(reply, 'DATA, DONE or FAIL');
}
});
};
const reader = readNext()
.catch(Promise.CancellationError, err => {
return this.connection.end();
}).catch(err => transfer.emit('error', err)).finally(function () {
transfer.removeListener('cancel', cancelListener);
return transfer.end();
});
transfer.on('cancel', (cancelListener = () => reader.cancel()));
return transfer;
let cancelListener
const transfer = new PullTransfer
var readNext = () => {
return this.parser.readAscii(4)
.cancellable()
.then(reply => {
switch (reply) {
case Protocol.DATA:
return this.parser.readBytes(4)
.then(lengthData => {
const length = lengthData.readUInt32LE(0)
return this.parser.readByteFlow(length, transfer)
.then(readNext)
})
case Protocol.DONE:
return this.parser.readBytes(4)
.then(zero => true)
case Protocol.FAIL:
return this._readError()
default:
return this.parser.unexpected(reply, 'DATA, DONE or FAIL')
}
})
}
const reader = readNext()
.catch(Promise.CancellationError, err => {
return this.connection.end()
}).catch(err => transfer.emit('error', err)).finally(function() {
transfer.removeListener('cancel', cancelListener)
return transfer.end()
})
transfer.on('cancel', (cancelListener = () => reader.cancel())
)
return transfer
}
_readError() {
return this.parser.readBytes(4)
.then(length => {
return this.parser.readBytes(length.readUInt32LE(0))
.then(buf => Promise.reject(new Parser.FailError(buf.toString())));
return this.parser.readBytes(4)
.then(length => {
return this.parser.readBytes(length.readUInt32LE(0))
.then(buf => Promise.reject(new Parser.FailError(buf.toString())))
}).finally(() => {
return this.parser.end();
});
return this.parser.end()
})
}
_sendCommandWithLength(cmd, length) {
if (cmd !== Protocol.DATA) {
debug(cmd);
}
const payload = Buffer.alloc(cmd.length + 4);
payload.write(cmd, 0, cmd.length);
payload.writeUInt32LE(length, cmd.length);
return this.connection.write(payload);
if (cmd !== Protocol.DATA) { debug(cmd) }
const payload = Buffer.alloc(cmd.length + 4)
payload.write(cmd, 0, cmd.length)
payload.writeUInt32LE(length, cmd.length)
return this.connection.write(payload)
}
_sendCommandWithArg(cmd, arg) {
debug(`${cmd} ${arg}`);
const payload = Buffer.alloc(cmd.length + 4 + arg.length);
let pos = 0;
payload.write(cmd, pos, cmd.length);
pos += cmd.length;
payload.writeUInt32LE(arg.length, pos);
pos += 4;
payload.write(arg, pos);
return this.connection.write(payload);
debug(`${cmd} ${arg}`)
const payload = Buffer.alloc(cmd.length + 4 + arg.length)
let pos = 0
payload.write(cmd, pos, cmd.length)
pos += cmd.length
payload.writeUInt32LE(arg.length, pos)
pos += 4
payload.write(arg, pos)
return this.connection.write(payload)
}
_enoent(path) {
const err = new Error(`ENOENT, no such file or directory '${path}'`);
err.errno = 34;
err.code = 'ENOENT';
err.path = path;
return Promise.reject(err);
const err = new Error(`ENOENT, no such file or directory '${path}'`)
err.errno = 34
err.code = 'ENOENT'
err.path = path
return Promise.reject(err)
}
}
Sync.TEMP_PATH = '/data/local/tmp';
exports.Sync = Sync;
//# sourceMappingURL=sync.js.map
}
Sync.initClass()
return Sync
})()
module.exports = Sync
// TODO: This file was created by bulk-decaffeinate.
// Sanity-check the conversion and remove this comment.
class Packet {
static initClass() {
this.A_SYNC = 0x434e5953
this.A_CNXN = 0x4e584e43
this.A_OPEN = 0x4e45504f
this.A_OKAY = 0x59414b4f
this.A_CLSE = 0x45534c43
this.A_WRTE = 0x45545257
this.A_AUTH = 0x48545541
}
static initClass() {
this.A_SYNC = 0x434e5953;
this.A_CNXN = 0x4e584e43;
this.A_OPEN = 0x4e45504f;
this.A_OKAY = 0x59414b4f;
this.A_CLSE = 0x45534c43;
this.A_WRTE = 0x45545257;
this.A_AUTH = 0x48545541
}
static checksum(data) {
let sum = 0
if (data) { for (let char of data) { sum += char } }
return sum
}
static checksum(data) {
let sum = 0;
if (data) {
for (let char of data) {
sum += char
}
}
return sum
}
static magic(command) {
// We need the full uint32 range, which ">>> 0" thankfully allows us to use
return (command ^ 0xffffffff) >>> 0
}
static magic(command) {
// We need the full uint32 range, which ">>> 0" thankfully allows us to use
return (command ^ 0xffffffff) >>> 0
}
static assemble(command, arg0, arg1, data) {
let chunk
if (data) {
chunk = Buffer.alloc(24 + data.length)
chunk.writeUInt32LE(command, 0)
chunk.writeUInt32LE(arg0, 4)
chunk.writeUInt32LE(arg1, 8)
chunk.writeUInt32LE(data.length, 12)
chunk.writeUInt32LE(Packet.checksum(data), 16)
chunk.writeUInt32LE(Packet.magic(command), 20)
data.copy(chunk, 24)
return chunk
} else {
chunk = Buffer.alloc(24)
chunk.writeUInt32LE(command, 0)
chunk.writeUInt32LE(arg0, 4)
chunk.writeUInt32LE(arg1, 8)
chunk.writeUInt32LE(0, 12)
chunk.writeUInt32LE(0, 16)
chunk.writeUInt32LE(Packet.magic(command), 20)
return chunk
static assemble(command, arg0, arg1, data) {
let chunk;
if (data) {
chunk = Buffer.alloc(24 + data.length);
chunk.writeUInt32LE(command, 0);
chunk.writeUInt32LE(arg0, 4);
chunk.writeUInt32LE(arg1, 8);
chunk.writeUInt32LE(data.length, 12);
chunk.writeUInt32LE(Packet.checksum(data), 16);
chunk.writeUInt32LE(Packet.magic(command), 20);
data.copy(chunk, 24);
return chunk
} else {
chunk = Buffer.alloc(24);
chunk.writeUInt32LE(command, 0);
chunk.writeUInt32LE(arg0, 4);
chunk.writeUInt32LE(arg1, 8);
chunk.writeUInt32LE(0, 12);
chunk.writeUInt32LE(0, 16);
chunk.writeUInt32LE(Packet.magic(command), 20);
return chunk
}
}
}
static swap32(n) {
const buffer = Buffer.alloc(4)
buffer.writeUInt32LE(n, 0)
return buffer.readUInt32BE(0)
}
static swap32(n) {
const buffer = Buffer.alloc(4);
buffer.writeUInt32LE(n, 0);
return buffer.readUInt32BE(0)
}
constructor(command, arg0, arg1, length, check, magic, data) {
this.command = command
this.arg0 = arg0
this.arg1 = arg1
this.length = length
this.check = check
this.magic = magic
this.data = data
}
constructor(command, arg0, arg1, length, check, magic, data) {
this.command = command;
this.arg0 = arg0;
this.arg1 = arg1;
this.length = length;
this.check = check;
this.magic = magic;
this.data = data
}
verifyChecksum() {
return this.check === Packet.checksum(this.data)
}
verifyChecksum() {
return this.check === Packet.checksum(this.data)
}
verifyMagic() {
return this.magic === Packet.magic(this.command)
}
verifyMagic() {
return this.magic === Packet.magic(this.command)
}
toString() {
const type = (() => { switch (this.command) {
case Packet.A_SYNC:
return 'SYNC'
case Packet.A_CNXN:
return 'CNXN'
case Packet.A_OPEN:
return 'OPEN'
case Packet.A_OKAY:
return 'OKAY'
case Packet.A_CLSE:
return 'CLSE'
case Packet.A_WRTE:
return 'WRTE'
case Packet.A_AUTH:
return 'AUTH'
default:
throw new Error('Unknown command {@command}')
} })()
return `${type} arg0=${this.arg0} arg1=${this.arg1} length=${this.length}`
}
toString() {
const type = (() => {
switch (this.command) {
case Packet.A_SYNC:
return 'SYNC';
case Packet.A_CNXN:
return 'CNXN';
case Packet.A_OPEN:
return 'OPEN';
case Packet.A_OKAY:
return 'OKAY';
case Packet.A_CLSE:
return 'CLSE';
case Packet.A_WRTE:
return 'WRTE';
case Packet.A_AUTH:
return 'AUTH';
default:
throw new Error('Unknown command {@command}')
}
})();
return `${type} arg0=${this.arg0} arg1=${this.arg1} length=${this.length}`
}
}
Packet.initClass()
module.exports = Packet
Packet.initClass();
module.exports = Packet;
// TODO: This file was created by bulk-decaffeinate.
// Sanity-check the conversion and remove this comment.
const {EventEmitter} = require('events');
const {EventEmitter} = require('events')
const Packet = require('./packet');
const Packet = require('./packet')
class PacketReader extends EventEmitter {
constructor(stream) {
super();
this.stream = stream;
this.inBody = false;
this.buffer = null;
this.packet = null;
this.stream.on('readable', this._tryRead.bind(this));
this.stream.on('error', err => this.emit('error', err));
this.stream.on('end', () => this.emit('end'));
super()
this.stream = stream
this.inBody = false
this.buffer = null
this.packet = null
this.stream.on('readable', this._tryRead.bind(this))
this.stream.on('error', err => this.emit('error', err))
this.stream.on('end', () => this.emit('end'))
setImmediate(this._tryRead.bind(this))

@@ -27,8 +27,8 @@ }

}
this.packet.data = this._consume(this.packet.length);
this.packet.data = this._consume(this.packet.length)
if (!this.packet.verifyChecksum()) {
this.emit('error', new PacketReader.ChecksumError(this.packet));
this.emit('error', new PacketReader.ChecksumError(this.packet))
return
}
this.emit('packet', this.packet);
this.emit('packet', this.packet)
this.inBody = false

@@ -39,3 +39,3 @@ } else {

}
const header = this._consume(24);
const header = this._consume(24)
this.packet = new Packet(

@@ -49,5 +49,5 @@ header.readUInt32LE(0),

Buffer.alloc(0)
);
)
if (!this.packet.verifyMagic()) {
this.emit('error', new PacketReader.MagicError(this.packet));
this.emit('error', new PacketReader.MagicError(this.packet))
return

@@ -66,3 +66,3 @@ }

_appendChunk() {
let chunk;
let chunk
if ((chunk = this.stream.read())) {

@@ -80,4 +80,4 @@ if (this.buffer) {

_consume(length) {
const chunk = this.buffer.slice(0, length);
this.buffer = length === this.buffer.length ? null : this.buffer.slice(length);
const chunk = this.buffer.slice(0, length)
this.buffer = length === this.buffer.length ? null : this.buffer.slice(length)
return chunk

@@ -89,22 +89,22 @@ }

constructor(packet) {
super(); // TODO check sanity
Error.call(this);
this.name = 'ChecksumError';
this.message = 'Checksum mismatch';
this.packet = packet;
super() // TODO check sanity
Error.call(this)
this.name = 'ChecksumError'
this.message = 'Checksum mismatch'
this.packet = packet
Error.captureStackTrace(this, PacketReader.ChecksumError)
}
};
}
PacketReader.MagicError = class MagicError extends Error {
constructor(packet) {
super(); // TODO check sanity
Error.call(this);
this.name = 'MagicError';
this.message = 'Magic value mismatch';
this.packet = packet;
super() // TODO check sanity
Error.call(this)
this.name = 'MagicError'
this.message = 'Magic value mismatch'
this.packet = packet
Error.captureStackTrace(this, PacketReader.MagicError)
}
};
}
module.exports = PacketReader;
module.exports = PacketReader

@@ -1,51 +0,56 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const socket_1 = require("./socket");
const Net = require('net');
const { EventEmitter } = require('events');
// TODO: This file was created by bulk-decaffeinate.
// Sanity-check the conversion and remove this comment.
const Net = require('net')
const {EventEmitter} = require('events')
const Socket = require('./socket')
class Server extends EventEmitter {
constructor(client, serial, options) {
super();
this.client = client;
this.serial = serial;
this.options = options;
this.connections = [];
this.server = Net.createServer({ allowHalfOpen: true });
this.server.on('error', err => {
return this.emit('error', err);
});
this.server.on('listening', () => {
return this.emit('listening');
});
this.server.on('close', () => {
return this.emit('close');
});
this.server.on('connection', conn => {
const socket = new socket_1.Socket(this.client, this.serial, conn, this.options);
this.connections.push(socket);
socket.on('error', err => {
return this.emit('error', err);
});
socket.once('end', () => {
return this.connections = this.connections.filter(val => val !== socket);
});
return this.emit('connection', socket);
});
}
listen() {
this.server.listen.apply(this.server, arguments);
return this;
}
close() {
this.server.close();
return this;
}
end() {
for (let conn of this.connections) {
conn.end();
}
return this;
}
constructor(client, serial, options) {
super()
this.client = client
this.serial = serial
this.options = options
this.connections = []
this.server = Net.createServer({allowHalfOpen: true})
this.server.on('error', err => {
return this.emit('error', err)
})
this.server.on('listening', () => {
return this.emit('listening')
})
this.server.on('close', () => {
return this.emit('close')
})
this.server.on('connection', conn => {
const socket = new Socket(this.client, this.serial, conn, this.options)
this.connections.push(socket)
socket.on('error', err => {
// 'conn' is guaranteed to get ended
return this.emit('error', err)
})
socket.once('end', () => {
// 'conn' is guaranteed to get ended
return this.connections = this.connections.filter(val => val !== socket)
})
return this.emit('connection', socket)
})
}
listen() {
this.server.listen.apply(this.server, arguments)
return this
}
close() {
this.server.close()
return this
}
end() {
for (let conn of this.connections) { conn.end() }
return this
}
}
exports.Server = Server;
//# sourceMappingURL=server.js.map
module.exports = Server

@@ -1,7 +0,15 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const bluebird_1 = require("bluebird");
/* eslint-disable
no-unused-vars,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
const crypto = require('crypto');
const { EventEmitter } = require('events');
const {EventEmitter} = require('events');
const Promise = require('bluebird');
const Forge = require('node-forge');
const debug = require('debug')('adb:tcpusb:socket');
const Parser = require('../parser');
const Protocol = require('../protocol');
const Auth = require('../auth');

@@ -13,224 +21,258 @@ const Packet = require('./packet');

const RollingCounter = require('./rollingcounter');
class Socket extends EventEmitter {
constructor(client, serial, socket, options = {}) {
super();
this.UINT32_MAX = 0xFFFFFFFF;
this.UINT16_MAX = 0xFFFF;
this.AUTH_TOKEN = 1;
this.AUTH_SIGNATURE = 2;
this.AUTH_RSAPUBLICKEY = 3;
this.TOKEN_LENGTH = 20;
this.client = client;
this.serial = serial;
this.socket = socket;
this.options = options;
if (!this.options.auth) {
this.options.auth = bluebird_1.default.resolve(true);
var Socket = (function () {
let UINT32_MAX = undefined;
let UINT16_MAX = undefined;
let AUTH_TOKEN = undefined;
let AUTH_SIGNATURE = undefined;
let AUTH_RSAPUBLICKEY = undefined;
let TOKEN_LENGTH = undefined;
Socket = class Socket extends EventEmitter {
static initClass() {
UINT32_MAX = 0xFFFFFFFF;
UINT16_MAX = 0xFFFF;
AUTH_TOKEN = 1;
AUTH_SIGNATURE = 2;
AUTH_RSAPUBLICKEY = 3;
TOKEN_LENGTH = 20
}
this.ended = false;
this.socket.setNoDelay(true);
this.reader = new PacketReader(this.socket)
.on('packet', this._handle.bind(this))
.on('error', err => {
debug(`PacketReader error: ${err.message}`);
return this.end();
}).on('end', this.end.bind(this));
this.version = 1;
this.maxPayload = 4096;
this.authorized = false;
this.syncToken = new RollingCounter(this.UINT32_MAX);
this.remoteId = new RollingCounter(this.UINT32_MAX);
this.services = new ServiceMap;
this.remoteAddress = this.socket.remoteAddress;
this.token = null;
this.signature = null;
}
end() {
if (this.ended) {
return this;
constructor(client, serial, socket, options = {}) {
super();
this.client = client;
this.serial = serial;
this.socket = socket;
this.options = options;
if (!this.options.auth) {
this.options.auth = Promise.resolve(true)
}
this.ended = false;
this.socket.setNoDelay(true);
this.reader = new PacketReader(this.socket)
.on('packet', this._handle.bind(this))
.on('error', err => {
debug(`PacketReader error: ${err.message}`);
return this.end()
}).on('end', this.end.bind(this));
this.version = 1;
this.maxPayload = 4096;
this.authorized = false;
this.syncToken = new RollingCounter(UINT32_MAX);
this.remoteId = new RollingCounter(UINT32_MAX);
this.services = new ServiceMap;
this.remoteAddress = this.socket.remoteAddress;
this.token = null;
this.signature = null
}
this.services.end();
this.socket.end();
this.ended = true;
this.emit('end');
return this;
}
_error(err) {
this.emit('error', err);
return this.end();
}
_handle(packet) {
if (this.ended) {
return;
end() {
if (this.ended) {
return this
}
// End services first so that they can send a final payload before FIN.
this.services.end();
this.socket.end();
this.ended = true;
this.emit('end');
return this
}
this.emit('userActivity', packet);
return bluebird_1.default.try(() => {
switch (packet.command) {
case Packet.A_SYNC:
return this._handleSyncPacket(packet);
case Packet.A_CNXN:
return this._handleConnectionPacket(packet);
case Packet.A_OPEN:
return this._handleOpenPacket(packet);
case Packet.A_OKAY:
case Packet.A_WRTE:
case Packet.A_CLSE:
return this._forwardServicePacket(packet);
case Packet.A_AUTH:
return this._handleAuthPacket(packet);
default:
throw new Error(`Unknown command ${packet.command}`);
_error(err) {
this.emit('error', err);
return this.end()
}
_handle(packet) {
if (this.ended) {
return
}
}).catch(Socket.AuthError, () => {
return this.end();
}).catch(Socket.UnauthorizedError, () => {
return this.end();
}).catch(err => {
return this._error(err);
});
}
_handleSyncPacket(packet) {
debug('I:A_SYNC');
debug('O:A_SYNC');
return this.write(Packet.assemble(Packet.A_SYNC, 1, this.syncToken.next(), null));
}
_handleConnectionPacket(packet) {
debug('I:A_CNXN', packet);
const version = Packet.swap32(packet.arg0);
this.maxPayload = Math.min(this.UINT16_MAX, packet.arg1);
return this._createToken()
.then(token => {
this.token = token;
debug(`Created challenge '${this.token.toString('base64')}'`);
debug('O:A_AUTH');
return this.write(Packet.assemble(Packet.A_AUTH, this.AUTH_TOKEN, 0, this.token));
});
}
_handleAuthPacket(packet) {
debug('I:A_AUTH', packet);
switch (packet.arg0) {
case this.AUTH_SIGNATURE:
debug(`Received signature '${packet.data.toString('base64')}'`);
if (!this.signature) {
this.signature = packet.data;
this.emit('userActivity', packet);
return Promise.try(() => {
switch (packet.command) {
case Packet.A_SYNC:
return this._handleSyncPacket(packet);
case Packet.A_CNXN:
return this._handleConnectionPacket(packet);
case Packet.A_OPEN:
return this._handleOpenPacket(packet);
case Packet.A_OKAY:
case Packet.A_WRTE:
case Packet.A_CLSE:
return this._forwardServicePacket(packet);
case Packet.A_AUTH:
return this._handleAuthPacket(packet);
default:
throw new Error(`Unknown command ${packet.command}`)
}
debug('O:A_AUTH');
return this.write(Packet.assemble(Packet.A_AUTH, this.AUTH_TOKEN, 0, this.token));
case this.AUTH_RSAPUBLICKEY:
if (!this.signature) {
throw new Socket.AuthError('Public key sent before signature');
}
if (!packet.data || !(packet.data.length >= 2)) {
throw new Socket.AuthError('Empty RSA public key');
}
debug(`Received RSA public key '${packet.data.toString('base64')}'`);
return Auth.parsePublicKey(this._skipNull(packet.data))
.then(key => {
const digest = this.token.toString('binary');
const sig = this.signature.toString('binary');
if (!key.verify(digest, sig)) {
debug('Signature mismatch');
throw new Socket.AuthError('Signature mismatch');
}).catch(Socket.AuthError, () => {
return this.end()
}).catch(Socket.UnauthorizedError, () => {
return this.end()
}).catch(err => {
return this._error(err)
})
}
_handleSyncPacket(packet) {
// No need to do anything?
debug('I:A_SYNC');
debug('O:A_SYNC');
return this.write(Packet.assemble(Packet.A_SYNC, 1, this.syncToken.next(), null))
}
_handleConnectionPacket(packet) {
debug('I:A_CNXN', packet);
const version = Packet.swap32(packet.arg0);
this.maxPayload = Math.min(UINT16_MAX, packet.arg1);
return this._createToken()
.then(token => {
this.token = token;
debug(`Created challenge '${this.token.toString('base64')}'`);
debug('O:A_AUTH');
return this.write(Packet.assemble(Packet.A_AUTH, AUTH_TOKEN, 0, this.token))
})
}
_handleAuthPacket(packet) {
debug('I:A_AUTH', packet);
switch (packet.arg0) {
case AUTH_SIGNATURE:
// Store first signature, ignore the rest
debug(`Received signature '${packet.data.toString('base64')}'`);
if (!this.signature) {
this.signature = packet.data
}
debug('Signature verified');
return key;
}).then(key => {
return this.options.auth(key)
.catch(function (err) {
debug('Connection rejected by user-defined auth handler');
throw new Socket.AuthError('Rejected by user-defined handler');
});
}).then(() => {
return this._deviceId();
}).then(id => {
this.authorized = true;
debug('O:A_CNXN');
return this.write(Packet.assemble(Packet.A_CNXN, Packet.swap32(this.version), this.maxPayload, id));
});
default:
throw new Error(`Unknown authentication method ${packet.arg0}`);
debug('O:A_AUTH');
return this.write(Packet.assemble(Packet.A_AUTH, AUTH_TOKEN, 0, this.token));
case AUTH_RSAPUBLICKEY:
if (!this.signature) {
throw new Socket.AuthError('Public key sent before signature')
}
if (!packet.data || !(packet.data.length >= 2)) {
throw new Socket.AuthError('Empty RSA public key')
}
debug(`Received RSA public key '${packet.data.toString('base64')}'`);
return Auth.parsePublicKey(this._skipNull(packet.data))
.then(key => {
const digest = this.token.toString('binary');
const sig = this.signature.toString('binary');
if (!key.verify(digest, sig)) {
debug('Signature mismatch');
throw new Socket.AuthError('Signature mismatch')
}
debug('Signature verified');
return key
}).then(key => {
return this.options.auth(key)
.catch(function (err) {
debug('Connection rejected by user-defined auth handler');
throw new Socket.AuthError('Rejected by user-defined handler')
})
}).then(() => {
return this._deviceId()
}).then(id => {
this.authorized = true;
debug('O:A_CNXN');
return this.write(Packet.assemble(Packet.A_CNXN,
Packet.swap32(this.version), this.maxPayload, id)
)
});
default:
throw new Error(`Unknown authentication method ${packet.arg0}`)
}
}
}
_handleOpenPacket(packet) {
if (!this.authorized) {
throw new Socket.UnauthorizedError();
_handleOpenPacket(packet) {
if (!this.authorized) {
throw new Socket.UnauthorizedError()
}
const remoteId = packet.arg0;
const localId = this.remoteId.next();
if (!packet.data || !(packet.data.length >= 2)) {
throw new Error('Empty service name')
}
const name = this._skipNull(packet.data);
debug(`Calling ${name}`);
const service = new Service(this.client, this.serial, localId, remoteId, this);
return new Promise((resolve, reject) => {
service.on('error', reject);
service.on('end', resolve);
this.services.insert(localId, service);
debug(`Handling ${this.services.count} services simultaneously`);
return service.handle(packet)
}).catch(err => true).finally(() => {
this.services.remove(localId);
debug(`Handling ${this.services.count} services simultaneously`);
return service.end()
})
}
const remoteId = packet.arg0;
const localId = this.remoteId.next();
if (!packet.data || !(packet.data.length >= 2)) {
throw new Error('Empty service name');
_forwardServicePacket(packet) {
let service;
if (!this.authorized) {
throw new Socket.UnauthorizedError()
}
const remoteId = packet.arg0;
const localId = packet.arg1;
if ((service = this.services.get(localId))) {
return service.handle(packet)
} else {
return debug('Received a packet to a service that may have been closed already')
}
}
const name = this._skipNull(packet.data);
debug(`Calling ${name}`);
const service = new Service(this.client, this.serial, localId, remoteId, this);
return new bluebird_1.default((resolve, reject) => {
service.on('error', reject);
service.on('end', resolve);
this.services.insert(localId, service);
debug(`Handling ${this.services.count} services simultaneously`);
return service.handle(packet);
}).catch(err => true).finally(() => {
this.services.remove(localId);
debug(`Handling ${this.services.count} services simultaneously`);
return service.end();
});
}
_forwardServicePacket(packet) {
let service;
if (!this.authorized) {
throw new Socket.UnauthorizedError();
write(chunk) {
if (this.ended) {
return
}
return this.socket.write(chunk)
}
const remoteId = packet.arg0;
const localId = packet.arg1;
if ((service = this.services.get(localId))) {
return service.handle(packet);
_createToken() {
return Promise.promisify(crypto.randomBytes)(TOKEN_LENGTH)
}
else {
return debug('Received a packet to a service that may have been closed already');
_skipNull(data) {
return data.slice(0, -1) // Discard null byte at end
}
}
write(chunk) {
if (this.ended) {
return;
_deviceId() {
debug('Loading device properties to form a standard device ID');
return this.client.getProperties(this.serial)
.then(function (properties) {
const id = (([
'ro.product.name',
'ro.product.model',
'ro.product.device'
]).map((prop) => `${prop}=${properties[prop]};`)).join('');
return Buffer.from(`device::${id}\0`)
})
}
return this.socket.write(chunk);
}
_createToken() {
return bluebird_1.default.promisify(crypto.randomBytes)(this.TOKEN_LENGTH);
}
_skipNull(data) {
return data.slice(0, -1);
}
_deviceId() {
debug('Loading device properties to form a standard device ID');
return this.client.getProperties(this.serial)
.then(function (properties) {
const id = (([
'ro.product.name',
'ro.product.model',
'ro.product.device'
]).map((prop) => `${prop}=${properties[prop]};`)).join('');
return Buffer.from(`device::${id}\0`);
});
}
}
};
Socket.initClass();
return Socket
})();
Socket.AuthError = class AuthError extends Error {
constructor(message) {
super();
super(); // TODO check sanity
Error.call(this);
this.name = 'AuthError';
this.message = message;
Error.captureStackTrace(this, Socket.AuthError);
Error.captureStackTrace(this, Socket.AuthError)
}
};
Socket.UnauthorizedError = class UnauthorizedError extends Error {
constructor() {
super();
super(); // TODO check sanity
Error.call(this);
this.name = 'UnauthorizedError';
this.message = 'Unauthorized access';
Error.captureStackTrace(this, Socket.UnauthorizedError);
Error.captureStackTrace(this, Socket.UnauthorizedError)
}
};
exports.Socket = Socket;
//# sourceMappingURL=socket.js.map
module.exports = Socket;

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc