@honeybbq/teamspeak 1.0.0-beta.19 → 1.0.0-beta.21

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.
Files changed (179) hide show
  1. package/dist/client/api/avatars.d.ts.map +1 -1
  2. package/dist/client/api/avatars.js +11 -2
  3. package/dist/client/api/avatars.js.map +1 -1
  4. package/dist/client/api/files.d.ts +36 -14
  5. package/dist/client/api/files.d.ts.map +1 -1
  6. package/dist/client/api/files.js +58 -9
  7. package/dist/client/api/files.js.map +1 -1
  8. package/dist/client/api/upload-checks.d.ts +36 -0
  9. package/dist/client/api/upload-checks.d.ts.map +1 -0
  10. package/dist/client/api/upload-checks.js +77 -0
  11. package/dist/client/api/upload-checks.js.map +1 -0
  12. package/dist/client/api/voice.d.ts +2 -1
  13. package/dist/client/api/voice.d.ts.map +1 -1
  14. package/dist/client/api/voice.js +6 -2
  15. package/dist/client/api/voice.js.map +1 -1
  16. package/dist/client/client.d.ts +13 -3
  17. package/dist/client/client.d.ts.map +1 -1
  18. package/dist/client/client.js +151 -49
  19. package/dist/client/client.js.map +1 -1
  20. package/dist/client/crypto/crypt.d.ts +6 -0
  21. package/dist/client/crypto/crypt.d.ts.map +1 -1
  22. package/dist/client/crypto/crypt.js +13 -7
  23. package/dist/client/crypto/crypt.js.map +1 -1
  24. package/dist/client/crypto/eax.d.ts +4 -0
  25. package/dist/client/crypto/eax.d.ts.map +1 -1
  26. package/dist/client/crypto/eax.js +27 -21
  27. package/dist/client/crypto/eax.js.map +1 -1
  28. package/dist/client/errors.d.ts +13 -0
  29. package/dist/client/errors.d.ts.map +1 -1
  30. package/dist/client/errors.js +23 -0
  31. package/dist/client/errors.js.map +1 -1
  32. package/dist/client/handshake/crypt-handshake.d.ts +2 -1
  33. package/dist/client/handshake/crypt-handshake.d.ts.map +1 -1
  34. package/dist/client/handshake/crypt-handshake.js +4 -2
  35. package/dist/client/handshake/crypt-handshake.js.map +1 -1
  36. package/dist/client/index.d.ts +1 -1
  37. package/dist/client/index.d.ts.map +1 -1
  38. package/dist/client/index.js +1 -1
  39. package/dist/client/index.js.map +1 -1
  40. package/dist/client/throttle.d.ts +11 -0
  41. package/dist/client/throttle.d.ts.map +1 -1
  42. package/dist/client/throttle.js +38 -3
  43. package/dist/client/throttle.js.map +1 -1
  44. package/dist/client/transfer.d.ts +37 -4
  45. package/dist/client/transfer.d.ts.map +1 -1
  46. package/dist/client/transfer.js +155 -15
  47. package/dist/client/transfer.js.map +1 -1
  48. package/dist/client/transport/handler.d.ts.map +1 -1
  49. package/dist/client/transport/handler.js +47 -43
  50. package/dist/client/transport/handler.js.map +1 -1
  51. package/dist/core/api/clients.d.ts +15 -15
  52. package/dist/core/api/clients.d.ts.map +1 -1
  53. package/dist/core/api/clients.js.map +1 -1
  54. package/dist/core/api/command.d.ts +8 -6
  55. package/dist/core/api/command.d.ts.map +1 -1
  56. package/dist/core/api/command.js +1 -1
  57. package/dist/core/api/command.js.map +1 -1
  58. package/dist/core/api/files.d.ts +23 -6
  59. package/dist/core/api/files.d.ts.map +1 -1
  60. package/dist/core/api/files.js +12 -9
  61. package/dist/core/api/files.js.map +1 -1
  62. package/dist/core/api/groups.d.ts +17 -2
  63. package/dist/core/api/groups.d.ts.map +1 -1
  64. package/dist/core/api/groups.js +13 -11
  65. package/dist/core/api/groups.js.map +1 -1
  66. package/dist/core/api/parse.d.ts +5 -5
  67. package/dist/core/api/parse.d.ts.map +1 -1
  68. package/dist/core/api/parse.js +16 -15
  69. package/dist/core/api/parse.js.map +1 -1
  70. package/dist/core/command/request.d.ts +6 -0
  71. package/dist/core/command/request.d.ts.map +1 -1
  72. package/dist/core/command/request.js +12 -0
  73. package/dist/core/command/request.js.map +1 -1
  74. package/dist/core/errors.d.ts +46 -3
  75. package/dist/core/errors.d.ts.map +1 -1
  76. package/dist/core/errors.js +73 -20
  77. package/dist/core/errors.js.map +1 -1
  78. package/dist/core/events.d.ts +24 -8
  79. package/dist/core/events.d.ts.map +1 -1
  80. package/dist/core/internal.d.ts +1 -1
  81. package/dist/core/internal.d.ts.map +1 -1
  82. package/dist/core/internal.js +1 -1
  83. package/dist/core/internal.js.map +1 -1
  84. package/dist/core/notifications.d.ts +1 -1
  85. package/dist/core/notifications.js +9 -8
  86. package/dist/core/notifications.js.map +1 -1
  87. package/dist/core/reconnect.d.ts +16 -5
  88. package/dist/core/reconnect.d.ts.map +1 -1
  89. package/dist/core/reconnect.js +32 -4
  90. package/dist/core/reconnect.js.map +1 -1
  91. package/dist/core/types.d.ts +15 -16
  92. package/dist/core/types.d.ts.map +1 -1
  93. package/dist/core/types.js.map +1 -1
  94. package/dist/query/client.d.ts +4 -0
  95. package/dist/query/client.d.ts.map +1 -1
  96. package/dist/query/client.js +145 -23
  97. package/dist/query/client.js.map +1 -1
  98. package/dist/query/errors.d.ts +20 -0
  99. package/dist/query/errors.d.ts.map +1 -1
  100. package/dist/query/errors.js +31 -0
  101. package/dist/query/errors.js.map +1 -1
  102. package/dist/query/index.d.ts +1 -1
  103. package/dist/query/index.d.ts.map +1 -1
  104. package/dist/query/index.js +1 -1
  105. package/dist/query/index.js.map +1 -1
  106. package/dist/query/lines.d.ts +11 -0
  107. package/dist/query/lines.d.ts.map +1 -1
  108. package/dist/query/lines.js +36 -6
  109. package/dist/query/lines.js.map +1 -1
  110. package/dist/query/options.d.ts +30 -0
  111. package/dist/query/options.d.ts.map +1 -1
  112. package/dist/query/options.js +7 -0
  113. package/dist/query/options.js.map +1 -1
  114. package/dist/query/reconnect.d.ts +5 -0
  115. package/dist/query/reconnect.d.ts.map +1 -1
  116. package/dist/query/reconnect.js +26 -7
  117. package/dist/query/reconnect.js.map +1 -1
  118. package/dist/query/ssh.js +9 -4
  119. package/dist/query/ssh.js.map +1 -1
  120. package/dist/query/stream.d.ts +2 -0
  121. package/dist/query/stream.d.ts.map +1 -1
  122. package/dist/query/stream.js +19 -1
  123. package/dist/query/stream.js.map +1 -1
  124. package/dist/query/transport.d.ts +12 -2
  125. package/dist/query/transport.d.ts.map +1 -1
  126. package/dist/query/web.d.ts +3 -1
  127. package/dist/query/web.d.ts.map +1 -1
  128. package/dist/query/web.js +82 -18
  129. package/dist/query/web.js.map +1 -1
  130. package/dist/stream/published.d.ts.map +1 -1
  131. package/dist/stream/published.js +61 -25
  132. package/dist/stream/published.js.map +1 -1
  133. package/dist/stream/streams.d.ts.map +1 -1
  134. package/dist/stream/streams.js +51 -10
  135. package/dist/stream/streams.js.map +1 -1
  136. package/dist/stream/wire.d.ts +2 -2
  137. package/dist/stream/wire.d.ts.map +1 -1
  138. package/dist/stream/wire.js +27 -7
  139. package/dist/stream/wire.js.map +1 -1
  140. package/package.json +1 -1
  141. package/src/client/api/avatars.ts +15 -2
  142. package/src/client/api/files.ts +83 -23
  143. package/src/client/api/upload-checks.ts +96 -0
  144. package/src/client/api/voice.ts +5 -2
  145. package/src/client/client.ts +154 -42
  146. package/src/client/crypto/crypt.ts +15 -7
  147. package/src/client/crypto/eax.ts +27 -22
  148. package/src/client/errors.ts +25 -0
  149. package/src/client/handshake/crypt-handshake.ts +6 -3
  150. package/src/client/index.ts +1 -0
  151. package/src/client/throttle.ts +41 -3
  152. package/src/client/transfer.ts +172 -28
  153. package/src/client/transport/handler.ts +54 -46
  154. package/src/core/api/clients.ts +24 -21
  155. package/src/core/api/command.ts +9 -7
  156. package/src/core/api/files.ts +30 -16
  157. package/src/core/api/groups.ts +32 -13
  158. package/src/core/api/parse.ts +16 -15
  159. package/src/core/command/request.ts +18 -0
  160. package/src/core/errors.ts +74 -20
  161. package/src/core/events.ts +24 -8
  162. package/src/core/internal.ts +7 -1
  163. package/src/core/notifications.ts +9 -8
  164. package/src/core/reconnect.ts +60 -8
  165. package/src/core/types.ts +15 -16
  166. package/src/query/client.ts +144 -20
  167. package/src/query/errors.ts +34 -0
  168. package/src/query/index.ts +1 -0
  169. package/src/query/lines.ts +38 -6
  170. package/src/query/options.ts +36 -0
  171. package/src/query/reconnect.ts +27 -7
  172. package/src/query/ssh.ts +11 -4
  173. package/src/query/stream.ts +17 -1
  174. package/src/query/testing/live.ts +4 -4
  175. package/src/query/transport.ts +10 -2
  176. package/src/query/web.ts +76 -21
  177. package/src/stream/published.ts +70 -23
  178. package/src/stream/streams.ts +47 -13
  179. package/src/stream/wire.ts +30 -11
@@ -5,10 +5,17 @@
5
5
  * the bytes then go over a separate TCP connection to the server's file
6
6
  * transfer port, opened with the key the negotiation returned.
7
7
  */
8
- import { type Duplex, type Readable, type Writable } from "node:stream";
8
+ import { Writable, type Duplex, type Readable } from "node:stream";
9
9
  import type { FileUploadInfo, FileDownloadInfo } from "@honeybbq/teamspeak";
10
10
  import type { FileTransferSocketFactory } from "./types.js";
11
11
  import { FileTransferError } from "./errors.js";
12
+ /**
13
+ * Whether `error` is a dial that never got a connection: refused, unreachable,
14
+ * or timed out while connecting. Not one the caller's signal or the idle limit
15
+ * ended, nor one after the connection opened, where the key may have been
16
+ * written and the server may hold or have dropped the transfer.
17
+ */
18
+ export declare function failedToConnect(error: unknown): boolean;
12
19
  /** Where a failed transfer failed. */
13
20
  export type FileTransferStage = "dial" | "transfer";
14
21
  /** The file transfer port is about to be dialled. */
@@ -29,7 +36,7 @@ export interface FileTransferDialDoneInfo {
29
36
  export interface FileTransferProgressInfo {
30
37
  /** The bytes moved so far. */
31
38
  readonly bytes: number;
32
- /** The size the negotiation gave; 0 when it is not known, as for an upload. */
39
+ /** The bytes the transfer will move, as the negotiation fixed them. */
33
40
  readonly total: number;
34
41
  }
35
42
  /** The transfer succeeded. */
@@ -103,9 +110,35 @@ export interface FileTransferOptions {
103
110
  * The caller owns the returned stream and must end or destroy it.
104
111
  */
105
112
  export declare function dialFileTransfer(host: string, port: number, key: string, options?: FileTransferOptions): Promise<Duplex>;
106
- /** Upload `data` over a negotiated transfer. Resolves once every byte is sent. */
113
+ /**
114
+ * Upload `data` over a negotiated transfer. `data` is the file from
115
+ * `info.seekPosition` on, and must give exactly the bytes left of
116
+ * `info.size`: a stream that gives fewer or more fails the transfer.
117
+ *
118
+ * Resolves once the server has closed the transfer connection, which it does
119
+ * when it has the file. Measured on TeamSpeak 3 3.13.8 and TeamSpeak 6 6.0.0:
120
+ * the server closes about 200 ms after the last byte of a 100 000-byte file,
121
+ * and at once after the declared size when more is sent. A connection that
122
+ * closes before every byte is written, or that stays open for the idle limit,
123
+ * fails the transfer.
124
+ *
125
+ * A close after the last byte is not proof that the file is stored: the server
126
+ * sends nothing on the transfer connection, and over the voice protocol its
127
+ * `notifystatusfiletransfer` comes only for a failure (2066 canceled, 2063
128
+ * lost connection, 2052 more than declared), after the close, never for
129
+ * success; over ServerQuery nothing comes. `uploadFile` therefore asks the
130
+ * server for the file's size with `ftgetfileinfo` before it resolves.
131
+ */
107
132
  export declare function uploadFileData(host: string, info: FileUploadInfo, data: Readable, options?: FileTransferOptions): Promise<void>;
108
- /** Download a negotiated transfer into `dest`. Resolves once the file is written. */
133
+ /**
134
+ * Download a negotiated transfer into `dest`. Resolves once the file is
135
+ * written; `dest` is not ended, so it may take another download.
136
+ *
137
+ * A download from `info.seekPosition` brings the bytes from there to the end
138
+ * of the file: measured on TeamSpeak 3 3.13.8 and TeamSpeak 6 6.0.0, a
139
+ * `seekpos` of 40 000 on a 100 000-byte file is answered with the whole size
140
+ * and then 60 000 bytes.
141
+ */
109
142
  export declare function downloadFileData(host: string, info: FileDownloadInfo, dest: Writable, options?: FileTransferOptions): Promise<void>;
110
143
  export { FileTransferError };
111
144
  //# sourceMappingURL=transfer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"transfer.d.ts","sourceRoot":"","sources":["../../src/client/transfer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"transfer.d.ts","sourceRoot":"","sources":["../../src/client/transfer.ts"],"names":[],"mappings":"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"}
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import { connect } from "node:net";
9
9
  import { pipeline } from "node:stream/promises";
10
- import { Transform } from "node:stream";
10
+ import { Transform, Writable } from "node:stream";
11
11
  import { FileTransferError } from "./errors.js";
12
12
  import { callHook } from "./hooks.js";
13
13
  import { joinHostPort } from "./address.js";
@@ -18,6 +18,22 @@ const DIAL_TIMEOUT_MS = 10_000;
18
18
  const DEFAULT_IDLE_TIMEOUT_MS = 30_000;
19
19
  /** How many bytes move between two calls of the `progress` hook, at least. */
20
20
  const PROGRESS_STEP_BYTES = 64 * 1024;
21
+ /** The file transfer ports a connection can be made to. */
22
+ const MAX_PORT = 65535;
23
+ /**
24
+ * The errors of dials that failed before the connection opened. Nothing has
25
+ * reached the server then: not the key, and no byte of the file.
26
+ */
27
+ const failedBeforeConnect = new WeakSet();
28
+ /**
29
+ * Whether `error` is a dial that never got a connection: refused, unreachable,
30
+ * or timed out while connecting. Not one the caller's signal or the idle limit
31
+ * ended, nor one after the connection opened, where the key may have been
32
+ * written and the server may hold or have dropped the transfer.
33
+ */
34
+ export function failedToConnect(error) {
35
+ return typeof error === "object" && error !== null && failedBeforeConnect.has(error);
36
+ }
21
37
  function newIdleGuard(options) {
22
38
  const limitMs = options.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
23
39
  if (!Number.isFinite(limitMs) || limitMs < 0) {
@@ -79,6 +95,9 @@ export async function dialFileTransfer(host, port, key, options = {}) {
79
95
  }
80
96
  async function dial(host, port, key, options, t, idle) {
81
97
  const { signal, socketFactory } = options;
98
+ if (!Number.isInteger(port) || port < 1 || port > MAX_PORT) {
99
+ throw new FileTransferError(`the file transfer port is ${String(port)}, not 1 to ${MAX_PORT}`);
100
+ }
82
101
  // One budget for the connection and the key write: a peer that accepts the
83
102
  // connection and never reads would otherwise hold the write forever.
84
103
  const timeout = AbortSignal.timeout(DIAL_TIMEOUT_MS);
@@ -91,8 +110,10 @@ async function dial(host, port, key, options, t, idle) {
91
110
  // report: a stream's unhandled `error` event takes the process down.
92
111
  const swallow = () => { };
93
112
  socket.on("error", swallow);
113
+ let open = false;
94
114
  try {
95
115
  await abortable(connected(socket), dialSignal);
116
+ open = true;
96
117
  idle.touch();
97
118
  await abortable(new Promise((resolve, reject) => {
98
119
  socket.write(key, (err) => err
@@ -106,7 +127,12 @@ async function dial(host, port, key, options, t, idle) {
106
127
  catch (error) {
107
128
  socket.destroy();
108
129
  if (timeout.aborted && error === timeout.reason) {
109
- throw new FileTransferError("file transfer connection timed out", { cause: error });
130
+ const timedOut = new FileTransferError("file transfer connection timed out", {
131
+ cause: error,
132
+ });
133
+ if (!open)
134
+ failedBeforeConnect.add(timedOut);
135
+ throw timedOut;
110
136
  }
111
137
  throw error;
112
138
  }
@@ -144,9 +170,10 @@ function countingStream(t, total, idle) {
144
170
  }
145
171
  /**
146
172
  * Passes exactly `expected` bytes. One more byte fails the transfer, and is
147
- * not passed on; a stream that ends before `expected` fails it too.
173
+ * not passed on; a stream that ends before `expected` fails it too. `what`
174
+ * says who fixed the size, for the message.
148
175
  */
149
- function exactSize(expected) {
176
+ function exactSize(expected, what) {
150
177
  let received = 0;
151
178
  return new Transform({
152
179
  transform(chunk, _encoding, callback) {
@@ -154,7 +181,7 @@ function exactSize(expected) {
154
181
  if (chunk.length > room) {
155
182
  this.push(chunk.subarray(0, room));
156
183
  received = expected;
157
- callback(new FileTransferError(`file transfer sent more than the announced ${expected} bytes`));
184
+ callback(new FileTransferError(`file transfer sent more than the ${what} ${expected} bytes`));
158
185
  return;
159
186
  }
160
187
  received += chunk.length;
@@ -163,7 +190,7 @@ function exactSize(expected) {
163
190
  flush(callback) {
164
191
  callback(received === expected
165
192
  ? null
166
- : new FileTransferError(`file transfer ended after ${received} of the announced ${expected} bytes`));
193
+ : new FileTransferError(`file transfer ended after ${received} of the ${what} ${expected} bytes`));
167
194
  },
168
195
  });
169
196
  }
@@ -192,6 +219,11 @@ async function transfer(host, port, key, total, options, move) {
192
219
  reportFailed(t, failure, "transfer");
193
220
  throw failure;
194
221
  }
222
+ finally {
223
+ // The server ends a transfer it has finished, and a failed one is
224
+ // abandoned here; either way nothing is left to keep the socket for.
225
+ socket.destroy();
226
+ }
195
227
  }
196
228
  finally {
197
229
  idle.stop();
@@ -223,21 +255,129 @@ function connected(socket) {
223
255
  reject(error);
224
256
  };
225
257
  const onConnect = () => done();
226
- const onError = (error) => done(new FileTransferError(`file transfer connection failed: ${error.message}`, {
227
- cause: error,
228
- }));
258
+ const onError = (error) => {
259
+ const failure = new FileTransferError(`file transfer connection failed: ${error.message}`, {
260
+ cause: error,
261
+ });
262
+ failedBeforeConnect.add(failure);
263
+ done(failure);
264
+ };
229
265
  socket.once("connect", onConnect);
230
266
  socket.once("ready", onConnect);
231
267
  socket.once("error", onError);
232
268
  });
233
269
  }
234
- /** Upload `data` over a negotiated transfer. Resolves once every byte is sent. */
235
- export function uploadFileData(host, info, data, options = {}) {
236
- return transfer(host, info.port, info.fileTransferKey, 0, options, (socket, counter, pipeOptions) => pipeline(data, counter, socket, pipeOptions));
270
+ /**
271
+ * How many bytes a negotiated transfer moves: the file's size less the
272
+ * position it starts from.
273
+ */
274
+ function bytesToMove(size, seekPosition) {
275
+ if (seekPosition < 0n || seekPosition > size) {
276
+ throw new FileTransferError(`the transfer starts at ${seekPosition}, outside a file of ${size} bytes`);
277
+ }
278
+ return Number(size - seekPosition);
279
+ }
280
+ /**
281
+ * A sink that hands what it is given to `dest`, one write at a time, without
282
+ * ever ending it: the stream is the caller's, and may take more transfers.
283
+ * `dest`'s errors fail the sink, so the pipeline sees them.
284
+ */
285
+ function intoStream(dest) {
286
+ const sink = new Writable({
287
+ write(chunk, _encoding, callback) {
288
+ dest.write(chunk, callback);
289
+ },
290
+ });
291
+ const onError = (error) => {
292
+ sink.destroy(error);
293
+ };
294
+ dest.on("error", onError);
295
+ // A failed `dest` reports its error a tick after the write that failed, by
296
+ // which time this sink is closed: keep listening until that has been said.
297
+ sink.on("close", () => setImmediate(() => dest.off("error", onError)));
298
+ return sink;
299
+ }
300
+ /**
301
+ * The same for a socket that is not to be ended: an upload is over when the
302
+ * server says so, not when the last byte has left.
303
+ */
304
+ function intoSocket(socket) {
305
+ // A write after the server closed the connection fails with the socket's own
306
+ // error (EPIPE, or "ended by the other party"): the transfer's failure.
307
+ const failure = (error) => new FileTransferError(`file transfer connection failed: ${error.message}`, {
308
+ cause: error,
309
+ });
310
+ const sink = new Writable({
311
+ write(chunk, _encoding, callback) {
312
+ socket.write(chunk, (error) => callback(error ? failure(error) : null));
313
+ },
314
+ });
315
+ socket.on("error", (error) => {
316
+ sink.destroy(failure(error));
317
+ });
318
+ return sink;
319
+ }
320
+ /** Resolves once the server has closed the transfer connection. */
321
+ function serverClosed(socket, signal) {
322
+ if (socket.readableEnded || socket.destroyed)
323
+ return Promise.resolve();
324
+ const closed = new Promise((resolve, reject) => {
325
+ const done = (error) => {
326
+ socket.off("end", onEnd);
327
+ socket.off("close", onEnd);
328
+ socket.off("error", done);
329
+ if (error === undefined)
330
+ resolve();
331
+ else
332
+ reject(error);
333
+ };
334
+ const onEnd = () => done();
335
+ socket.once("end", onEnd);
336
+ socket.once("close", onEnd);
337
+ socket.once("error", done);
338
+ });
339
+ // Nothing is sent back, but the end of the stream is only seen by reading.
340
+ socket.resume();
341
+ return abortable(closed, signal);
342
+ }
343
+ /**
344
+ * Upload `data` over a negotiated transfer. `data` is the file from
345
+ * `info.seekPosition` on, and must give exactly the bytes left of
346
+ * `info.size`: a stream that gives fewer or more fails the transfer.
347
+ *
348
+ * Resolves once the server has closed the transfer connection, which it does
349
+ * when it has the file. Measured on TeamSpeak 3 3.13.8 and TeamSpeak 6 6.0.0:
350
+ * the server closes about 200 ms after the last byte of a 100 000-byte file,
351
+ * and at once after the declared size when more is sent. A connection that
352
+ * closes before every byte is written, or that stays open for the idle limit,
353
+ * fails the transfer.
354
+ *
355
+ * A close after the last byte is not proof that the file is stored: the server
356
+ * sends nothing on the transfer connection, and over the voice protocol its
357
+ * `notifystatusfiletransfer` comes only for a failure (2066 canceled, 2063
358
+ * lost connection, 2052 more than declared), after the close, never for
359
+ * success; over ServerQuery nothing comes. `uploadFile` therefore asks the
360
+ * server for the file's size with `ftgetfileinfo` before it resolves.
361
+ */
362
+ export async function uploadFileData(host, info, data, options = {}) {
363
+ const expected = bytesToMove(info.size, info.seekPosition);
364
+ await transfer(host, info.port, info.fileTransferKey, expected, options, async (socket, counter, pipeOptions) => {
365
+ await pipeline(data, exactSize(expected, "declared"), counter, intoSocket(socket), pipeOptions);
366
+ await serverClosed(socket, pipeOptions.signal);
367
+ });
237
368
  }
238
- /** Download a negotiated transfer into `dest`. Resolves once the file is written. */
239
- export function downloadFileData(host, info, dest, options = {}) {
240
- return transfer(host, info.port, info.fileTransferKey, Number(info.size), options, (socket, counter, pipeOptions) => pipeline(socket, exactSize(Number(info.size)), counter, dest, pipeOptions));
369
+ /**
370
+ * Download a negotiated transfer into `dest`. Resolves once the file is
371
+ * written; `dest` is not ended, so it may take another download.
372
+ *
373
+ * A download from `info.seekPosition` brings the bytes from there to the end
374
+ * of the file: measured on TeamSpeak 3 3.13.8 and TeamSpeak 6 6.0.0, a
375
+ * `seekpos` of 40 000 on a 100 000-byte file is answered with the whole size
376
+ * and then 60 000 bytes.
377
+ */
378
+ export async function downloadFileData(host, info, dest, options = {}) {
379
+ const expected = bytesToMove(info.size, info.seekPosition);
380
+ await transfer(host, info.port, info.fileTransferKey, expected, options, (socket, counter, pipeOptions) => pipeline(socket, exactSize(expected, "announced"), counter, intoStream(dest), pipeOptions));
241
381
  }
242
382
  export { FileTransferError };
243
383
  //# sourceMappingURL=transfer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"transfer.js","sourceRoot":"","sources":["../../src/client/transfer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"transfer.js","sourceRoot":"","sources":["../../src/client/transfer.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/client/transport/handler.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,EACL,KAAK,MAAM,EACX,UAAU,EAMX,MAAM,aAAa,CAAC;AAMrB,OAAO,EAAoC,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AA8BtF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAa,CAAC;AAE9C;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAgB,CAAC;AA4BhD,qBAAa,aAAa;;IACxB,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IAC9C,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IACtD;;;;OAIG;IACH,cAAc,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IACzD,2FAA2F;IAC3F,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IAkDzD,YAAY,KAAK,EAAE,KAAK,EAAE,MAAM,GAAE,MAAmB,EAAE,aAAa,CAAC,EAAE,aAAa,EAInF;IAED,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAE5B;IAED;;;;;;;OAOG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAyD/D;IAOD,sGAAsG;IACtG,KAAK,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,CA+ChC;IAED;;;;;;OAMG;IACH,oBAAoB,IAAI,IAAI,CAE3B;IAED,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAOnE;IAED,eAAe,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CA6BrD;IAED;;;;OAIG;IACH,iBAAiB,CACf,IAAI,EAAE,UAAU,EAChB,eAAe,EAAE,SAAS,MAAM,EAAE,EAClC,KAAK,EAAE,MAAM,EACb,gBAAgB,GAAE,SAAS,MAAM,EAAO,GACvC,IAAI,CAiCN;IAED;;;;OAIG;IACH,sBAAsB,CACpB,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,GACZ,IAAI,CAiBN;IA4BD,wEAAwE;IACxE,eAAe,IAAI,eAAe,CAEjC;IAED,oEAAoE;IACpE,IAAI,SAAS,IAAI;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAEhF;IAED,4EAA4E;IAC5E,iFAAiF;IACjF,IAAI,eAAe,IAAI,OAAO,CAE7B;IAED,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,iDAAiD;IACjD,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,KAAK,IAAI,IAAI,CAmBZ;CA8hBF"}
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/client/transport/handler.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,EACL,KAAK,MAAM,EACX,UAAU,EAMX,MAAM,aAAa,CAAC;AAMrB,OAAO,EAAoC,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAoCtF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAa,CAAC;AAE9C;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAgB,CAAC;AAkChD,qBAAa,aAAa;;IACxB,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IAC9C,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IACtD;;;;OAIG;IACH,cAAc,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IACzD,2FAA2F;IAC3F,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IAkDzD,YAAY,KAAK,EAAE,KAAK,EAAE,MAAM,GAAE,MAAmB,EAAE,aAAa,CAAC,EAAE,aAAa,EAInF;IAED,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAE5B;IAED;;;;;;;OAOG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAyD/D;IAOD,sGAAsG;IACtG,KAAK,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,CA+ChC;IAED;;;;;;OAMG;IACH,oBAAoB,IAAI,IAAI,CAE3B;IAED,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAOnE;IAED,eAAe,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CA6BrD;IAED;;;;OAIG;IACH,iBAAiB,CACf,IAAI,EAAE,UAAU,EAChB,eAAe,EAAE,SAAS,MAAM,EAAE,EAClC,KAAK,EAAE,MAAM,EACb,gBAAgB,GAAE,SAAS,MAAM,EAAO,GACvC,IAAI,CAiCN;IAED;;;;OAIG;IACH,sBAAsB,CACpB,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,GACZ,IAAI,CAiBN;IA4BD,wEAAwE;IACxE,eAAe,IAAI,eAAe,CAEjC;IAED,oEAAoE;IACpE,IAAI,SAAS,IAAI;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAEhF;IAED,4EAA4E;IAC5E,iFAAiF;IACjF,IAAI,eAAe,IAAI,OAAO,CAE7B;IAED,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,iDAAiD;IACjD,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,KAAK,IAAI,IAAI,CAmBZ;CAqiBF"}
@@ -3,7 +3,7 @@ import { lookup } from "node:dns/promises";
3
3
  import { parseConnectAddress } from "../address.js";
4
4
  import { noopLogger } from "@honeybbq/teamspeak";
5
5
  import { PacketType, PacketFlags, packetType, packetFlags, buildC2SHeader, parseS2CHeader, } from "./packet.js";
6
- import { ConnectionTimeoutError } from "../errors.js";
6
+ import { ConnectionStalledError, ConnectionTimeoutError } from "../errors.js";
7
7
  import { abortable, abortReason } from "../abort.js";
8
8
  import { NotConnectedError, TeamspeakError } from "@honeybbq/teamspeak";
9
9
  import { GenerationWindow } from "./generation-window.js";
@@ -28,6 +28,12 @@ const WHISPER_HEADER_SIZE = 5;
28
28
  const GROUP_WHISPER_HEADER_SIZE = 13;
29
29
  const RESEND_BASE_INTERVAL_MS = 500;
30
30
  const RESEND_LOOP_INTERVAL_MS = 100;
31
+ /**
32
+ * How long a command packet may stay missing while later ones wait for it. The
33
+ * server sends a command again until it is acknowledged, so a hole that stays
34
+ * this long is not going to fill.
35
+ */
36
+ const COMMAND_HOLE_TIMEOUT_MS = 5_000;
31
37
  /**
32
38
  * The largest command reassembled from fragments. The receive window already
33
39
  * bounds how many fragments one command can span; this bounds their total
@@ -464,6 +470,7 @@ export class PacketHandler {
464
470
  lastSend: performance.now(),
465
471
  retryCount: 0,
466
472
  nextInterval: RESEND_BASE_INTERVAL_MS,
473
+ dummy,
467
474
  };
468
475
  this.#trackResend(pType, p, rp);
469
476
  }
@@ -499,7 +506,6 @@ export class PacketHandler {
499
506
  const header = raw.slice(TAG_SIZE, TAG_SIZE + 3);
500
507
  const ciphertext = raw.slice(TAG_SIZE + 3);
501
508
  const parsed = parseS2CHeader(header);
502
- this.#traffic.recordReceived(parsed.typeFlagged & 0x0f, raw.length, performance.now());
503
509
  // Init1 belongs to the start of the handshake; once crypto init has
504
510
  // completed, another one can only restart a session that is already set up.
505
511
  const parsedType = parsed.typeFlagged & 0x0f;
@@ -521,6 +527,7 @@ export class PacketHandler {
521
527
  // Only a packet that decrypted shows the server is there: anyone can send
522
528
  // datagrams that do not, and they must not keep a dead session alive.
523
529
  this.#lastMessageReceived = performance.now();
530
+ this.#traffic.recordReceived(pType, raw.length, p.receivedAt);
524
531
  if (pType === PacketType.Pong && p.data.length >= 2) {
525
532
  const acked = new DataView(p.data.buffer, p.data.byteOffset).getUint16(0, false);
526
533
  const sentAt = this.#pingsSent.get(acked);
@@ -637,9 +644,13 @@ export class PacketHandler {
637
644
  }
638
645
  const queue = pType === PacketType.Command ? this.#commandQueue : this.#commandLowQueue;
639
646
  const held = queue.get(p.id)?.data.length ?? 0;
640
- // The packet the queue waits for is always taken: it is what drains it.
641
- const next = pType === PacketType.Command ? this.#nextCommandID : this.#nextCommandLowID;
642
- if (p.id !== next && this.#queuedBytes - held + p.data.length > MAX_QUEUED_BYTES) {
647
+ // The packet the queue needs next, the first id from the next expected one
648
+ // that it does not hold, is always taken: it is what drains it, and what
649
+ // lets a command larger than the queue reach its last fragment.
650
+ let needed = pType === PacketType.Command ? this.#nextCommandID : this.#nextCommandLowID;
651
+ for (let i = 0; i < queue.size && queue.has(needed); i++)
652
+ needed = (needed + 1) & 0xffff;
653
+ if (p.id !== needed && this.#queuedBytes - held + p.data.length > MAX_QUEUED_BYTES) {
643
654
  // Not acknowledged: the server sends it again.
644
655
  this.#logger.debug("dropped a command packet: the receive queues are full", { id: p.id });
645
656
  return false;
@@ -667,12 +678,6 @@ export class PacketHandler {
667
678
  const queue = isCommand ? this.#commandQueue : this.#commandLowQueue;
668
679
  const win = isCommand ? this.#recvWindowCommand : this.#recvWindowCommandLow;
669
680
  this.#hold(queue, p);
670
- if (isCommand) {
671
- this.#fastForwardMissingPackets(queue, win, true);
672
- }
673
- else {
674
- this.#fastForwardMissingPackets(queue, win, false);
675
- }
676
681
  while (true) {
677
682
  const current = isCommand ? this.#nextCommandID : this.#nextCommandLowID;
678
683
  const packet = queue.get(current);
@@ -710,16 +715,19 @@ export class PacketHandler {
710
715
  }
711
716
  #nextCommandID = 0;
712
717
  #nextCommandLowID = 0;
713
- #fastForwardMissingPackets(queue, win, isCommand) {
714
- let nextID = isCommand ? this.#nextCommandID : this.#nextCommandLowID;
715
- while (!queue.has(nextID) && hasOldNewerPacket(queue, nextID)) {
716
- nextID = (nextID + 1) & 0xffff;
717
- win.advance(1);
718
+ /**
719
+ * Whether a command packet is missing from `queue` while a later one has
720
+ * waited for it for COMMAND_HOLE_TIMEOUT_MS.
721
+ */
722
+ #hasStalledHole(queue, nextID, now) {
723
+ if (queue.has(nextID))
724
+ return false;
725
+ for (const [id, pkg] of queue) {
726
+ const diff = (id - nextID + 0x10000) & 0xffff;
727
+ if (diff < 0x8000 && now - pkg.receivedAt > COMMAND_HOLE_TIMEOUT_MS)
728
+ return true;
718
729
  }
719
- if (isCommand)
720
- this.#nextCommandID = nextID;
721
- else
722
- this.#nextCommandLowID = nextID;
730
+ return false;
723
731
  }
724
732
  #tryReassemble(startPacket, queue, nextID, win) {
725
733
  if ((packetFlags(startPacket) & PacketFlags.Fragmented) === 0) {
@@ -732,23 +740,15 @@ export class PacketHandler {
732
740
  let currID = nextID;
733
741
  let startSeen = false;
734
742
  // Ends at the fragment that closes the command, or returns while one is
735
- // still missing.
743
+ // still missing. The size is checked once the whole command is there, so an
744
+ // oversize one is released to its end marker and never leaves the stream
745
+ // part-way through a command.
736
746
  while (true) {
737
747
  const frag = queue.get(currID);
738
748
  if (!frag)
739
749
  return null;
740
750
  fragments.push(frag);
741
751
  totalSize += frag.data.length;
742
- if (totalSize > MAX_REASSEMBLED_SIZE) {
743
- // Dropped whole, so the window moves past it rather than waiting on
744
- // the rest of a command that will never be accepted.
745
- for (let i = 0; i < fragments.length; i++) {
746
- this.#release(queue, nextID);
747
- win.advance(1);
748
- nextID = (nextID + 1) & 0xffff;
749
- }
750
- return [null, nextID];
751
- }
752
752
  const fragmented = (packetFlags(frag) & PacketFlags.Fragmented) !== 0;
753
753
  if (!startSeen) {
754
754
  startSeen = true;
@@ -760,6 +760,15 @@ export class PacketHandler {
760
760
  }
761
761
  currID = (currID + 1) & 0xffff;
762
762
  }
763
+ if (totalSize > MAX_REASSEMBLED_SIZE) {
764
+ // Dropped whole, so the window moves past it.
765
+ for (let i = 0; i < fragments.length; i++) {
766
+ this.#release(queue, nextID);
767
+ win.advance(1);
768
+ nextID = (nextID + 1) & 0xffff;
769
+ }
770
+ return [null, nextID];
771
+ }
763
772
  const combined = new Uint8Array(totalSize);
764
773
  let pos = 0;
765
774
  for (const frag of fragments) {
@@ -836,6 +845,12 @@ export class PacketHandler {
836
845
  this.#triggerClose(new ConnectionTimeoutError());
837
846
  return;
838
847
  }
848
+ if (this.#hasStalledHole(this.#commandQueue, this.#nextCommandID, now) ||
849
+ this.#hasStalledHole(this.#commandLowQueue, this.#nextCommandLowID, now)) {
850
+ this.#logger.warn("a command from the server never arrived");
851
+ this.#triggerClose(new ConnectionStalledError());
852
+ return;
853
+ }
839
854
  if (this.#initPacketCheck) {
840
855
  this.#doResend(this.#initPacketCheck, now);
841
856
  }
@@ -855,11 +870,10 @@ export class PacketHandler {
855
870
  rp.retryCount++;
856
871
  this.#resends++;
857
872
  rp.nextInterval = Math.min(rp.nextInterval * 2, MAX_RETRY_INTERVAL_MS);
858
- const dummy = !this.#crypt.cryptoInitComplete;
859
873
  const unencrypted = (packetFlags(rp.packet) & PacketFlags.Unencrypted) !== 0;
860
874
  const header = buildC2SHeader(rp.packet);
861
875
  const pType = packetType(rp.packet);
862
- const [ciphertext, tag] = this.#crypt.encrypt(pType, rp.packet.id, rp.packet.generationID, header, rp.packet.data, dummy, unencrypted);
876
+ const [ciphertext, tag] = this.#crypt.encrypt(pType, rp.packet.id, rp.packet.generationID, header, rp.packet.data, rp.dummy, unencrypted);
863
877
  const final = new Uint8Array(TAG_SIZE + HEADER_SIZE + ciphertext.length);
864
878
  final.set(tag.slice(0, TAG_SIZE), 0);
865
879
  final.set(header, TAG_SIZE);
@@ -889,14 +903,4 @@ function applyProtocolFlags(pType, flags) {
889
903
  }
890
904
  return flags;
891
905
  }
892
- function hasOldNewerPacket(queue, nextID) {
893
- const now = performance.now();
894
- for (const [id, pkg] of queue) {
895
- const diff = (id - nextID + 0x10000) & 0xffff;
896
- if (diff < 0x8000 && now - pkg.receivedAt > 5_000) {
897
- return true;
898
- }
899
- }
900
- return false;
901
- }
902
906
  //# sourceMappingURL=handler.js.map