Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
S
srvpro
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nanahira
srvpro
Commits
cb52f62b
Commit
cb52f62b
authored
Feb 11, 2026
by
nanahira
1
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'neos-split' of ../srvpro into develop
parents
ffe6f9a1
5ecb95fa
Pipeline
#43050
passed with stages
in 7 minutes and 27 seconds
Changes
5
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
277 additions
and
19 deletions
+277
-19
data/default_config.json
data/default_config.json
+1
-0
tcp-protocol-detector.js
tcp-protocol-detector.js
+71
-0
tcp-protocol-detector.ts
tcp-protocol-detector.ts
+85
-0
ygopro-server.coffee
ygopro-server.coffee
+58
-8
ygopro-server.js
ygopro-server.js
+62
-11
No files found.
data/default_config.json
View file @
cb52f62b
...
@@ -242,6 +242,7 @@
...
@@ -242,6 +242,7 @@
"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"
:
{
...
...
tcp-protocol-detector.js
0 → 100644
View file @
cb52f62b
"
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
);
}
tcp-protocol-detector.ts
0 → 100644
View file @
cb52f62b
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
);
}
ygopro-server.coffee
View file @
cb52f62b
...
@@ -12,6 +12,7 @@ spawnSync = require('child_process').spawnSync
...
@@ -12,6 +12,7 @@ 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'
...
@@ -739,6 +740,52 @@ init = () ->
...
@@ -739,6 +740,52 @@ init = () ->
,
1000
,
1000
log
.
info
(
"Starting server."
)
log
.
info
(
"Starting server."
)
# 用于存储 neos 相关的服务器对象
neosHttpServer
=
null
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
,
->
net
.
createServer
(
netRequestHandler
).
listen
settings
.
port
,
->
log
.
info
"server started"
,
settings
.
port
log
.
info
"server started"
,
settings
.
port
return
return
...
@@ -750,6 +797,7 @@ init = () ->
...
@@ -750,6 +797,7 @@ 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
)
...
@@ -762,7 +810,8 @@ init = () ->
...
@@ -762,7 +810,8 @@ 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
if
settings
.
modules
.
neos
.
enabled
and
not
neosReuseMainPort
# neos 启用但不复用主端口,单独监听
ws
=
require
'ws'
ws
=
require
'ws'
neosHttpServer
=
null
neosHttpServer
=
null
if
settings
.
modules
.
http
.
ssl
.
enabled
if
settings
.
modules
.
http
.
ssl
.
enabled
...
@@ -772,6 +821,7 @@ init = () ->
...
@@ -772,6 +821,7 @@ 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"
,
...
...
ygopro-server.js
View file @
cb52f62b
// 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
,
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
,
t
cpDetector
,
t
ips
,
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,6 +26,8 @@
...
@@ -26,6 +26,8 @@
// ts utility
// ts utility
utility
=
require
(
'
./utility.js
'
);
utility
=
require
(
'
./utility.js
'
);
tcpDetector
=
require
(
'
./tcp-protocol-detector.js
'
);
// 三方库
// 三方库
_
=
global
.
_
=
require
(
'
underscore
'
);
_
=
global
.
_
=
require
(
'
underscore
'
);
...
@@ -416,7 +418,7 @@
...
@@ -416,7 +418,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
,
main
_http_server
,
mkdirList
,
n
,
neosHttpServer
,
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
TcpServer
,
main_http_server
,
mkdirList
,
n
,
neosHttpServer
,
neosReuseMainPort
,
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
();
...
@@ -959,20 +961,67 @@
...
@@ -959,20 +961,67 @@
return
results
;
return
results
;
},
1000
);
},
1000
);
log
.
info
(
"
Starting server.
"
);
log
.
info
(
"
Starting server.
"
);
// 用于存储 neos 相关的服务器对象
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
()
{
net
.
createServer
(
netRequestHandler
).
listen
(
settings
.
port
,
function
()
{
log
.
info
(
"
server started
"
,
settings
.
port
);
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
;
...
@@ -981,7 +1030,8 @@
...
@@ -981,7 +1030,8 @@
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
)
{
if
(
settings
.
modules
.
neos
.
enabled
&&
!
neosReuseMainPort
)
{
// neos 启用但不复用主端口,单独监听
ws
=
require
(
'
ws
'
);
ws
=
require
(
'
ws
'
);
neosHttpServer
=
null
;
neosHttpServer
=
null
;
if
(
settings
.
modules
.
http
.
ssl
.
enabled
)
{
if
(
settings
.
modules
.
http
.
ssl
.
enabled
)
{
...
@@ -994,6 +1044,7 @@
...
@@ -994,6 +1044,7 @@
});
});
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
++
)
{
...
...
nanahira
@nanahira
mentioned in commit
c3621213
·
Feb 11, 2026
mentioned in commit
c3621213
mentioned in commit c3621213436a2532ab58ba020f7698ad91becada
Toggle commit list
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment