WIP: http2 transport
This commit is contained in:
parent
be9dd7adcc
commit
a706f42f7d
@ -122,11 +122,13 @@ export class Config {
|
||||
this.server_host = hostname;
|
||||
this.server_port = +port;
|
||||
|
||||
// preload tls_cert or tls_key
|
||||
if (this.transport === 'tls') {
|
||||
logger.info(`[config] loading ${server.tls_cert}`);
|
||||
this.tls_cert = loadFileSync(server.tls_cert);
|
||||
if (this.is_server) {
|
||||
// preload tls_cert and tls_key
|
||||
if (this.transport === 'tls' || this.transport === 'h2') {
|
||||
if (server.tls_cert) {
|
||||
logger.info(`[config] loading ${server.tls_cert}`);
|
||||
this.tls_cert = loadFileSync(server.tls_cert);
|
||||
}
|
||||
if (this.is_server && server.tls_key) {
|
||||
logger.info(`[config] loading ${server.tls_key}`);
|
||||
this.tls_key = loadFileSync(server.tls_key);
|
||||
}
|
||||
@ -336,14 +338,14 @@ export class Config {
|
||||
|
||||
const protocol = _protocol.slice(0, -1);
|
||||
const available_server_protocols = [
|
||||
'tcp', 'ws', 'tls'
|
||||
'tcp', 'ws', 'tls', 'h2'
|
||||
];
|
||||
if (!available_server_protocols.includes(protocol)) {
|
||||
throw Error(`service.protocol must be: ${available_server_protocols.join(', ')}`);
|
||||
}
|
||||
|
||||
// tls_cert, tls_key
|
||||
if (protocol === 'tls') {
|
||||
if (protocol === 'tls' || protocol === 'h2') {
|
||||
if (typeof server.tls_cert !== 'string' || server.tls_cert === '') {
|
||||
throw Error('"tls_cert" must be provided');
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import _sodium from 'libsodium-wrappers';
|
||||
import dgram from 'dgram';
|
||||
import net from 'net';
|
||||
import { URL } from 'url';
|
||||
import http2 from 'http2';
|
||||
import tls from 'tls';
|
||||
import ws from 'ws';
|
||||
import LRU from 'lru-cache';
|
||||
@ -225,6 +226,12 @@ export class Hub {
|
||||
server.listen(address, () => onListening(server));
|
||||
break;
|
||||
}
|
||||
case 'h2': {
|
||||
server = http2.createSecureServer({ key: tls_key, cert: tls_cert });
|
||||
server.on('stream', (stream) => this._onConnection(stream));
|
||||
server.listen(address, () => onListening(server));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return reject(Error(`unsupported protocol: "${local_protocol}"`));
|
||||
}
|
||||
@ -308,19 +315,16 @@ export class Hub {
|
||||
this._upSpeedTester.feed(size);
|
||||
};
|
||||
|
||||
_onConnection = (socket, proxyRequest = null) => {
|
||||
logger.verbose(`[hub] [${socket.remoteAddress}:${socket.remotePort}] connected`);
|
||||
_onConnection = (conn, proxyRequest = null) => {
|
||||
const sourceAddress = this._getSourceAddress(conn);
|
||||
const updateConnStatus = (event, extra) => this._updateConnStatus(event, sourceAddress, extra);
|
||||
|
||||
const sourceAddress = { host: socket.remoteAddress, port: socket.remotePort };
|
||||
|
||||
const updateConnStatus = (event, extra) => {
|
||||
this._updateConnStatus(event, sourceAddress, extra);
|
||||
};
|
||||
logger.verbose(`[hub] [${sourceAddress.host}:${sourceAddress.port}] connected`);
|
||||
|
||||
updateConnStatus('new');
|
||||
|
||||
const context = {
|
||||
socket,
|
||||
socket: conn,
|
||||
proxyRequest,
|
||||
remoteInfo: sourceAddress,
|
||||
};
|
||||
@ -366,6 +370,18 @@ export class Hub {
|
||||
this._tcpRelays.set(relay.id, relay);
|
||||
};
|
||||
|
||||
_getSourceAddress(conn) {
|
||||
let sourceHost, sourcePort;
|
||||
if (conn.session) {
|
||||
sourceHost = conn.session.socket.remoteAddress;
|
||||
sourcePort = conn.session.socket.remotePort;
|
||||
} else {
|
||||
sourceHost = conn.remoteAddress;
|
||||
sourcePort = conn.remotePort;
|
||||
}
|
||||
return { host: sourceHost, port: sourcePort };
|
||||
}
|
||||
|
||||
_getMuxRelayOnClient(context, cid) {
|
||||
// get a mux relay
|
||||
let muxRelay = this._selectMuxRelay();
|
||||
|
@ -8,6 +8,7 @@ import {
|
||||
TcpInbound, TcpOutbound,
|
||||
UdpInbound, UdpOutbound,
|
||||
TlsInbound, TlsOutbound,
|
||||
Http2Inbound, Http2Outbound,
|
||||
WsInbound, WsOutbound,
|
||||
MuxInbound, MuxOutbound,
|
||||
} from '../transports';
|
||||
@ -131,6 +132,7 @@ export class Relay extends EventEmitter {
|
||||
'tcp': [TcpInbound, TcpOutbound],
|
||||
'udp': [UdpInbound, UdpOutbound],
|
||||
'tls': [TlsInbound, TlsOutbound],
|
||||
'h2': [Http2Inbound, Http2Outbound],
|
||||
'ws': [WsInbound, WsOutbound],
|
||||
'mux': [MuxInbound, MuxOutbound],
|
||||
};
|
||||
|
27
src/transports/h2.js
Normal file
27
src/transports/h2.js
Normal file
@ -0,0 +1,27 @@
|
||||
import http2 from 'http2';
|
||||
import { TcpInbound, TcpOutbound } from './tcp';
|
||||
import { logger } from '../utils';
|
||||
|
||||
const { HTTP2_HEADER_PATH } = http2.constants;
|
||||
|
||||
export class Http2Inbound extends TcpInbound {
|
||||
|
||||
get name() {
|
||||
return 'h2:inbound';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class Http2Outbound extends TcpOutbound {
|
||||
|
||||
get name() {
|
||||
return 'h2:outbound';
|
||||
}
|
||||
|
||||
async _connect({ host, port }) {
|
||||
logger.info(`[h2:outbound] [${this.remote}] connecting to h2://${host}:${port}`);
|
||||
const session = http2.connect(`https://${host}:${port}`, { ca: [this._config.tls_cert] });
|
||||
return session.request({ [HTTP2_HEADER_PATH]: '/' });
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
export * from './tcp';
|
||||
export * from './udp';
|
||||
export * from './tls';
|
||||
export * from './h2';
|
||||
export * from './ws';
|
||||
export * from './mux';
|
||||
|
Loading…
Reference in New Issue
Block a user