Steam transport: identity-resolved accepts + load-proof timeout
Round four reached one step from the race: eggs delivered, both members ACKed with complete meshes, one member entered LoadingMission. Two failures remained, both now fixed. One: Steam reports incoming callers under locally-allocated ALIAS FakeIPs, not their global ones - the owner accepted both mesh legs but its identity check compared the alias against the egg address and never counted the connections (no Connected to GameMachineHost on the owner). The peer table now carries each member SteamID (lobby go roster gained a field) and Accept resolves the caller identity back to the global FakeIP the egg promised. Two: mission load stalls the game thread for 10-30s with nothing pumping, and Steam default 10s connected-timeout sheared every connection mid-load (end reason 4001, rx ages 11.5-20.5s - right at load duration). Connected timeout is now 90s; TCP never timed out an idle arcade link and races pump every frame once running. Self-test still green (ping, survives listener close). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -65,6 +65,7 @@ namespace
|
||||
unsigned long fakeIP; // host order
|
||||
unsigned short fakeConsolePort; // host order
|
||||
unsigned short fakeGamePort; // host order
|
||||
unsigned __int64 steamID; // identity -> global FakeIP on accept
|
||||
};
|
||||
|
||||
// engine-side port convention (lobby default; game port is +1)
|
||||
@@ -500,14 +501,38 @@ namespace
|
||||
}
|
||||
--listener->pendingCount;
|
||||
|
||||
// the remote engine port is the same engine port we accept
|
||||
// on: all pods share the -net convention under Steam
|
||||
//
|
||||
// The remote engine port is the same engine port we accept
|
||||
// on (all pods share the -net convention under Steam). The
|
||||
// caller's address: Steam reports incoming connections
|
||||
// under a locally-allocated ALIAS FakeIP, so resolve the
|
||||
// caller's identity through the peer table to the GLOBAL
|
||||
// FakeIP the egg's [pilots] list promised - the engine's
|
||||
// mesh identity checks compare against that.
|
||||
//
|
||||
unsigned long remote_ip_net = 0;
|
||||
SteamNetworkingIPAddr remote_fake;
|
||||
if (SteamNetworkingSockets()->GetRemoteFakeIPForConnection(
|
||||
handle, &remote_fake) == k_EResultOK)
|
||||
SteamNetConnectionInfo_t info;
|
||||
if (SteamNetworkingSockets()->GetConnectionInfo(handle, &info))
|
||||
{
|
||||
remote_ip_net = htonl(remote_fake.GetIPv4());
|
||||
unsigned __int64 caller_id = info.m_identityRemote.GetSteamID64();
|
||||
for (int p = 0; p < gPeerCount; ++p)
|
||||
{
|
||||
if (gPeers[p].steamID != 0 && gPeers[p].steamID == caller_id)
|
||||
{
|
||||
remote_ip_net = htonl(gPeers[p].fakeIP);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (remote_ip_net == 0)
|
||||
{
|
||||
// unregistered caller: fall back to the alias address
|
||||
SteamNetworkingIPAddr remote_fake;
|
||||
if (SteamNetworkingSockets()->GetRemoteFakeIPForConnection(
|
||||
handle, &remote_fake) == k_EResultOK)
|
||||
{
|
||||
remote_ip_net = htonl(remote_fake.GetIPv4());
|
||||
}
|
||||
}
|
||||
ConnectionRecord *record = AddConnection(
|
||||
handle, remote_ip_net, htons(listener->enginePort));
|
||||
@@ -676,6 +701,16 @@ Logical
|
||||
|
||||
SteamNetworkingUtils()->InitRelayNetworkAccess();
|
||||
|
||||
//
|
||||
// Mission load stalls the game thread for 10-30s with nothing
|
||||
// pumping - Steam's default 10s connected-timeout would shear
|
||||
// every connection mid-load (seen live: end reason 4001 with rx
|
||||
// ages right at load duration). TCP never timed out idle arcade
|
||||
// links; 90s keeps that spirit.
|
||||
//
|
||||
SteamNetworkingUtils()->SetGlobalConfigValueInt32(
|
||||
k_ESteamNetworkingConfig_TimeoutConnected, 90 * 1000);
|
||||
|
||||
if (!SteamNetworkingSockets()->BeginAsyncRequestFakeIP(2))
|
||||
{
|
||||
DEBUG_STREAM << "SteamNetTransport: BeginAsyncRequestFakeIP failed - staying on TCP\n" << std::flush;
|
||||
@@ -734,7 +769,8 @@ Logical
|
||||
{
|
||||
DEBUG_STREAM << "SteamNetTransport: SELF TEST starting\n" << std::flush;
|
||||
SteamNetTransport_RegisterPeer(
|
||||
gLocalFakeAddressString, gLocalFakePorts[0], gLocalFakePorts[1]);
|
||||
gLocalFakeAddressString, gLocalFakePorts[0], gLocalFakePorts[1],
|
||||
SteamUser()->GetSteamID().ConvertToUint64());
|
||||
|
||||
NetTransport *transport = &gSteamTransport;
|
||||
NetTransport::Connection listener = transport->Listen(1501, 1);
|
||||
@@ -833,7 +869,8 @@ void
|
||||
SteamNetTransport_RegisterPeer(
|
||||
const char *fake_ip,
|
||||
int fake_console_port,
|
||||
int fake_game_port
|
||||
int fake_game_port,
|
||||
unsigned __int64 steam_id
|
||||
)
|
||||
{
|
||||
SteamNetworkingIPAddr parsed;
|
||||
@@ -847,6 +884,7 @@ void
|
||||
{
|
||||
gPeers[i].fakeConsolePort = (unsigned short) fake_console_port;
|
||||
gPeers[i].fakeGamePort = (unsigned short) fake_game_port;
|
||||
gPeers[i].steamID = steam_id;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -857,10 +895,11 @@ void
|
||||
gPeers[gPeerCount].fakeIP = parsed.GetIPv4();
|
||||
gPeers[gPeerCount].fakeConsolePort = (unsigned short) fake_console_port;
|
||||
gPeers[gPeerCount].fakeGamePort = (unsigned short) fake_game_port;
|
||||
gPeers[gPeerCount].steamID = steam_id;
|
||||
++gPeerCount;
|
||||
DEBUG_STREAM << "SteamNetTransport: peer registered: " << fake_ip
|
||||
<< " (console " << fake_console_port << ", game "
|
||||
<< fake_game_port << ")\n" << std::flush;
|
||||
<< fake_game_port << ", id " << steam_id << ")\n" << std::flush;
|
||||
}
|
||||
|
||||
#endif // RP412_STEAM
|
||||
|
||||
@@ -81,13 +81,17 @@ int
|
||||
void
|
||||
SteamNetTransport_SetEnginePorts(int console_port);
|
||||
|
||||
// The lobby feeds every member's FakeIP + fake ports here before
|
||||
// anything dials out. Registering is idempotent per IP.
|
||||
// The lobby feeds every member's FakeIP + fake ports + SteamID here
|
||||
// before anything dials out. The SteamID matters on accept: Steam
|
||||
// reports incoming callers under locally-allocated alias addresses,
|
||||
// so the transport maps the caller's identity back to the global
|
||||
// FakeIP the egg promised. Registering is idempotent per IP.
|
||||
void
|
||||
SteamNetTransport_RegisterPeer(
|
||||
const char *fake_ip,
|
||||
int fake_console_port,
|
||||
int fake_game_port
|
||||
int fake_game_port,
|
||||
unsigned __int64 steam_id
|
||||
);
|
||||
|
||||
#endif // RP412_STEAM
|
||||
|
||||
+15
-6
@@ -205,7 +205,8 @@ namespace
|
||||
if (members[i].published)
|
||||
{
|
||||
SteamNetTransport_RegisterPeer(
|
||||
members[i].ip, members[i].consolePort, members[i].gamePort);
|
||||
members[i].ip, members[i].consolePort, members[i].gamePort,
|
||||
members[i].id.ConvertToUint64());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -513,13 +514,14 @@ namespace
|
||||
if (all_published && room.memberCount >= 1)
|
||||
{
|
||||
++gLastGoNonce;
|
||||
char go[600];
|
||||
char go[800];
|
||||
sprintf(go, "%d:", gLastGoNonce);
|
||||
for (int i = 0; i < room.memberCount; ++i)
|
||||
{
|
||||
char entry[64];
|
||||
sprintf(entry, "%s|%d|%d;", room.members[i].ip,
|
||||
room.members[i].consolePort, room.members[i].gamePort);
|
||||
char entry[96];
|
||||
sprintf(entry, "%s|%d|%d|%I64u;", room.members[i].ip,
|
||||
room.members[i].consolePort, room.members[i].gamePort,
|
||||
room.members[i].id.ConvertToUint64());
|
||||
if (strlen(go) + strlen(entry) < sizeof(go))
|
||||
{
|
||||
strcat(go, entry);
|
||||
@@ -554,6 +556,7 @@ namespace
|
||||
{
|
||||
char ip[32];
|
||||
int console_port = 0, game_port = 0;
|
||||
unsigned __int64 steam_id = 0;
|
||||
int n = 0;
|
||||
while (cursor[n] != '\0' && cursor[n] != '|' &&
|
||||
n < (int) sizeof(ip) - 1)
|
||||
@@ -571,13 +574,19 @@ namespace
|
||||
if (*cursor == '|')
|
||||
{
|
||||
game_port = atoi(++cursor);
|
||||
while (*cursor != '\0' && *cursor != '|' && *cursor != ';') ++cursor;
|
||||
}
|
||||
if (*cursor == '|')
|
||||
{
|
||||
steam_id = _strtoui64(++cursor, NULL, 10);
|
||||
}
|
||||
while (*cursor != '\0' && *cursor != ';') ++cursor;
|
||||
if (*cursor == ';') ++cursor;
|
||||
|
||||
if (ip[0] != '\0' && console_port > 0 && game_port > 0)
|
||||
{
|
||||
SteamNetTransport_RegisterPeer(ip, console_port, game_port);
|
||||
SteamNetTransport_RegisterPeer(
|
||||
ip, console_port, game_port, steam_id);
|
||||
}
|
||||
}
|
||||
outcome = LobbyLaunchMember;
|
||||
|
||||
Reference in New Issue
Block a user