APIs

Show:
"use strict";
/**
 * @module opcua.miscellaneous
 */

const assert = require("node-opcua-assert").assert;
const _ = require("underscore");

const BinaryStream = require("node-opcua-binary-stream").BinaryStream;
const ec = require("node-opcua-basic-types");

const SequenceNumberGenerator = require("./sequence_number_generator").SequenceNumberGenerator;


const AsymmetricAlgorithmSecurityHeader = require("node-opcua-service-secure-channel").AsymmetricAlgorithmSecurityHeader;
const SymmetricAlgorithmSecurityHeader = require("node-opcua-service-secure-channel").SymmetricAlgorithmSecurityHeader;

const SecureMessageChunkManager = require("./secure_message_chunk_manager").SecureMessageChunkManager;

/**
 * @class MessageChunker
 * @param options {Object}
 * @param options.securityHeader  {Object} SecurityHeader
 * @param [options.derivedKeys] {Object} derivedKeys
 * @constructor
 */
function MessageChunker(options) {

    this.sequenceNumberGenerator = new SequenceNumberGenerator();
    this.update(options);

}

MessageChunker.prototype.dispose = function() {

    this.sequenceNumberGenerator = null;
    this.securityHeader = null;
    this.derivedKeys = null;
    this._stream = null;
};

/** update security information
 * @method update
 * @param options {Object}
 * @param options.securityHeader  {Object} SecurityHeader
 * @param [options.derivedKeys] {Object} derivedKeys
 *
 */
MessageChunker.prototype.update = function(options) {

    options = options || {};
    options.securityHeader = options.securityHeader ||
        new AsymmetricAlgorithmSecurityHeader({securityPolicyUri: "http://opcfoundation.org/UA/SecurityPolicy#None"});

    assert(_.isObject(options));
    assert(_.isObject(options.securityHeader));

    this.securityHeader = options.securityHeader;
    this.derivedKeys = options.derivedKeys || null;
};

/**
 * @method chunkSecureMessage
 * @param msgType {String}
 * @param options
 * @param options.tokenId
 * @param options.chunkSize    [default=8192]
 *
 * @param options.signatureLength  {number} [default=0]
 * @param options.signingFunc {Function} [default=null]
 *
 * @param message {Object}
 * @param messageChunkCallback   {Function}
 */
MessageChunker.prototype.chunkSecureMessage = function (msgType, options, message, messageChunkCallback) {

    assert(_.isFunction(messageChunkCallback));

    // calculate message size ( with its  encodingDefaultBinary)
    const binSize = message.binaryStoreSize() + 4;
    
    const stream = new BinaryStream(binSize);
    this._stream = stream;

    ec.encodeExpandedNodeId(message.encodingDefaultBinary, stream);
    message.encode(stream);

    let securityHeader;
    if (msgType === "OPN") {
        securityHeader = this.securityHeader;
    } else {
        securityHeader = new SymmetricAlgorithmSecurityHeader({tokenId: options.tokenId});
    }

    const secure_chunker = new SecureMessageChunkManager(
        msgType, options, securityHeader, this.sequenceNumberGenerator
    )
        .on("chunk", function (messageChunk) {
            messageChunkCallback(messageChunk);
        })
        .on("finished", function () {
            messageChunkCallback(null);
        });

    secure_chunker.write(stream._buffer, stream._buffer.length);
    secure_chunker.end();
};

exports.MessageChunker = MessageChunker;