@basmilius/apple-rtsp 0.9.19 → 0.10.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/dist/index.d.mts CHANGED
@@ -1,54 +1,183 @@
1
1
  import { Connection, Context } from "@basmilius/apple-common";
2
2
 
3
3
  //#region src/encoding.d.ts
4
+ /**
5
+ * Supported RTSP/HTTP method verbs used in Apple protocol communication.
6
+ */
4
7
  type Method = "ANNOUNCE" | "FLUSH" | "GET" | "GET_PARAMETER" | "OPTIONS" | "POST" | "PUT" | "RECORD" | "SETUP" | "SET_PARAMETER" | "TEARDOWN";
8
+ /**
9
+ * Parsed RTSP request containing method, path, headers, body, and total byte length.
10
+ */
5
11
  type RtspRequest = {
6
- readonly headers: Record<string, string>;
7
- readonly method: Method;
8
- readonly path: string;
9
- readonly body: Buffer;
12
+ /** Parsed request headers with normalized (capitalized) names. */readonly headers: Record<string, string>; /** The RTSP/HTTP method verb. */
13
+ readonly method: Method; /** The request target path (e.g. `/info`, `/pair-setup`). */
14
+ readonly path: string; /** The request body as a raw buffer, empty if no body was present. */
15
+ readonly body: Buffer; /** Total number of bytes consumed from the input buffer for this request (headers + body). */
10
16
  readonly requestLength: number;
11
17
  };
18
+ /**
19
+ * Parsed RTSP response wrapping a standard `Response` object alongside the total byte length consumed.
20
+ */
12
21
  type RtspResponse = {
13
- readonly response: Response;
22
+ /** The parsed response as a standard web `Response` object. */readonly response: Response; /** Total number of bytes consumed from the input buffer for this response (headers + body). */
14
23
  readonly responseLength: number;
15
24
  };
25
+ /**
26
+ * Options for building a serialized RTSP/HTTP response buffer.
27
+ */
16
28
  type BuildResponseOptions = {
17
- readonly status: number;
18
- readonly statusText: string;
19
- readonly headers?: Record<string, string | number>;
20
- readonly body?: Buffer;
29
+ /** HTTP status code (e.g. 200, 404). */readonly status: number; /** HTTP status reason phrase (e.g. "OK", "Not Found"). */
30
+ readonly statusText: string; /** Additional response headers. Content-Length is set automatically. */
31
+ readonly headers?: Record<string, string | number>; /** Optional response body. */
32
+ readonly body?: Buffer; /** Protocol version line prefix. Defaults to `'RTSP/1.0'`. */
21
33
  readonly protocol?: "RTSP/1.0" | "HTTP/1.1";
22
34
  };
35
+ /**
36
+ * Builds a serialized RTSP/HTTP response buffer from the given options.
37
+ *
38
+ * Automatically sets the `Content-Length` header based on the body size.
39
+ * The resulting buffer is ready to be sent over a TCP socket.
40
+ *
41
+ * @param options - Response configuration including status, headers, and body.
42
+ * @returns A buffer containing the fully formatted response.
43
+ */
23
44
  declare function buildResponse(options: BuildResponseOptions): Buffer;
45
+ /**
46
+ * Attempts to parse an RTSP/HTTP request from the given buffer.
47
+ *
48
+ * Returns `null` if the buffer does not yet contain a complete request
49
+ * (i.e. headers are incomplete or the body has not fully arrived).
50
+ * This allows incremental parsing as TCP data arrives in chunks.
51
+ *
52
+ * @param buffer - The raw input buffer to parse from.
53
+ * @returns The parsed request, or `null` if the buffer is incomplete.
54
+ * @throws Error if the request line is malformed.
55
+ */
24
56
  declare function parseRequest(buffer: Buffer): RtspRequest | null;
57
+ /**
58
+ * Attempts to parse an RTSP/HTTP response from the given buffer.
59
+ *
60
+ * Returns `null` if the buffer does not yet contain a complete response
61
+ * (i.e. headers are incomplete or the body has not fully arrived).
62
+ * This allows incremental parsing as TCP data arrives in chunks.
63
+ *
64
+ * @param buffer - The raw input buffer to parse from.
65
+ * @returns The parsed response wrapped in an {@link RtspResponse}, or `null` if the buffer is incomplete.
66
+ * @throws Error if the status line is malformed.
67
+ */
25
68
  declare function parseResponse(buffer: Buffer): RtspResponse | null;
26
69
  //#endregion
27
70
  //#region src/client.d.ts
71
+ /**
72
+ * Options for configuring an RTSP/HTTP request-response exchange.
73
+ */
28
74
  type ExchangeOptions = {
29
- contentType?: string;
30
- headers?: Record<string, string>;
31
- body?: Buffer | string | Record<string, unknown>;
32
- allowError?: boolean;
33
- protocol?: "RTSP/1.0" | "HTTP/1.1";
75
+ /** Explicit Content-Type header. Automatically set to `application/x-apple-binary-plist` when body is a plain object. */contentType?: string; /** Additional headers to include in the request. Merged after default headers. */
76
+ headers?: Record<string, string>; /** Request body. Plain objects are serialized as binary plist; strings and buffers are sent as-is. */
77
+ body?: Buffer | string | Record<string, unknown>; /** When `true`, non-OK responses resolve instead of rejecting with {@link InvalidResponseError}. */
78
+ allowError?: boolean; /** Protocol version for the request line. Defaults to `'RTSP/1.0'`. */
79
+ protocol?: "RTSP/1.0" | "HTTP/1.1"; /** Response timeout in milliseconds. Defaults to `HTTP_TIMEOUT`. */
34
80
  timeout?: number;
35
81
  };
82
+ /**
83
+ * RTSP client for Apple protocol communication over TCP.
84
+ *
85
+ * Extends {@link Connection} with RTSP-specific request/response handling, including
86
+ * CSeq-based request tracking, automatic body serialization (binary plist for objects),
87
+ * and support for encryption via overridable transform hooks. Maintains separate buffers
88
+ * for encrypted and decrypted data to prevent corruption during partial TCP delivery.
89
+ *
90
+ * Subclasses should override {@link transformIncoming} and {@link transformOutgoing} to
91
+ * add encryption/decryption, and {@link getDefaultHeaders} to inject per-request headers.
92
+ */
36
93
  declare class RtspClient extends Connection<{}> {
37
94
  #private;
95
+ /**
96
+ * Creates a new RTSP client and binds internal event handlers.
97
+ *
98
+ * @param context - Device context providing logger and configuration.
99
+ * @param address - The target host address to connect to.
100
+ * @param port - The target TCP port to connect to.
101
+ */
38
102
  constructor(context: Context, address: string, port: number);
39
103
  /**
40
- * Override to provide default headers for every request.
104
+ * Returns default headers that are included in every outgoing request.
105
+ *
106
+ * Override in subclasses to inject session-specific headers (e.g. DACP-ID,
107
+ * Active-Remote). These headers are placed after CSeq but before any
108
+ * per-request headers from {@link ExchangeOptions.headers}.
109
+ *
110
+ * @returns A record of header name-value pairs.
41
111
  */
42
112
  protected getDefaultHeaders(): Record<string, string | number>;
43
113
  /**
44
- * Override to transform incoming data before RTSP parsing (e.g. decryption).
114
+ * Transforms incoming raw TCP data before RTSP response parsing.
115
+ *
116
+ * Override in subclasses to perform decryption. Return `false` if the buffer
117
+ * does not yet contain enough data for a complete decryption block, signaling
118
+ * that more data should be accumulated before retrying.
119
+ *
120
+ * @param data - The raw (potentially encrypted) incoming data buffer.
121
+ * @returns The transformed (decrypted) buffer, or `false` if more data is needed.
45
122
  */
46
123
  protected transformIncoming(data: Buffer): Buffer | false;
47
124
  /**
48
- * Override to transform outgoing data after RTSP formatting (e.g. encryption).
125
+ * Transforms outgoing data after RTSP request formatting.
126
+ *
127
+ * Override in subclasses to perform encryption on the fully formatted
128
+ * request buffer before it is written to the socket.
129
+ *
130
+ * @param data - The fully formatted RTSP request buffer (headers + body).
131
+ * @returns The transformed (encrypted) buffer ready for transmission.
49
132
  */
50
133
  protected transformOutgoing(data: Buffer): Buffer;
134
+ /**
135
+ * Sends an RTSP/HTTP request and waits for the matching response.
136
+ *
137
+ * Automatically assigns a CSeq header, serializes the body (plain objects become
138
+ * binary plist), applies outgoing transformation (e.g. encryption), and tracks
139
+ * the pending response via a timeout-guarded promise.
140
+ *
141
+ * @param method - The RTSP/HTTP method verb.
142
+ * @param path - The request target path.
143
+ * @param options - Additional request configuration.
144
+ * @returns The response from the remote device.
145
+ * @throws TimeoutError if no response is received within the configured timeout.
146
+ * @throws InvalidResponseError if the response has a non-OK status and `allowError` is not set.
147
+ */
51
148
  protected exchange(method: Method, path: string, options?: ExchangeOptions): Promise<Response>;
149
+ /**
150
+ * Handles TCP connection close events.
151
+ *
152
+ * Resets both internal buffers and rejects all pending requests with a
153
+ * {@link ConnectionClosedError}.
154
+ */
155
+ onRtspClose(): void;
156
+ /**
157
+ * Handles incoming TCP data by accumulating, transforming, and parsing RTSP responses.
158
+ *
159
+ * Raw data is first appended to the encrypted buffer, then passed through
160
+ * {@link transformIncoming} for decryption. The resulting plaintext is appended
161
+ * to the parse buffer and consumed as complete RTSP responses. Each response is
162
+ * matched to its pending request via the CSeq header.
163
+ *
164
+ * If the buffer exceeds {@link MAX_BUFFER_SIZE}, all buffers are reset and
165
+ * pending requests are rejected to prevent memory exhaustion.
166
+ *
167
+ * @param data - Raw TCP data received from the socket.
168
+ */
169
+ onRtspData(data: Buffer): void;
170
+ /**
171
+ * Handles socket error events by rejecting all pending requests with the error.
172
+ *
173
+ * @param err - The error that occurred on the socket.
174
+ */
175
+ onRtspError(err: Error): void;
176
+ /**
177
+ * Handles socket timeout events by rejecting all pending requests with a
178
+ * {@link ConnectionTimeoutError}.
179
+ */
180
+ onRtspTimeout(): void;
52
181
  }
53
182
  //#endregion
54
183
  export { type BuildResponseOptions, type ExchangeOptions, type Method, RtspClient, type RtspRequest, type RtspResponse, buildResponse, parseRequest, parseResponse };
package/dist/index.mjs CHANGED
@@ -2,6 +2,15 @@ import { Connection, ConnectionClosedError, ConnectionTimeoutError, HTTP_TIMEOUT
2
2
  import { Plist } from "@basmilius/apple-encoding";
3
3
 
4
4
  //#region src/encoding.ts
5
+ /**
6
+ * Builds a serialized RTSP/HTTP response buffer from the given options.
7
+ *
8
+ * Automatically sets the `Content-Length` header based on the body size.
9
+ * The resulting buffer is ready to be sent over a TCP socket.
10
+ *
11
+ * @param options - Response configuration including status, headers, and body.
12
+ * @returns A buffer containing the fully formatted response.
13
+ */
5
14
  function buildResponse(options) {
6
15
  const { status, statusText, headers: extraHeaders = {}, body, protocol = "RTSP/1.0" } = options;
7
16
  const headers = {
@@ -17,6 +26,17 @@ function buildResponse(options) {
17
26
  if (body && body.byteLength > 0) return Buffer.concat([Buffer.from(headerLines), body]);
18
27
  return Buffer.from(headerLines);
19
28
  }
29
+ /**
30
+ * Attempts to parse an RTSP/HTTP request from the given buffer.
31
+ *
32
+ * Returns `null` if the buffer does not yet contain a complete request
33
+ * (i.e. headers are incomplete or the body has not fully arrived).
34
+ * This allows incremental parsing as TCP data arrives in chunks.
35
+ *
36
+ * @param buffer - The raw input buffer to parse from.
37
+ * @returns The parsed request, or `null` if the buffer is incomplete.
38
+ * @throws Error if the request line is malformed.
39
+ */
20
40
  function parseRequest(buffer) {
21
41
  const headerLength = buffer.indexOf("\r\n\r\n");
22
42
  if (headerLength === -1) return null;
@@ -33,6 +53,17 @@ function parseRequest(buffer) {
33
53
  requestLength
34
54
  };
35
55
  }
56
+ /**
57
+ * Attempts to parse an RTSP/HTTP response from the given buffer.
58
+ *
59
+ * Returns `null` if the buffer does not yet contain a complete response
60
+ * (i.e. headers are incomplete or the body has not fully arrived).
61
+ * This allows incremental parsing as TCP data arrives in chunks.
62
+ *
63
+ * @param buffer - The raw input buffer to parse from.
64
+ * @returns The parsed response wrapped in an {@link RtspResponse}, or `null` if the buffer is incomplete.
65
+ * @throws Error if the status line is malformed.
66
+ */
36
67
  function parseResponse(buffer) {
37
68
  const headerLength = buffer.indexOf("\r\n\r\n");
38
69
  if (headerLength === -1) return null;
@@ -51,20 +82,40 @@ function parseResponse(buffer) {
51
82
  responseLength
52
83
  };
53
84
  }
85
+ /**
86
+ * Parses raw header lines into a key-value record.
87
+ *
88
+ * Header names are normalized to capitalized form (e.g. `content-length` becomes
89
+ * `Content-Length`) so that lookups work regardless of the sender's casing.
90
+ * Lines without a valid colon separator are silently skipped.
91
+ *
92
+ * @param lines - Individual header lines (without the request/status line).
93
+ * @returns A record mapping normalized header names to their values.
94
+ */
54
95
  function parseHeaders(lines) {
55
96
  const headers = {};
56
97
  for (let i = 0; i < lines.length; i++) {
57
98
  const colon = lines[i].indexOf(":");
58
99
  if (colon <= 0) continue;
59
- const name = lines[i].substring(0, colon).trim();
100
+ const name = lines[i].substring(0, colon).trim().replace(/(^|-)(\w)/g, (_, prefix, char) => prefix + char.toUpperCase());
60
101
  headers[name] = lines[i].substring(colon + 1).trim();
61
102
  }
62
103
  return headers;
63
104
  }
105
+ /**
106
+ * Parses the header section of an RTSP/HTTP request buffer into structured components.
107
+ *
108
+ * Extracts the method, path, and headers from the raw header bytes. The first line
109
+ * is expected to match the format `METHOD /path RTSP/1.0` or `METHOD /path HTTP/1.1`.
110
+ *
111
+ * @param buffer - The raw header bytes (up to but not including the `\r\n\r\n` delimiter).
112
+ * @returns An object containing the parsed headers, method, and path.
113
+ * @throws Error if the request line does not match the expected format.
114
+ */
64
115
  function parseRequestHeaders(buffer) {
65
116
  const lines = buffer.toString("utf8").split("\r\n");
66
- const rawRequest = lines[0].match(/^(\S+)\s+(\S+)\s+RTSP\/1\.0$/);
67
- if (!rawRequest) throw new Error(`Invalid RTSP request line: ${lines[0]}`);
117
+ const rawRequest = lines[0].match(/^(\S+)\s+(\S+)\s+(?:RTSP|HTTP)\/[\d.]+$/);
118
+ if (!rawRequest) throw new Error(`Invalid RTSP/HTTP request line: ${lines[0]}`);
68
119
  const method = rawRequest[1];
69
120
  const path = rawRequest[2];
70
121
  return {
@@ -73,6 +124,16 @@ function parseRequestHeaders(buffer) {
73
124
  path
74
125
  };
75
126
  }
127
+ /**
128
+ * Parses the header section of an RTSP/HTTP response buffer into structured components.
129
+ *
130
+ * Extracts the status code, status text, and headers from the raw header bytes. The first
131
+ * line is expected to match the format `RTSP/1.0 200 OK` or `HTTP/1.1 200 OK`.
132
+ *
133
+ * @param buffer - The raw header bytes (up to but not including the `\r\n\r\n` delimiter).
134
+ * @returns An object containing the parsed headers, status code, and status text.
135
+ * @throws Error if the status line does not match the expected format.
136
+ */
76
137
  function parseResponseHeaders(buffer) {
77
138
  const lines = buffer.toString("utf8").split("\r\n");
78
139
  const rawStatus = lines[0].match(/(HTTP|RTSP)\/[\d.]+\s+(\d+)\s+(.+)/);
@@ -88,36 +149,97 @@ function parseResponseHeaders(buffer) {
88
149
 
89
150
  //#endregion
90
151
  //#region src/client.ts
152
+ /** Maximum allowed buffer size (2 MB) before resetting to prevent memory exhaustion. */
91
153
  const MAX_BUFFER_SIZE = 2 * 1024 * 1024;
154
+ /**
155
+ * RTSP client for Apple protocol communication over TCP.
156
+ *
157
+ * Extends {@link Connection} with RTSP-specific request/response handling, including
158
+ * CSeq-based request tracking, automatic body serialization (binary plist for objects),
159
+ * and support for encryption via overridable transform hooks. Maintains separate buffers
160
+ * for encrypted and decrypted data to prevent corruption during partial TCP delivery.
161
+ *
162
+ * Subclasses should override {@link transformIncoming} and {@link transformOutgoing} to
163
+ * add encryption/decryption, and {@link getDefaultHeaders} to inject per-request headers.
164
+ */
92
165
  var RtspClient = class extends Connection {
166
+ /** Accumulates decrypted plaintext data waiting to be parsed as RTSP responses. */
93
167
  #buffer = Buffer.alloc(0);
168
+ /** Accumulates raw encrypted TCP data before transformation/decryption. */
169
+ #encryptedBuffer = Buffer.alloc(0);
170
+ /** Monotonically increasing RTSP CSeq counter for request tracking. */
94
171
  #cseq = 0;
172
+ /** Map of in-flight requests keyed by CSeq, awaiting their matching response. */
95
173
  #requests = /* @__PURE__ */ new Map();
174
+ /**
175
+ * Creates a new RTSP client and binds internal event handlers.
176
+ *
177
+ * @param context - Device context providing logger and configuration.
178
+ * @param address - The target host address to connect to.
179
+ * @param port - The target TCP port to connect to.
180
+ */
96
181
  constructor(context, address, port) {
97
182
  super(context, address, port);
98
- this.on("close", this.#onClose.bind(this));
99
- this.on("data", this.#onData.bind(this));
100
- this.on("error", this.#onError.bind(this));
101
- this.on("timeout", this.#onTimeout.bind(this));
183
+ this.onRtspClose = this.onRtspClose.bind(this);
184
+ this.onRtspData = this.onRtspData.bind(this);
185
+ this.onRtspError = this.onRtspError.bind(this);
186
+ this.onRtspTimeout = this.onRtspTimeout.bind(this);
187
+ this.on("close", this.onRtspClose);
188
+ this.on("data", this.onRtspData);
189
+ this.on("error", this.onRtspError);
190
+ this.on("timeout", this.onRtspTimeout);
102
191
  }
103
192
  /**
104
- * Override to provide default headers for every request.
193
+ * Returns default headers that are included in every outgoing request.
194
+ *
195
+ * Override in subclasses to inject session-specific headers (e.g. DACP-ID,
196
+ * Active-Remote). These headers are placed after CSeq but before any
197
+ * per-request headers from {@link ExchangeOptions.headers}.
198
+ *
199
+ * @returns A record of header name-value pairs.
105
200
  */
106
201
  getDefaultHeaders() {
107
202
  return {};
108
203
  }
109
204
  /**
110
- * Override to transform incoming data before RTSP parsing (e.g. decryption).
205
+ * Transforms incoming raw TCP data before RTSP response parsing.
206
+ *
207
+ * Override in subclasses to perform decryption. Return `false` if the buffer
208
+ * does not yet contain enough data for a complete decryption block, signaling
209
+ * that more data should be accumulated before retrying.
210
+ *
211
+ * @param data - The raw (potentially encrypted) incoming data buffer.
212
+ * @returns The transformed (decrypted) buffer, or `false` if more data is needed.
111
213
  */
112
214
  transformIncoming(data) {
113
215
  return data;
114
216
  }
115
217
  /**
116
- * Override to transform outgoing data after RTSP formatting (e.g. encryption).
218
+ * Transforms outgoing data after RTSP request formatting.
219
+ *
220
+ * Override in subclasses to perform encryption on the fully formatted
221
+ * request buffer before it is written to the socket.
222
+ *
223
+ * @param data - The fully formatted RTSP request buffer (headers + body).
224
+ * @returns The transformed (encrypted) buffer ready for transmission.
117
225
  */
118
226
  transformOutgoing(data) {
119
227
  return data;
120
228
  }
229
+ /**
230
+ * Sends an RTSP/HTTP request and waits for the matching response.
231
+ *
232
+ * Automatically assigns a CSeq header, serializes the body (plain objects become
233
+ * binary plist), applies outgoing transformation (e.g. encryption), and tracks
234
+ * the pending response via a timeout-guarded promise.
235
+ *
236
+ * @param method - The RTSP/HTTP method verb.
237
+ * @param path - The request target path.
238
+ * @param options - Additional request configuration.
239
+ * @returns The response from the remote device.
240
+ * @throws TimeoutError if no response is received within the configured timeout.
241
+ * @throws InvalidResponseError if the response has a non-OK status and `allowError` is not set.
242
+ */
121
243
  async exchange(method, path, options = {}) {
122
244
  const { contentType, headers: extraHeaders = {}, allowError = false, protocol = "RTSP/1.0", timeout = HTTP_TIMEOUT } = options;
123
245
  let { body } = options;
@@ -165,19 +287,40 @@ var RtspClient = class extends Connection {
165
287
  this.write(data);
166
288
  });
167
289
  }
168
- #onClose() {
290
+ /**
291
+ * Handles TCP connection close events.
292
+ *
293
+ * Resets both internal buffers and rejects all pending requests with a
294
+ * {@link ConnectionClosedError}.
295
+ */
296
+ onRtspClose() {
169
297
  this.#buffer = Buffer.alloc(0);
298
+ this.#encryptedBuffer = Buffer.alloc(0);
170
299
  for (const [cseq, { reject }] of this.#requests) {
171
300
  reject(new ConnectionClosedError("Connection closed."));
172
301
  this.#requests.delete(cseq);
173
302
  }
174
- this.context.logger.net("[rtsp]", "#onClose()");
303
+ this.context.logger.net("[rtsp]", "onRtspClose()");
175
304
  }
176
- #onData(data) {
305
+ /**
306
+ * Handles incoming TCP data by accumulating, transforming, and parsing RTSP responses.
307
+ *
308
+ * Raw data is first appended to the encrypted buffer, then passed through
309
+ * {@link transformIncoming} for decryption. The resulting plaintext is appended
310
+ * to the parse buffer and consumed as complete RTSP responses. Each response is
311
+ * matched to its pending request via the CSeq header.
312
+ *
313
+ * If the buffer exceeds {@link MAX_BUFFER_SIZE}, all buffers are reset and
314
+ * pending requests are rejected to prevent memory exhaustion.
315
+ *
316
+ * @param data - Raw TCP data received from the socket.
317
+ */
318
+ onRtspData(data) {
177
319
  try {
178
- this.#buffer = Buffer.concat([this.#buffer, data]);
179
- if (this.#buffer.byteLength > MAX_BUFFER_SIZE) {
180
- this.context.logger.error("[rtsp]", `Buffer exceeded max size (${this.#buffer.byteLength} bytes), resetting.`);
320
+ this.#encryptedBuffer = Buffer.concat([this.#encryptedBuffer, data]);
321
+ if (this.#encryptedBuffer.byteLength > MAX_BUFFER_SIZE) {
322
+ this.context.logger.error("[rtsp]", `Buffer exceeded max size (${this.#encryptedBuffer.byteLength} bytes), resetting.`);
323
+ this.#encryptedBuffer = Buffer.alloc(0);
181
324
  this.#buffer = Buffer.alloc(0);
182
325
  const err = /* @__PURE__ */ new Error("Buffer overflow: exceeded maximum buffer size");
183
326
  for (const [cseq, { reject }] of this.#requests) {
@@ -187,9 +330,10 @@ var RtspClient = class extends Connection {
187
330
  this.emit("error", err);
188
331
  return;
189
332
  }
190
- const transformed = this.transformIncoming(this.#buffer);
333
+ const transformed = this.transformIncoming(this.#encryptedBuffer);
191
334
  if (transformed === false) return;
192
- this.#buffer = transformed;
335
+ this.#encryptedBuffer = Buffer.alloc(0);
336
+ this.#buffer = Buffer.concat([this.#buffer, transformed]);
193
337
  while (this.#buffer.byteLength > 0) {
194
338
  const result = parseResponse(this.#buffer);
195
339
  if (result === null) return;
@@ -203,24 +347,33 @@ var RtspClient = class extends Connection {
203
347
  } else this.context.logger.warn("[rtsp]", `Unexpected response for CSeq ${cseq}`);
204
348
  }
205
349
  } catch (err) {
206
- this.context.logger.error("[rtsp]", "#onData()", err);
350
+ this.context.logger.error("[rtsp]", "onRtspData()", err);
207
351
  this.emit("error", err);
208
352
  }
209
353
  }
210
- #onError(err) {
354
+ /**
355
+ * Handles socket error events by rejecting all pending requests with the error.
356
+ *
357
+ * @param err - The error that occurred on the socket.
358
+ */
359
+ onRtspError(err) {
211
360
  for (const [cseq, { reject }] of this.#requests) {
212
361
  reject(err);
213
362
  this.#requests.delete(cseq);
214
363
  }
215
- this.context.logger.error("[rtsp]", "#onError()", err);
364
+ this.context.logger.error("[rtsp]", "onRtspError()", err);
216
365
  }
217
- #onTimeout() {
366
+ /**
367
+ * Handles socket timeout events by rejecting all pending requests with a
368
+ * {@link ConnectionTimeoutError}.
369
+ */
370
+ onRtspTimeout() {
218
371
  const err = new ConnectionTimeoutError();
219
372
  for (const [cseq, { reject }] of this.#requests) {
220
373
  reject(err);
221
374
  this.#requests.delete(cseq);
222
375
  }
223
- this.context.logger.net("[rtsp]", "#onTimeout()");
376
+ this.context.logger.net("[rtsp]", "onRtspTimeout()");
224
377
  }
225
378
  };
226
379
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@basmilius/apple-rtsp",
3
3
  "description": "RTSP protocol implementation for Apple Protocols.",
4
- "version": "0.9.19",
4
+ "version": "0.10.1",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "author": {
@@ -42,8 +42,8 @@
42
42
  }
43
43
  },
44
44
  "dependencies": {
45
- "@basmilius/apple-common": "0.9.19",
46
- "@basmilius/apple-encoding": "0.9.19"
45
+ "@basmilius/apple-common": "0.10.1",
46
+ "@basmilius/apple-encoding": "0.10.1"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@types/bun": "^1.3.11",