Some fixes

This commit is contained in:
Vladislav Khorev committed 2026-11-10 18:31:53 +06:00
1 parent 28fb81ad45
commit 6b8aa0efec
4 files changed
+62 -11

No files matched your search

+16 -6
View File
@@ -144,14 +144,15 @@ Networking is enabled for Windows and the Emscripten web client:
- `proj-web/CMakeLists.txt` defines `NETWORK`, compiles the shared protocol, - `proj-web/CMakeLists.txt` defines `NETWORK`, compiles the shared protocol,
replica, and remote-host code, and links Emscripten's `websocket.js` library. replica, and remote-host code, and links Emscripten's `websocket.js` library.
`WebsocketGameClient.cpp` selects the browser WebSocket API on Emscripten; it `WebsocketGameClient.cpp` selects the browser WebSocket API on Emscripten; it
does not use Boost.Asio or Boost.Beast there. does not use Boost.Asio, Boost.Beast, or OpenSSL there. The browser performs
- `wss://` (TLS) is supported by the Windows client only. `proj-windows` also defines the TLS handshake and certificate/hostname validation for `wss://`.
- `proj-windows` defines
`NETWORK_TLS` and links static OpenSSL 3.4.1, which CMake downloads and builds `NETWORK_TLS` and links static OpenSSL 3.4.1, which CMake downloads and builds
automatically at configure time (`cmake/ThirdParty.cmake`, section 12) using a automatically at configure time (`cmake/ThirdParty.cmake`, section 12) using a
downloaded portable Strawberry Perl and the nmake from the installed Visual Studio downloaded portable Strawberry Perl and the nmake from the installed Visual Studio
(located through `vswhere`). Builds go to `thirdparty/openssl-3.4.1/install-Debug` (located through `vswhere`). Builds go to `thirdparty/openssl-3.4.1/install-Debug`
and `install-Release`; later configures skip them. `NETWORK_TLS` unset (server tests) and `install-Release`; later configures skip them. `NETWORK_TLS` unset (server tests)
means `wss://` endpoints fail with a logged error. means native `wss://` endpoints fail with a logged error.
- Linux and Android builds do not define `NETWORK` and do not compile the - Linux and Android builds do not define `NETWORK` and do not compile the
network transport. network transport.
@@ -170,15 +171,24 @@ Run it from the repository root:
.\server\build\Debug\GameServer.exe --campaign battle_zone_multiplayer --location uni_exterior .\server\build\Debug\GameServer.exe --campaign battle_zone_multiplayer --location uni_exterior
``` ```
The listener defaults to `0.0.0.0:8080`. It can be changed with: The listener defaults to `0.0.0.0:8080` and serves plain WebSocket traffic. It can be changed with:
```text ```text
--address IP --address IP
--port N --port N
``` ```
Launch the Windows game and select `battle_zone_multiplayer`. The client connects to Launch the Windows game and select `battle_zone_multiplayer`. The production client
`127.0.0.1:8080`. Selecting another campaign continues to use the local server. default is `wss://api.shadowoverbishkek.com/server001/`; the endpoint is currently
configured in `Game.cpp`. Selecting another campaign continues to use the local
server.
For the Web build, serve the page over HTTPS and ensure the TLS-terminating reverse
proxy presents a valid certificate for `api.shadowoverbishkek.com`, accepts the
WebSocket upgrade at `/server001/`, and forwards the upgraded connection to the
plain server listener. A page served over HTTPS cannot connect to a `ws://` endpoint
because browsers block that mixed-content request. Certificate and hostname errors
are enforced by the browser and cannot be bypassed by the C++ client.
## Verification ## Verification
+25
View File
@@ -32,6 +32,31 @@ bool waitFor(Predicate predicate)
int main() int main()
{ {
FRG::WebsocketEndpoint secureEndpoint;
require(
secureEndpoint.parse(
"wss://api.shadowoverbishkek.com/server001/"),
"secure WebSocket endpoint was rejected");
require(
secureEndpoint.host == "api.shadowoverbishkek.com" &&
secureEndpoint.port == "443" &&
secureEndpoint.path == "/server001/" &&
secureEndpoint.useTls,
"secure WebSocket endpoint was parsed incorrectly");
FRG::WebsocketEndpoint insecureEndpoint;
require(
insecureEndpoint.parse("ws://127.0.0.1:8080/"),
"insecure WebSocket endpoint was rejected");
require(
insecureEndpoint.host == "127.0.0.1" &&
insecureEndpoint.port == "8080" &&
!insecureEndpoint.useTls,
"insecure WebSocket endpoint was parsed incorrectly");
FRG::WebsocketEndpoint invalidEndpoint;
require(
!invalidEndpoint.parse("https://api.shadowoverbishkek.com/"),
"non-WebSocket endpoint was accepted");
FRG::CampaignConfig campaign; FRG::CampaignConfig campaign;
campaign.id = "test_lockstep"; campaign.id = "test_lockstep";
campaign.networkPlayerSlots = {"player", "player2"}; campaign.networkPlayerSlots = {"player", "player2"};
+4
View File
@@ -564,6 +564,10 @@ namespace FRG
if (!endpoint.parse(kMultiplayerServerUrl)) { if (!endpoint.parse(kMultiplayerServerUrl)) {
logger() << "[network] Invalid multiplayer server URL: " logger() << "[network] Invalid multiplayer server URL: "
<< kMultiplayerServerUrl << std::endl; << kMultiplayerServerUrl << std::endl;
remoteCampaignActive = false;
gameServer.use(internalGameServer);
gameServerHost.use(localGameServerHost);
return;
} }
websocketGameClient = std::make_unique<WebsocketGameClient>(endpoint); websocketGameClient = std::make_unique<WebsocketGameClient>(endpoint);
remoteGameServerHost = remoteGameServerHost =
+17 -5
View File
@@ -145,7 +145,7 @@ public:
attributes.createOnMainThread = EM_TRUE; attributes.createOnMainThread = EM_TRUE;
socket_ = emscripten_websocket_new(&attributes); socket_ = emscripten_websocket_new(&attributes);
if (socket_ <= 0) { if (socket_ <= 0) {
fail("create WebSocket"); fail("create WebSocket", socket_);
return; return;
} }
@@ -205,11 +205,21 @@ private:
} }
static EM_BOOL onClose( static EM_BOOL onClose(
int, const EmscriptenWebSocketCloseEvent*, void* userData) int, const EmscriptenWebSocketCloseEvent* event, void* userData)
{ {
auto* self = static_cast<Impl*>(userData); auto* self = static_cast<Impl*>(userData);
self->connected_ = false; self->connected_ = false;
if (!self->closing_) self->fail("WebSocket close"); if (!self->closing_) {
std::cerr << "[network] WebSocket closed";
if (event) {
std::cerr << " (code " << event->code;
if (event->reason[0] != '\0')
std::cerr << ", reason: " << event->reason;
std::cerr << ')';
}
std::cerr << '\n';
self->connectionFailed_ = true;
}
return EM_TRUE; return EM_TRUE;
} }
@@ -226,11 +236,13 @@ private:
return EM_TRUE; return EM_TRUE;
} }
void fail(const char* operation) void fail(const char* operation, int result = 0)
{ {
connected_ = false; connected_ = false;
connectionFailed_ = true; connectionFailed_ = true;
std::cerr << "[network] " << operation << " failed" << std::endl; std::cerr << "[network] " << operation << " failed";
if (result != 0) std::cerr << " (result " << result << ')';
std::cerr << std::endl;
} }
std::string host_; std::string host_;