Commit c3621213 authored by nanahira's avatar nanahira

Revert "Merge branch 'neos-split' of ../srvpro into develop"

This reverts commit cb52f62b, reversing
changes made to ffe6f9a1.
parent cb52f62b
Pipeline #43057 failed with stages
in 9 minutes and 53 seconds
...@@ -242,7 +242,6 @@ ...@@ -242,7 +242,6 @@
"neos": { "neos": {
"enabled": false, "enabled": false,
"port": 7977, "port": 7977,
"reuse_port": false,
"ip_header": "x-forwarded-for" "ip_header": "x-forwarded-for"
}, },
"chatgpt": { "chatgpt": {
......
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isHttp = isHttp;
exports.isHttps = isHttps;
exports.detectAndHandle = detectAndHandle;
/**
* 检测 TCP 连接的第一个包是否为 HTTP 请求
* @param firstChunk 第一个数据包
* @returns 是否为 HTTP 请求
*/
function isHttp(firstChunk) {
if (!firstChunk || firstChunk.length === 0) {
return false;
}
const str = firstChunk.toString('ascii', 0, Math.min(firstChunk.length, 16));
// HTTP 请求方法
const httpMethods = [
'GET ', 'POST ', 'PUT ', 'DELETE ', 'HEAD ', 'OPTIONS ', 'PATCH ', 'TRACE ', 'CONNECT '
];
return httpMethods.some(method => str.startsWith(method));
}
/**
* 检测 TCP 连接的第一个包是否为 HTTPS 请求(TLS/SSL ClientHello)
* @param firstChunk 第一个数据包
* @returns 是否为 HTTPS 请求
*/
function isHttps(firstChunk) {
if (!firstChunk || firstChunk.length < 3) {
return false;
}
// TLS/SSL ClientHello 的特征:
// 第一个字节:0x16 (Handshake)
// 第二个字节:0x03 (SSL 3.0/TLS 1.x)
// 第三个字节:0x00-0x03 (版本号:SSL 3.0, TLS 1.0, 1.1, 1.2, 1.3)
return (firstChunk[0] === 0x16 &&
firstChunk[1] === 0x03 &&
firstChunk[2] >= 0x00 &&
firstChunk[2] <= 0x04);
}
/**
* 检测 TCP 连接的协议类型并调用相应的处理函数
* @param socket TCP socket
* @param httpHandler HTTP/HTTPS 处理函数
* @param defaultHandler 默认处理函数(非 HTTP/HTTPS)
* @param isHttpsMode 是否为 HTTPS 模式
*/
function detectAndHandle(socket, httpHandler, defaultHandler, isHttpsMode) {
let firstDataReceived = false;
const dataHandler = (chunk) => {
if (firstDataReceived) {
return;
}
firstDataReceived = true;
// 移除数据监听器,避免重复处理
socket.removeListener('data', dataHandler);
const isHttpRequest = isHttpsMode ? isHttps(chunk) : isHttp(chunk);
if (isHttpRequest) {
// 是 HTTP/HTTPS 请求,交给 HTTP 服务器处理
// 需要把第一个数据包重新放回去
socket.unshift(chunk);
httpHandler(socket, chunk);
}
else {
// 不是 HTTP/HTTPS 请求,交给默认处理器(YGOPro 协议)
// 同样需要把第一个数据包重新放回去
socket.unshift(chunk);
defaultHandler(socket);
}
};
socket.once('data', dataHandler);
}
import { Socket } from 'net';
/**
* 检测 TCP 连接的第一个包是否为 HTTP 请求
* @param firstChunk 第一个数据包
* @returns 是否为 HTTP 请求
*/
export function isHttp(firstChunk: Buffer): boolean {
if (!firstChunk || firstChunk.length === 0) {
return false;
}
const str = firstChunk.toString('ascii', 0, Math.min(firstChunk.length, 16));
// HTTP 请求方法
const httpMethods = [
'GET ', 'POST ', 'PUT ', 'DELETE ', 'HEAD ', 'OPTIONS ', 'PATCH ', 'TRACE ', 'CONNECT '
];
return httpMethods.some(method => str.startsWith(method));
}
/**
* 检测 TCP 连接的第一个包是否为 HTTPS 请求(TLS/SSL ClientHello)
* @param firstChunk 第一个数据包
* @returns 是否为 HTTPS 请求
*/
export function isHttps(firstChunk: Buffer): boolean {
if (!firstChunk || firstChunk.length < 3) {
return false;
}
// TLS/SSL ClientHello 的特征:
// 第一个字节:0x16 (Handshake)
// 第二个字节:0x03 (SSL 3.0/TLS 1.x)
// 第三个字节:0x00-0x03 (版本号:SSL 3.0, TLS 1.0, 1.1, 1.2, 1.3)
return (
firstChunk[0] === 0x16 &&
firstChunk[1] === 0x03 &&
firstChunk[2] >= 0x00 &&
firstChunk[2] <= 0x04
);
}
/**
* 检测 TCP 连接的协议类型并调用相应的处理函数
* @param socket TCP socket
* @param httpHandler HTTP/HTTPS 处理函数
* @param defaultHandler 默认处理函数(非 HTTP/HTTPS)
* @param isHttpsMode 是否为 HTTPS 模式
*/
export function detectAndHandle(
socket: Socket,
httpHandler: (socket: Socket, firstChunk: Buffer) => void,
defaultHandler: (socket: Socket) => void,
isHttpsMode: boolean
): void {
let firstDataReceived = false;
const dataHandler = (chunk: Buffer) => {
if (firstDataReceived) {
return;
}
firstDataReceived = true;
// 移除数据监听器,避免重复处理
socket.removeListener('data', dataHandler);
const isHttpRequest = isHttpsMode ? isHttps(chunk) : isHttp(chunk);
if (isHttpRequest) {
// 是 HTTP/HTTPS 请求,交给 HTTP 服务器处理
// 需要把第一个数据包重新放回去
socket.unshift(chunk);
httpHandler(socket, chunk);
} else {
// 不是 HTTP/HTTPS 请求,交给默认处理器(YGOPro 协议)
// 同样需要把第一个数据包重新放回去
socket.unshift(chunk);
defaultHandler(socket);
}
};
socket.once('data', dataHandler);
}
...@@ -12,7 +12,6 @@ spawnSync = require('child_process').spawnSync ...@@ -12,7 +12,6 @@ spawnSync = require('child_process').spawnSync
# ts utility # ts utility
utility = require './utility.js' utility = require './utility.js'
tcpDetector = require './tcp-protocol-detector.js'
# 三方库 # 三方库
_ = global._ = require 'underscore' _ = global._ = require 'underscore'
...@@ -740,55 +739,9 @@ init = () -> ...@@ -740,55 +739,9 @@ init = () ->
, 1000 , 1000
log.info("Starting server.") log.info("Starting server.")
net.createServer(netRequestHandler).listen settings.port, ->
# 用于存储 neos 相关的服务器对象 log.info "server started", settings.port
neosHttpServer = null return
neosWsServer = null
# 检查是否需要在主端口上复用检测 HTTP/HTTPS
neosReuseMainPort = settings.modules.neos.enabled and (
settings.modules.neos.port == settings.port or
settings.modules.neos.reuse_port
)
if neosReuseMainPort
# 需要复用主端口,创建 neos HTTP 服务器但不监听端口
log.info "neos will reuse main port #{settings.port}"
ws = require 'ws'
if settings.modules.http.ssl.enabled
https = require 'https'
httpsOptions =
cert: await fs.promises.readFile(settings.modules.http.ssl.cert)
key: await fs.promises.readFile(settings.modules.http.ssl.key)
neosHttpServer = https.createServer(httpsOptions)
else
neosHttpServer = http.createServer()
neosWsServer = new ws.WebSocketServer({server: neosHttpServer})
neosWsServer.on 'connection', neosRequestListener
# 创建主服务器,带协议检测
mainTcpServer = net.createServer (socket) ->
isHttpsMode = settings.modules.http.ssl.enabled
tcpDetector.detectAndHandle socket,
# HTTP/HTTPS 处理器
(sock, firstChunk) ->
# 将 socket 交给 neos HTTP 服务器处理
neosHttpServer.emit 'connection', sock
,
# 默认处理器(YGOPro 协议)
(sock) ->
netRequestHandler(sock)
,
isHttpsMode
mainTcpServer.listen settings.port, ->
log.info "server started with neos port reuse", settings.port
else
# 不需要复用,直接创建普通的 TCP 服务器
net.createServer(netRequestHandler).listen settings.port, ->
log.info "server started", settings.port
return
if settings.modules.stop if settings.modules.stop
log.info "NOTE: server not open due to config, ", settings.modules.stop log.info "NOTE: server not open due to config, ", settings.modules.stop
...@@ -797,11 +750,10 @@ init = () -> ...@@ -797,11 +750,10 @@ init = () ->
main_http_server = http_server main_http_server = http_server
if settings.modules.http.ssl.enabled if settings.modules.http.ssl.enabled
unless neosReuseMainPort # 如果没有在上面创建 https 相关对象 https = require 'https'
https = require 'https' httpsOptions =
httpsOptions = cert: await fs.promises.readFile(settings.modules.http.ssl.cert)
cert: await fs.promises.readFile(settings.modules.http.ssl.cert) key: await fs.promises.readFile(settings.modules.http.ssl.key)
key: await fs.promises.readFile(settings.modules.http.ssl.key)
https_server = https.createServer(httpsOptions, httpRequestListener) https_server = https.createServer(httpsOptions, httpRequestListener)
https_server.listen settings.modules.http.ssl.port https_server.listen settings.modules.http.ssl.port
main_http_server = https_server main_http_server = https_server
...@@ -810,8 +762,7 @@ init = () -> ...@@ -810,8 +762,7 @@ init = () ->
roomlist.init main_http_server, ROOM_all roomlist.init main_http_server, ROOM_all
http_server.listen settings.modules.http.port http_server.listen settings.modules.http.port
if settings.modules.neos.enabled and not neosReuseMainPort if settings.modules.neos.enabled
# neos 启用但不复用主端口,单独监听
ws = require 'ws' ws = require 'ws'
neosHttpServer = null neosHttpServer = null
if settings.modules.http.ssl.enabled if settings.modules.http.ssl.enabled
...@@ -821,7 +772,6 @@ init = () -> ...@@ -821,7 +772,6 @@ init = () ->
neosWsServer = new ws.WebSocketServer({server: neosHttpServer}) neosWsServer = new ws.WebSocketServer({server: neosHttpServer})
neosWsServer.on 'connection', neosRequestListener neosWsServer.on 'connection', neosRequestListener
neosHttpServer.listen settings.modules.neos.port neosHttpServer.listen settings.modules.neos.port
log.info "neos listening on separate port #{settings.modules.neos.port}"
mkdirList = [ mkdirList = [
"./plugins", "./plugins",
......
// Generated by CoffeeScript 2.7.0 // Generated by CoffeeScript 2.7.0
(function() { (function() {
// 标准库 // 标准库
var Aragami, CLIENT_check_vip, CLIENT_get_absolute_pos, CLIENT_get_authorize_key, CLIENT_get_kick_reconnect_target, CLIENT_get_partner, CLIENT_get_save_data, CLIENT_heartbeat_register, CLIENT_heartbeat_unregister, CLIENT_import_data, CLIENT_is_able_to_kick_reconnect, CLIENT_is_able_to_reconnect, CLIENT_is_banned_by_mc, CLIENT_is_player, CLIENT_kick, CLIENT_kick_reconnect, CLIENT_pre_reconnect, CLIENT_reconnect, CLIENT_reconnect_register, CLIENT_reconnect_unregister, CLIENT_send_pre_reconnect_info, CLIENT_send_reconnect_info, CLIENT_send_replays, CLIENT_send_replays_and_kick, CLIENT_send_vip_status, CLIENT_set_ip, CLIENT_use_cdkey, PQueue, ROOM_all, ROOM_bad_ip, ROOM_ban_player, ROOM_clear_disconnect, ROOM_connected_ip, ROOM_find_by_name, ROOM_find_by_pid, ROOM_find_by_port, ROOM_find_by_title, ROOM_find_or_create_ai, ROOM_find_or_create_by_name, ROOM_find_or_create_random, ROOM_kick, ROOM_player_flee, ROOM_player_get_score, ROOM_player_lose, ROOM_player_win, ROOM_players_oppentlist, ROOM_unwelcome, ROOM_validate, ReplayParser, ResolveData, Room, SERVER_clear_disconnect, SERVER_kick, SOCKET_flush_data, VIP_generate_cdkeys, YGOProDeck, YGOProMsg, YGOProYrp, _, addCallback, aragami, aragami_classes, athleticChecker, auth, axios, badwordR, badwords, ban_user, bunyan, call_match_api, challonge, checkFileExists, concat_name, createDirectoryIfNotExists, crypto, dataManager, deck_name_match, dialogues, disconnect_list, exec, execFile, extra_mode_list, fs, geoip, getDuelLogQueryFromQs, getRealIp, get_memory_usage, gpt_tokenizer, http, httpRequestListener, importOldConfig, import_datas, init, ip6addr, isTrustedProxy, lflists, loadJSON, loadJSONAsync, loadLFList, loadRemoteData, load_dialogues, load_dialogues_custom, load_tips, load_tips_zh, load_words, log, long_resolve_cards, memory_usage, merge, moment, moment_long_ago_string, moment_now, moment_now_string, msg_polyfill, mustache, neosRequestListener, net, netRequestHandler, os, osu, path, qs, real_windbot_server_ip, release_disconnect, report_to_big_brother, request, roomlist, rooms_count, setting_change, setting_get, setting_save, settings, spawn, spawnSync, spawn_windbot, tcpDetector, tips, toIpv4, toIpv6, util, utility, wait_room_start, wait_room_start_arena, windbot_looplimit, windbot_process, windbots, words, ygopro, zlib; var Aragami, CLIENT_check_vip, CLIENT_get_absolute_pos, CLIENT_get_authorize_key, CLIENT_get_kick_reconnect_target, CLIENT_get_partner, CLIENT_get_save_data, CLIENT_heartbeat_register, CLIENT_heartbeat_unregister, CLIENT_import_data, CLIENT_is_able_to_kick_reconnect, CLIENT_is_able_to_reconnect, CLIENT_is_banned_by_mc, CLIENT_is_player, CLIENT_kick, CLIENT_kick_reconnect, CLIENT_pre_reconnect, CLIENT_reconnect, CLIENT_reconnect_register, CLIENT_reconnect_unregister, CLIENT_send_pre_reconnect_info, CLIENT_send_reconnect_info, CLIENT_send_replays, CLIENT_send_replays_and_kick, CLIENT_send_vip_status, CLIENT_set_ip, CLIENT_use_cdkey, PQueue, ROOM_all, ROOM_bad_ip, ROOM_ban_player, ROOM_clear_disconnect, ROOM_connected_ip, ROOM_find_by_name, ROOM_find_by_pid, ROOM_find_by_port, ROOM_find_by_title, ROOM_find_or_create_ai, ROOM_find_or_create_by_name, ROOM_find_or_create_random, ROOM_kick, ROOM_player_flee, ROOM_player_get_score, ROOM_player_lose, ROOM_player_win, ROOM_players_oppentlist, ROOM_unwelcome, ROOM_validate, ReplayParser, ResolveData, Room, SERVER_clear_disconnect, SERVER_kick, SOCKET_flush_data, VIP_generate_cdkeys, YGOProDeck, YGOProMsg, YGOProYrp, _, addCallback, aragami, aragami_classes, athleticChecker, auth, axios, badwordR, badwords, ban_user, bunyan, call_match_api, challonge, checkFileExists, concat_name, createDirectoryIfNotExists, crypto, dataManager, deck_name_match, dialogues, disconnect_list, exec, execFile, extra_mode_list, fs, geoip, getDuelLogQueryFromQs, getRealIp, get_memory_usage, gpt_tokenizer, http, httpRequestListener, importOldConfig, import_datas, init, ip6addr, isTrustedProxy, lflists, loadJSON, loadJSONAsync, loadLFList, loadRemoteData, load_dialogues, load_dialogues_custom, load_tips, load_tips_zh, load_words, log, long_resolve_cards, memory_usage, merge, moment, moment_long_ago_string, moment_now, moment_now_string, msg_polyfill, mustache, neosRequestListener, net, netRequestHandler, os, osu, path, qs, real_windbot_server_ip, release_disconnect, report_to_big_brother, request, roomlist, rooms_count, setting_change, setting_get, setting_save, settings, spawn, spawnSync, spawn_windbot, tips, toIpv4, toIpv6, util, utility, wait_room_start, wait_room_start_arena, windbot_looplimit, windbot_process, windbots, words, ygopro, zlib;
net = require('net'); net = require('net');
...@@ -26,8 +26,6 @@ ...@@ -26,8 +26,6 @@
// ts utility // ts utility
utility = require('./utility.js'); utility = require('./utility.js');
tcpDetector = require('./tcp-protocol-detector.js');
// 三方库 // 三方库
_ = global._ = require('underscore'); _ = global._ = require('underscore');
...@@ -418,7 +416,7 @@ ...@@ -418,7 +416,7 @@
}; };
init = async function() { init = async function() {
var AthleticChecker, Challonge, DataManager, chat_color, config, cppversion, defaultConfig, default_data, dirPath, dns, e, expansions, get_rooms_count, http_server, https, httpsOptions, https_server, imported, j, key, keysFromEnv, l, len, len1, len2, len3, m, mainTcpServer, main_http_server, mkdirList, n, neosHttpServer, neosReuseMainPort, neosWsServer, plugin_filename, plugin_list, plugin_path, ref, settingKey, val, valFromDefault, vip_info, ws; var AthleticChecker, Challonge, DataManager, chat_color, config, cppversion, defaultConfig, default_data, dirPath, dns, e, expansions, get_rooms_count, http_server, https, httpsOptions, https_server, imported, j, key, keysFromEnv, l, len, len1, len2, len3, m, main_http_server, mkdirList, n, neosHttpServer, neosWsServer, plugin_filename, plugin_list, plugin_path, ref, settingKey, val, valFromDefault, vip_info, ws;
log.info('Reading config.'); log.info('Reading config.');
await createDirectoryIfNotExists("./config"); await createDirectoryIfNotExists("./config");
await importOldConfig(); await importOldConfig();
...@@ -961,67 +959,20 @@ ...@@ -961,67 +959,20 @@
return results; return results;
}, 1000); }, 1000);
log.info("Starting server."); log.info("Starting server.");
net.createServer(netRequestHandler).listen(settings.port, function() {
// 用于存储 neos 相关的服务器对象 log.info("server started", settings.port);
neosHttpServer = null; });
neosWsServer = null;
// 检查是否需要在主端口上复用检测 HTTP/HTTPS
neosReuseMainPort = settings.modules.neos.enabled && (settings.modules.neos.port === settings.port || settings.modules.neos.reuse_port);
if (neosReuseMainPort) {
// 需要复用主端口,创建 neos HTTP 服务器但不监听端口
log.info(`neos will reuse main port ${settings.port}`);
ws = require('ws');
if (settings.modules.http.ssl.enabled) {
https = require('https');
httpsOptions = {
cert: (await fs.promises.readFile(settings.modules.http.ssl.cert)),
key: (await fs.promises.readFile(settings.modules.http.ssl.key))
};
neosHttpServer = https.createServer(httpsOptions);
} else {
neosHttpServer = http.createServer();
}
neosWsServer = new ws.WebSocketServer({
server: neosHttpServer
});
neosWsServer.on('connection', neosRequestListener);
// 创建主服务器,带协议检测
mainTcpServer = net.createServer(function(socket) {
var isHttpsMode;
isHttpsMode = settings.modules.http.ssl.enabled;
// HTTP/HTTPS 处理器
return tcpDetector.detectAndHandle(socket, function(sock, firstChunk) {
// 将 socket 交给 neos HTTP 服务器处理
return neosHttpServer.emit('connection', sock);
// 默认处理器(YGOPro 协议)
}, function(sock) {
return netRequestHandler(sock);
}, isHttpsMode);
});
mainTcpServer.listen(settings.port, function() {
return log.info("server started with neos port reuse", settings.port);
});
} else {
// 不需要复用,直接创建普通的 TCP 服务器
net.createServer(netRequestHandler).listen(settings.port, function() {
log.info("server started", settings.port);
});
}
if (settings.modules.stop) { if (settings.modules.stop) {
log.info("NOTE: server not open due to config, ", settings.modules.stop); log.info("NOTE: server not open due to config, ", settings.modules.stop);
} }
http_server = http.createServer(httpRequestListener); http_server = http.createServer(httpRequestListener);
main_http_server = http_server; main_http_server = http_server;
if (settings.modules.http.ssl.enabled) { if (settings.modules.http.ssl.enabled) {
if (!neosReuseMainPort) { // 如果没有在上面创建 https 相关对象 https = require('https');
https = require('https'); httpsOptions = {
httpsOptions = { cert: (await fs.promises.readFile(settings.modules.http.ssl.cert)),
cert: (await fs.promises.readFile(settings.modules.http.ssl.cert)), key: (await fs.promises.readFile(settings.modules.http.ssl.key))
key: (await fs.promises.readFile(settings.modules.http.ssl.key)) };
};
}
https_server = https.createServer(httpsOptions, httpRequestListener); https_server = https.createServer(httpsOptions, httpRequestListener);
https_server.listen(settings.modules.http.ssl.port); https_server.listen(settings.modules.http.ssl.port);
main_http_server = https_server; main_http_server = https_server;
...@@ -1030,8 +981,7 @@ ...@@ -1030,8 +981,7 @@
roomlist.init(main_http_server, ROOM_all); roomlist.init(main_http_server, ROOM_all);
} }
http_server.listen(settings.modules.http.port); http_server.listen(settings.modules.http.port);
if (settings.modules.neos.enabled && !neosReuseMainPort) { if (settings.modules.neos.enabled) {
// neos 启用但不复用主端口,单独监听
ws = require('ws'); ws = require('ws');
neosHttpServer = null; neosHttpServer = null;
if (settings.modules.http.ssl.enabled) { if (settings.modules.http.ssl.enabled) {
...@@ -1044,7 +994,6 @@ ...@@ -1044,7 +994,6 @@
}); });
neosWsServer.on('connection', neosRequestListener); neosWsServer.on('connection', neosRequestListener);
neosHttpServer.listen(settings.modules.neos.port); neosHttpServer.listen(settings.modules.neos.port);
log.info(`neos listening on separate port ${settings.modules.neos.port}`);
} }
mkdirList = ["./plugins", settings.modules.tournament_mode.deck_path, settings.modules.tournament_mode.replay_path, settings.modules.tournament_mode.log_save_path, settings.modules.deck_log.local]; mkdirList = ["./plugins", settings.modules.tournament_mode.deck_path, settings.modules.tournament_mode.replay_path, settings.modules.tournament_mode.log_save_path, settings.modules.deck_log.local];
for (m = 0, len2 = mkdirList.length; m < len2; m++) { for (m = 0, len2 = mkdirList.length; m < len2; m++) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment