alphatheta-connect 0.28.1 → 0.28.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/cli.js CHANGED
@@ -2238,7 +2238,16 @@ class DeviceManager {
2238
2238
  this.off = __classPrivateFieldGet(this, _DeviceManager_emitter, "f").removeListener.bind(__classPrivateFieldGet(this, _DeviceManager_emitter, "f"));
2239
2239
  this.once = __classPrivateFieldGet(this, _DeviceManager_emitter, "f").once.bind(__classPrivateFieldGet(this, _DeviceManager_emitter, "f"));
2240
2240
  _DeviceManager_handleAnnounce.set(this, (message) => {
2241
- const device = (0, utils_1.deviceFromPacket)(message);
2241
+ // This runs on every UDP datagram the announce socket receives, so a parse
2242
+ // failure here would surface as an uncaught exception on the socket and
2243
+ // crash the process. Foreign or truncated packets are ignored instead.
2244
+ let device;
2245
+ try {
2246
+ device = (0, utils_1.deviceFromPacket)(message);
2247
+ }
2248
+ catch {
2249
+ return;
2250
+ }
2242
2251
  if (device === null) {
2243
2252
  return;
2244
2253
  }
@@ -2354,10 +2363,15 @@ const ip = __importStar(__webpack_require__(/*! ip-address */ "ip-address"));
2354
2363
  const constants_1 = __webpack_require__(/*! src/constants */ "./src/constants.ts");
2355
2364
  /**
2356
2365
  * Converts a announce packet to a device object.
2366
+ *
2367
+ * Returns null for any packet that is not a stage-3 Pro DJ Link announce. The
2368
+ * announce socket receives every UDP broadcast on its port, so foreign traffic
2369
+ * (other apps, other protocols) is normal and must be ignored, not treated as
2370
+ * an error.
2357
2371
  */
2358
2372
  function deviceFromPacket(packet) {
2359
2373
  if (packet.indexOf(constants_1.PROLINK_HEADER) !== 0) {
2360
- throw new Error('Announce packet does not start with expected header');
2374
+ return null;
2361
2375
  }
2362
2376
  if (packet[0x0a] !== 0x06) {
2363
2377
  return null;
@@ -8915,6 +8929,14 @@ class Connection {
8915
8929
  readMessage(expect, span) {
8916
8930
  return __classPrivateFieldGet(this, _Connection_lock, "f").runExclusive(() => message_1.Message.fromStream(__classPrivateFieldGet(this, _Connection_socket, "f"), expect, span));
8917
8931
  }
8932
+ /**
8933
+ * False once the device has closed its end of the connection or the socket
8934
+ * has failed. Every write after that fails with "write after end".
8935
+ */
8936
+ get isOpen() {
8937
+ const { stream } = __classPrivateFieldGet(this, _Connection_socket, "f");
8938
+ return stream.writable && !stream.closed && !stream.destroyed;
8939
+ }
8918
8940
  close() {
8919
8941
  __classPrivateFieldGet(this, _Connection_socket, "f").destroy();
8920
8942
  }
@@ -9046,7 +9068,14 @@ class RemoteDatabase {
9046
9068
  type: types_2.MessageType.Disconnect,
9047
9069
  args: [],
9048
9070
  });
9049
- await conn.writeMessage(goodbye, tx);
9071
+ // The goodbye is a courtesy. A device that has already closed the
9072
+ // connection can't receive it, and its socket still has to be released.
9073
+ try {
9074
+ await conn.writeMessage(goodbye, tx);
9075
+ }
9076
+ catch {
9077
+ // Ignore errors during disconnect
9078
+ }
9050
9079
  conn.close();
9051
9080
  __classPrivateFieldGet(this, _RemoteDatabase_connections, "f").delete(device.id);
9052
9081
  __classPrivateFieldGet(this, _RemoteDatabase_queryIds, "f").delete(device.id);
@@ -9085,6 +9114,15 @@ class RemoteDatabase {
9085
9114
  const releaseLock = await lock.acquire();
9086
9115
  try {
9087
9116
  let conn = __classPrivateFieldGet(this, _RemoteDatabase_connections, "f").get(deviceId);
9117
+ // A device that closed its end of the connection (it restarted, or it
9118
+ // dropped off the network and came back) would fail every query on it
9119
+ // with "write after end". Open a new one instead.
9120
+ if (conn !== undefined && !conn.isOpen) {
9121
+ conn.close();
9122
+ __classPrivateFieldGet(this, _RemoteDatabase_connections, "f").delete(deviceId);
9123
+ __classPrivateFieldGet(this, _RemoteDatabase_queryIds, "f").delete(deviceId);
9124
+ conn = undefined;
9125
+ }
9088
9126
  if (conn === undefined) {
9089
9127
  await this.connectToDevice(device);
9090
9128
  }