Skip to content

Commit cc6a04e

Browse files
committed
Fixed version
2 parents 1f3cf0f + 0e34ada commit cc6a04e

File tree

4 files changed

+119
-63
lines changed

4 files changed

+119
-63
lines changed

client.js

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -165,19 +165,28 @@ S101Socket.prototype.connect = function (timeout = 2) {
165165
self.emit('connecting');
166166

167167
self.codec = new S101Codec();
168+
169+
const connectTimeoutListener = () => {
170+
self.socket.destroy();
171+
self.emit("error", new Error(`Could not connect to ${self.address}:${self.port} after a timeout of ${timeout} seconds`));
172+
};
173+
168174
self.socket = net.createConnection({
169175
port: self.port,
170176
host: self.address,
171-
timeout: timeout
177+
timeout: 1000 * timeout
172178
},
173179
() => {
174180
winston.debug('socket connected');
175181

182+
// Disable connect timeout to hand-over to keepalive mechanism
183+
self.socket.removeListener("timeout", connectTimeoutListener);
184+
self.socket.setTimeout(0);
185+
176186
self.keepaliveIntervalTimer = setInterval(() => {
177187
try {
178188
self.sendKeepaliveRequest();
179-
}
180-
catch(e) {
189+
} catch (e) {
181190
self.emit("error", e);
182191
}
183192
}, 1000 * self.keepaliveInterval);
@@ -201,23 +210,22 @@ S101Socket.prototype.connect = function (timeout = 2) {
201210
});
202211

203212
self.emit('connected');
204-
}
205-
).on('error', (e) => {
206-
self.emit("error", e);
207-
});
208-
209-
self.socket.on('data', (data) => {
210-
if (self.isConnected()) {
211-
self.codec.dataIn(data);
212-
}
213-
});
214-
215-
self.socket.on('close', () => {
216-
clearInterval(self.keepaliveIntervalTimer);
217-
self.emit('disconnected');
218-
self.status = "disconnected";
219-
self.socket = null;
220-
});
213+
})
214+
.on('error', (e) => {
215+
self.emit("error", e);
216+
})
217+
.once("timeout", connectTimeoutListener)
218+
.on('data', (data) => {
219+
if (self.isConnected()) {
220+
self.codec.dataIn(data);
221+
}
222+
})
223+
.on('close', () => {
224+
clearInterval(self.keepaliveIntervalTimer);
225+
self.emit('disconnected');
226+
self.status = "disconnected";
227+
self.socket = null;
228+
});
221229
}
222230

223231
S101Socket.prototype.isConnected = function () {

device.js

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ DeviceTree.prototype.getDirectory = function (qnode) {
150150
}
151151

152152
self.callback = (error, node) => {
153-
if (node == null) { return; }
153+
if (node == null) { return; }
154154
if (error) {
155155
if (self._debug) {
156156
console.log("Received getDirectory error", error);
@@ -160,25 +160,37 @@ DeviceTree.prototype.getDirectory = function (qnode) {
160160
reject(error);
161161
return;
162162
}
163-
let requestedPath = qnode.getPath();
164-
if (requestedPath === "") {
163+
if (qnode instanceof ember.Root) {
165164
if (qnode.elements == null || qnode.elements.length === 0) {
166165
if (self._debug) {
167-
console.log("getDirectory response", node);
166+
console.log("getDirectory response", node);
168167
}
169168
return self.callback(new Error("Invalid qnode for getDirectory"));
170169
}
171-
requestedPath = qnode.elements["0"].getPath();
172-
}
173-
const nodeElements = node == null ? null : node.elements;
174-
if (nodeElements != null
175-
&& nodeElements.every(el => el.getPath() === requestedPath || isDirectSubPathOf(el.getPath(), requestedPath))) {
176-
if (self._debug) {
177-
console.log("Received getDirectory response", node);
170+
171+
const nodeElements = node == null ? null : node.elements;
172+
173+
if (nodeElements != null
174+
&& nodeElements.every(el => el._parent instanceof ember.Root)) {
175+
if (self._debug) {
176+
console.log("Received getDirectory response", node);
177+
}
178+
self.clearTimeout(); // clear the timeout now. The resolve below may take a while.
179+
self.finishRequest();
180+
resolve(node); // make sure the info is treated before going to next request.
181+
}
182+
} else {
183+
let requestedPath = qnode.getPath();
184+
const nodeElements = node == null ? null : node.elements;
185+
if (nodeElements != null
186+
&& nodeElements.every(el => isDirectSubPathOf(el.getPath(), requestedPath))) {
187+
if (self._debug) {
188+
console.log("Received getDirectory response", node);
189+
}
190+
self.clearTimeout(); // clear the timeout now. The resolve below may take a while.
191+
self.finishRequest();
192+
resolve(node); // make sure the info is treated before going to next request.
178193
}
179-
self.clearTimeout(); // clear the timeout now. The resolve below may take a while.
180-
self.finishRequest();
181-
resolve(node); // make sure the info is treated before going to next request.
182194
}
183195
};
184196

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "emberplus",
3-
"version": "1.7.20",
3+
"version": "1.7.22",
44
"description": "Javascript implementation of the Ember+ automation protocol",
55
"main": "index.js",
66
"scripts": {

test/DeviceTree.test.js

Lines changed: 64 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,40 +4,76 @@ const DeviceTree = require("../").DeviceTree;
44
const TreeServer = require("../").TreeServer;
55

66
const LOCALHOST = "127.0.0.1";
7+
const UNKNOWN_HOST = "192.168.99.99";
78
const PORT = 9008;
89

910
describe("DeviceTree", () => {
10-
let server;
11-
12-
beforeAll(() => {
13-
return Promise.resolve()
14-
.then(() => new Promise((resolve, reject) => {
15-
fs.readFile("./embrionix.ember", (e, data) => {
16-
if (e) {
17-
reject(e);
18-
}
19-
resolve(Decoder(data));
11+
describe("With server", () => {
12+
let server;
13+
beforeAll(() => {
14+
return Promise.resolve()
15+
.then(() => new Promise((resolve, reject) => {
16+
fs.readFile("./embrionix.ember", (e, data) => {
17+
if (e) {
18+
reject(e);
19+
}
20+
resolve(Decoder(data));
21+
});
22+
}))
23+
.then(root => {
24+
server = new TreeServer(LOCALHOST, PORT, root);
25+
return server.listen();
2026
});
21-
}))
22-
.then(root => {
23-
server = new TreeServer(LOCALHOST, PORT, root);
24-
return server.listen();
25-
});
26-
});
27+
});
28+
29+
afterAll(() => server.close());
30+
31+
it("should gracefully connect and disconnect", () => {
32+
return Promise.resolve()
33+
.then(() => {
34+
let tree = new DeviceTree(LOCALHOST, PORT);
35+
return Promise.resolve()
36+
.then(() => tree.connect())
37+
.then(() => tree.getDirectory())
38+
.then(() => tree.disconnect())
39+
.then(() => tree.connect())
40+
.then(() => tree.getDirectory())
41+
.then(() => tree.disconnect())
42+
})
43+
});
44+
45+
it("should not disconnect after 5 seconds of inactivity", () => {
46+
return Promise.resolve()
47+
.then(() => {
48+
let tree = new DeviceTree(LOCALHOST, PORT);
2749

28-
afterAll(() => server.close());
50+
tree.on("error", error => {
51+
throw error;
52+
});
2953

30-
it("should gracefully connect and disconnect", () => {
31-
return Promise.resolve()
54+
return Promise.resolve()
55+
.then(() => tree.connect())
56+
.then(() => new Promise(resolve => setTimeout(resolve, 5000)))
57+
.then(() => tree.disconnect())
58+
})
59+
}, 7000);
60+
});
61+
62+
it("timeout should be taken into account when connecting to unknown host", () => {
63+
let tree = new DeviceTree(UNKNOWN_HOST, PORT);
64+
tree.on("error", () => {
65+
});
66+
const expectedTimeoutInSec = 2;
67+
const initialTime = performance.now();
68+
return tree.connect(expectedTimeoutInSec)
3269
.then(() => {
33-
let tree = new DeviceTree(LOCALHOST, PORT);
34-
return Promise.resolve()
35-
.then(() => tree.connect())
36-
.then(() => tree.getDirectory())
37-
.then(() => tree.disconnect())
38-
.then(() => tree.connect())
39-
.then(() => tree.getDirectory())
40-
.then(() => tree.disconnect())
41-
})
70+
throw new Error("Should have thrown");
71+
},
72+
error => {
73+
const durationMs = performance.now() - initialTime;
74+
const deltaMs = Math.abs(expectedTimeoutInSec * 1000 - durationMs);
75+
expect(deltaMs).toBeLessThan(10);
76+
expect(error.message).toBe(`Could not connect to ${UNKNOWN_HOST}:${PORT} after a timeout of ${expectedTimeoutInSec} seconds`)
77+
});
4278
});
4379
});

0 commit comments

Comments
 (0)