Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/MHSanaei/3x-ui.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'web/assets/js/model')
-rw-r--r--web/assets/js/model/models.js185
-rw-r--r--web/assets/js/model/xray.js1819
2 files changed, 2004 insertions, 0 deletions
diff --git a/web/assets/js/model/models.js b/web/assets/js/model/models.js
new file mode 100644
index 00000000..768bf4de
--- /dev/null
+++ b/web/assets/js/model/models.js
@@ -0,0 +1,185 @@
+class User {
+
+ constructor() {
+ this.username = "";
+ this.password = "";
+ }
+}
+
+class Msg {
+
+ constructor(success, msg, obj) {
+ this.success = false;
+ this.msg = "";
+ this.obj = null;
+
+ if (success != null) {
+ this.success = success;
+ }
+ if (msg != null) {
+ this.msg = msg;
+ }
+ if (obj != null) {
+ this.obj = obj;
+ }
+ }
+}
+
+class DBInbound {
+
+ constructor(data) {
+ this.id = 0;
+ this.userId = 0;
+ this.up = 0;
+ this.down = 0;
+ this.total = 0;
+ this.remark = "";
+ this.enable = true;
+ this.expiryTime = 0;
+
+ this.listen = "";
+ this.port = 0;
+ this.protocol = "";
+ this.settings = "";
+ this.streamSettings = "";
+ this.tag = "";
+ this.sniffing = "";
+ this.clientStats = ""
+ if (data == null) {
+ return;
+ }
+ ObjectUtil.cloneProps(this, data);
+ }
+
+ get totalGB() {
+ return toFixed(this.total / ONE_GB, 2);
+ }
+
+ set totalGB(gb) {
+ this.total = toFixed(gb * ONE_GB, 0);
+ }
+
+ get isVMess() {
+ return this.protocol === Protocols.VMESS;
+ }
+
+ get isVLess() {
+ return this.protocol === Protocols.VLESS;
+ }
+
+ get isTrojan() {
+ return this.protocol === Protocols.TROJAN;
+ }
+
+ get isSS() {
+ return this.protocol === Protocols.SHADOWSOCKS;
+ }
+
+ get isSocks() {
+ return this.protocol === Protocols.SOCKS;
+ }
+
+ get isHTTP() {
+ return this.protocol === Protocols.HTTP;
+ }
+
+ get address() {
+ let address = location.hostname;
+ if (!ObjectUtil.isEmpty(this.listen) && this.listen !== "0.0.0.0") {
+ address = this.listen;
+ }
+ return address;
+ }
+
+ get _expiryTime() {
+ if (this.expiryTime === 0) {
+ return null;
+ }
+ return moment(this.expiryTime);
+ }
+
+ set _expiryTime(t) {
+ if (t == null) {
+ this.expiryTime = 0;
+ } else {
+ this.expiryTime = t.valueOf();
+ }
+ }
+
+ get isExpiry() {
+ return this.expiryTime < new Date().getTime();
+ }
+
+ toInbound() {
+ let settings = {};
+ if (!ObjectUtil.isEmpty(this.settings)) {
+ settings = JSON.parse(this.settings);
+ }
+
+ let streamSettings = {};
+ if (!ObjectUtil.isEmpty(this.streamSettings)) {
+ streamSettings = JSON.parse(this.streamSettings);
+ }
+
+ let sniffing = {};
+ if (!ObjectUtil.isEmpty(this.sniffing)) {
+ sniffing = JSON.parse(this.sniffing);
+ }
+
+ const config = {
+ port: this.port,
+ listen: this.listen,
+ protocol: this.protocol,
+ settings: settings,
+ streamSettings: streamSettings,
+ tag: this.tag,
+ sniffing: sniffing,
+ clientStats: this.clientStats,
+ };
+ return Inbound.fromJson(config);
+ }
+
+ hasLink() {
+ switch (this.protocol) {
+ case Protocols.VMESS:
+ case Protocols.VLESS:
+ case Protocols.TROJAN:
+ case Protocols.SHADOWSOCKS:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ genLink() {
+ const inbound = this.toInbound();
+ return inbound.genLink(this.address, this.remark);
+ }
+}
+
+class AllSetting {
+
+ constructor(data) {
+ this.webListen = "";
+ this.webPort = 54321;
+ this.webCertFile = "";
+ this.webKeyFile = "";
+ this.webBasePath = "/";
+ this.tgBotEnable = false;
+ this.tgBotToken = "";
+ this.tgBotChatId = 0;
+ this.tgRunTime = "";
+ this.xrayTemplateConfig = "";
+
+ this.timeLocation = "Asia/Shanghai";
+
+ if (data == null) {
+ return
+ }
+ ObjectUtil.cloneProps(this, data);
+ }
+
+ equals(other) {
+ return ObjectUtil.equals(this, other);
+ }
+} \ No newline at end of file
diff --git a/web/assets/js/model/xray.js b/web/assets/js/model/xray.js
new file mode 100644
index 00000000..78af69b6
--- /dev/null
+++ b/web/assets/js/model/xray.js
@@ -0,0 +1,1819 @@
+const Protocols = {
+ VMESS: 'vmess',
+ VLESS: 'vless',
+ TROJAN: 'trojan',
+ SHADOWSOCKS: 'shadowsocks',
+ DOKODEMO: 'dokodemo-door',
+ MTPROTO: 'mtproto',
+ SOCKS: 'socks',
+ HTTP: 'http',
+};
+
+const VmessMethods = {
+ AES_128_GCM: 'aes-128-gcm',
+ CHACHA20_POLY1305: 'chacha20-poly1305',
+ AUTO: 'auto',
+ NONE: 'none',
+};
+
+const SSMethods = {
+ // AES_256_CFB: 'aes-256-cfb',
+ // AES_128_CFB: 'aes-128-cfb',
+ // CHACHA20: 'chacha20',
+ // CHACHA20_IETF: 'chacha20-ietf',
+ CHACHA20_POLY1305: 'chacha20-poly1305',
+ AES_256_GCM: 'aes-256-gcm',
+ AES_128_GCM: 'aes-128-gcm',
+ BLAKE3_AES_128_GCM: '2022-blake3-aes-128-gcm',
+ BLAKE3_AES_256_GCM: '2022-blake3-aes-256-gcm',
+ BLAKE3_CHACHA20_POLY1305: '2022-blake3-chacha20-poly1305',
+};
+
+const RULE_IP = {
+ PRIVATE: 'geoip:private',
+ CN: 'geoip:cn',
+};
+
+const RULE_DOMAIN = {
+ ADS: 'geosite:category-ads',
+ ADS_ALL: 'geosite:category-ads-all',
+ CN: 'geosite:cn',
+ GOOGLE: 'geosite:google',
+ FACEBOOK: 'geosite:facebook',
+ SPEEDTEST: 'geosite:speedtest',
+};
+
+const XTLS_FLOW_CONTROL = {
+ ORIGIN: "xtls-rprx-origin",
+ DIRECT: "xtls-rprx-direct",
+};
+
+const TLS_FLOW_CONTROL = {
+ VISION: "xtls-rprx-vision",
+};
+
+const TLS_VERSION_OPTION = {
+ TLS10: "1.0",
+ TLS11: "1.1",
+ TLS12: "1.2",
+ TLS13: "1.3",
+}
+
+const TLS_CIPHER_OPTION = {
+ RSA_AES_128_CBC: "TLS_RSA_WITH_AES_128_CBC_SHA",
+ RSA_AES_256_CBC: "TLS_RSA_WITH_AES_256_CBC_SHA",
+ RSA_AES_128_GCM: "TLS_RSA_WITH_AES_128_GCM_SHA256",
+ RSA_AES_256_GCM: "TLS_RSA_WITH_AES_256_GCM_SHA384",
+ AES_128_GCM: "TLS_AES_128_GCM_SHA256",
+ AES_256_GCM: "TLS_AES_256_GCM_SHA384",
+ CHACHA20_POLY1305: "TLS_CHACHA20_POLY1305_SHA256",
+ ECDHE_ECDSA_AES_128_CBC: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
+ ECDHE_ECDSA_AES_256_CBC: "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
+ ECDHE_RSA_AES_128_CBC: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
+ ECDHE_RSA_AES_256_CBC: "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
+ ECDHE_ECDSA_AES_128_GCM: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
+ ECDHE_ECDSA_AES_256_GCM: "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
+ ECDHE_RSA_AES_128_GCM: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+ ECDHE_RSA_AES_256_GCM: "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
+ ECDHE_ECDSA_CHACHA20_POLY1305: "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
+ ECDHE_RSA_CHACHA20_POLY1305: "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
+};
+
+const UTLS_FINGERPRINT = {
+ UTLS_CHROME: "chrome",
+ UTLS_FIREFOX: "firefox",
+ UTLS_SAFARI: "safari",
+ UTLS_IOS: "ios",
+ UTLS_android: "android",
+ UTLS_EDGE: "edge",
+ UTLS_360: "360",
+ UTLS_QQ: "qq",
+ UTLS_RANDOM: "random",
+ UTLS_RANDOMIZED: "randomized",
+};
+
+Object.freeze(Protocols);
+Object.freeze(VmessMethods);
+Object.freeze(SSMethods);
+Object.freeze(RULE_IP);
+Object.freeze(RULE_DOMAIN);
+Object.freeze(XTLS_FLOW_CONTROL);
+Object.freeze(TLS_FLOW_CONTROL);
+Object.freeze(TLS_VERSION_OPTION);
+Object.freeze(TLS_CIPHER_OPTION);
+
+class XrayCommonClass {
+
+ static toJsonArray(arr) {
+ return arr.map(obj => obj.toJson());
+ }
+
+ static fromJson() {
+ return new XrayCommonClass();
+ }
+
+ toJson() {
+ return this;
+ }
+
+ toString(format=true) {
+ return format ? JSON.stringify(this.toJson(), null, 2) : JSON.stringify(this.toJson());
+ }
+
+ static toHeaders(v2Headers) {
+ let newHeaders = [];
+ if (v2Headers) {
+ Object.keys(v2Headers).forEach(key => {
+ let values = v2Headers[key];
+ if (typeof(values) === 'string') {
+ newHeaders.push({ name: key, value: values });
+ } else {
+ for (let i = 0; i < values.length; ++i) {
+ newHeaders.push({ name: key, value: values[i] });
+ }
+ }
+ });
+ }
+ return newHeaders;
+ }
+
+ static toV2Headers(headers, arr=true) {
+ let v2Headers = {};
+ for (let i = 0; i < headers.length; ++i) {
+ let name = headers[i].name;
+ let value = headers[i].value;
+ if (ObjectUtil.isEmpty(name) || ObjectUtil.isEmpty(value)) {
+ continue;
+ }
+ if (!(name in v2Headers)) {
+ v2Headers[name] = arr ? [value] : value;
+ } else {
+ if (arr) {
+ v2Headers[name].push(value);
+ } else {
+ v2Headers[name] = value;
+ }
+ }
+ }
+ return v2Headers;
+ }
+}
+
+class TcpStreamSettings extends XrayCommonClass {
+ constructor(
+ type = 'none',
+ acceptProxyProtocol = false,
+ request = new TcpStreamSettings.TcpRequest(),
+ response = new TcpStreamSettings.TcpResponse(),
+ ) {
+ super();
+ this.type = type;
+ this.request = request;
+ this.response = response;
+ this.acceptProxyProtocol = acceptProxyProtocol;
+ }
+
+ static fromJson(json = {}) {
+ let header = json.header;
+ if (!header) {
+ header = {};
+ }
+ return new TcpStreamSettings(
+ header.type,
+ json.acceptProxyProtocol,
+ TcpStreamSettings.TcpRequest.fromJson(header.request),
+ TcpStreamSettings.TcpResponse.fromJson(header.response),
+ );
+ }
+
+ toJson() {
+ return {
+ header: {
+ type: this.type,
+ request: this.type === 'http' ? this.request.toJson() : undefined,
+ response: this.type === 'http' ? this.response.toJson() : undefined,
+ },
+ acceptProxyProtocol: this.acceptProxyProtocol,
+ };
+ }
+}
+
+TcpStreamSettings.TcpRequest = class extends XrayCommonClass {
+ constructor(version = '1.1',
+ method = 'GET',
+ path = ['/'],
+ headers = [],
+ ) {
+ super();
+ this.version = version;
+ this.method = method;
+ this.path = path.length === 0 ? ['/'] : path;
+ this.headers = headers;
+ }
+
+ addPath(path) {
+ this.path.push(path);
+ }
+
+ removePath(index) {
+ this.path.splice(index, 1);
+ }
+
+ addHeader(name, value) {
+ this.headers.push({ name: name, value: value });
+ }
+
+ getHeader(name) {
+ for (const header of this.headers) {
+ if (header.name.toLowerCase() === name.toLowerCase()) {
+ return header.value;
+ }
+ }
+ return null;
+ }
+
+ removeHeader(index) {
+ this.headers.splice(index, 1);
+ }
+
+ static fromJson(json = {}) {
+ return new TcpStreamSettings.TcpRequest(
+ json.version,
+ json.method,
+ json.path,
+ XrayCommonClass.toHeaders(json.headers),
+ );
+ }
+
+ toJson() {
+ return {
+ method: this.method,
+ path: ObjectUtil.clone(this.path),
+ headers: XrayCommonClass.toV2Headers(this.headers),
+ };
+ }
+};
+
+TcpStreamSettings.TcpResponse = class extends XrayCommonClass {
+ constructor(version = '1.1',
+ status = '200',
+ reason = 'OK',
+ headers = [],
+ ) {
+ super();
+ this.version = version;
+ this.status = status;
+ this.reason = reason;
+ this.headers = headers;
+ }
+
+ addHeader(name, value) {
+ this.headers.push({ name: name, value: value });
+ }
+
+ removeHeader(index) {
+ this.headers.splice(index, 1);
+ }
+
+ static fromJson(json = {}) {
+ return new TcpStreamSettings.TcpResponse(
+ json.version,
+ json.status,
+ json.reason,
+ XrayCommonClass.toHeaders(json.headers),
+ );
+ }
+
+ toJson() {
+ return {
+ version: this.version,
+ status: this.status,
+ reason: this.reason,
+ headers: XrayCommonClass.toV2Headers(this.headers),
+ };
+ }
+};
+
+class KcpStreamSettings extends XrayCommonClass {
+ constructor(mtu=1350, tti=20,
+ uplinkCapacity=5,
+ downlinkCapacity=20,
+ congestion=false,
+ readBufferSize=2,
+ writeBufferSize=2,
+ type='none',
+ seed=RandomUtil.randomSeq(10),
+ ) {
+ super();
+ this.mtu = mtu;
+ this.tti = tti;
+ this.upCap = uplinkCapacity;
+ this.downCap = downlinkCapacity;
+ this.congestion = congestion;
+ this.readBuffer = readBufferSize;
+ this.writeBuffer = writeBufferSize;
+ this.type = type;
+ this.seed = seed;
+ }
+
+ static fromJson(json={}) {
+ return new KcpStreamSettings(
+ json.mtu,
+ json.tti,
+ json.uplinkCapacity,
+ json.downlinkCapacity,
+ json.congestion,
+ json.readBufferSize,
+ json.writeBufferSize,
+ ObjectUtil.isEmpty(json.header) ? 'none' : json.header.type,
+ json.seed,
+ );
+ }
+
+ toJson() {
+ return {
+ mtu: this.mtu,
+ tti: this.tti,
+ uplinkCapacity: this.upCap,
+ downlinkCapacity: this.downCap,
+ congestion: this.congestion,
+ readBufferSize: this.readBuffer,
+ writeBufferSize: this.writeBuffer,
+ header: {
+ type: this.type,
+ },
+ seed: this.seed,
+ };
+ }
+}
+
+class WsStreamSettings extends XrayCommonClass {
+ constructor(acceptProxyProtocol=false, path='/', headers=[]) {
+ super();
+ this.acceptProxyProtocol = acceptProxyProtocol;
+ this.path = path;
+ this.headers = headers;
+ }
+
+ addHeader(name, value) {
+ this.headers.push({ name: name, value: value });
+ }
+
+ getHeader(name) {
+ for (const header of this.headers) {
+ if (header.name.toLowerCase() === name.toLowerCase()) {
+ return header.value;
+ }
+ }
+ return null;
+ }
+
+ removeHeader(index) {
+ this.headers.splice(index, 1);
+ }
+
+ static fromJson(json={}) {
+ return new WsStreamSettings(
+ json.acceptProxyProtocol,
+ json.path,
+ XrayCommonClass.toHeaders(json.headers),
+ );
+ }
+
+ toJson() {
+ return {
+ acceptProxyProtocol: this.acceptProxyProtocol,
+ path: this.path,
+ headers: XrayCommonClass.toV2Headers(this.headers, false),
+ };
+ }
+}
+
+class HttpStreamSettings extends XrayCommonClass {
+ constructor(path='/', host=['']) {
+ super();
+ this.path = path;
+ this.host = host.length === 0 ? [''] : host;
+ }
+
+ addHost(host) {
+ this.host.push(host);
+ }
+
+ removeHost(index) {
+ this.host.splice(index, 1);
+ }
+
+ static fromJson(json={}) {
+ return new HttpStreamSettings(json.path, json.host);
+ }
+
+ toJson() {
+ let host = [];
+ for (let i = 0; i < this.host.length; ++i) {
+ if (!ObjectUtil.isEmpty(this.host[i])) {
+ host.push(this.host[i]);
+ }
+ }
+ return {
+ path: this.path,
+ host: host,
+ }
+ }
+}
+
+class QuicStreamSettings extends XrayCommonClass {
+ constructor(security=VmessMethods.NONE,
+ key='', type='none') {
+ super();
+ this.security = security;
+ this.key = key;
+ this.type = type;
+ }
+
+ static fromJson(json={}) {
+ return new QuicStreamSettings(
+ json.security,
+ json.key,
+ json.header ? json.header.type : 'none',
+ );
+ }
+
+ toJson() {
+ return {
+ security: this.security,
+ key: this.key,
+ header: {
+ type: this.type,
+ }
+ }
+ }
+}
+
+class GrpcStreamSettings extends XrayCommonClass {
+ constructor(serviceName="") {
+ super();
+ this.serviceName = serviceName;
+ }
+
+ static fromJson(json={}) {
+ return new GrpcStreamSettings(json.serviceName);
+ }
+
+ toJson() {
+ return {
+ serviceName: this.serviceName,
+ }
+ }
+}
+
+class TlsStreamSettings extends XrayCommonClass {
+ constructor(serverName = '', minVersion = TLS_VERSION_OPTION.TLS12, maxVersion = TLS_VERSION_OPTION.TLS13,
+ cipherSuites = '',
+ certificates = [new TlsStreamSettings.Cert()], alpn = ["h2", "http/1.1"]) {
+ super();
+ this.server = serverName;
+ this.minVersion = minVersion;
+ this.maxVersion = maxVersion;
+ this.cipherSuites = cipherSuites;
+ this.certs = certificates;
+ this.alpn = alpn;
+ }
+
+ addCert(cert) {
+ this.certs.push(cert);
+ }
+
+ removeCert(index) {
+ this.certs.splice(index, 1);
+ }
+
+ static fromJson(json={}) {
+ let certs;
+ if (!ObjectUtil.isEmpty(json.certificates)) {
+ certs = json.certificates.map(cert => TlsStreamSettings.Cert.fromJson(cert));
+ }
+
+ return new TlsStreamSettings(
+ json.serverName,
+ json.minVersion,
+ json.maxVersion,
+ json.cipherSuites,
+ certs,
+ json.alpn,
+ );
+ }
+
+ toJson() {
+ return {
+ serverName: this.server,
+ minVersion: this.minVersion,
+ maxVersion: this.maxVersion,
+ cipherSuites: this.cipherSuites,
+ certificates: TlsStreamSettings.toJsonArray(this.certs),
+ alpn: this.alpn
+ };
+ }
+}
+
+TlsStreamSettings.Cert = class extends XrayCommonClass {
+ constructor(useFile=true, certificateFile='', keyFile='', certificate='', key='') {
+ super();
+ this.useFile = useFile;
+ this.certFile = certificateFile;
+ this.keyFile = keyFile;
+ this.cert = certificate instanceof Array ? certificate.join('\n') : certificate;
+ this.key = key instanceof Array ? key.join('\n') : key;
+ }
+
+ static fromJson(json={}) {
+ if ('certificateFile' in json && 'keyFile' in json) {
+ return new TlsStreamSettings.Cert(
+ true,
+ json.certificateFile,
+ json.keyFile,
+ );
+ } else {
+ return new TlsStreamSettings.Cert(
+ false, '', '',
+ json.certificate.join('\n'),
+ json.key.join('\n'),
+ );
+ }
+ }
+
+ toJson() {
+ if (this.useFile) {
+ return {
+ certificateFile: this.certFile,
+ keyFile: this.keyFile,
+ };
+ } else {
+ return {
+ certificate: this.cert.split('\n'),
+ key: this.key.split('\n'),
+ };
+ }
+ }
+};
+
+class StreamSettings extends XrayCommonClass {
+ constructor(network='tcp',
+ security='none',
+ tlsSettings=new TlsStreamSettings(),
+ tcpSettings=new TcpStreamSettings(),
+ kcpSettings=new KcpStreamSettings(),
+ wsSettings=new WsStreamSettings(),
+ httpSettings=new HttpStreamSettings(),
+ quicSettings=new QuicStreamSettings(),
+ grpcSettings=new GrpcStreamSettings(),
+ ) {
+ super();
+ this.network = network;
+ this.security = security;
+ this.tls = tlsSettings;
+ this.tcp = tcpSettings;
+ this.kcp = kcpSettings;
+ this.ws = wsSettings;
+ this.http = httpSettings;
+ this.quic = quicSettings;
+ this.grpc = grpcSettings;
+ }
+
+ get isTls() {
+ return this.security === 'tls';
+ }
+
+ set isTls(isTls) {
+ if (isTls) {
+ this.security = 'tls';
+ } else {
+ this.security = 'none';
+ }
+ }
+
+ get isXTls() {
+ return this.security === "xtls";
+ }
+
+ set isXTls(isXTls) {
+ if (isXTls) {
+ this.security = 'xtls';
+ } else {
+ this.security = 'none';
+ }
+ }
+
+ static fromJson(json={}) {
+ let tls;
+ if (json.security === "xtls") {
+ tls = TlsStreamSettings.fromJson(json.xtlsSettings);
+ } else {
+ tls = TlsStreamSettings.fromJson(json.tlsSettings);
+ }
+ return new StreamSettings(
+ json.network,
+ json.security,
+ tls,
+ TcpStreamSettings.fromJson(json.tcpSettings),
+ KcpStreamSettings.fromJson(json.kcpSettings),
+ WsStreamSettings.fromJson(json.wsSettings),
+ HttpStreamSettings.fromJson(json.httpSettings),
+ QuicStreamSettings.fromJson(json.quicSettings),
+ GrpcStreamSettings.fromJson(json.grpcSettings),
+ );
+ }
+
+ toJson() {
+ const network = this.network;
+ return {
+ network: network,
+ security: this.security,
+ tlsSettings: this.isTls ? this.tls.toJson() : undefined,
+ xtlsSettings: this.isXTls ? this.tls.toJson() : undefined,
+ tcpSettings: network === 'tcp' ? this.tcp.toJson() : undefined,
+ kcpSettings: network === 'kcp' ? this.kcp.toJson() : undefined,
+ wsSettings: network === 'ws' ? this.ws.toJson() : undefined,
+ httpSettings: network === 'http' ? this.http.toJson() : undefined,
+ quicSettings: network === 'quic' ? this.quic.toJson() : undefined,
+ grpcSettings: network === 'grpc' ? this.grpc.toJson() : undefined,
+ };
+ }
+}
+
+class Sniffing extends XrayCommonClass {
+ constructor(enabled=true, destOverride=['http', 'tls']) {
+ super();
+ this.enabled = enabled;
+ this.destOverride = destOverride;
+ }
+
+ static fromJson(json={}) {
+ let destOverride = ObjectUtil.clone(json.destOverride);
+ if (!ObjectUtil.isEmpty(destOverride) && !ObjectUtil.isArrEmpty(destOverride)) {
+ if (ObjectUtil.isEmpty(destOverride[0])) {
+ destOverride = ['http', 'tls'];
+ }
+ }
+ return new Sniffing(
+ !!json.enabled,
+ destOverride,
+ );
+ }
+}
+
+class Inbound extends XrayCommonClass {
+ constructor(port=RandomUtil.randomIntRange(10000, 60000),
+ listen='',
+ protocol=Protocols.VMESS,
+ settings=null,
+ streamSettings=new StreamSettings(),
+ tag='',
+ sniffing=new Sniffing(),
+ clientStats='',
+ ) {
+ super();
+ this.port = port;
+ this.listen = listen;
+ this._protocol = protocol;
+ this.settings = ObjectUtil.isEmpty(settings) ? Inbound.Settings.getSettings(protocol) : settings;
+ this.stream = streamSettings;
+ this.tag = tag;
+ this.sniffing = sniffing;
+ this.clientStats = clientStats;
+ }
+ getClientStats() {
+ return this.clientStats;
+ }
+
+ get protocol() {
+ return this._protocol;
+ }
+
+ set protocol(protocol) {
+ this._protocol = protocol;
+ this.settings = Inbound.Settings.getSettings(protocol);
+ if (protocol === Protocols.TROJAN) {
+ this.tls = true;
+ }
+ }
+ get tls() {
+ return this.stream.security === 'tls';
+ }
+
+ set tls(isTls) {
+ if (isTls) {
+ this.stream.security = 'tls';
+ } else {
+ this.stream.security = 'none';
+ }
+ }
+
+ get xtls() {
+ return this.stream.security === 'xtls';
+ }
+
+ set xtls(isXTls) {
+ if (isXTls) {
+ this.stream.security = 'xtls';
+ } else {
+ this.stream.security = 'none';
+ }
+ }
+
+ get network() {
+ return this.stream.network;
+ }
+
+ set network(network) {
+ this.stream.network = network;
+ }
+
+ get isTcp() {
+ return this.network === "tcp";
+ }
+
+ get isWs() {
+ return this.network === "ws";
+ }
+
+ get isKcp() {
+ return this.network === "kcp";
+ }
+
+ get isQuic() {
+ return this.network === "quic"
+ }
+
+ get isGrpc() {
+ return this.network === "grpc";
+ }
+
+ get isH2() {
+ return this.network === "http";
+ }
+
+ isInboundEmpty() {
+ if (this.protocol == Protocols.VMESS && this.settings.vmesses.length == 0) {
+ return true;
+ } else if (this.protocol == Protocols.VLESS && this.settings.vlesses.length == 0) {
+ return true;
+ } else if (this.protocol == Protocols.TROJAN && this.settings.trojans.length == 0) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ // VMess & VLess
+ get uuid() {
+ switch (this.protocol) {
+ case Protocols.VMESS:
+ return this.settings.vmesses[0].id;
+ case Protocols.VLESS:
+ return this.settings.vlesses[0].id;
+ default:
+ return "";
+ }
+ }
+
+ // VLess & Trojan
+ get flow() {
+ switch (this.protocol) {
+ case Protocols.VLESS:
+ return this.settings.vlesses[0].flow;
+ case Protocols.TROJAN:
+ return this.settings.trojans[0].flow;
+ default:
+ return "";
+ }
+ }
+
+ // VMess
+ get alterId() {
+ switch (this.protocol) {
+ case Protocols.VMESS:
+ return this.settings.vmesses[0].alterId;
+ default:
+ return "";
+ }
+ }
+
+ // Socks & HTTP
+ get username() {
+ switch (this.protocol) {
+ case Protocols.SOCKS:
+ case Protocols.HTTP:
+ return this.settings.accounts[0].user;
+ default:
+ return "";
+ }
+ }
+
+ // Trojan & Shadowsocks & Socks & HTTP
+ get password() {
+ switch (this.protocol) {
+ case Protocols.TROJAN:
+ return this.settings.trojans[0].password;
+ case Protocols.SHADOWSOCKS:
+ return this.settings.password;
+ case Protocols.SOCKS:
+ case Protocols.HTTP:
+ return this.settings.accounts[0].pass;
+ default:
+ return "";
+ }
+ }
+
+ // Shadowsocks
+ get method() {
+ switch (this.protocol) {
+ case Protocols.SHADOWSOCKS:
+ return this.settings.method;
+ default:
+ return "";
+ }
+ }
+
+ get serverName() {
+ if (this.stream.isTls || this.stream.isXTls) {
+ return this.stream.tls.server;
+ }
+ return "";
+ }
+
+ get host() {
+ if (this.isTcp) {
+ return this.stream.tcp.request.getHeader("Host");
+ } else if (this.isWs) {
+ return this.stream.ws.getHeader("Host");
+ } else if (this.isH2) {
+ return this.stream.http.host[0];
+ }
+ return null;
+ }
+
+ get path() {
+ if (this.isTcp) {
+ return this.stream.tcp.request.path[0];
+ } else if (this.isWs) {
+ return this.stream.ws.path;
+ } else if (this.isH2) {
+ return this.stream.http.path[0];
+ }
+ return null;
+ }
+
+ get quicSecurity() {
+ return this.stream.quic.security;
+ }
+
+ get quicKey() {
+ return this.stream.quic.key;
+ }
+
+ get quicType() {
+ return this.stream.quic.type;
+ }
+
+ get kcpType() {
+ return this.stream.kcp.type;
+ }
+
+ get kcpSeed() {
+ return this.stream.kcp.seed;
+ }
+
+ get serviceName() {
+ return this.stream.grpc.serviceName;
+ }
+
+ isExpiry(index) {
+ switch (this.protocol) {
+ case Protocols.VMESS:
+ if(this.settings.vmesses[index]._expiryTime != null)
+ return this.settings.vmesses[index]._expiryTime < new Date().getTime();
+ return false
+ case Protocols.VLESS:
+ if(this.settings.vlesses[index]._expiryTime != null)
+ return this.settings.vlesses[index]._expiryTime < new Date().getTime();
+ return false
+ case Protocols.TROJAN:
+ if(this.settings.trojans[index]._expiryTime != null)
+ return this.settings.trojans[index]._expiryTime < new Date().getTime();
+ return false
+ default:
+ return false;
+ }
+ }
+
+ canEnableTls() {
+ switch (this.protocol) {
+ case Protocols.VMESS:
+ case Protocols.VLESS:
+ case Protocols.TROJAN:
+ case Protocols.SHADOWSOCKS:
+ break;
+ default:
+ return false;
+ }
+
+ switch (this.network) {
+ case "tcp":
+ case "ws":
+ case "http":
+ case "quic":
+ case "grpc":
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ //this is used for xtls-rprx-vison
+ canEnableTlsFlow() {
+ if ((this.stream.security === 'tls') && (this.network === "tcp")) {
+ switch (this.protocol) {
+ case Protocols.VLESS:
+ return true;
+ default:
+ return false;
+ }
+ }
+ return false;
+ }
+
+ canSetTls() {
+ return this.canEnableTls();
+ }
+
+ canEnableXTls() {
+ switch (this.protocol) {
+ case Protocols.VLESS:
+ case Protocols.TROJAN:
+ break;
+ default:
+ return false;
+ }
+ return this.network === "tcp";
+ }
+
+ canEnableStream() {
+ switch (this.protocol) {
+ case Protocols.VMESS:
+ case Protocols.VLESS:
+ case Protocols.TROJAN:
+ case Protocols.SHADOWSOCKS:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ canSniffing() {
+ switch (this.protocol) {
+ case Protocols.VMESS:
+ case Protocols.VLESS:
+ case Protocols.TROJAN:
+ case Protocols.SHADOWSOCKS:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ reset() {
+ this.port = RandomUtil.randomIntRange(10000, 60000);
+ this.listen = '';
+ this.protocol = Protocols.VMESS;
+ this.settings = Inbound.Settings.getSettings(Protocols.VMESS);
+ this.stream = new StreamSettings();
+ this.tag = '';
+ this.sniffing = new Sniffing();
+ }
+
+ genVmessLink(address='', remark='', clientIndex=0) {
+ if (this.protocol !== Protocols.VMESS) {
+ return '';
+ }
+ let network = this.stream.network;
+ let type = 'none';
+ let host = '';
+ let path = '';
+ if (network === 'tcp') {
+ let tcp = this.stream.tcp;
+ type = tcp.type;
+ if (type === 'http') {
+ let request = tcp.request;
+ path = request.path.join(',');
+ let index = request.headers.findIndex(header => header.name.toLowerCase() === 'host');
+ if (index >= 0) {
+ host = request.headers[index].value;