@apocaliss92/nodelink-js 0.4.1 → 0.4.2

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.
@@ -3,7 +3,7 @@ import {
3
3
  BaichuanRtspServer,
4
4
  ReolinkBaichuanApi,
5
5
  autoDetectDeviceType
6
- } from "../chunk-SDRNJQ5U.js";
6
+ } from "../chunk-TJNPGYJA.js";
7
7
  import {
8
8
  __require
9
9
  } from "../chunk-DUHWTZ7U.js";
package/dist/index.cjs CHANGED
@@ -13410,6 +13410,7 @@ var BaichuanRtspServer = class _BaichuanRtspServer extends import_node_events4.E
13410
13410
  flow;
13411
13411
  deviceId;
13412
13412
  dedicatedSessionRelease;
13413
+ externalListener;
13413
13414
  // Authentication
13414
13415
  authCredentials = [];
13415
13416
  requireAuth;
@@ -13577,6 +13578,7 @@ var BaichuanRtspServer = class _BaichuanRtspServer extends import_node_events4.E
13577
13578
  this.logger = options.logger ?? console;
13578
13579
  this.tcpRtpFraming = options.tcpRtpFraming ?? "rfc4571";
13579
13580
  this.deviceId = options.deviceId;
13581
+ this.externalListener = options.externalListener ?? false;
13580
13582
  this.authCredentials = options.credentials ?? [];
13581
13583
  this.requireAuth = options.requireAuth ?? this.authCredentials.length > 0;
13582
13584
  const transport = this.api.client.getTransport();
@@ -13707,41 +13709,56 @@ var BaichuanRtspServer = class _BaichuanRtspServer extends import_node_events4.E
13707
13709
  this.streamMetadata = { frameRate: 25 };
13708
13710
  this.setFlowVideoType("H264", "metadata unavailable");
13709
13711
  }
13710
- this.clientConnectionServer = net2.createServer((socket) => {
13711
- this.handleRtspConnection(socket);
13712
- });
13713
- await new Promise((resolve, reject) => {
13714
- this.clientConnectionServer.listen(
13715
- this.listenPort,
13716
- this.listenHost,
13717
- () => {
13718
- const address = this.clientConnectionServer.address();
13719
- if (address && typeof address === "object" && "port" in address) {
13720
- this.listenPort = address.port;
13712
+ if (!this.externalListener) {
13713
+ this.clientConnectionServer = net2.createServer((socket) => {
13714
+ this.handleRtspConnection(socket);
13715
+ });
13716
+ await new Promise((resolve, reject) => {
13717
+ this.clientConnectionServer.listen(
13718
+ this.listenPort,
13719
+ this.listenHost,
13720
+ () => {
13721
+ const address = this.clientConnectionServer.address();
13722
+ if (address && typeof address === "object" && "port" in address) {
13723
+ this.listenPort = address.port;
13724
+ }
13725
+ resolve();
13721
13726
  }
13722
- resolve();
13723
- }
13724
- );
13725
- this.clientConnectionServer.on("error", (error) => {
13726
- reject(error);
13727
+ );
13728
+ this.clientConnectionServer.on("error", (error) => {
13729
+ reject(error);
13730
+ });
13727
13731
  });
13728
- });
13732
+ }
13729
13733
  this.active = true;
13730
13734
  this.logger.info(
13731
13735
  `[BaichuanRtspServer] RTSP server started on ${this.listenHost}:${this.listenPort}, path: ${this.path}`
13732
13736
  );
13733
13737
  }
13738
+ /**
13739
+ * Accept an externally-routed RTSP connection.
13740
+ * Used in directHandoff mode where RtspProxyServer routes sockets here.
13741
+ * @param socket - The client TCP socket (already authenticated by proxy)
13742
+ * @param initialBuffer - Any bytes already read during path parsing/auth
13743
+ */
13744
+ acceptConnection(socket, initialBuffer) {
13745
+ if (!this.active) {
13746
+ socket.end("RTSP/1.0 503 Service Unavailable\r\n\r\n");
13747
+ return;
13748
+ }
13749
+ this.handleRtspConnection(socket, initialBuffer);
13750
+ }
13734
13751
  /**
13735
13752
  * Handle RTSP connection from a client.
13736
13753
  */
13737
- handleRtspConnection(socket) {
13754
+ handleRtspConnection(socket, initialBuffer) {
13738
13755
  const clientId = `${socket.remoteAddress}:${socket.remotePort}`;
13739
13756
  const connectTime = Date.now();
13740
13757
  this.logger.info(
13741
13758
  `[rebroadcast] client connected client=${clientId} path=${this.path} profile=${this.profile} channel=${this.channel}`
13742
13759
  );
13743
13760
  let sessionId = "";
13744
- let buffer = Buffer.alloc(0);
13761
+ let buffer = initialBuffer ?? Buffer.alloc(0);
13745
13762
  let clientFfmpeg;
13746
13763
  let useTcpInterleaved = false;
13747
13764
  let clientUdpSocket = null;
@@ -13826,8 +13843,7 @@ var BaichuanRtspServer = class _BaichuanRtspServer extends import_node_events4.E
13826
13843
  }
13827
13844
  cleanup();
13828
13845
  });
13829
- socket.on("data", async (data) => {
13830
- buffer = Buffer.concat([buffer, data]);
13846
+ const processBuffer = async () => {
13831
13847
  while (buffer.includes("\r\n\r\n")) {
13832
13848
  const endIndex = buffer.indexOf("\r\n\r\n");
13833
13849
  const requestText = buffer.subarray(0, endIndex).toString();
@@ -14102,7 +14118,14 @@ var BaichuanRtspServer = class _BaichuanRtspServer extends import_node_events4.E
14102
14118
  sendResponse(501, "Not Implemented");
14103
14119
  }
14104
14120
  }
14121
+ };
14122
+ socket.on("data", (data) => {
14123
+ buffer = Buffer.concat([buffer, data]);
14124
+ void processBuffer();
14105
14125
  });
14126
+ if (buffer.includes("\r\n\r\n")) {
14127
+ void processBuffer();
14128
+ }
14106
14129
  }
14107
14130
  /**
14108
14131
  * Generate SDP (Session Description Protocol) for RTSP DESCRIBE.
@@ -15070,21 +15093,27 @@ var BaichuanRtspServer = class _BaichuanRtspServer extends import_node_events4.E
15070
15093
  res.seenFirstVideoKeyframe = false;
15071
15094
  res.rtpSentVideoConfig = false;
15072
15095
  }
15073
- if (this.dedicatedSessionRelease) {
15074
- const release = this.dedicatedSessionRelease;
15075
- this.dedicatedSessionRelease = void 0;
15076
- release().catch(() => {
15077
- });
15078
- }
15079
15096
  this.logger.info(
15080
15097
  `[rebroadcast] native stream ended (camera sleeping or connection lost) profile=${this.profile} channel=${this.channel} clients=${this.connectedClients.size}`
15081
15098
  );
15082
- if (this.connectedClients.size > 0) {
15083
- this.logger.info(
15084
- `[rebroadcast] restarting native stream for ${this.connectedClients.size} active client(s)`
15085
- );
15086
- setImmediate(() => void this.startNativeStream());
15087
- }
15099
+ const releaseAndRestart = async () => {
15100
+ if (this.dedicatedSessionRelease) {
15101
+ const release = this.dedicatedSessionRelease;
15102
+ this.dedicatedSessionRelease = void 0;
15103
+ try {
15104
+ await release();
15105
+ } catch {
15106
+ }
15107
+ }
15108
+ if (this.connectedClients.size > 0) {
15109
+ this.logger.info(
15110
+ `[rebroadcast] restarting native stream for ${this.connectedClients.size} active client(s)`
15111
+ );
15112
+ await new Promise((r) => setTimeout(r, 500));
15113
+ void this.startNativeStream();
15114
+ }
15115
+ };
15116
+ void releaseAndRestart();
15088
15117
  }
15089
15118
  });
15090
15119
  this.nativeFanout.start();
@@ -15308,6 +15337,31 @@ var BaichuanRtspServer = class _BaichuanRtspServer extends import_node_events4.E
15308
15337
  getClientCount() {
15309
15338
  return this.connectedClients.size;
15310
15339
  }
15340
+ /**
15341
+ * Subscribe to the raw native stream for diagnostic purposes.
15342
+ * The subscriber receives the same frames as RTSP clients.
15343
+ * Counts as a "consumer" for lifecycle — prevents auto-stop while subscribed.
15344
+ * If the native stream is not active, starts it automatically.
15345
+ */
15346
+ async subscribeDiagnostic(id) {
15347
+ this.connectedClients.add(`diag:${id}`);
15348
+ if (!this.nativeStreamActive) {
15349
+ await this.startNativeStream();
15350
+ }
15351
+ return this.nativeFanout.subscribe(`diag:${id}`);
15352
+ }
15353
+ /**
15354
+ * Unsubscribe a diagnostic session.
15355
+ */
15356
+ unsubscribeDiagnostic(id) {
15357
+ this.removeClient(`diag:${id}`);
15358
+ }
15359
+ /**
15360
+ * Returns detected audio metadata (available after first audio frame).
15361
+ */
15362
+ getAudioInfo() {
15363
+ return this.audioInfo;
15364
+ }
15311
15365
  };
15312
15366
 
15313
15367
  // src/reolink/baichuan/ReolinkBaichuanApi.ts