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,
replica, and remote-host code, and links Emscripten's `websocket.js` library.
`WebsocketGameClient.cpp` selects the browser WebSocket API on Emscripten; it
does not use Boost.Asio or Boost.Beast there.
- `wss://` (TLS) is supported by the Windows client only. `proj-windows` also defines
does not use Boost.Asio, Boost.Beast, or OpenSSL there. The browser performs
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
automatically at configure time (`cmake/ThirdParty.cmake`, section 12) using a
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`
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
network transport.
@@ -170,15 +171,24 @@ Run it from the repository root:
.\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
--address IP
--port N
```
Launch the Windows game and select `battle_zone_multiplayer`. The client connects to
`127.0.0.1:8080`. Selecting another campaign continues to use the local server.
Launch the Windows game and select `battle_zone_multiplayer`. The production client
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
+25
View File
@@ -32,6 +32,31 @@ bool waitFor(Predicate predicate)
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;
campaign.id = "test_lockstep";
campaign.networkPlayerSlots = {"player", "player2"};
+4
View File
@@ -564,6 +564,10 @@ namespace FRG
if (!endpoint.parse(kMultiplayerServerUrl)) {
logger() << "[network] Invalid multiplayer server URL: "
<< kMultiplayerServerUrl << std::endl;
remoteCampaignActive = false;
gameServer.use(internalGameServer);
gameServerHost.use(localGameServerHost);
return;
}
websocketGameClient = std::make_unique<WebsocketGameClient>(endpoint);
remoteGameServerHost =
+17 -5
View File
@@ -145,7 +145,7 @@ public:
attributes.createOnMainThread = EM_TRUE;
socket_ = emscripten_websocket_new(&attributes);
if (socket_ <= 0) {
fail("create WebSocket");
fail("create WebSocket", socket_);
return;
}
@@ -205,11 +205,21 @@ private:
}
static EM_BOOL onClose(
int, const EmscriptenWebSocketCloseEvent*, void* userData)
int, const EmscriptenWebSocketCloseEvent* event, void* userData)
{
auto* self = static_cast<Impl*>(userData);
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;
}
@@ -226,11 +236,13 @@ private:
return EM_TRUE;
}
void fail(const char* operation)
void fail(const char* operation, int result = 0)
{
connected_ = false;
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_;