opcjs-base 0.1.29-alpha → 0.1.32-alpha

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.cjs CHANGED
@@ -2932,12 +2932,22 @@ var SecureChannelTypeEncoder = class extends TransformStream {
2932
2932
  }
2933
2933
  };
2934
2934
 
2935
+ // src/secureChannel/messages/msgType.ts
2936
+ var MsgTypeOpenFinal = "O".charCodeAt(0) | "P".charCodeAt(0) << 8 | "N".charCodeAt(0) << 16 | "F".charCodeAt(0) << 24;
2937
+ var MsgTypeOpenChunk = "O".charCodeAt(0) | "P".charCodeAt(0) << 8 | "N".charCodeAt(0) << 16 | "C".charCodeAt(0) << 24;
2938
+ var MsgTypeAbort = "M".charCodeAt(0) | "S".charCodeAt(0) << 8 | "G".charCodeAt(0) << 16 | "A".charCodeAt(0) << 24;
2939
+ var MsgTypeChunk = "M".charCodeAt(0) | "S".charCodeAt(0) << 8 | "G".charCodeAt(0) << 16 | "C".charCodeAt(0) << 24;
2940
+ var MsgTypeFinal = "M".charCodeAt(0) | "S".charCodeAt(0) << 8 | "G".charCodeAt(0) << 16 | "F".charCodeAt(0) << 24;
2941
+ var MsgTypeCloseFinal = "C".charCodeAt(0) | "L".charCodeAt(0) << 8 | "O".charCodeAt(0) << 16 | "F".charCodeAt(0) << 24;
2942
+
2935
2943
  // src/secureChannel/secureChannelTypeDecoder.ts
2936
2944
  var SecureChannelTypeDecoder = class extends TransformStream {
2937
2945
  constructor(decoder) {
2938
2946
  super({
2939
2947
  transform(msg, controller) {
2940
- msg.body = decoder.decode(msg.body, "binary");
2948
+ if (msg.header.msgType !== MsgTypeAbort) {
2949
+ msg.body = decoder.decode(msg.body, "binary");
2950
+ }
2941
2951
  controller.enqueue(msg);
2942
2952
  }
2943
2953
  });
@@ -17399,13 +17409,6 @@ var MsgSymmetric = class _MsgSymmetric extends MsgBase2 {
17399
17409
  }
17400
17410
  };
17401
17411
 
17402
- // src/secureChannel/messages/msgType.ts
17403
- var MsgTypeOpenFinal = "O".charCodeAt(0) | "P".charCodeAt(0) << 8 | "N".charCodeAt(0) << 16 | "F".charCodeAt(0) << 24;
17404
- var MsgTypeAbort = "M".charCodeAt(0) | "S".charCodeAt(0) << 8 | "G".charCodeAt(0) << 16 | "A".charCodeAt(0) << 24;
17405
- var MsgTypeChunk = "M".charCodeAt(0) | "S".charCodeAt(0) << 8 | "G".charCodeAt(0) << 16 | "C".charCodeAt(0) << 24;
17406
- var MsgTypeFinal = "M".charCodeAt(0) | "S".charCodeAt(0) << 8 | "G".charCodeAt(0) << 16 | "F".charCodeAt(0) << 24;
17407
- var MsgTypeCloseFinal = "C".charCodeAt(0) | "L".charCodeAt(0) << 8 | "O".charCodeAt(0) << 16 | "F".charCodeAt(0) << 24;
17408
-
17409
17412
  // src/secureChannel/pendingRequests.ts
17410
17413
  var PendingRequests = class {
17411
17414
  map = /* @__PURE__ */ new Map();
@@ -17457,6 +17460,7 @@ var Certificate = class {
17457
17460
  };
17458
17461
 
17459
17462
  // src/secureChannel/secureChannelFacade.ts
17463
+ var TOKEN_RENEW_FRACTION = 0.75;
17460
17464
  var SecureChannelFacade = class {
17461
17465
  // ─── Constructor ────────────────────────────────────────────────────────────────
17462
17466
  constructor(context, readerTransform, writerTransform) {
@@ -17471,11 +17475,17 @@ var SecureChannelFacade = class {
17471
17475
  logger = getLogger("secureChannel.SecureChannelFacade");
17472
17476
  writer;
17473
17477
  reader;
17478
+ /** Timer handle for the scheduled token renewal; undefined when no renewal is pending. */
17479
+ renewalTimer;
17474
17480
  /**
17475
- * Sends the OpenSecureChannel request and resolves once the server replies.
17476
- * Updates `context.channelId` and `context.tokenId` on success.
17481
+ * Builds and sends an OpenSecureChannel request.
17482
+ * Called for both the initial Issue and subsequent Renew requests.
17483
+ *
17484
+ * On success the context `channelId` and `tokenId` are updated and a new
17485
+ * renewal is scheduled at 75 % of the server-revised token lifetime, per
17486
+ * OPC UA Part 4 Section 5.4.1 / Part 6 Section 6.7.3.
17477
17487
  */
17478
- async openSecureChannel() {
17488
+ async sendOpenSecureChannel(requestType) {
17479
17489
  const requestHeader = new RequestHeader();
17480
17490
  requestHeader.authenticationToken = NodeId.newTwoByte(0);
17481
17491
  requestHeader.timestamp = /* @__PURE__ */ new Date();
@@ -17487,31 +17497,72 @@ var SecureChannelFacade = class {
17487
17497
  const request = new OpenSecureChannelRequest();
17488
17498
  request.requestHeader = requestHeader;
17489
17499
  request.clientProtocolVersion = 0;
17490
- request.requestType = 0 /* Issue */;
17500
+ request.requestType = requestType;
17491
17501
  request.securityMode = this.context.securityPolicy.getSecurityMode();
17492
17502
  request.clientNonce = null;
17493
17503
  request.requestedLifetime = 36e5;
17494
17504
  const { sequenceNumber, requestId } = this.context.nextIds();
17495
- this.context.securityAlgorithm = this.context.securityPolicy.getAlgorithmAsymmetric(new Uint8Array(), new Uint8Array());
17505
+ this.context.securityAlgorithm = this.context.securityPolicy.getAlgorithmAsymmetric(
17506
+ new Uint8Array(),
17507
+ new Uint8Array()
17508
+ );
17496
17509
  const msg = new MsgAsymmetric(
17497
- new MsgHeader2(MsgTypeOpenFinal, 0, 0),
17510
+ new MsgHeader2(MsgTypeOpenFinal, 0, this.context.channelId),
17498
17511
  new MsgSecurityHeaderAsymmetric(
17499
17512
  "http://opcfoundation.org/UA/SecurityPolicy#None"
17500
17513
  ),
17501
17514
  new MsgSequenceHeader(sequenceNumber, requestId),
17502
17515
  request
17503
17516
  );
17504
- this.logger.debug("Sending OpenSecureChannelRequest...");
17505
- return this.pushMessage(msg).then((response) => {
17506
- const openResponse = response;
17507
- this.logger.debug("OpenSecureChannelResponse received");
17508
- this.context.channelId = openResponse.securityToken?.channelId;
17509
- this.context.tokenId = openResponse.securityToken?.tokenId;
17510
- this.context.securityAlgorithm = this.context.securityPolicy.getAlgorithmSymmetric(
17511
- new Certificate(),
17512
- new Certificate()
17513
- );
17514
- });
17517
+ const response = await this.pushMessage(msg);
17518
+ this.context.channelId = response.securityToken?.channelId;
17519
+ this.context.tokenId = response.securityToken?.tokenId;
17520
+ this.context.securityAlgorithm = this.context.securityPolicy.getAlgorithmSymmetric(
17521
+ new Certificate(),
17522
+ new Certificate()
17523
+ );
17524
+ const revisedLifetimeMs = response.securityToken?.revisedLifetime;
17525
+ this.scheduleRenewal(revisedLifetimeMs);
17526
+ }
17527
+ /**
17528
+ * Schedules a proactive token renewal at {@link TOKEN_RENEW_FRACTION} of
17529
+ * `lifetimeMs`. Any previously scheduled renewal is cancelled first.
17530
+ */
17531
+ scheduleRenewal(lifetimeMs) {
17532
+ if (this.renewalTimer !== void 0) {
17533
+ clearTimeout(this.renewalTimer);
17534
+ }
17535
+ const delayMs = Math.floor(lifetimeMs * TOKEN_RENEW_FRACTION);
17536
+ this.logger.debug(
17537
+ `Scheduling SecurityToken renewal in ${delayMs} ms (75 % of ${lifetimeMs} ms lifetime).`
17538
+ );
17539
+ this.renewalTimer = setTimeout(() => {
17540
+ this.renewalTimer = void 0;
17541
+ this.logger.info("Renewing SecurityToken...");
17542
+ this.sendOpenSecureChannel(1 /* Renew */).catch((err) => {
17543
+ this.logger.error("SecurityToken renewal failed:", err);
17544
+ });
17545
+ }, delayMs);
17546
+ }
17547
+ /**
17548
+ * Sends the initial OpenSecureChannel request and resolves once the server
17549
+ * replies. Updates `context.channelId` and `context.tokenId` on success
17550
+ * and schedules automatic renewal at 75 % of the token lifetime.
17551
+ */
17552
+ openSecureChannel() {
17553
+ this.logger.debug("Sending OpenSecureChannelRequest (Issue)...");
17554
+ return this.sendOpenSecureChannel(0 /* Issue */);
17555
+ }
17556
+ /**
17557
+ * Cancels any pending token renewal timer and releases the stream writer.
17558
+ * Call this when the secure channel is no longer needed.
17559
+ */
17560
+ close() {
17561
+ if (this.renewalTimer !== void 0) {
17562
+ clearTimeout(this.renewalTimer);
17563
+ this.renewalTimer = void 0;
17564
+ }
17565
+ this.writer.releaseLock();
17515
17566
  }
17516
17567
  // ─── ISecureChannel implementation ─────────────────────────────────────────────
17517
17568
  getSecurityPolicy() {
@@ -17548,14 +17599,20 @@ var SecureChannelFacade = class {
17548
17599
  if (!value) {
17549
17600
  this.logger.error("Received empty frame");
17550
17601
  }
17551
- const response = value.body;
17552
- if (response instanceof ServiceFault) {
17553
- this.pending.failAll(
17554
- // todo: create a human readable error message based on the ServiceFault content
17555
- new Error(`ServiceFault: ${JSON.stringify(response)}`)
17556
- );
17602
+ const requestId = value.sequenceHeader.requestId;
17603
+ if (value.header.msgType === MsgTypeAbort) {
17604
+ const reader = new BinaryReader(value.body);
17605
+ const statusCode = reader.readUInt32();
17606
+ const reason = reader.readString();
17607
+ this.context.chunkBuffers.delete(requestId);
17608
+ this.pending.fail(requestId, new Error(`Abort 0x${statusCode.toString(16).toUpperCase()}: ${reason}`));
17557
17609
  } else {
17558
- this.pending.settle(value.sequenceHeader.requestId, response);
17610
+ const response = value.body;
17611
+ if (response instanceof ServiceFault) {
17612
+ this.pending.fail(requestId, new Error(`ServiceFault: ${JSON.stringify(response)}`));
17613
+ } else {
17614
+ this.pending.settle(requestId, response);
17615
+ }
17559
17616
  }
17560
17617
  }
17561
17618
  } catch (e) {
@@ -17686,33 +17743,67 @@ var SecurityPolicyNone = class {
17686
17743
  };
17687
17744
 
17688
17745
  // src/secureChannel/secureChannelContext.ts
17689
- var INT32_MAX = 2147483647;
17746
+ var SEQ_WRAP_THRESHOLD = 4294967295 - 1024;
17747
+ var SEQ_WRAP_START = 1;
17690
17748
  var SecureChannelContext = class {
17691
17749
  constructor(endpointUrl) {
17692
17750
  this.endpointUrl = endpointUrl;
17693
17751
  }
17694
- sequenceNumber = 0;
17695
- requestNumber = 1;
17752
+ /**
17753
+ * Next outgoing sequence number. Starts at 1 for non-ECC legacy profiles
17754
+ * per OPC UA Part 6, Section 6.7.2.4. The value 0 is used only as the
17755
+ * LastSequenceNumber sentinel in the OPN request ("no prior sequence").
17756
+ */
17757
+ sequenceNumber = 1;
17758
+ /** Next outgoing request ID. The value 0 is reserved and must be skipped. */
17759
+ requestId = 1;
17696
17760
  channelId = 0;
17697
17761
  tokenId = 0;
17698
- maxSendBufferSize = INT32_MAX;
17699
- maxRecvBufferSize = INT32_MAX;
17700
- chunkBuffers = [];
17762
+ maxSendBufferSize = 2147483647;
17763
+ maxRecvBufferSize = 2147483647;
17764
+ /** Pending chunk bodies keyed by requestId, for reassembling multi-chunk messages. */
17765
+ chunkBuffers = /* @__PURE__ */ new Map();
17701
17766
  securityAlgorithm;
17767
+ /** Last remote sequence number seen; undefined before the first received message. */
17768
+ lastRemoteSequenceNumber = void 0;
17702
17769
  securityPolicy = new SecurityPolicyNone();
17703
17770
  /**
17704
- * Atomically increments and returns the next sequence number and request id.
17705
- * Call once per outgoing message so both counters stay in sync.
17771
+ * Returns the current outgoing sequence number then advances it with
17772
+ * UInt32 wrap-around per OPC UA Part 6, Section 6.7.2.4. Only advances
17773
+ * the sequence counter — use when creating additional chunks for the same
17774
+ * message (each chunk needs its own sequence number but the same requestId).
17775
+ */
17776
+ nextSequenceNumber() {
17777
+ const seq = this.sequenceNumber;
17778
+ if (this.sequenceNumber >= SEQ_WRAP_THRESHOLD) {
17779
+ this.sequenceNumber = SEQ_WRAP_START;
17780
+ } else {
17781
+ this.sequenceNumber++;
17782
+ }
17783
+ return seq;
17784
+ }
17785
+ /**
17786
+ * Returns the next outgoing sequence number and request ID, then advances
17787
+ * both counters. Call once per outgoing message; use {@link nextSequenceNumber}
17788
+ * for additional chunks of the same message.
17789
+ *
17790
+ * Handles UInt32 wrap-around per OPC UA Part 6, Section 6.7.2.4:
17791
+ * sequence numbers reset to 1 after reaching 0xFFFFFFFF-1024; request IDs
17792
+ * skip the reserved value 0 on wrap.
17706
17793
  */
17707
17794
  nextIds() {
17708
- return {
17709
- sequenceNumber: this.sequenceNumber++,
17710
- requestId: this.requestNumber++
17711
- };
17795
+ const result = { sequenceNumber: this.nextSequenceNumber(), requestId: this.requestId };
17796
+ this.requestId++;
17797
+ if (this.requestId === 0) {
17798
+ this.requestId = 1;
17799
+ }
17800
+ return result;
17712
17801
  }
17713
17802
  };
17714
17803
 
17715
17804
  // src/secureChannel/secureChannelMessageDecoder.ts
17805
+ var SEQ_WRAP_THRESHOLD2 = 4294967295 - 1024;
17806
+ var SEQ_WRAP_MAX = 1024;
17716
17807
  var SecureChannelMessageDecoder = class extends TransformStream {
17717
17808
  constructor(context) {
17718
17809
  super({
@@ -17721,12 +17812,34 @@ var SecureChannelMessageDecoder = class extends TransformStream {
17721
17812
  this.context = context;
17722
17813
  }
17723
17814
  logger = getLogger("secureChannel.SecureChannelMessageDecoder");
17815
+ /**
17816
+ * Validates that `sequenceNumber` is strictly increasing from the last
17817
+ * seen remote sequence. Allows exactly one UInt32 wrap-around per token.
17818
+ * Returns false and logs an error if the number is a duplicate or out of order.
17819
+ */
17820
+ validateSequenceNumber(sequenceNumber, controller) {
17821
+ const last = this.context.lastRemoteSequenceNumber;
17822
+ if (last === void 0) {
17823
+ this.context.lastRemoteSequenceNumber = sequenceNumber;
17824
+ return true;
17825
+ }
17826
+ const isIncrement = sequenceNumber === last + 1;
17827
+ const isWrap = last >= SEQ_WRAP_THRESHOLD2 && sequenceNumber < SEQ_WRAP_MAX;
17828
+ if (!isIncrement && !isWrap) {
17829
+ this.logger.error(`Invalid remote sequence number: expected ${last + 1}, got ${sequenceNumber}`);
17830
+ controller.error(new Error(`Invalid remote sequence number: expected ${last + 1}, got ${sequenceNumber}`));
17831
+ return false;
17832
+ }
17833
+ this.context.lastRemoteSequenceNumber = sequenceNumber;
17834
+ return true;
17835
+ }
17724
17836
  transform(data, controller) {
17725
17837
  const buffer = new BinaryReader(data);
17726
17838
  const header = MsgHeader2.decode(buffer);
17727
17839
  switch (header.msgType) {
17728
- case MsgTypeOpenFinal: {
17729
- this.logger.debug("SecureChannel received OpenFinal message");
17840
+ case MsgTypeOpenFinal:
17841
+ case MsgTypeOpenChunk: {
17842
+ this.logger.debug("SecureChannel received OpenFinal/OpenChunk message");
17730
17843
  const secHeader = MsgSecurityHeaderAsymmetric.decode(buffer);
17731
17844
  const msgAsym = MsgAsymmetric.decode(
17732
17845
  buffer,
@@ -17734,16 +17847,22 @@ var SecureChannelMessageDecoder = class extends TransformStream {
17734
17847
  secHeader,
17735
17848
  this.context.securityAlgorithm
17736
17849
  );
17850
+ if (!this.validateSequenceNumber(msgAsym.sequenceHeader.sequenceNumber, controller)) return;
17737
17851
  controller.enqueue(msgAsym);
17738
17852
  break;
17739
17853
  }
17740
- case MsgTypeAbort:
17741
- this.logger.warn("Unimplemented Abort message");
17854
+ case MsgTypeAbort: {
17855
+ this.logger.warn("SecureChannel received Abort message");
17856
+ const secHeader = MsgSecurityHeaderSymmetric.decode(buffer);
17857
+ const msgSym = MsgSymmetric.decode(buffer, header, secHeader, this.context.securityAlgorithm);
17858
+ controller.enqueue(msgSym);
17742
17859
  break;
17860
+ }
17743
17861
  case MsgTypeChunk: {
17744
17862
  this.logger.debug("SecureChannel received Chunk message.");
17745
17863
  const secHeader = MsgSecurityHeaderSymmetric.decode(buffer);
17746
17864
  const msgSym = MsgSymmetric.decode(buffer, header, secHeader, this.context.securityAlgorithm);
17865
+ if (!this.validateSequenceNumber(msgSym.sequenceHeader.sequenceNumber, controller)) return;
17747
17866
  controller.enqueue(msgSym);
17748
17867
  break;
17749
17868
  }
@@ -17751,11 +17870,12 @@ var SecureChannelMessageDecoder = class extends TransformStream {
17751
17870
  this.logger.debug("SecureChannel received Final message");
17752
17871
  const secHeader = MsgSecurityHeaderSymmetric.decode(buffer);
17753
17872
  const msgSym = MsgSymmetric.decode(buffer, header, secHeader, this.context.securityAlgorithm);
17873
+ if (!this.validateSequenceNumber(msgSym.sequenceHeader.sequenceNumber, controller)) return;
17754
17874
  controller.enqueue(msgSym);
17755
17875
  break;
17756
17876
  }
17757
17877
  case MsgTypeCloseFinal:
17758
- this.logger.warn("Unimplemented CloseFinal message. ");
17878
+ this.logger.warn("Unimplemented CloseFinal message.");
17759
17879
  break;
17760
17880
  default:
17761
17881
  this.logger.warn("SecureChannel received unknown message type:", header.msgType);
@@ -17765,7 +17885,7 @@ var SecureChannelMessageDecoder = class extends TransformStream {
17765
17885
  };
17766
17886
 
17767
17887
  // src/secureChannel/secureChannelMessageEncoder.ts
17768
- var SecureChannelMesssageEncoder = class extends TransformStream {
17888
+ var SecureChannelMessageEncoder = class extends TransformStream {
17769
17889
  constructor(context) {
17770
17890
  super({
17771
17891
  transform(msg, controller) {
@@ -17780,24 +17900,33 @@ var SecureChannelMesssageEncoder = class extends TransformStream {
17780
17900
  // src/secureChannel/secureChannelChunkReader.ts
17781
17901
  var SecureChannelChunkReader = class extends TransformStream {
17782
17902
  logger = getLogger("secureChannel.SecureChannelChunkReader");
17783
- prependChunk(chunk, body) {
17784
- const result = new Uint8Array(chunk.byteLength + body.byteLength);
17785
- result.set(chunk, 0);
17786
- result.set(body, chunk.byteLength);
17787
- return result;
17788
- }
17789
17903
  transform(msg, context, controller) {
17904
+ const requestId = msg.sequenceHeader.requestId;
17790
17905
  switch (msg.header.msgType) {
17791
- case MsgTypeChunk: {
17906
+ case MsgTypeChunk:
17907
+ case MsgTypeOpenChunk: {
17792
17908
  this.logger.debug("Received Chunk message");
17793
- context.chunkBuffers.push(msg.body);
17909
+ const chunks = context.chunkBuffers.get(requestId) ?? [];
17910
+ chunks.push(msg.body);
17911
+ context.chunkBuffers.set(requestId, chunks);
17794
17912
  break;
17795
17913
  }
17796
- case MsgTypeFinal: {
17914
+ case MsgTypeFinal:
17915
+ case MsgTypeOpenFinal: {
17797
17916
  this.logger.debug("Received Final message");
17798
- while (context.chunkBuffers.length > 0) {
17799
- const chunk = context.chunkBuffers.pop();
17800
- msg.body = this.prependChunk(chunk, msg.body);
17917
+ const chunks = context.chunkBuffers.get(requestId);
17918
+ if (chunks && chunks.length > 0) {
17919
+ const finalBody = msg.body;
17920
+ const totalLength = chunks.reduce((sum, c) => sum + c.byteLength, 0) + finalBody.byteLength;
17921
+ const assembled = new Uint8Array(totalLength);
17922
+ let offset = 0;
17923
+ for (const chunk of chunks) {
17924
+ assembled.set(chunk, offset);
17925
+ offset += chunk.byteLength;
17926
+ }
17927
+ assembled.set(finalBody, offset);
17928
+ msg.body = assembled;
17929
+ context.chunkBuffers.delete(requestId);
17801
17930
  }
17802
17931
  controller.enqueue(msg);
17803
17932
  break;
@@ -17831,29 +17960,39 @@ var SecureChannelChunkWriter = class extends TransformStream {
17831
17960
  this.logger.debug("Received Final message");
17832
17961
  const securityAlgorithm = this.context.securityAlgorithm;
17833
17962
  const maxCipherTextSize = this.context.maxSendBufferSize - MsgHeader2.Size - MsgSecurityHeaderSymmetric.Size;
17834
- const maxPlainTextSize = maxCipherTextSize / securityAlgorithm.GetEncryptedSize(maxCipherTextSize);
17835
- const maxPayloadSize = maxPlainTextSize - securityAlgorithm.GetSignatureLength() - 1 - MsgSecurityHeaderSymmetric.Size + (securityAlgorithm.IsAuthenticated() ? 1 : 0);
17963
+ const maxPayloadSize = securityAlgorithm.GetMaxPayload(maxCipherTextSize) - MsgSequenceHeader.Size;
17836
17964
  const data = msgSymmetric.body;
17837
- const chunkCount = data.byteLength / maxPayloadSize;
17838
- if (chunkCount > 1) {
17839
- this.logger.debug(`Message body exceeds max chunk size, splitting into ${chunkCount} chunks.`);
17840
- for (let i = 0; i < chunkCount; i++) {
17965
+ const numChunks = Math.ceil(data.byteLength / maxPayloadSize);
17966
+ if (numChunks > 1) {
17967
+ this.logger.debug(`Message body exceeds max chunk size, splitting into ${numChunks} chunks.`);
17968
+ for (let i = 0; i < numChunks - 1; i++) {
17841
17969
  const chunkMsg = new MsgSymmetric(
17842
- new MsgHeader2(MsgTypeChunk, -1, msgSymmetric.header.secureChannelId),
17970
+ // messageSize=0 is a placeholder: MsgBase.Encrypt() overwrites it at byte offset 4
17971
+ // with the actual encrypted size before writing to the wire.
17972
+ new MsgHeader2(MsgTypeChunk, 0, msgSymmetric.header.secureChannelId),
17843
17973
  msgSymmetric.securityHeader,
17844
- msgSymmetric.sequenceHeader,
17974
+ new MsgSequenceHeader(
17975
+ this.context.nextSequenceNumber(),
17976
+ msgSymmetric.sequenceHeader.requestId
17977
+ ),
17845
17978
  data.subarray(i * maxPayloadSize, (i + 1) * maxPayloadSize)
17846
17979
  );
17847
- this.logger.trace(`Enqueuing chunk ${i + 1}/${chunkCount} with size ${chunkMsg.body.byteLength} bytes.`);
17980
+ this.logger.trace(
17981
+ `Enqueuing chunk ${i + 1}/${numChunks} with size ${chunkMsg.body.byteLength} bytes.`
17982
+ );
17848
17983
  controller.enqueue(chunkMsg);
17849
17984
  }
17850
- msg.body = data.subarray(chunkCount * maxPayloadSize);
17985
+ msg.sequenceHeader = new MsgSequenceHeader(
17986
+ this.context.nextSequenceNumber(),
17987
+ msgSymmetric.sequenceHeader.requestId
17988
+ );
17989
+ msg.body = data.subarray((numChunks - 1) * maxPayloadSize);
17851
17990
  }
17852
17991
  break;
17853
17992
  }
17854
17993
  }
17855
17994
  }
17856
- this.logger.trace(`Enqueuing message default message with body size ${msg.body.byteLength} bytes.`);
17995
+ this.logger.trace(`Enqueuing final message with body size ${msg.body.byteLength} bytes.`);
17857
17996
  controller.enqueue(msg);
17858
17997
  }
17859
17998
  };
@@ -18196,7 +18335,7 @@ exports.SecureChannelChunkWriter = SecureChannelChunkWriter;
18196
18335
  exports.SecureChannelContext = SecureChannelContext;
18197
18336
  exports.SecureChannelFacade = SecureChannelFacade;
18198
18337
  exports.SecureChannelMessageDecoder = SecureChannelMessageDecoder;
18199
- exports.SecureChannelMesssageEncoder = SecureChannelMesssageEncoder;
18338
+ exports.SecureChannelMessageEncoder = SecureChannelMessageEncoder;
18200
18339
  exports.SecureChannelTypeDecoder = SecureChannelTypeDecoder;
18201
18340
  exports.SecureChannelTypeEncoder = SecureChannelTypeEncoder;
18202
18341
  exports.SecurityGroupDataType = SecurityGroupDataType;