diff --git a/src/steamnetworkingsockets/clientlib/steamnetworkingsockets_ice_client.cpp b/src/steamnetworkingsockets/clientlib/steamnetworkingsockets_ice_client.cpp index 2de3a4e..0d0e4bf 100644 --- a/src/steamnetworkingsockets/clientlib/steamnetworkingsockets_ice_client.cpp +++ b/src/steamnetworkingsockets/clientlib/steamnetworkingsockets_ice_client.cpp @@ -1303,43 +1303,23 @@ void CSteamNetworkingICESession::GatherInterfaces() // the list was empty). for ( const LocalAddress_t &addr: vecAddrs ) { + std::unique_ptr pIntf = std::make_unique( *this, uNextPriority, addr.m_nPrefixLen ); SteamDatagramErrMsg errMsg; SteamNetworkingIPAddr bindAddr = addr.m_addr; - IRawUDPSocket *pSock = OpenRawUDPSocket( CRecvPacketCallback( CSteamNetworkingICESession::StaticPacketReceived, this ), errMsg, &bindAddr, nullptr ); - if ( pSock == nullptr ) + pIntf->m_pSocket = OpenRawUDPSocket( CRecvPacketCallback( CSteamNetworkingICESession::StaticPacketReceived, pIntf.get() ), errMsg, &bindAddr, nullptr ); + if ( pIntf->m_pSocket == nullptr ) { SpewWarning( "Could not bind to %s, skipping interface. %s\n", SteamNetworkingIPAddrRender( addr.m_addr ).c_str(), errMsg ); continue; } - m_vecInterfaces.emplace_back( std::make_unique( uNextPriority, addr.m_nPrefixLen, pSock ) ); + m_vecInterfaces.emplace_back( std::move( pIntf ) ); if ( uNextPriority > 0 ) --uNextPriority; } } -CSteamNetworkingSocketsSTUNRequest *CSteamNetworkingICESession::FindPendingRequestByTransactionID( const uint32 nTransactionID[3] ) const -{ - auto fnMatches = [nTransactionID]( const CSteamNetworkingSocketsSTUNRequest *pRequest ) - { - return pRequest != nullptr - && pRequest->m_nTransactionID[0] == nTransactionID[0] - && pRequest->m_nTransactionID[1] == nTransactionID[1] - && pRequest->m_nTransactionID[2] == nTransactionID[2]; - }; - - for ( const auto &pIntf : m_vecInterfaces ) - if ( fnMatches( pIntf->m_pPendingSTUNRequest ) ) - return pIntf->m_pPendingSTUNRequest; - - for ( CSteamNetworkingSocketsSTUNRequest *pRequest : m_vecPendingPeerRequests ) - if ( fnMatches( pRequest ) ) - return pRequest; - - return nullptr; -} - -void CSteamNetworkingICESession::OnPacketReceived( const RecvPktInfo_t &info ) +void CSteamNetworkingICESession::OnPacketReceived( const RecvPktInfo_t &info, ICESessionInterface *pInterface ) { SteamNetworkingGlobalLock::AssertHeldByCurrentThread( "CSteamNetworkingICESession::OnPacketReceived" ); @@ -1351,7 +1331,27 @@ void CSteamNetworkingICESession::OnPacketReceived( const RecvPktInfo_t &info ) UnpackSTUNHeader( reinterpret_cast( info.m_pPkt ), &quickHeader ); if ( IsValidSTUNHeader( &quickHeader, info.m_cbPkt, nullptr ) && quickHeader.m_nMessageType != k_nSTUN_BindingRequest ) { - CSteamNetworkingSocketsSTUNRequest *pRequest = FindPendingRequestByTransactionID( quickHeader.m_nTransactionID ); + CSteamNetworkingSocketsSTUNRequest *pRequest = pInterface->m_pPendingSTUNRequest; + if ( + pRequest == nullptr + || pRequest->m_nTransactionID[0] != quickHeader.m_nTransactionID[0] + || pRequest->m_nTransactionID[1] != quickHeader.m_nTransactionID[1] + || pRequest->m_nTransactionID[2] != quickHeader.m_nTransactionID[2] + ) { + pRequest = nullptr; + for ( CSteamNetworkingSocketsSTUNRequest *p : m_vecPendingPeerRequests ) + { + if ( + p->m_pInterface == pInterface + && p->m_nTransactionID[0] == quickHeader.m_nTransactionID[0] + && p->m_nTransactionID[1] == quickHeader.m_nTransactionID[1] + && p->m_nTransactionID[2] == quickHeader.m_nTransactionID[2] + ) { + pRequest = p; + break; + } + } + } if ( pRequest != nullptr ) { pRequest->OnPacketReceived( info ); @@ -1414,14 +1414,13 @@ void CSteamNetworkingICESession::OnPacketReceived( const RecvPktInfo_t &info ) CUtlVector< STUNAttribute > outAttrs; { - const SteamNetworkingIPAddr localAddr = info.m_pSock->m_boundAddr; - SpewMsg( "Incoming binding request from %s to %s.\n\n", SteamNetworkingIPAddrRender( fromAddr ).c_str(), SteamNetworkingIPAddrRender( localAddr ).c_str() ); + SpewMsg( "Incoming binding request from %s to %s.\n\n", SteamNetworkingIPAddrRender( fromAddr ).c_str(), SteamNetworkingIPAddrRender( pInterface->m_pSocket->m_boundAddr ).c_str() ); ICECandidatePair *pThisPair = nullptr; for ( ICECandidatePair *pPair : m_vecCandidatePairs ) { if ( pPair->m_remoteCandidate.m_addr == fromAddr - && pPair->m_localCandidate.m_pInterface->m_pSocket == info.m_pSock ) + && pPair->m_localCandidate.m_pInterface == pInterface ) { pThisPair = pPair; break; @@ -1439,7 +1438,7 @@ void CSteamNetworkingICESession::OnPacketReceived( const RecvPktInfo_t &info ) ICELocalCandidate *pLocalCandidate = nullptr; for ( ICELocalCandidate &c : m_vecCandidates ) { - if ( c.m_pInterface->m_pSocket == info.m_pSock ) + if ( c.m_pInterface == pInterface ) { pLocalCandidate = &c; break; @@ -1521,10 +1520,9 @@ void CSteamNetworkingICESession::OnPacketReceived( const RecvPktInfo_t &info ) } } -void CSteamNetworkingICESession::StaticPacketReceived( const RecvPktInfo_t &info, CSteamNetworkingICESession *pContext ) +void CSteamNetworkingICESession::StaticPacketReceived( const RecvPktInfo_t &info, ICESessionInterface *pContext ) { - if ( pContext != nullptr ) - pContext->OnPacketReceived( info ); + pContext->m_session.OnPacketReceived( info, pContext ); } void CSteamNetworkingICESession::Think( SteamNetworkingMicroseconds usecNow ) diff --git a/src/steamnetworkingsockets/clientlib/steamnetworkingsockets_ice_client.h b/src/steamnetworkingsockets/clientlib/steamnetworkingsockets_ice_client.h index 614d9c1..a11c3ca 100644 --- a/src/steamnetworkingsockets/clientlib/steamnetworkingsockets_ice_client.h +++ b/src/steamnetworkingsockets/clientlib/steamnetworkingsockets_ice_client.h @@ -14,11 +14,15 @@ namespace SteamNetworkingSocketsLib { class CSteamNetworkingSocketsSTUNRequest; class CSteamNetworkingICESessionCallbacks; + class CSteamNetworkingICESession; /// Represents one local network interface used for ICE candidate gathering. /// Owns its socket and tracks at most one in-flight server-reflexive STUN request. struct ICESessionInterface { + // The session that owns this interface. + CSteamNetworkingICESession &m_session; + // Local-preference component of the ICE priority formula // (RFC 8445 ยง5.1.2). Assigned as a countdown from 65535 in // enumeration order so the first adapter returned by the OS gets @@ -31,17 +35,18 @@ namespace SteamNetworkingSocketsLib { int m_nPrefixLen; // Raw UDP socket bound to this interface for sending and receiving - // ICE traffic. Always non-NULL, owned by this object. + // ICE traffic. Null only transiently during construction before + // the socket is successfully opened. Owned by this object; // m_pSocket->m_boundAddr is the local IP:port for this interface. - IRawUDPSocket * const m_pSocket; + IRawUDPSocket *m_pSocket; // In-flight STUN bind request for server-reflexive discovery or // keepalive, or null if none is active. At most one per interface. CSteamNetworkingSocketsSTUNRequest *m_pPendingSTUNRequest = nullptr; - ICESessionInterface( uint32 p, int nPrefixLen, IRawUDPSocket *pSocket ) - : m_nPriority( p ), m_nPrefixLen( nPrefixLen ), m_pSocket( pSocket ) {} - ~ICESessionInterface() { m_pSocket->Close(); } + ICESessionInterface( CSteamNetworkingICESession &session, uint32 nPriority, int nPrefixLen ) + : m_session( session ), m_nPriority( nPriority ), m_nPrefixLen( nPrefixLen ), m_pSocket( nullptr ) {} + ~ICESessionInterface() { if ( m_pSocket ) m_pSocket->Close(); } ICESessionInterface( const ICESessionInterface& ) = delete; ICESessionInterface& operator=( const ICESessionInterface& ) = delete; @@ -372,7 +377,6 @@ namespace SteamNetworkingSocketsLib { // each Think() pass before the regular check list. std_vector< ICECandidatePair* > m_vecTriggeredCheckQueue; - CSteamNetworkingSocketsSTUNRequest *FindPendingRequestByTransactionID( const uint32 nTransactionID[3] ) const; void GatherInterfaces(); void UpdateHostCandidates(); void UpdateKeepalive( const ICELocalCandidate& c ); @@ -399,8 +403,8 @@ namespace SteamNetworkingSocketsLib { void STUNRequestCallback_PeerConnectivityCheck( const RecvSTUNPktInfo_t &info ); static void StaticSTUNRequestCallback_PeerConnectivityCheck( const RecvSTUNPktInfo_t &info, CSteamNetworkingICESession* pContext ); - void OnPacketReceived( const RecvPktInfo_t &info ); - static void StaticPacketReceived( const RecvPktInfo_t &info, CSteamNetworkingICESession *pContext ); + void OnPacketReceived( const RecvPktInfo_t &info, ICESessionInterface *pInterface ); + static void StaticPacketReceived( const RecvPktInfo_t &info, ICESessionInterface *pContext ); }; class CSteamNetworkingICESessionCallbacks