@microsoft/dev-tunnels-ssh
Version:
SSH library for Dev Tunnels
347 lines • 14.2 kB
JavaScript
"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=connectionMessages.js.map