"use strict";
//
//  Copyright (c) Microsoft Corporation. All rights reserved.
//
Object.defineProperty(exports, "__esModule", { value: true });
exports.ChannelFailureMessage = exports.ChannelSuccessMessage = exports.ChannelSignalMessage = exports.CommandRequestMessage = exports.ChannelRequestMessage = exports.ChannelRequestType = exports.ChannelCloseMessage = exports.ChannelEofMessage = exports.ChannelExtendedDataMessage = exports.ChannelDataMessage = exports.ChannelWindowAdjustMessage = exports.ChannelOpenFailureMessage = exports.SshChannelOpenFailureReason = exports.ChannelOpenConfirmationMessage = exports.ChannelOpenMessage = exports.ChannelMessage = exports.ConnectionMessage = void 0;
const sshMessage_1 = require("./sshMessage");
const sshData_1 = require("../io/sshData");
class ConnectionMessage extends sshMessage_1.SshMessage {
}
exports.ConnectionMessage = ConnectionMessage;
class ChannelMessage extends ConnectionMessage {
    get recipientChannel() {
        return this.recipientChannelValue;
    }
    set recipientChannel(value) {
        if (value !== this.recipientChannelValue) {
            this.recipientChannelValue = value;
            if (this.rawBytes) {
                // The recipientChannel can be updated without re-serializing the message.
                // This supports piping channel messages with re-mapped channel IDs.
                // The recipientChannel field follows the 1-byte message type.
                sshData_1.SshDataWriter.writeUInt32(this.rawBytes, 1, value !== null && value !== void 0 ? value : 0);
            }
        }
    }
    onRead(reader) {
        this.recipientChannel = reader.readUInt32();
    }
    onWrite(writer) {
        writer.writeUInt32(this.validateField(this.recipientChannel, 'recipient channel'));
    }
    toString() {
        return `${super.toString()} (recipientChannel=${this.recipientChannel})`;
    }
}
exports.ChannelMessage = ChannelMessage;
class ChannelOpenMessage extends ConnectionMessage {
    get messageType() {
        return 90;
    }
    get senderChannel() {
        return this.senderChannelValue;
    }
    set senderChannel(value) {
        if (value !== this.senderChannelValue) {
            this.senderChannelValue = value;
            if (this.rawBytes && this.channelType) {
                // The senderChannel can be updated without re-serializing the message.
                // This supports piping channel messages with re-mapped channel IDs.
                // The senderChannel field follows the 1-byte message type and
                // length-prefixed channelType string.
                sshData_1.SshDataWriter.writeUInt32(this.rawBytes, 1 + 4 + this.channelType.length, value !== null && value !== void 0 ? value : 0);
            }
        }
    }
    onRead(reader) {
        this.channelType = reader.readString('ascii');
        this.senderChannel = reader.readUInt32();
        this.maxWindowSize = reader.readUInt32();
        this.maxPacketSize = reader.readUInt32();
    }
    onWrite(writer) {
        writer.writeString(this.validateField(this.channelType, 'channel type'), 'ascii');
        writer.writeUInt32(this.validateField(this.senderChannel, 'sender channel'));
        writer.writeUInt32(this.maxWindowSize || ChannelOpenMessage.defaultMaxWindowSize);
        writer.writeUInt32(this.maxPacketSize || ChannelOpenMessage.defaultMaxPacketSize);
    }
    toString() {
        return `${super.toString()}(channelType=${this.channelType}, senderChannel=${this.senderChannel})`;
    }
}
exports.ChannelOpenMessage = ChannelOpenMessage;
/* @internal */
ChannelOpenMessage.defaultMaxPacketSize = 32 * 1024;
/* @internal */
ChannelOpenMessage.defaultMaxWindowSize = 1024 * 1024;
class ChannelOpenConfirmationMessage extends ChannelMessage {
    get messageType() {
        return 91;
    }
    onRead(reader) {
        super.onRead(reader);
        this.senderChannel = reader.readUInt32();
        this.maxWindowSize = reader.readUInt32();
        this.maxPacketSize = reader.readUInt32();
    }
    onWrite(writer) {
        super.onWrite(writer);
        writer.writeUInt32(this.validateField(this.senderChannel, 'sender channel'));
        writer.writeUInt32(this.validateField(this.maxWindowSize, 'max window size'));
        writer.writeUInt32(this.validateField(this.maxPacketSize, 'max packet size'));
    }
    toString() {
        return `${super.toString()}(senderChannel=${this.senderChannel})`;
    }
}
exports.ChannelOpenConfirmationMessage = ChannelOpenConfirmationMessage;
var SshChannelOpenFailureReason;
(function (SshChannelOpenFailureReason) {
    SshChannelOpenFailureReason[SshChannelOpenFailureReason["none"] = 0] = "none";
    SshChannelOpenFailureReason[SshChannelOpenFailureReason["administrativelyProhibited"] = 1] = "administrativelyProhibited";
    SshChannelOpenFailureReason[SshChannelOpenFailureReason["connectFailed"] = 2] = "connectFailed";
    SshChannelOpenFailureReason[SshChannelOpenFailureReason["unknownChannelType"] = 3] = "unknownChannelType";
    SshChannelOpenFailureReason[SshChannelOpenFailureReason["resourceShortage"] = 4] = "resourceShortage";
})(SshChannelOpenFailureReason = exports.SshChannelOpenFailureReason || (exports.SshChannelOpenFailureReason = {}));
class ChannelOpenFailureMessage extends ChannelMessage {
    get messageType() {
        return 92;
    }
    onRead(reader) {
        super.onRead(reader);
        this.reasonCode = reader.readUInt32();
        this.description = reader.readString('utf8');
        this.language = reader.readString('ascii');
    }
    onWrite(writer) {
        super.onWrite(writer);
        writer.writeUInt32(this.validateField(this.reasonCode, 'reason code'));
        writer.writeString(this.description || '', 'utf8');
        writer.writeString(this.language || 'en', 'ascii');
    }
    toString() {
        return `${super.toString()} (${SshChannelOpenFailureReason[this.reasonCode || 0]}: ${this.description})`;
    }
}
exports.ChannelOpenFailureMessage = ChannelOpenFailureMessage;
class ChannelWindowAdjustMessage extends ChannelMessage {
    get messageType() {
        return 93;
    }
    onRead(reader) {
        super.onRead(reader);
        this.bytesToAdd = reader.readUInt32();
    }
    onWrite(writer) {
        super.onWrite(writer);
        writer.writeUInt32(this.validateField(this.bytesToAdd, 'bytes to add'));
    }
    toString() {
        return `${super.toString()} (bytesToAdd=${this.bytesToAdd})`;
    }
}
exports.ChannelWindowAdjustMessage = ChannelWindowAdjustMessage;
class ChannelDataMessage extends ChannelMessage {
    get messageType() {
        return 94;
    }
    onRead(reader) {
        super.onRead(reader);
        this.data = reader.readBinary();
    }
    onWrite(writer) {
        super.onWrite(writer);
        writer.writeBinary(this.validateField(this.data, 'data'));
    }
    toString() {
        return this.data ? (0, sshData_1.formatBuffer)(this.data, '') : '[0]';
    }
}
exports.ChannelDataMessage = ChannelDataMessage;
class ChannelExtendedDataMessage extends ChannelMessage {
    get messageType() {
        return 95;
    }
    onRead(reader) {
        super.onRead(reader);
        this.dataTypeCode = reader.readUInt32();
        this.data = reader.readBinary();
    }
    onWrite(writer) {
        super.onWrite(writer);
        writer.writeUInt32(this.validateField(this.dataTypeCode, 'data type code'));
        writer.writeBinary(this.validateField(this.data, 'data'));
    }
    toString() {
        return `${super.toString()} (dataTypeCode=${this.dataTypeCode}, data=${this.data ? (0, sshData_1.formatBuffer)(this.data, '') : '[0]'})`;
    }
}
exports.ChannelExtendedDataMessage = ChannelExtendedDataMessage;
class ChannelEofMessage extends ChannelMessage {
    get messageType() {
        return 96;
    }
}
exports.ChannelEofMessage = ChannelEofMessage;
class ChannelCloseMessage extends ChannelMessage {
    get messageType() {
        return 97;
    }
}
exports.ChannelCloseMessage = ChannelCloseMessage;
var ChannelRequestType;
(function (ChannelRequestType) {
    ChannelRequestType["command"] = "exec";
    ChannelRequestType["shell"] = "shell";
    ChannelRequestType["terminal"] = "pty-req";
    ChannelRequestType["signal"] = "signal";
    ChannelRequestType["exitSignal"] = "exit-signal";
    ChannelRequestType["exitStatus"] = "exit-status";
})(ChannelRequestType = exports.ChannelRequestType || (exports.ChannelRequestType = {}));
class ChannelRequestMessage extends ChannelMessage {
    constructor(requestType, wantReply) {
        super();
        this.requestType = requestType;
        this.wantReply = wantReply !== null && wantReply !== void 0 ? wantReply : false;
    }
    get messageType() {
        return 98;
    }
    onRead(reader) {
        super.onRead(reader);
        this.requestType = reader.readString('ascii');
        this.wantReply = reader.readBoolean();
    }
    onWrite(writer) {
        if (typeof this.recipientChannel === 'undefined') {
            // The recipient channel field may be uninitialized when sending a channel request
            // that is bundled with the channel-open request.
            this.recipientChannel = 0;
        }
        super.onWrite(writer);
        writer.writeString(this.validateField(this.requestType, 'request type'), 'ascii');
        writer.writeBoolean(this.wantReply);
    }
}
exports.ChannelRequestMessage = ChannelRequestMessage;
class CommandRequestMessage extends ChannelRequestMessage {
    constructor() {
        super();
        this.requestType = ChannelRequestType.command;
    }
    onRead(reader) {
        super.onRead(reader);
        this.command = reader.readString('utf8');
    }
    onWrite(writer) {
        super.onWrite(writer);
        writer.writeString(this.validateField(this.command, 'command'), 'utf8');
    }
    toString() {
        return `${super.toString()} (requestType=${this.requestType})`;
    }
}
exports.CommandRequestMessage = CommandRequestMessage;
class ChannelSignalMessage extends ChannelRequestMessage {
    constructor() {
        super();
    }
    get signal() {
        return this.signalValue;
    }
    set signal(value) {
        this.requestType = ChannelRequestType.signal;
        this.signalValue = value;
    }
    get exitSignal() {
        return this.signalValue;
    }
    set exitSignal(value) {
        this.requestType = ChannelRequestType.exitSignal;
        this.signalValue = value;
    }
    get errorMessage() {
        return this.errorMessageValue;
    }
    set errorMessage(value) {
        if (this.requestType !== ChannelRequestType.exitSignal) {
            throw new Error(`Error message property is only valid for ${ChannelRequestType.exitSignal} messages.`);
        }
        this.errorMessageValue = value;
    }
    get exitStatus() {
        return this.statusValue;
    }
    set exitStatus(value) {
        this.requestType = ChannelRequestType.exitStatus;
        this.statusValue = value;
    }
    onRead(reader) {
        super.onRead(reader);
        switch (this.requestType) {
            case ChannelRequestType.exitStatus:
                this.exitStatus = reader.readUInt32();
                break;
            case ChannelRequestType.signal:
                this.signal = reader.readString('ascii');
                break;
            case ChannelRequestType.exitSignal:
                this.exitSignal = reader.readString('ascii');
                reader.readBoolean(); // Core dumped
                this.errorMessage = reader.readString('utf8');
                reader.readString('ascii'); // Language tag
                break;
            default:
                break;
        }
    }
    onWrite(writer) {
        if (!this.requestType) {
            throw new Error('Signal message request type not set.');
        }
        this.wantReply = false;
        super.onWrite(writer);
        switch (this.requestType) {
            case ChannelRequestType.exitStatus:
                writer.writeUInt32(this.validateField(this.exitStatus, 'exit status'));
                break;
            case ChannelRequestType.signal:
                writer.writeString(this.validateField(this.signal, 'signal'), 'ascii');
                break;
            case ChannelRequestType.exitSignal:
                writer.writeString(this.validateField(this.exitSignal, 'exit signal'), 'ascii');
                writer.writeBoolean(false); // Core dumped
                writer.writeString(this.errorMessage || '', 'utf8');
                writer.writeString('', 'ascii'); // Language tag
                break;
            default:
                throw new Error(`Unknown signal message request type: ${this.requestType}`);
        }
    }
}
exports.ChannelSignalMessage = ChannelSignalMessage;
class ChannelSuccessMessage extends ChannelMessage {
    get messageType() {
        return 99;
    }
}
exports.ChannelSuccessMessage = ChannelSuccessMessage;
class ChannelFailureMessage extends ChannelMessage {
    get messageType() {
        return 100;
    }
}
exports.ChannelFailureMessage = ChannelFailureMessage;
sshMessage_1.SshMessage.index.set(90, ChannelOpenMessage);
sshMessage_1.SshMessage.index.set(91, ChannelOpenConfirmationMessage);
sshMessage_1.SshMessage.index.set(92, ChannelOpenFailureMessage);
sshMessage_1.SshMessage.index.set(93, ChannelWindowAdjustMessage);
sshMessage_1.SshMessage.index.set(94, ChannelDataMessage);
sshMessage_1.SshMessage.index.set(95, ChannelExtendedDataMessage);
sshMessage_1.SshMessage.index.set(96, ChannelEofMessage);
sshMessage_1.SshMessage.index.set(97, ChannelCloseMessage);
sshMessage_1.SshMessage.index.set(98, ChannelRequestMessage);
sshMessage_1.SshMessage.index.set(99, ChannelSuccessMessage);
sshMessage_1.SshMessage.index.set(100, ChannelFailureMessage);
//# sourceMappingURL=https://main.vscode-cdn.net/sourcemaps/6a44c352bd24569c417e530095901b649960f9f8/node_modules/@microsoft/dev-tunnels-ssh/messages/connectionMessages.js.map