Initial commit

This commit is contained in:
NI
2019-08-07 15:56:51 +08:00
commit 02f14eb14f
206 changed files with 38863 additions and 0 deletions

228
ui/commands/address.js Normal file
View File

@@ -0,0 +1,228 @@
// Sshwifty - A Web SSH client
//
// Copyright (C) 2019 Rui NI <nirui@gmx.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import Exception from "./exception.js";
import * as reader from "../stream/reader.js";
import * as common from "./common.js";
export const LOOPBACK = 0x00;
export const IPV4 = 0x01;
export const IPV6 = 0x02;
export const HOSTNAME = 0x03;
export const MAX_ADDR_LEN = 0x3f;
export class Address {
/**
* Read builds an Address from data readed from the reader
*
* @param {reader.Reader} rd The reader
*
* @returns {Address} The Address
*
* @throws {Exception} when address type is invalid
*/
static async read(rd) {
let readed = await reader.readN(rd, 3),
portNum = 0,
addrType = LOOPBACK,
addrData = null;
portNum |= readed[0];
portNum <<= 8;
portNum |= readed[1];
addrType = readed[2] >> 6;
switch (addrType) {
case LOOPBACK:
break;
case IPV4:
addrData = await reader.readN(rd, 4);
break;
case IPV6:
addrData = await reader.readN(rd, 16);
break;
case HOSTNAME:
addrData = await reader.readN(rd, 0x3f & readed[2]);
break;
default:
throw new Exception("Unknown address type");
}
return new Address(addrType, addrData, portNum);
}
/**
* constructor
*
* @param {number} type Type of the address
* @param {Uint8Array} address Address data
* @param {number} port port number of the address
*
*/
constructor(type, address, port) {
this.addrType = type;
this.addrData = address;
this.addrPort = port;
}
/**
* Return the address type
*
*/
type() {
return this.addrType;
}
/**
* Return the address data
*
*/
address() {
return this.addrData;
}
/**
* Return the port data
*
*/
port() {
return this.addrPort;
}
/**
* Buffer returns the marshalled address
*
* @returns {Uint8Array} Marshalled address
*
* @throws {Exception} When address data is invalid
*
*/
buffer() {
switch (this.type()) {
case LOOPBACK:
return new Uint8Array([
this.addrPort >> 8,
this.addrPort & 0xff,
LOOPBACK << 6
]);
case IPV4:
if (this.addrData.length != 4) {
throw new Exception("Invalid address length");
}
return new Uint8Array([
this.addrPort >> 8,
this.addrPort & 0xff,
IPV4 << 6,
this.addrData[0],
this.addrData[1],
this.addrData[2],
this.addrData[3]
]);
case IPV6:
if (this.addrData.length != 16) {
throw new Exception("Invalid address length");
}
return new Uint8Array([
this.addrPort >> 8,
this.addrPort & 0xff,
IPV6 << 6,
this.addrData[0],
this.addrData[1],
this.addrData[2],
this.addrData[3],
this.addrData[4],
this.addrData[5],
this.addrData[6],
this.addrData[7],
this.addrData[8],
this.addrData[9],
this.addrData[10],
this.addrData[11],
this.addrData[12],
this.addrData[13],
this.addrData[14],
this.addrData[15]
]);
case HOSTNAME:
if (this.addrData.length > MAX_ADDR_LEN) {
throw new Exception("Host name cannot longer than " + MAX_ADDR_LEN);
}
let dataBuf = new Uint8Array(this.addrData.length + 3);
dataBuf[0] = (this.addrPort >> 8) & 0xff;
dataBuf[1] = this.addrPort & 0xff;
dataBuf[2] = HOSTNAME << 6;
dataBuf[2] |= this.addrData.length;
dataBuf.set(this.addrData, 3);
return dataBuf;
default:
throw new Exception("Unknown address type");
}
}
}
/**
* Get address data
*
* @param {string} s Address string
* @param {number} defaultPort Default port number
*
* @returns {object} result
*
* @throws {Exception} when the address is invalid
*/
export function parseHostPort(s, defaultPort) {
let d = common.splitHostPort(s, defaultPort),
t = HOSTNAME;
switch (d.type) {
case "IPv4":
t = IPV4;
break;
case "IPv6":
t = IPV6;
break;
case "Hostname":
break;
default:
throw new Exception("Invalid address type");
}
return {
type: t,
address: d.addr,
port: d.port
};
}