Skip to content

Commit 23966f1

Browse files
authored
Add support for socket timeouts (#303)
* Add support for socket timeouts Signed-off-by: Wolfgang Haupt <[email protected]> * Add new timeout option to Readme Signed-off-by: Wolfgang Haupt <[email protected]>
1 parent c249c91 commit 23966f1

File tree

4 files changed

+45
-2
lines changed

4 files changed

+45
-2
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ Creates a client instance with the provided options. Note that this will not aut
196196
- **port** The port where the ADB server is listening. Defaults to `5037`.
197197
- **host** The host of the ADB server. Defaults to `'127.0.0.1'`.
198198
- **bin** As the sole exception, this option provides the path to the `adb` binary, used for starting the server locally if initial connection fails. Defaults to `'adb'`.
199+
- **timeout** The socket timeout in ms as defined by [Net.connect][net-connect]'s options. Defaults to `0` which means no timeout.
199200
- Returns: The client instance.
200201

201202
#### adb.util.parsePublicKey(androidKey)

src/adb.ts

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ interface Options {
77
host?: string;
88
port?: number;
99
bin?: string;
10+
timeout?: number;
1011
}
1112

1213
export default class Adb {
@@ -18,6 +19,7 @@ export default class Adb {
1819
bin: options.bin,
1920
host: options.host || process.env.ADB_HOST,
2021
port: options.port || 5037,
22+
timeout: options.timeout || 0
2123
};
2224
if (!opts.port) {
2325
const port = parseInt(process.env.ADB_PORT || '5037', 10);

src/adb/client.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@ export default class Client extends EventEmitter {
2424
public readonly host: string;
2525
public readonly port: number | string;
2626
public readonly bin: string;
27+
public readonly timeout: number;
2728

28-
constructor({ host = '127.0.0.1', port = 5037, bin = 'adb' }: ClientOptions = { port: 5037 }) {
29+
constructor({ host = '127.0.0.1', port = 5037, bin = 'adb', timeout = 0 }: ClientOptions = { port: 5037 }) {
2930
super();
3031
this.host = host;
3132
this.port = port;
3233
this.bin = bin;
33-
this.options = { host, port, bin };
34+
this.timeout = timeout;
35+
this.options = { host, port, bin, timeout };
3436
}
3537

3638
public createTcpUsbBridge(serial: string, options: SocketOptions): TcpUsbServer {

src/adb/parser.ts

+38
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ class UnexpectedDataError extends Error {
3131
}
3232
}
3333

34+
class TimeoutError extends Error {
35+
constructor() {
36+
super(`Socket timeout reached.`);
37+
Object.setPrototypeOf(this, TimeoutError.prototype);
38+
this.name = 'TimeoutError';
39+
Error.captureStackTrace(this, TimeoutError);
40+
}
41+
}
42+
3443
Bluebird.config({
3544
// Enable warnings
3645
// warnings: true,
@@ -46,6 +55,7 @@ export default class Parser {
4655
public static FailError = FailError;
4756
public static PrematureEOFError = PrematureEOFError;
4857
public static UnexpectedDataError = UnexpectedDataError;
58+
public static TimeoutError = TimeoutError;
4959
private ended = false;
5060

5161
constructor(public stream: Duplex) {
@@ -59,6 +69,7 @@ export default class Parser {
5969
let tryRead: () => void;
6070
let errorListener: (error: Error) => void;
6171
let endListener: () => void;
72+
let timeoutListener: () => void;
6273
return new Bluebird<boolean>((resolve, reject, onCancel) => {
6374
tryRead = () => {
6475
while (this.stream.read()) {
@@ -72,9 +83,14 @@ export default class Parser {
7283
this.ended = true;
7384
return resolve(true);
7485
};
86+
timeoutListener = () => {
87+
this.stream.end()
88+
return reject(new Parser.TimeoutError());
89+
};
7590
this.stream.on('readable', tryRead);
7691
this.stream.on('error', errorListener);
7792
this.stream.on('end', endListener);
93+
this.stream.on('timeout', timeoutListener);
7894
this.stream.read(0);
7995
this.stream.end();
8096
onCancel(() => {
@@ -84,6 +100,7 @@ export default class Parser {
84100
this.stream.removeListener('readable', tryRead);
85101
this.stream.removeListener('error', errorListener);
86102
this.stream.removeListener('end', endListener);
103+
this.stream.removeListener('timeout', timeoutListener);
87104
// return r;
88105
});
89106
}
@@ -98,6 +115,7 @@ export default class Parser {
98115
let tryRead: () => void;
99116
let errorListener: (error: Error) => void;
100117
let endListener: () => void;
118+
let timeoutListener: () => void;
101119

102120
return new Bluebird<Buffer>((resolve, reject, onCancel) => {
103121
tryRead = () => {
@@ -116,9 +134,14 @@ export default class Parser {
116134
this.ended = true;
117135
return resolve(all);
118136
};
137+
timeoutListener = () => {
138+
this.stream.end()
139+
return reject(new Parser.TimeoutError());
140+
};
119141
this.stream.on('readable', tryRead);
120142
this.stream.on('error', errorListener);
121143
this.stream.on('end', endListener);
144+
this.stream.on('timeout', timeoutListener);
122145
tryRead();
123146
onCancel(() => {
124147
// console.log('2-onCanceled');
@@ -127,6 +150,7 @@ export default class Parser {
127150
this.stream.removeListener('readable', tryRead);
128151
this.stream.removeListener('error', errorListener);
129152
this.stream.removeListener('end', endListener);
153+
this.stream.removeListener('timeout', timeoutListener);
130154
});
131155
}
132156

@@ -138,6 +162,7 @@ export default class Parser {
138162
let tryRead: () => void;
139163
let errorListener: (error: Error) => void;
140164
let endListener: () => void;
165+
let timeoutListener: () => void;
141166
return new Bluebird<Buffer>((resolve, reject /*, onCancel*/) => {
142167
tryRead = () => {
143168
if (howMany) {
@@ -161,23 +186,30 @@ export default class Parser {
161186
this.ended = true;
162187
return reject(new Parser.PrematureEOFError(howMany));
163188
};
189+
timeoutListener = () => {
190+
this.stream.end()
191+
return reject(new Parser.TimeoutError());
192+
};
164193
errorListener = (err) => reject(err);
165194
this.stream.on('readable', tryRead);
166195
this.stream.on('error', errorListener);
167196
this.stream.on('end', endListener);
197+
this.stream.on('timeout', timeoutListener);
168198
tryRead();
169199
// onCancel(() => {});
170200
}).finally(() => {
171201
this.stream.removeListener('readable', tryRead);
172202
this.stream.removeListener('error', errorListener);
173203
this.stream.removeListener('end', endListener);
204+
this.stream.removeListener('timeout', timeoutListener);
174205
});
175206
}
176207

177208
public readByteFlow(howMany: number, targetStream: Duplex): Bluebird<void> {
178209
let tryRead: () => void;
179210
let errorListener: (error: Error) => void;
180211
let endListener: () => void;
212+
let timeoutListener: () => void;
181213
return new Bluebird<void>((resolve, reject /*, onCancel*/) => {
182214
tryRead = () => {
183215
if (howMany) {
@@ -206,15 +238,21 @@ export default class Parser {
206238
errorListener = function (err) {
207239
return reject(err);
208240
};
241+
timeoutListener = () => {
242+
this.stream.end()
243+
return reject(new Parser.TimeoutError());
244+
};
209245
this.stream.on('readable', tryRead);
210246
this.stream.on('error', errorListener);
211247
this.stream.on('end', endListener);
248+
this.stream.on('timeout', timeoutListener);
212249
tryRead();
213250
// onCancel(() => {});
214251
}).finally(() => {
215252
this.stream.removeListener('readable', tryRead);
216253
this.stream.removeListener('error', errorListener);
217254
this.stream.removeListener('end', endListener);
255+
this.stream.removeListener('timeout', timeoutListener);
218256
});
219257
}
220258

0 commit comments

Comments
 (0)