@@ -112,7 +112,9 @@ void OnSteamNetConnectionStatusChanged(SteamNetConnectionStatusChangedCallback_t
112112 NGMP_OnlineServices_LobbyInterface* pJoinOrderLobby = NGMP_OnlineServicesManager::GetInterface<NGMP_OnlineServices_LobbyInterface>();
113113 const bool bWeJoinedLater = pJoinOrderLobby == nullptr || !pJoinOrderLobby->IsJoinOrderKnown () || pJoinOrderLobby->JoinedAfter (userID);
114114 const bool bPeerLeft = pJoinOrderLobby != nullptr && pJoinOrderLobby->IsJoinOrderKnown () && !pJoinOrderLobby->IsLobbyMember (userID);
115- bool bShouldRetry = serviceConf.retry_signalling && ((!bWeJoinedLater && !bPeerLeft) || signallingAttemptsBeforeDisconnect < numSignallingAttempts);
115+ // a match can't leave its lobby, so keep repairing the link until the game drops the player
116+ const bool bInMatch = TheGameLogic != nullptr && TheGameLogic->isInInternetGame ();
117+ bool bShouldRetry = serviceConf.retry_signalling && (bInMatch || (!bWeJoinedLater && !bPeerLeft) || signallingAttemptsBeforeDisconnect < numSignallingAttempts);
116118
117119 bool bWasError = pInfo->m_info .m_eState == k_ESteamNetworkingConnectionState_ProblemDetectedLocally || pInfo->m_info .m_eEndReason != k_ESteamNetConnectionEnd_App_Generic;
118120 plrConnection.SetDisconnected (bWasError, pMesh, bShouldRetry && bWasError);
@@ -173,7 +175,12 @@ void OnSteamNetConnectionStatusChanged(SteamNetConnectionStatusChangedCallback_t
173175 NetworkLog (ELogVerbosity::LOG_RELEASE , " [STEAM NETWORKING][DISCONNECT HANDLER] Not retrying, handling disconnect as failure..." );
174176
175177 NGMP_OnlineServices_LobbyInterface* pLobbyInterface = NGMP_OnlineServicesManager::GetInterface<NGMP_OnlineServices_LobbyInterface>();
176- if (pLobbyInterface != nullptr )
178+ if (pLobbyInterface != nullptr && pLobbyInterface->IsHost ())
179+ {
180+ // the host keeps its lobby; the peer that can't connect is the one to go
181+ NetworkLog (ELogVerbosity::LOG_RELEASE , " [STEAM NETWORKING][DISCONNECT HANDLER] Not leaving, we host this lobby; dropping user %lld only" , userID);
182+ }
183+ else if (pLobbyInterface != nullptr )
177184 {
178185 NetworkLog (ELogVerbosity::LOG_RELEASE , " [STEAM NETWORKING][DISCONNECT HANDLER] Performing local removal for user %lld from lobby due to failure to connect\n " , userID);
179186
@@ -871,6 +878,14 @@ void NetworkMesh::StartConnectionSignalling(const char* szMiddlewareID, int64_t
871878 }
872879 else
873880 {
881+ // no relay without our TURN credentials
882+ if (m_bAwaitingTurnCredentials)
883+ {
884+ NetworkLog (ELogVerbosity::LOG_RELEASE , " [SIGNAL] Holding signalling with %lld until our TURN credentials arrive" , remoteUserID);
885+ m_vecSignallingAwaitingTurn.push_back ({ szMiddlewareID != nullptr ? szMiddlewareID : " " , remoteUserID, preferredPort });
886+ return ;
887+ }
888+
874889 // if we already have a connection to this use, drop it, having a single-direction connection will break signalling
875890 int previousAttempts = 0 ;
876891 auto it = m_mapConnections.find (remoteUserID);
@@ -992,7 +1007,44 @@ void NetworkMesh::StartConnectionSignalling(const char* szMiddlewareID, int64_t
9921007 m_mapConnections[remoteUserID].m_SignallingAttempts = previousAttempts + 1 ;
9931008 }
9941009 }
995-
1010+
1011+ }
1012+
1013+ void NetworkMesh::AwaitTurnCredentials ()
1014+ {
1015+ std::lock_guard<std::recursive_mutex> lock (m_mapConnectionsMutex);
1016+ m_bAwaitingTurnCredentials = true ;
1017+ }
1018+
1019+ void NetworkMesh::SetTurnCredentials (const std::string& strUsername, const std::string& strToken)
1020+ {
1021+ std::vector<PendingSignalling> vecPending;
1022+ {
1023+ std::lock_guard<std::recursive_mutex> lock (m_mapConnectionsMutex);
1024+
1025+ m_strTurnUsername = strUsername;
1026+ m_strTurnToken = strToken;
1027+ m_strTurnUsernameString = std::format (" {},{}" , m_strTurnUsername.c_str (), m_strTurnUsername.c_str ());
1028+ m_strTurnTokenString = std::format (" {},{}" , m_strTurnToken.c_str (), m_strTurnToken.c_str ());
1029+
1030+ // incoming connections use the listen socket's TURN settings
1031+ if (m_hListenSock != k_HSteamListenSocket_Invalid)
1032+ {
1033+ SteamNetworkingUtils ()->SetConfigValue (k_ESteamNetworkingConfig_P2P_TURN_UserList, k_ESteamNetworkingConfig_ListenSocket,
1034+ (intptr_t )m_hListenSock, k_ESteamNetworkingConfig_String, m_strTurnUsernameString.c_str ());
1035+ SteamNetworkingUtils ()->SetConfigValue (k_ESteamNetworkingConfig_P2P_TURN_PassList, k_ESteamNetworkingConfig_ListenSocket,
1036+ (intptr_t )m_hListenSock, k_ESteamNetworkingConfig_String, m_strTurnTokenString.c_str ());
1037+ }
1038+
1039+ m_bAwaitingTurnCredentials = false ;
1040+ vecPending.swap (m_vecSignallingAwaitingTurn);
1041+ }
1042+
1043+ NetworkLog (ELogVerbosity::LOG_RELEASE , " [SIGNAL] Got TURN credentials, starting %d held signalling request(s)" , (int )vecPending.size ());
1044+ for (const PendingSignalling& pending : vecPending)
1045+ {
1046+ StartConnectionSignalling (pending.strMiddlewareID .c_str (), pending.remoteUserID , pending.preferredPort );
1047+ }
9961048}
9971049
9981050
0 commit comments