feat: TCP server/client mode config, protocol display in settings
This commit is contained in:
@@ -17,6 +17,7 @@ DEFAULT_CONFIG: dict[str, Any] = {
|
|||||||
"theme": "dark",
|
"theme": "dark",
|
||||||
"sidebar_collapsed": False,
|
"sidebar_collapsed": False,
|
||||||
"telemetry_port": 20777,
|
"telemetry_port": 20777,
|
||||||
|
"tcp_port": 20778,
|
||||||
"use_unified_port": True,
|
"use_unified_port": True,
|
||||||
"game_ports": {},
|
"game_ports": {},
|
||||||
"ui_test_mode": False,
|
"ui_test_mode": False,
|
||||||
|
|||||||
@@ -107,13 +107,32 @@ class TelemetryListener:
|
|||||||
self._current_protocol = "udp"
|
self._current_protocol = "udp"
|
||||||
|
|
||||||
if self._current_protocol == "tcp":
|
if self._current_protocol == "tcp":
|
||||||
self._tcp = TCPListener(self._handle_packet)
|
import json as _json
|
||||||
ok = await self._tcp.start(host, port)
|
mode = "server"
|
||||||
if ok:
|
tcp_path = "/"
|
||||||
|
if selected_game:
|
||||||
|
gp = game_plugin_manager.get(selected_game)
|
||||||
|
if gp and gp.manifest_path:
|
||||||
|
try:
|
||||||
|
with open(f"{gp.manifest_path}/manifest.json", "r") as f:
|
||||||
|
m = _json.load(f)
|
||||||
|
mode = m.get("mode", "server")
|
||||||
|
tcp_path = m.get("path", "/")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if mode == "server":
|
||||||
|
self._tcp = TCPListener(self._handle_packet)
|
||||||
|
ok = await self._tcp.start(host, port)
|
||||||
|
if ok:
|
||||||
|
self._running = True
|
||||||
|
self.forwarder.reload_targets()
|
||||||
|
logger.info("TCP server started on %s:%d [game=%s]", host, port, selected_game or "none")
|
||||||
|
return ok
|
||||||
|
else:
|
||||||
|
logger.info("TCP client mode - awaiting manual connection to upstream")
|
||||||
self._running = True
|
self._running = True
|
||||||
self.forwarder.reload_targets()
|
return True
|
||||||
logger.info("TCP listener started on %s:%d [game=%s]", host, port, selected_game or "none")
|
|
||||||
return ok
|
|
||||||
else:
|
else:
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -221,7 +221,12 @@ const PageSettings = {
|
|||||||
|
|
||||||
_gamePortListHtml(games, cfg) {
|
_gamePortListHtml(games, cfg) {
|
||||||
const gamePorts = cfg.game_ports || {};
|
const gamePorts = cfg.game_ports || {};
|
||||||
return games.map(g => '<div class="game-port-row" style="display:flex;gap:8px;align-items:center;margin-bottom:6px"><span class="gp-id" style="width:140px;font-size:13px;color:var(--text-secondary)">' + g.name + '</span><input class="gp-port" type="number" value="' + (gamePorts[g.id] || g.default_port || 20777) + '" min="1024" max="65535" style="width:100px"><span style="font-size:11px;color:var(--text-tertiary)">默认: ' + (g.default_port || 20777) + '</span></div>').join('');
|
return games.map(g => {
|
||||||
|
const proto = g.protocol || 'udp';
|
||||||
|
const mode = g.mode || (proto === 'tcp' ? 'server' : '');
|
||||||
|
const protoLabel = proto.toUpperCase() + (mode ? '/' + mode : '');
|
||||||
|
return '<div class="game-port-row" style="display:flex;gap:8px;align-items:center;margin-bottom:6px"><span class="gp-id" style="width:120px;font-size:13px;color:var(--text-secondary)">' + g.name + '</span><span style="width:70px;font-size:11px;color:var(--text-tertiary)">' + protoLabel + '</span><input class="gp-port" type="number" value="' + (gamePorts[g.id] || g.default_port || (proto==='tcp'?cfg.tcp_port||20778:20777)) + '" min="1024" max="65535" style="width:100px"><span style="font-size:11px;color:var(--text-tertiary)">默认: ' + (g.default_port || (proto==='tcp'?cfg.tcp_port||20778:20777)) + '</span></div>';
|
||||||
|
}).join('');
|
||||||
},
|
},
|
||||||
|
|
||||||
_forwardListHtml(forwards) {
|
_forwardListHtml(forwards) {
|
||||||
|
|||||||
Reference in New Issue
Block a user