core,test: support "service" option in config
This commit is contained in:
parent
abf630d6bd
commit
8294d87bf8
@ -11,15 +11,26 @@ describe('Config#init', () => {
|
||||
expect(() => Config.init([])).toThrow();
|
||||
});
|
||||
|
||||
it('should throw when host is not provided', () => {
|
||||
it('should throw when host(if provided) is invalid', () => {
|
||||
expect(() => Config.init({})).toThrow();
|
||||
expect(() => Config.init({host: ''})).toThrow();
|
||||
});
|
||||
|
||||
it('should throw when port is not natural number', () => {
|
||||
it('should throw when port(if provided) is invalid', () => {
|
||||
expect(() => Config.init({host: 'localhost', port: -1})).toThrow();
|
||||
});
|
||||
|
||||
it('should throw when service(if provided) is invalid', () => {
|
||||
expect(() => Config.init({service: null})).toThrow();
|
||||
expect(() => Config.init({service: 'xxx'})).toThrow();
|
||||
expect(() => Config.init({service: 'xxx://abc:1080'})).toThrow();
|
||||
expect(() => Config.init({service: 'tcp://-:1080'})).toThrow();
|
||||
expect(() => Config.init({service: 'tcp://abc:0'})).toThrow();
|
||||
expect(() => Config.init({service: 'tls://abc:1080'})).toThrow();
|
||||
expect(() => Config.init({service: 'tls://abc:1080', tls_cert: 'a'})).toThrow();
|
||||
expect(() => Config.init({service: 'tls://abc:1080', tls_cert: 'a', tls_key: null})).toThrow();
|
||||
});
|
||||
|
||||
it('should throw when servers(if provided) is invalid', () => {
|
||||
expect(() => Config.init({host: 'localhost', port: 1080, servers: ''})).toThrow();
|
||||
expect(() => Config.init({host: 'localhost', port: 1080, servers: []})).toThrow();
|
||||
@ -122,12 +133,12 @@ describe('Config#init', () => {
|
||||
|
||||
describe('Config#_validateServer', () => {
|
||||
|
||||
it('should throw when server.host is invalid', () => {
|
||||
it('should throw when server.host(is provided) is invalid', () => {
|
||||
expect(() => Config._validateServer({host: null})).toThrow();
|
||||
expect(() => Config._validateServer({host: ''})).toThrow();
|
||||
});
|
||||
|
||||
it('should throw when server.port is invalid', () => {
|
||||
it('should throw when server.port(is provided) is invalid', () => {
|
||||
expect(() => Config._validateServer({host: 'abc', port: null})).toThrow();
|
||||
});
|
||||
|
||||
@ -136,7 +147,7 @@ describe('Config#_validateServer', () => {
|
||||
expect(() => Config._validateServer({host: 'abc', port: 123, key: ''})).toThrow();
|
||||
});
|
||||
|
||||
let baseConf = {host: 'abc', port: 123, key: 'secret'};
|
||||
let baseConf = {service: 'tcp://abc:123', key: 'secret'};
|
||||
|
||||
it('should throw when server.presets is not an array', () => {
|
||||
expect(() => Config._validateServer({...baseConf, presets: null})).toThrow();
|
||||
@ -178,7 +189,7 @@ describe('Config#_validateServer', () => {
|
||||
});
|
||||
|
||||
it('__TLS_CERT__ and __TLS_KEY__ should be set', () => {
|
||||
Config.init({...baseConf, transport: 'tls', tls_cert: 'mock_cert.pem', tls_key: 'mock_key.pem'});
|
||||
Config.init({...baseConf, service: 'tls://abc:123', tls_cert: 'mock_cert.pem', tls_key: 'mock_key.pem'});
|
||||
expect(__TRANSPORT__).toBe('tls');
|
||||
expect(__TLS_CERT__).toBeDefined();
|
||||
expect(__TLS_KEY__).toBeDefined();
|
||||
|
@ -3,20 +3,27 @@ import fs from 'fs';
|
||||
import path from 'path';
|
||||
import os from 'os';
|
||||
import net from 'net';
|
||||
import url from 'url';
|
||||
import winston from 'winston';
|
||||
import isPlainObject from 'lodash.isplainobject';
|
||||
import {getPresetClassByName} from '../presets';
|
||||
import {isValidHostname, isValidPort, logger} from '../utils';
|
||||
import {DNS_DEFAULT_EXPIRE} from './dns-cache';
|
||||
|
||||
export const AVAILABLE_PROTOCOLS = [
|
||||
'tcp', 'socks', 'socks5', 'socks4', 'socks4a',
|
||||
'http', 'https', 'ws', 'tls'
|
||||
];
|
||||
|
||||
function loadFileSync(file) {
|
||||
return fs.readFileSync(path.resolve(process.cwd(), file));
|
||||
}
|
||||
|
||||
export class Config {
|
||||
|
||||
static init(json) {
|
||||
this._validate(json);
|
||||
|
||||
global.__LOCAL_HOST__ = json.host;
|
||||
global.__LOCAL_PORT__ = json.port;
|
||||
|
||||
if (json.servers !== undefined) {
|
||||
global.__SERVERS__ = json.servers.filter((server) => server.enabled);
|
||||
global.__IS_CLIENT__ = true;
|
||||
@ -27,11 +34,21 @@ export class Config {
|
||||
this.initServer(json);
|
||||
}
|
||||
|
||||
if (json.service !== undefined) {
|
||||
const {protocol, hostname: host, port} = url.parse(json.service);
|
||||
global.__LOCAL_PROTOCOL__ = protocol.slice(0, -1);
|
||||
global.__LOCAL_HOST__ = host;
|
||||
global.__LOCAL_PORT__ = port;
|
||||
} else {
|
||||
global.__LOCAL_PROTOCOL__ = __IS_CLIENT__ ? 'socks5' : __TRANSPORT__;
|
||||
global.__LOCAL_HOST__ = json.host;
|
||||
global.__LOCAL_PORT__ = json.port;
|
||||
}
|
||||
|
||||
global.__TIMEOUT__ = (json.timeout !== undefined) ? json.timeout * 1e3 : 600 * 1e3;
|
||||
global.__REDIRECT__ = (json.redirect !== '') ? json.redirect : null;
|
||||
global.__WORKERS__ = (json.workers !== undefined) ? json.workers : 0;
|
||||
global.__DNS_EXPIRE__ = (json.dns_expire !== undefined) ? json.dns_expire * 1e3 : DNS_DEFAULT_EXPIRE;
|
||||
global.__ALL_CONFIG__ = json;
|
||||
|
||||
// dns
|
||||
if (json.dns !== undefined && json.dns.length > 0) {
|
||||
@ -70,17 +87,28 @@ export class Config {
|
||||
}
|
||||
|
||||
static initServer(server) {
|
||||
global.__TRANSPORT__ = (server.transport !== undefined) ? server.transport : 'tcp';
|
||||
// service
|
||||
if (server.service !== undefined) {
|
||||
const {protocol, hostname: host, port} = url.parse(server.service);
|
||||
global.__TRANSPORT__ = protocol.slice(0, -1);
|
||||
global.__SERVER_HOST__ = host;
|
||||
global.__SERVER_PORT__ = port;
|
||||
} else {
|
||||
global.__TRANSPORT__ = server.transport || 'tcp';
|
||||
global.__SERVER_HOST__ = server.host;
|
||||
global.__SERVER_PORT__ = server.port;
|
||||
}
|
||||
|
||||
// preload tls cert or tls key
|
||||
if (__TRANSPORT__ === 'tls') {
|
||||
logger.info(`[config] loading ${server.tls_cert}`);
|
||||
global.__TLS_CERT__ = fs.readFileSync(path.resolve(process.cwd(), server.tls_cert));
|
||||
global.__TLS_CERT__ = loadFileSync(server.tls_cert);
|
||||
if (__IS_SERVER__) {
|
||||
logger.info(`[config] loading ${server.tls_key}`);
|
||||
global.__TLS_KEY__ = fs.readFileSync(path.resolve(process.cwd(), server.tls_key));
|
||||
global.__TLS_KEY__ = loadFileSync(server.tls_key);
|
||||
}
|
||||
}
|
||||
global.__SERVER_HOST__ = server.host;
|
||||
global.__SERVER_PORT__ = server.port;
|
||||
|
||||
global.__KEY__ = server.key;
|
||||
global.__PRESETS__ = server.presets;
|
||||
}
|
||||
@ -90,14 +118,18 @@ export class Config {
|
||||
throw Error('invalid configuration file');
|
||||
}
|
||||
|
||||
// host
|
||||
if (typeof json.host !== 'string' || json.host === '') {
|
||||
throw Error('\'host\' must be provided and is not empty');
|
||||
}
|
||||
|
||||
// port
|
||||
if (!isValidPort(json.port)) {
|
||||
throw Error('\'port\' is invalid');
|
||||
// service
|
||||
if (json.service !== undefined) {
|
||||
Config._validateService(json);
|
||||
} else {
|
||||
// host
|
||||
if (!isValidHostname(json.host)) {
|
||||
throw Error('\'host\' is invalid');
|
||||
}
|
||||
// port
|
||||
if (!isValidPort(json.port)) {
|
||||
throw Error('\'port\' is invalid');
|
||||
}
|
||||
}
|
||||
|
||||
// servers
|
||||
@ -211,8 +243,8 @@ export class Config {
|
||||
static _validateServer(server) {
|
||||
// transport
|
||||
if (server.transport !== undefined) {
|
||||
if (!['tcp', 'tls', 'websocket'].includes(server.transport)) {
|
||||
throw Error('\'server.transport\' must be "tcp", "tls" or "websocket"');
|
||||
if (!['tcp', 'tls', 'ws'].includes(server.transport)) {
|
||||
throw Error('\'server.transport\' must be "tcp", "tls" or "ws"');
|
||||
}
|
||||
if (server.transport === 'tls') {
|
||||
if (typeof server.tls_cert !== 'string') {
|
||||
@ -224,14 +256,18 @@ export class Config {
|
||||
}
|
||||
}
|
||||
|
||||
// host
|
||||
if (!isValidHostname(server.host)) {
|
||||
throw Error('\'server.host\' is invalid');
|
||||
}
|
||||
|
||||
// port
|
||||
if (!isValidPort(server.port)) {
|
||||
throw Error('\'server.port\' is invalid');
|
||||
// service
|
||||
if (server.service !== undefined) {
|
||||
Config._validateService(server);
|
||||
} else {
|
||||
// host
|
||||
if (!isValidHostname(server.host)) {
|
||||
throw Error('\'server.host\' is invalid');
|
||||
}
|
||||
// port
|
||||
if (!isValidPort(server.port)) {
|
||||
throw Error('\'server.port\' is invalid');
|
||||
}
|
||||
}
|
||||
|
||||
// key
|
||||
@ -268,4 +304,32 @@ export class Config {
|
||||
}
|
||||
}
|
||||
|
||||
static _validateService(json) {
|
||||
const {protocol, hostname: host, port} = url.parse(json.service);
|
||||
// protocol
|
||||
if (typeof protocol !== 'string') {
|
||||
throw Error('service protocol is invalid');
|
||||
}
|
||||
const _protocol = protocol.slice(0, -1);
|
||||
if (!AVAILABLE_PROTOCOLS.includes(_protocol)) {
|
||||
throw Error(`service protocol must be: ${AVAILABLE_PROTOCOLS.join(', ')}`);
|
||||
}
|
||||
if (_protocol === 'tls') {
|
||||
if (typeof json.tls_cert !== 'string' || json.tls_cert === '') {
|
||||
throw Error('\'tls_cert\' must be set');
|
||||
}
|
||||
if (json.tls_key !== undefined && typeof json.tls_key !== 'string') {
|
||||
throw Error('\'tls_key\' must be set');
|
||||
}
|
||||
}
|
||||
// host
|
||||
if (!isValidHostname(host)) {
|
||||
throw Error('service host is invalid');
|
||||
}
|
||||
// port
|
||||
if (!isValidPort(+port)) {
|
||||
throw Error('service port is invalid');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user