@honeybbq/teamspeak-client 0.3.1 → 1.0.0-beta.1
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/README.md +322 -60
- package/dist/abort.d.ts +5 -0
- package/dist/abort.d.ts.map +1 -0
- package/dist/address.d.ts +8 -0
- package/dist/address.d.ts.map +1 -1
- package/dist/api/voice.d.ts +24 -0
- package/dist/api/voice.d.ts.map +1 -0
- package/dist/capabilities.d.ts +62 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/client.d.ts +172 -39
- package/dist/client.d.ts.map +1 -1
- package/dist/commands.d.ts +45 -27
- package/dist/commands.d.ts.map +1 -1
- package/dist/crypto/crypt.d.ts +19 -4
- package/dist/crypto/crypt.d.ts.map +1 -1
- package/dist/crypto/identity.d.ts +87 -8
- package/dist/crypto/identity.d.ts.map +1 -1
- package/dist/crypto/index.d.ts +2 -1
- package/dist/crypto/index.d.ts.map +1 -1
- package/dist/diagnostics.d.ts +45 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/discovery/resolver.d.ts +21 -3
- package/dist/discovery/resolver.d.ts.map +1 -1
- package/dist/errors.d.ts +70 -16
- package/dist/errors.d.ts.map +1 -1
- package/dist/events.d.ts +4 -5
- package/dist/events.d.ts.map +1 -1
- package/dist/handshake/crypt-handshake.d.ts +1 -0
- package/dist/handshake/crypt-handshake.d.ts.map +1 -1
- package/dist/handshake/crypt-init2.d.ts.map +1 -1
- package/dist/handshake/license.d.ts +7 -0
- package/dist/handshake/license.d.ts.map +1 -1
- package/dist/handshake.d.ts +14 -5
- package/dist/handshake.d.ts.map +1 -1
- package/dist/helpers.d.ts +0 -8
- package/dist/helpers.d.ts.map +1 -1
- package/dist/index.d.ts +20 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3967 -0
- package/dist/index.js.map +1 -0
- package/dist/notifications.d.ts +7 -15
- package/dist/notifications.d.ts.map +1 -1
- package/dist/reconnect.d.ts +69 -0
- package/dist/reconnect.d.ts.map +1 -0
- package/dist/throttle.d.ts +9 -0
- package/dist/throttle.d.ts.map +1 -1
- package/dist/transfer.d.ts +27 -25
- package/dist/transfer.d.ts.map +1 -1
- package/dist/transport/handler.d.ts +37 -5
- package/dist/transport/handler.d.ts.map +1 -1
- package/dist/transport/quicklz.d.ts +19 -0
- package/dist/transport/quicklz.d.ts.map +1 -1
- package/dist/types.d.ts +277 -97
- package/dist/types.d.ts.map +1 -1
- package/package.json +21 -56
- package/src/abort.ts +24 -0
- package/src/address.ts +74 -0
- package/src/api/voice.ts +61 -0
- package/src/capabilities.ts +92 -0
- package/src/client.ts +1392 -0
- package/src/commands.ts +193 -0
- package/src/crypto/crypt-ops.ts +6 -0
- package/src/crypto/crypt.ts +274 -0
- package/src/crypto/eax.ts +152 -0
- package/src/crypto/identity.ts +484 -0
- package/src/crypto/index.ts +21 -0
- package/src/crypto/primitives.ts +141 -0
- package/src/diagnostics.ts +58 -0
- package/src/discovery/index.ts +1 -0
- package/src/discovery/resolver.ts +272 -0
- package/src/errors.ts +156 -0
- package/src/events.ts +28 -0
- package/src/handshake/crypt-handshake.ts +135 -0
- package/src/handshake/crypt-init2.ts +48 -0
- package/src/handshake/index.ts +3 -0
- package/src/handshake/license.test.ts +49 -0
- package/src/handshake/license.ts +208 -0
- package/src/handshake.ts +136 -0
- package/src/helpers.ts +10 -0
- package/src/index.ts +74 -0
- package/src/notifications.ts +136 -0
- package/src/reconnect.ts +141 -0
- package/src/throttle.ts +92 -0
- package/src/transfer.ts +127 -0
- package/src/transport/generation-window.ts +77 -0
- package/src/transport/handler.ts +914 -0
- package/src/transport/index.ts +14 -0
- package/src/transport/packet.ts +69 -0
- package/src/transport/quicklz.ts +209 -0
- package/src/types.ts +349 -0
- package/dist/address-BR-5unVo.cjs +0 -2
- package/dist/address-BR-5unVo.cjs.map +0 -1
- package/dist/address-BfmovVpp.js +0 -65
- package/dist/address-BfmovVpp.js.map +0 -1
- package/dist/api.d.ts +0 -17
- package/dist/api.d.ts.map +0 -1
- package/dist/command/command.d.ts +0 -12
- package/dist/command/command.d.ts.map +0 -1
- package/dist/command/index.cjs +0 -1
- package/dist/command/index.d.ts +0 -4
- package/dist/command/index.d.ts.map +0 -1
- package/dist/command/index.mjs +0 -3
- package/dist/command/parser.d.ts +0 -3
- package/dist/command/parser.d.ts.map +0 -1
- package/dist/command-BLe-C2L2.js +0 -74
- package/dist/command-BLe-C2L2.js.map +0 -1
- package/dist/command-DAK4pUBP.cjs +0 -4
- package/dist/command-DAK4pUBP.cjs.map +0 -1
- package/dist/crypt-handshake-CQkQreLx.cjs +0 -2
- package/dist/crypt-handshake-CQkQreLx.cjs.map +0 -1
- package/dist/crypt-handshake-DziOY4Lq.js +0 -55
- package/dist/crypt-handshake-DziOY4Lq.js.map +0 -1
- package/dist/crypt-init2-D70ha4LB.js +0 -158
- package/dist/crypt-init2-D70ha4LB.js.map +0 -1
- package/dist/crypt-init2-DparLekm.cjs +0 -2
- package/dist/crypt-init2-DparLekm.cjs.map +0 -1
- package/dist/crypto/index.cjs +0 -1
- package/dist/crypto/index.mjs +0 -3
- package/dist/crypto-Bg02m4ZE.js +0 -165
- package/dist/crypto-Bg02m4ZE.js.map +0 -1
- package/dist/crypto-CDlweUL3.cjs +0 -2
- package/dist/crypto-CDlweUL3.cjs.map +0 -1
- package/dist/discovery/index.cjs +0 -1
- package/dist/discovery/index.mjs +0 -2
- package/dist/handler-DI_abe9c.js +0 -483
- package/dist/handler-DI_abe9c.js.map +0 -1
- package/dist/handler-DuwoO5RC.cjs +0 -2
- package/dist/handler-DuwoO5RC.cjs.map +0 -1
- package/dist/handshake/index.cjs +0 -1
- package/dist/handshake/index.mjs +0 -3
- package/dist/index.cjs +0 -4
- package/dist/index.cjs.map +0 -1
- package/dist/index.mjs +0 -827
- package/dist/index.mjs.map +0 -1
- package/dist/parser-CL33R9tr.cjs +0 -2
- package/dist/parser-CL33R9tr.cjs.map +0 -1
- package/dist/parser-DZMv3Jm-.js +0 -33
- package/dist/parser-DZMv3Jm-.js.map +0 -1
- package/dist/primitives-cNNAeFCo.cjs +0 -2
- package/dist/primitives-cNNAeFCo.cjs.map +0 -1
- package/dist/primitives-xIr6Tjk4.js +0 -1457
- package/dist/primitives-xIr6Tjk4.js.map +0 -1
- package/dist/resolver-6B8dI9gr.js +0 -141
- package/dist/resolver-6B8dI9gr.js.map +0 -1
- package/dist/resolver-DCcmyWSK.cjs +0 -4
- package/dist/resolver-DCcmyWSK.cjs.map +0 -1
- package/dist/transport/index.cjs +0 -1
- package/dist/transport/index.mjs +0 -2
package/dist/client.d.ts
CHANGED
|
@@ -1,47 +1,180 @@
|
|
|
1
|
-
import { type EventMap, type ClientOptions, type
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import type {
|
|
1
|
+
import { type EventMap, type ClientOptions, type Listener, type Unsubscribe, ClientStatus } from "./types.js";
|
|
2
|
+
import { type ChannelID, type ClientID, type Codec, type CommandOptions, type UID } from "@honeybbq/teamspeak-core";
|
|
3
|
+
import { Identity } from "./crypto/index.js";
|
|
4
|
+
import type { CommandExecutor, CommandRequest } from "@honeybbq/teamspeak-core";
|
|
5
|
+
import type { FileUploadInfo, FileDownloadInfo } from "@honeybbq/teamspeak-core";
|
|
5
6
|
import type { Readable, Writable } from "node:stream";
|
|
7
|
+
import { type ServerCapabilities } from "./capabilities.js";
|
|
6
8
|
export { ClientStatus };
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* What clientinit sends about the connection, with the passwords already in
|
|
11
|
+
* their wire form, `base64(sha1(password))`: hashed once, when the client is
|
|
12
|
+
* made, so the plain text is never held.
|
|
13
|
+
*/
|
|
14
|
+
export interface ClientInitOptions {
|
|
15
|
+
readonly serverPasswordHash: string;
|
|
16
|
+
readonly defaultChannel: string;
|
|
17
|
+
readonly defaultChannelPasswordHash: string;
|
|
10
18
|
}
|
|
11
|
-
|
|
19
|
+
/**
|
|
20
|
+
* A TeamSpeak client over the voice protocol.
|
|
21
|
+
*
|
|
22
|
+
* Listeners run one at a time, in the order their events arrived, after the
|
|
23
|
+
* packet that carried them has been handled, so a listener may call the client
|
|
24
|
+
* and await an answer.
|
|
25
|
+
*/
|
|
26
|
+
export declare class Client implements CommandExecutor, AsyncDisposable {
|
|
12
27
|
#private;
|
|
13
|
-
/** @internal */ crypt: Crypt;
|
|
14
|
-
/** @internal */ handler: PacketHandler;
|
|
15
|
-
/** @internal */ logger: Logger;
|
|
16
|
-
/** @internal */ nickname: string;
|
|
17
|
-
/** @internal */ clid: number;
|
|
18
28
|
constructor(identity: Identity, addr: string, nickname: string, options?: ClientOptions);
|
|
29
|
+
/** Where the client is in its connection's life. */
|
|
19
30
|
get status(): ClientStatus;
|
|
20
|
-
/**
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Connect to the server. Resolves once the handshake completes.
|
|
33
|
+
*
|
|
34
|
+
* An address that cannot be one — no host, a port outside 1–65535 — rejects
|
|
35
|
+
* with an InvalidAddressError at once, before anything starts. A host name
|
|
36
|
+
* that does not resolve fails the attempt with a TeamspeakError whose
|
|
37
|
+
* `cause` is the lookup's error.
|
|
38
|
+
*
|
|
39
|
+
* A failed attempt rejects with its cause, such as the server's error for a
|
|
40
|
+
* rejected password. Aborting `signal` abandons the attempt and rejects with
|
|
41
|
+
* the signal's reason. The signal bounds only the connecting: once this
|
|
42
|
+
* resolves, the connection lasts until `disconnect()` or a drop.
|
|
43
|
+
* `connect()` does not retry; the `reconnect` option only retries a
|
|
44
|
+
* connection that drops after it was established.
|
|
45
|
+
*
|
|
46
|
+
* Called while a `disconnect()` is still saying goodbye, or while an earlier
|
|
47
|
+
* session's `disconnected` is still waiting to be delivered, this waits for
|
|
48
|
+
* that first, so the old session is closed, and its `disconnected`
|
|
49
|
+
* delivered, before the new one starts: no listener or `events()` iterator
|
|
50
|
+
* of the new session hears the old one end. A `disconnect()` called during
|
|
51
|
+
* that wait wins: this then rejects with a NotConnectedError.
|
|
52
|
+
*
|
|
53
|
+
* `connected` is delivered after this resolves, so a listener added right
|
|
54
|
+
* after `await client.connect()` still hears it.
|
|
55
|
+
*/
|
|
56
|
+
connect(options?: {
|
|
57
|
+
readonly signal?: AbortSignal | undefined;
|
|
58
|
+
}): Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Leave the server and close the connection.
|
|
61
|
+
*
|
|
62
|
+
* Says goodbye first, waiting for the server's acknowledgement for a second
|
|
63
|
+
* at most, or less if `signal` aborts sooner. The connection is closed
|
|
64
|
+
* either way. A `connect()` still waiting for its handshake rejects with a
|
|
65
|
+
* NotConnectedError, and so do the commands still waiting for an answer.
|
|
66
|
+
* Resolves once `disconnected` has been delivered to the listeners, so one
|
|
67
|
+
* added after `await client.disconnect()` does not hear it. Does nothing on
|
|
68
|
+
* a client that is not connected; called again while an earlier call is
|
|
69
|
+
* still saying goodbye, it waits for that one.
|
|
70
|
+
*/
|
|
71
|
+
disconnect(options?: {
|
|
72
|
+
readonly signal?: AbortSignal | undefined;
|
|
73
|
+
}): Promise<void>;
|
|
74
|
+
/** `await using client = …` disconnects when the scope ends. */
|
|
75
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
76
|
+
/**
|
|
77
|
+
* Send a raw command line and return the rows that answer it: the escape
|
|
78
|
+
* hatch for a command the typed functions do not cover. The line is sent as
|
|
79
|
+
* given, so its values must already be escaped and any channel password
|
|
80
|
+
* already hashed.
|
|
81
|
+
*
|
|
82
|
+
* Rejects with a NotConnectedError unless the client is connected: while it
|
|
83
|
+
* is still connecting, the session's keys may not exist yet.
|
|
84
|
+
*/
|
|
85
|
+
exec(command: string, options?: CommandOptions): Promise<Record<string, string>[]>;
|
|
86
|
+
/**
|
|
87
|
+
* Send a raw command line without waiting for an answer, for the few
|
|
88
|
+
* commands the server answers with nothing at all.
|
|
89
|
+
*
|
|
90
|
+
* Commands are paced by a flood throttle; aborting `signal` while this waits
|
|
91
|
+
* for its turn rejects with the signal's reason and sends nothing. Rejects
|
|
92
|
+
* with a NotConnectedError unless the client is connected.
|
|
93
|
+
*/
|
|
94
|
+
execNoWait(command: string, options?: {
|
|
95
|
+
readonly signal?: AbortSignal | undefined;
|
|
96
|
+
}): Promise<void>;
|
|
97
|
+
/**
|
|
98
|
+
* Send a typed command; this is the CommandExecutor the typed commands run on.
|
|
99
|
+
*
|
|
100
|
+
* The request passes through the `commandMiddleware` first. Channel
|
|
101
|
+
* passwords are then hashed, because that is this protocol's rule: the voice
|
|
102
|
+
* protocol expects `base64(sha1(password))`, where ServerQuery takes the
|
|
103
|
+
* password itself.
|
|
104
|
+
*/
|
|
105
|
+
send(request: CommandRequest, options?: CommandOptions): Promise<Record<string, string>[]>;
|
|
106
|
+
/**
|
|
107
|
+
* Listen for an event. Returns a function that removes the listener.
|
|
108
|
+
*
|
|
109
|
+
* A listener that throws does not stop the others: the rest of the event's
|
|
110
|
+
* listeners, and the events after it, are still delivered, and the exception
|
|
111
|
+
* is rethrown on its own, from a microtask, so it surfaces as an
|
|
112
|
+
* `uncaughtException` just as an EventEmitter listener's would. An async
|
|
113
|
+
* listener's rejection is not caught, and surfaces as an unhandled
|
|
114
|
+
* rejection.
|
|
115
|
+
*/
|
|
116
|
+
on<K extends keyof EventMap>(event: K, listener: Listener<K>): Unsubscribe;
|
|
117
|
+
/** Listen for the next occurrence of an event only. */
|
|
118
|
+
once<K extends keyof EventMap>(event: K, listener: Listener<K>): Unsubscribe;
|
|
119
|
+
/**
|
|
120
|
+
* An event as an async iterator, for `for await`:
|
|
121
|
+
*
|
|
122
|
+
* ```ts
|
|
123
|
+
* for await (const message of client.events("textMessage", { signal })) { … }
|
|
124
|
+
* ```
|
|
125
|
+
*
|
|
126
|
+
* Events that arrive while the loop body runs are buffered, so none is
|
|
127
|
+
* missed — except voice, of which at most 256 frames are buffered; the rest
|
|
128
|
+
* are dropped, as for a listener that falls behind. Iteration ends when
|
|
129
|
+
* `signal` aborts, when the loop exits early (`break`, `return`, a throw),
|
|
130
|
+
* and — for every event but `disconnected` — when the client disconnects.
|
|
131
|
+
* An abort stops listening at once and discards whatever is buffered.
|
|
132
|
+
*/
|
|
133
|
+
events<K extends keyof EventMap>(event: K, options?: {
|
|
134
|
+
readonly signal?: AbortSignal | undefined;
|
|
135
|
+
}): AsyncIterableIterator<EventMap[K]>;
|
|
136
|
+
/** This client's id on the server, assigned in the handshake; 0 before it. */
|
|
137
|
+
get clientID(): ClientID;
|
|
138
|
+
/**
|
|
139
|
+
* What the connected server is: version, generation, and the uid hash it
|
|
140
|
+
* uses. Read from `initserver`; before connecting the family is `unknown`
|
|
141
|
+
* and the uid hash SHA-1.
|
|
142
|
+
*/
|
|
143
|
+
get serverCapabilities(): ServerCapabilities;
|
|
144
|
+
/**
|
|
145
|
+
* Our own `client_unique_identifier`, hashed with the algorithm the connected
|
|
146
|
+
* server uses.
|
|
147
|
+
*
|
|
148
|
+
* TS3 uses SHA-1 and TS6 SHA-256, so this reads the algorithm learned during
|
|
149
|
+
* initserver rather than assuming one. Comparing a hard-coded SHA-1 UID to a
|
|
150
|
+
* TS6 server silently never matches.
|
|
151
|
+
*/
|
|
152
|
+
get uid(): UID;
|
|
153
|
+
/** The channel this client is in, as it last learned; 0 before connecting. */
|
|
154
|
+
get channelID(): ChannelID;
|
|
155
|
+
/**
|
|
156
|
+
* Send Opus voice directly to specific clients, bypassing channel routing.
|
|
157
|
+
* Throws a NotConnectedError unless the client is connected.
|
|
158
|
+
*/
|
|
159
|
+
sendWhisper(data: Uint8Array, targetClientIDs: readonly ClientID[], codec: Codec): void;
|
|
160
|
+
/**
|
|
161
|
+
* Send one encoded audio frame to the channel this client is in. Throws a
|
|
162
|
+
* NotConnectedError unless the client is connected.
|
|
163
|
+
*/
|
|
164
|
+
sendVoice(data: Uint8Array, codec: Codec): void;
|
|
165
|
+
/**
|
|
166
|
+
* Upload `data` over a negotiated transfer, through the client's
|
|
167
|
+
* `fileTransferSocketFactory` if it has one.
|
|
168
|
+
*/
|
|
169
|
+
uploadFileData(host: string, info: FileUploadInfo, data: Readable, options?: {
|
|
170
|
+
readonly signal?: AbortSignal | undefined;
|
|
171
|
+
}): Promise<void>;
|
|
172
|
+
/**
|
|
173
|
+
* Download a negotiated transfer into `dest`, through the client's
|
|
174
|
+
* `fileTransferSocketFactory` if it has one.
|
|
175
|
+
*/
|
|
176
|
+
downloadFileData(host: string, info: FileDownloadInfo, dest: Writable, options?: {
|
|
177
|
+
readonly signal?: AbortSignal | undefined;
|
|
178
|
+
}): Promise<void>;
|
|
46
179
|
}
|
|
47
180
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,aAAa,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/commands.d.ts
CHANGED
|
@@ -1,48 +1,66 @@
|
|
|
1
|
+
import type { ResponseSpec } from "@honeybbq/teamspeak-core/internal";
|
|
1
2
|
export interface CommandResult {
|
|
2
3
|
err: Error | null;
|
|
3
4
|
data: Record<string, string>[];
|
|
4
5
|
}
|
|
5
6
|
/**
|
|
6
|
-
*
|
|
7
|
+
* Matches the server's answers to the commands that asked for them.
|
|
7
8
|
*
|
|
8
|
-
* The
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* The server handles one client's commands in order and closes each answer
|
|
10
|
+
* with `error … return_code=N`, so every row seen since the previous `error`
|
|
11
|
+
* belongs to command N. Rows are therefore held, tagged with where they came
|
|
12
|
+
* from, until that `error` says whose they are — attributing them on arrival
|
|
13
|
+
* would mean guessing which in-flight command the server is answering, and a
|
|
14
|
+
* command can be registered here well before it is sent (it first waits on the
|
|
15
|
+
* throttle and the middleware chain).
|
|
12
16
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
+
* A nameless row always belongs to the command. A notification row belongs to
|
|
18
|
+
* it only if the command declared that notification as its answer (see
|
|
19
|
+
* command/responses.ts): the same `notifyclientmoved` that answers nothing can
|
|
20
|
+
* arrive between any two commands.
|
|
21
|
+
*
|
|
22
|
+
* The welcome sequence is the exception. The server pushes channellist,
|
|
23
|
+
* channelgrouplist and the rest unprompted right after the handshake, before
|
|
24
|
+
* `channellistfinished`; without the gate they would land in the first
|
|
25
|
+
* command's answer as duplicate rows and a phantom cid=0.
|
|
17
26
|
*/
|
|
18
27
|
export declare class CommandTracker {
|
|
19
28
|
#private;
|
|
20
|
-
|
|
29
|
+
/** @param ownClientID the client's clid, for answers filtered by invoker. */
|
|
30
|
+
constructor(ownClientID?: () => number);
|
|
31
|
+
register(spec?: ResponseSpec, correlation?: string): [rc: number, promise: Promise<CommandResult>];
|
|
21
32
|
unregister(rc: number): void;
|
|
22
|
-
/**
|
|
23
|
-
* Called when `notifycliententerview` for our own clid arrives.
|
|
24
|
-
* Marks the welcome sequence as complete and discards any accumulated data.
|
|
25
|
-
*/
|
|
33
|
+
/** Marks the end of the welcome sequence and drops what it left behind. */
|
|
26
34
|
signalWelcomeComplete(): void;
|
|
35
|
+
/** Whether some in-flight command declared `name` as its answer. */
|
|
36
|
+
expects(name: string): boolean;
|
|
37
|
+
/** Hold a row until the next `error` says which command it answered. */
|
|
38
|
+
buffer(params: Record<string, string>, source?: string): void;
|
|
27
39
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
40
|
+
* Offer a notification to commands answered after their `error`.
|
|
41
|
+
*
|
|
42
|
+
* Matching is on the echoed request field, so it does not matter whether the
|
|
43
|
+
* notification beats the `error` or follows it.
|
|
30
44
|
*/
|
|
31
|
-
|
|
45
|
+
offerCorrelated(name: string, params: Record<string, string>): void;
|
|
32
46
|
resolve(rc: number, err: Error | null): void;
|
|
33
47
|
discardBuffer(): void;
|
|
34
|
-
|
|
48
|
+
/**
|
|
49
|
+
* Forget every command and fail it with `err`.
|
|
50
|
+
*
|
|
51
|
+
* Dropping them silently would leave each caller waiting out its full
|
|
52
|
+
* timeout for an answer that can no longer come.
|
|
53
|
+
*/
|
|
54
|
+
reset(err: Error): void;
|
|
35
55
|
}
|
|
36
56
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Append a return_code parameter to a command string if not already present.
|
|
57
|
+
* Append the tracker's return_code to a command.
|
|
58
|
+
*
|
|
59
|
+
* The return_code belongs to the tracker: it is how an answer finds its
|
|
60
|
+
* command, so a caller-supplied one would detach the command from its answer.
|
|
61
|
+
* Checked as a parameter rather than as text, because a message body that
|
|
62
|
+
* merely contains "return_code=" used to suppress the real one and time the
|
|
63
|
+
* command out.
|
|
46
64
|
*/
|
|
47
65
|
export declare function appendReturnCode(cmd: string, rc: number): string;
|
|
48
66
|
//# sourceMappingURL=commands.d.ts.map
|
package/dist/commands.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AAEtE,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,KAAK,GAAG,IAAI,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;CAChC;AAoBD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,cAAc;;IAOzB,6EAA6E;IAC7E,YAAY,WAAW,GAAE,MAAM,MAAgB,EAE9C;IAED,QAAQ,CACN,IAAI,CAAC,EAAE,YAAY,EACnB,WAAW,CAAC,EAAE,MAAM,GACnB,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC,CAO/C;IAED,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAE3B;IAED,2EAA2E;IAC3E,qBAAqB,IAAI,IAAI,CAG5B;IAED,oEAAoE;IACpE,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAM7B;IAED,wEAAwE;IACxE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,SAAK,GAAG,IAAI,CAIxD;IAED;;;;;OAKG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAiBlE;IAED,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,GAAG,IAAI,GAAG,IAAI,CAkB3C;IAED,aAAa,IAAI,IAAI,CAEpB;IAED;;;;;OAKG;IACH,KAAK,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,CAOtB;CAaF;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAMhE"}
|
package/dist/crypto/crypt.d.ts
CHANGED
|
@@ -1,17 +1,32 @@
|
|
|
1
1
|
import type { Identity } from "./identity.js";
|
|
2
|
+
/**
|
|
3
|
+
* The most squarings the Init1 puzzle may ask for. TS3 3.13 and TS6 6.0 both
|
|
4
|
+
* ask for 10000; a level far beyond that is a server trying to pin the event
|
|
5
|
+
* loop, since the squarings run synchronously.
|
|
6
|
+
*/
|
|
7
|
+
export declare const MAX_RSA_CHALLENGE_LEVEL: number;
|
|
2
8
|
export interface KeyNonce {
|
|
3
9
|
key: Uint8Array;
|
|
4
10
|
nonce: Uint8Array;
|
|
5
11
|
gen: number;
|
|
6
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* A connection's encryption state. The session material — the IV the keys
|
|
15
|
+
* derive from — lives in private fields, so it shows in no `util.inspect()`
|
|
16
|
+
* or `JSON.stringify()` of anything holding a Crypt.
|
|
17
|
+
*/
|
|
7
18
|
export declare class Crypt {
|
|
8
19
|
#private;
|
|
9
20
|
readonly identity: Identity;
|
|
10
|
-
ivStruct: Uint8Array;
|
|
11
|
-
fakeSignature: Uint8Array;
|
|
12
|
-
alphaTmp: Uint8Array;
|
|
13
|
-
cryptoInitComplete: boolean;
|
|
14
21
|
constructor(identity: Identity);
|
|
22
|
+
/** Whether the session keys are set up; until then packets use the dummy key. */
|
|
23
|
+
get cryptoInitComplete(): boolean;
|
|
24
|
+
/** The signature unencrypted packets carry: zeros until crypto init completes. */
|
|
25
|
+
get fakeSignature(): Uint8Array;
|
|
26
|
+
/** The client's random contribution to the IV, sent in clientinitiv; empty before. */
|
|
27
|
+
get alpha(): Uint8Array;
|
|
28
|
+
/** Choose the client's random contribution to the IV, and return it. */
|
|
29
|
+
newAlpha(): Uint8Array;
|
|
15
30
|
solveRsaChallenge(data: Uint8Array, offset: number, level: number): Uint8Array;
|
|
16
31
|
initCrypto(alpha: string, beta: string, omega: string): void;
|
|
17
32
|
setSharedSecret(alpha: Uint8Array, beta: Uint8Array, sharedKey: Uint8Array): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crypt.d.ts","sourceRoot":"","sources":["../../src/crypto/crypt.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAW9C,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,UAAU,CAAC;IAChB,KAAK,EAAE,UAAU,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;CACb;AAMD,qBAAa,KAAK;;IAChB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"crypt.d.ts","sourceRoot":"","sources":["../../src/crypto/crypt.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAW9C;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,EAAE,MAAgB,CAAC;AAEvD,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,UAAU,CAAC;IAChB,KAAK,EAAE,UAAU,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;CACb;AAMD;;;;GAIG;AACH,qBAAa,KAAK;;IAChB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAS5B,YAAY,QAAQ,EAAE,QAAQ,EAE7B;IAED,iFAAiF;IACjF,IAAI,kBAAkB,IAAI,OAAO,CAEhC;IAED,kFAAkF;IAClF,IAAI,aAAa,IAAI,UAAU,CAE9B;IAED,sFAAsF;IACtF,IAAI,KAAK,IAAI,UAAU,CAEtB;IAED,wEAAwE;IACxE,QAAQ,IAAI,UAAU,CAGrB;IAED,iBAAiB,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,CAiB7E;IAED,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAa3D;IAED,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,GAAG,IAAI,CAqBhF;IAED,WAAW,CACT,UAAU,EAAE,OAAO,EACnB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,OAAO,GACb,CAAC,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,CAAC,CAkCtC;IAED,OAAO,CACL,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE,UAAU,EACrB,KAAK,EAAE,OAAO,EACd,WAAW,EAAE,OAAO,GACnB,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,CAAC,CAW3C;IAED,OAAO,CACL,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,UAAU,EAClB,UAAU,EAAE,UAAU,EACtB,GAAG,EAAE,UAAU,EACf,KAAK,EAAE,OAAO,EACd,WAAW,EAAE,OAAO,GACnB,UAAU,CAeZ;CAyBF"}
|
|
@@ -1,16 +1,95 @@
|
|
|
1
1
|
import { type KeyObject } from "node:crypto";
|
|
2
|
+
import { type UID } from "@honeybbq/teamspeak-core";
|
|
3
|
+
/**
|
|
4
|
+
* A TeamSpeak client identity: a P-256 key pair plus a counter, the offset,
|
|
5
|
+
* whose hash with the public key sets the identity's security level.
|
|
6
|
+
*
|
|
7
|
+
* Immutable: raising the level returns a new identity. Opaque: the private
|
|
8
|
+
* key is never exposed, and `toString()`, `toJSON()` and `util.inspect()`
|
|
9
|
+
* describe the identity without it, so an identity that reaches a log or an
|
|
10
|
+
* error message does not leak; `export()` is the one way to get the secret
|
|
11
|
+
* form, for storing it. Make one with `generateIdentity()` or
|
|
12
|
+
* `parseIdentity()`.
|
|
13
|
+
*/
|
|
2
14
|
export declare class Identity {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
15
|
+
#private;
|
|
16
|
+
private constructor();
|
|
17
|
+
/** The counter whose hash with the public key sets the security level. */
|
|
18
|
+
get offset(): bigint;
|
|
19
|
+
/** The public key in TeamSpeak's encoding: base64 of its DER form. */
|
|
20
|
+
publicKey(): string;
|
|
21
|
+
/**
|
|
22
|
+
* The identity's unique identifier, hashed with `algorithm`: SHA-1 for a
|
|
23
|
+
* TeamSpeak 3 server, SHA-256 for TeamSpeak 6. A connected client's `uid`
|
|
24
|
+
* already uses the one its server does.
|
|
25
|
+
*/
|
|
26
|
+
uid(algorithm: UIDAlgorithm): UID;
|
|
27
|
+
/**
|
|
28
|
+
* The identity in the form `parseIdentity()` reads, private key included.
|
|
29
|
+
* Store it as you would a password.
|
|
30
|
+
*/
|
|
31
|
+
export(): string;
|
|
32
|
+
/** Describes the identity, by its SHA-1 unique identifier, without its private key. */
|
|
7
33
|
toString(): string;
|
|
34
|
+
/** The same as `toString()`, so serialising an identity cannot leak its key. */
|
|
35
|
+
toJSON(): string;
|
|
36
|
+
/** The security level: trailing zero bits in SHA-1 of the public key and offset. */
|
|
8
37
|
securityLevel(): number;
|
|
9
|
-
|
|
38
|
+
/**
|
|
39
|
+
* The same key at an offset whose security level reaches `targetLevel`, as
|
|
40
|
+
* a new identity; this one is unchanged, and returned as it is when it
|
|
41
|
+
* already reaches the level.
|
|
42
|
+
*
|
|
43
|
+
* Each level doubles the expected work, so a high level can take a long
|
|
44
|
+
* time; `signal` bounds it, and the event loop keeps running meanwhile. A
|
|
45
|
+
* level above 160, the width of SHA-1, can never be reached and is refused
|
|
46
|
+
* with a RangeError.
|
|
47
|
+
*/
|
|
48
|
+
upgradeToLevel(targetLevel: number, options?: {
|
|
49
|
+
readonly signal?: AbortSignal | undefined;
|
|
50
|
+
}): Promise<Identity>;
|
|
10
51
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Read an identity from the form `Identity.export()` writes: the private key
|
|
54
|
+
* as canonical base64 of at most 32 bytes, a colon, and the offset as a
|
|
55
|
+
* decimal unsigned 64-bit integer. Anything else throws an
|
|
56
|
+
* InvalidIdentityError, with the underlying failure as its cause.
|
|
57
|
+
*/
|
|
58
|
+
export declare function parseIdentity(s: string): Identity;
|
|
59
|
+
/**
|
|
60
|
+
* Create an identity at the given security level, at most 160. Each level
|
|
61
|
+
* doubles the expected work; `signal` bounds it, and the event loop keeps
|
|
62
|
+
* running meanwhile.
|
|
63
|
+
*/
|
|
64
|
+
export declare function generateIdentity(targetLevel: number, options?: {
|
|
65
|
+
readonly signal?: AbortSignal | undefined;
|
|
66
|
+
}): Promise<Identity>;
|
|
67
|
+
/**
|
|
68
|
+
* Create an identity at the given security level, at most 160, blocking until
|
|
69
|
+
* done. Fine for a low level; a high one can block the event loop for minutes,
|
|
70
|
+
* so prefer `generateIdentity()` there.
|
|
71
|
+
*/
|
|
72
|
+
export declare function generateIdentitySync(targetLevel: number): Identity;
|
|
73
|
+
/**
|
|
74
|
+
* The hash a server uses for `client_unique_identifier`, keyed by the server's
|
|
75
|
+
* major version.
|
|
76
|
+
*
|
|
77
|
+
* TeamSpeak 3 hashes the canonical public key with SHA-1 (20 bytes); TeamSpeak
|
|
78
|
+
* 6 switched to SHA-256 (32 bytes). The algorithm is not negotiable on the
|
|
79
|
+
* wire, so a client that guesses wrong computes a UID that matches nothing the
|
|
80
|
+
* server ever sends — self-identification by UID silently fails.
|
|
81
|
+
*
|
|
82
|
+
* May gain members in a minor release, should a server generation change the
|
|
83
|
+
* hash again: a `switch` over it needs a default case.
|
|
84
|
+
*/
|
|
85
|
+
export type UIDAlgorithm = "sha1" | "sha256";
|
|
86
|
+
/** Pick the UID hash from a `virtualserver_version` string, e.g. "6.0.0-beta13.1". */
|
|
87
|
+
export declare function uidAlgorithmForVersion(version: string): UIDAlgorithm;
|
|
88
|
+
/**
|
|
89
|
+
* The unique identifier of a public key in TeamSpeak's encoding, hashed with
|
|
90
|
+
* `algorithm`: SHA-1 for a TeamSpeak 3 server, SHA-256 for TeamSpeak 6.
|
|
91
|
+
*/
|
|
92
|
+
export declare function uidFromPublicKey(publicKey: string, algorithm: UIDAlgorithm): UID;
|
|
14
93
|
export declare function hash512(data: Uint8Array): Uint8Array;
|
|
15
94
|
/** Import a TS3 public key (canonical or legacy ASN.1 DER) and return the
|
|
16
95
|
* uncompressed 65-byte point [0x04 || x || y]. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/crypto/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,SAAS,EACf,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/crypto/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,SAAS,EACf,MAAM,aAAa,CAAC;AAErB,OAAO,EAAS,KAAK,GAAG,EAAE,MAAM,0BAA0B,CAAC;AAY3D;;;;;;;;;;GAUG;AACH,qBAAa,QAAQ;;IAUnB,OAAO,eAGN;IAED,0EAA0E;IAC1E,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,sEAAsE;IACtE,SAAS,IAAI,MAAM,CAUlB;IAED;;;;OAIG;IACH,GAAG,CAAC,SAAS,EAAE,YAAY,GAAG,GAAG,CAEhC;IAED;;;OAGG;IACH,MAAM,IAAI,MAAM,CAKf;IAED,uFAAuF;IACvF,QAAQ,IAAI,MAAM,CAEjB;IAED,gFAAgF;IAChF,MAAM,IAAI,MAAM,CAEf;IAED,oFAAoF;IACpF,aAAa,IAAI,MAAM,CAEtB;IAED;;;;;;;;;OASG;IACG,cAAc,CAClB,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;QAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAA;KAAO,GAC1D,OAAO,CAAC,QAAQ,CAAC,CAgBnB;CACF;AAqCD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,QAAQ,CA0CjD;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;IAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAA;CAAO,GAC1D,OAAO,CAAC,QAAQ,CAAC,CAGnB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,QAAQ,CAOlE;AAMD;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE7C,sFAAsF;AACtF,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CAGpE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,GAAG,GAAG,CAEhF;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,CAEpD;AA+BD;mDACmD;AACnD,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,CAS3D"}
|
package/dist/crypto/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export { Identity,
|
|
1
|
+
export { Identity, parseIdentity, generateIdentity, generateIdentitySync, uidFromPublicKey, uidAlgorithmForVersion, hash512, importPublicKey, } from "./identity.js";
|
|
2
|
+
export type { UIDAlgorithm } from "./identity.js";
|
|
2
3
|
export { Crypt } from "./crypt.js";
|
|
3
4
|
export type { KeyNonce } from "./crypt.js";
|
|
4
5
|
export { EAX, aesCmac } from "./eax.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/crypto/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/crypto/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,aAAa,EACb,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,EACtB,OAAO,EACP,eAAe,GAChB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EACL,oBAAoB,EACpB,IAAI,EACJ,UAAU,EACV,gBAAgB,EAChB,WAAW,GACZ,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Diagnostics channels: the SDK's tracing points, for an application or an
|
|
3
|
+
* APM agent (OpenTelemetry instruments `diagnostics_channel` directly) to
|
|
4
|
+
* subscribe to.
|
|
5
|
+
*
|
|
6
|
+
* A library does not decide where its traces go, so the SDK publishes them
|
|
7
|
+
* here, and with no subscriber a channel costs a property read.
|
|
8
|
+
*
|
|
9
|
+
* Messages carry the command's name, never its parameters: those hold
|
|
10
|
+
* password hashes, which the server accepts as passwords, and privilege keys.
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { tracingChannel } from "node:diagnostics_channel";
|
|
14
|
+
*
|
|
15
|
+
* tracingChannel("honeybbq:teamspeak:command").subscribe({
|
|
16
|
+
* start: ({ command }) => console.time(command),
|
|
17
|
+
* asyncEnd: ({ command }) => console.timeEnd(command),
|
|
18
|
+
* error: ({ command, error }) => console.error(command, error),
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
import { type Channel, type TracingChannel } from "node:diagnostics_channel";
|
|
23
|
+
import type { Client } from "./client.js";
|
|
24
|
+
/** What `honeybbq:teamspeak:command` reports about a command. */
|
|
25
|
+
export interface CommandTrace {
|
|
26
|
+
/** The command's name, such as `clientlist`. */
|
|
27
|
+
readonly command: string;
|
|
28
|
+
/** The client sending it. Its fields are private, so it carries no secret. */
|
|
29
|
+
readonly client: Client;
|
|
30
|
+
}
|
|
31
|
+
/** What `honeybbq:teamspeak:packet` reports about a command arriving from the server. */
|
|
32
|
+
export interface PacketTrace {
|
|
33
|
+
/** The command's name, such as `notifytextmessage`, or `""` for a data row. */
|
|
34
|
+
readonly command: string;
|
|
35
|
+
/** The client receiving it. */
|
|
36
|
+
readonly client: Client;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Traces every command with an answer: `start` when it is sent, `asyncEnd`
|
|
40
|
+
* when its answer arrives, `error` when it fails.
|
|
41
|
+
*/
|
|
42
|
+
export declare const commandChannel: TracingChannel<CommandTrace>;
|
|
43
|
+
/** Publishes every command the server sends. */
|
|
44
|
+
export declare const packetChannel: Channel<PacketTrace>;
|
|
45
|
+
//# sourceMappingURL=diagnostics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAGL,KAAK,OAAO,EACZ,KAAK,cAAc,EACpB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,iEAAiE;AACjE,MAAM,WAAW,YAAY;IAC3B,gDAAgD;IAChD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,yFAAyF;AACzF,MAAM,WAAW,WAAW;IAC1B,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,+BAA+B;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,YAAY,CAEvD,CAAC;AAEF,gDAAgD;AAChD,eAAO,MAAM,aAAa,EAAE,OAAO,CAAC,WAAW,CAE9C,CAAC"}
|
|
@@ -1,8 +1,26 @@
|
|
|
1
|
-
import type { Logger } from "../types.js";
|
|
2
1
|
import type { ResolvedAddr } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* The most a TSDNS server or the nickname service is read for. Either answers
|
|
4
|
+
* with one short line; without a bound, one that kept sending would be held in
|
|
5
|
+
* memory until the resolution budget ran out.
|
|
6
|
+
*/
|
|
7
|
+
export declare const MAX_DISCOVERY_RESPONSE: number;
|
|
8
|
+
/** How the default resolver resolves. */
|
|
9
|
+
export interface ResolverOptions {
|
|
10
|
+
/** Look dot-less names up at named.myteamspeak.com; off by default. */
|
|
11
|
+
readonly resolveNicknames?: boolean | undefined;
|
|
12
|
+
}
|
|
3
13
|
export declare class Resolver {
|
|
4
14
|
#private;
|
|
5
|
-
constructor(
|
|
6
|
-
|
|
15
|
+
constructor(options?: ResolverOptions);
|
|
16
|
+
/**
|
|
17
|
+
* Resolve as the TeamSpeak application does: a server nickname (only with
|
|
18
|
+
* `resolveNicknames`), then SRV, then TSDNS, then the address as given. The
|
|
19
|
+
* whole resolution is bounded: past the budget, or when a step fails, the
|
|
20
|
+
* address as given is the answer.
|
|
21
|
+
*/
|
|
22
|
+
resolve(inputAddr: string, options?: {
|
|
23
|
+
readonly signal?: AbortSignal | undefined;
|
|
24
|
+
}): Promise<ResolvedAddr[]>;
|
|
7
25
|
}
|
|
8
26
|
//# sourceMappingURL=resolver.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/discovery/resolver.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/discovery/resolver.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAiBhD;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAiB,CAAC;AAEvD,yCAAyC;AACzC,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACjD;AAED,qBAAa,QAAQ;;IAInB,YAAY,OAAO,GAAE,eAAoB,EAExC;IAED;;;;;OAKG;IACG,OAAO,CACX,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;QAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAA;KAAO,GAC1D,OAAO,CAAC,YAAY,EAAE,CAAC,CAYzB;CAgHF"}
|