diff --git a/MUNGA_L4/L4STEAMTRANSPORT.cpp b/MUNGA_L4/L4STEAMTRANSPORT.cpp index 6e38734..ba4c55a 100644 --- a/MUNGA_L4/L4STEAMTRANSPORT.cpp +++ b/MUNGA_L4/L4STEAMTRANSPORT.cpp @@ -157,10 +157,13 @@ namespace } //--------------------------------------------------------------- - // Status-changed callback (fires inside SteamAPI_RunCallbacks on - // the game thread): accept incoming, queue connected, mark drops + // Status-changed handler (fires inside SteamAPI_RunCallbacks on + // the game thread): accept incoming, queue connected, mark drops. + // Registered through the CCallback dispatcher below - the + // config-value function pointer is NOT dispatched by the steam_api + // flavor of the library (Valve's own example uses STEAM_CALLBACK). //--------------------------------------------------------------- - void __cdecl + void OnConnectionStatusChanged(SteamNetConnectionStatusChangedCallback_t *status) { switch (status->m_info.m_eState) @@ -219,6 +222,25 @@ namespace } } + //--------------------------------------------------------------- + // The callback listener: constructed after SteamAPI_Init so the + // CCallback registration lands in a live callback manager + //--------------------------------------------------------------- + class SteamTransportCallbacks + { + public: + STEAM_CALLBACK(SteamTransportCallbacks, OnStatusChanged, + SteamNetConnectionStatusChangedCallback_t); + }; + + void SteamTransportCallbacks::OnStatusChanged( + SteamNetConnectionStatusChangedCallback_t *status) + { + OnConnectionStatusChanged(status); + } + + SteamTransportCallbacks *gCallbacks = NULL; + //--------------------------------------------------------------- // The transport //--------------------------------------------------------------- @@ -306,11 +328,6 @@ namespace << inet_ntoa(remote->sin_addr) << ":" << ntohs(remote->sin_port) << " (fake port " << fake_port << ")...\n" << std::flush; - SteamNetworkingConfigValue_t option; - option.SetPtr( - k_ESteamNetworkingConfig_Callback_ConnectionStatusChanged, - (void *) &OnConnectionStatusChanged); - SteamNetworkingIPAddr target; target.Clear(); target.SetIPv4(remote_fake_ip, fake_port); @@ -323,7 +340,7 @@ namespace { ++attempt; HSteamNetConnection handle = - SteamNetworkingSockets()->ConnectByIPAddress(target, 1, &option); + SteamNetworkingSockets()->ConnectByIPAddress(target, 0, NULL); if (handle == k_HSteamNetConnection_Invalid) { DEBUG_STREAM << "SteamNetTransport: ConnectByIPAddress refused the call\n" << std::flush; @@ -419,13 +436,8 @@ namespace << local_port << " (fake port " << gLocalFakePorts[index] << ")...\n" << std::flush; - SteamNetworkingConfigValue_t option; - option.SetPtr( - k_ESteamNetworkingConfig_Callback_ConnectionStatusChanged, - (void *) &OnConnectionStatusChanged); - HSteamListenSocket handle = - SteamNetworkingSockets()->CreateListenSocketP2PFakeIP(index, 1, &option); + SteamNetworkingSockets()->CreateListenSocketP2PFakeIP(index, 0, NULL); if (handle == k_HSteamListenSocket_Invalid) { return InvalidConnection; @@ -615,6 +627,12 @@ Logical return False; } + // connection status arrives through the CCallback dispatcher + if (gCallbacks == NULL) + { + gCallbacks = new SteamTransportCallbacks; + } + SteamNetworkingUtils()->InitRelayNetworkAccess(); if (!SteamNetworkingSockets()->BeginAsyncRequestFakeIP(2)) @@ -664,6 +682,63 @@ Logical gSteamReady = True; NetTransport_Set(&gSteamTransport); + + // + // dev: RP412STEAMSELFTEST=1 loops a connection back to ourselves, + // proving the listen/accept/connect/send/receive machinery (and + // the status-callback dispatch) without a second machine + // + const char *self_test = getenv("RP412STEAMSELFTEST"); + if (self_test != NULL && atoi(self_test) != 0) + { + DEBUG_STREAM << "SteamNetTransport: SELF TEST starting\n" << std::flush; + SteamNetTransport_RegisterPeer( + gLocalFakeAddressString, gLocalFakePorts[0], gLocalFakePorts[1]); + + NetTransport *transport = &gSteamTransport; + NetTransport::Connection listener = transport->Listen(1501, 1); + + SOCKADDR_IN self_address; + transport->Resolve(gLocalFakeAddressString, &self_address); + self_address.sin_port = htons(1501); + NetTransport::Connection outgoing = transport->Connect(&self_address, 0); + + NetTransport::Connection incoming = NetTransport::InvalidConnection; + DWORD accept_deadline = GetTickCount() + 10 * 1000; + while (incoming == NetTransport::InvalidConnection && + (LONG)(GetTickCount() - accept_deadline) < 0) + { + incoming = transport->Accept(listener); + Sleep(50); + } + + Logical ok = False; + if (outgoing != NetTransport::InvalidConnection && + incoming != NetTransport::InvalidConnection) + { + transport->Send(outgoing, "PING", 4); + char buffer[16]; + DWORD recv_deadline = GetTickCount() + 5 * 1000; + while ((LONG)(GetTickCount() - recv_deadline) < 0) + { + if (transport->Receive(incoming, buffer, sizeof(buffer)) == 4) + { + ok = (memcmp(buffer, "PING", 4) == 0); + break; + } + Sleep(25); + } + } + DEBUG_STREAM << "SteamNetTransport: SELF TEST " + << (ok ? "PASSED" : "FAILED") + << " (out " << (outgoing != NetTransport::InvalidConnection) + << ", in " << (incoming != NetTransport::InvalidConnection) + << ")\n" << std::flush; + + // leave the session pristine for the real race + gSteamTransport.Cleanup(); + gPeerCount = 0; + } return True; }