mirror of
https://github.com/ValveSoftware/GameNetworkingSockets.git
synced 2026-05-29 16:20:34 +00:00
ICE client refactor: Handling of received peer candidates
RFC5245CandidateAttr now store the address directly, nor address string and port. AddPeerCandidate will receive this directly, and return the type
This commit is contained in:
@@ -727,17 +727,6 @@ static uint32 CRC32( const unsigned char *buf, int len )
|
||||
|
||||
// Parse a candidate-attribute from https://datatracker.ietf.org/doc/html/rfc5245#section-15.1
|
||||
// Ex: candidate:2442523459 0 udp 2122262784 2602:801:f001:1034:5078:221c:76b:a3d6 63368 typ host generation 0 ufrag WLM82 network-id 2
|
||||
struct RFC5245CandidateAttr {
|
||||
std::string sFoundation;
|
||||
int nComponent;
|
||||
std::string sTransport;
|
||||
int nPriority;
|
||||
std::string sAddress;
|
||||
int nPort;
|
||||
std::string sType;
|
||||
CSteamNetworkingICESession::ICECandidateType nType;
|
||||
CUtlVector< std::pair< std::string, std::string > > vAttrs;
|
||||
};
|
||||
bool ParseRFC5245CandidateAttribute( const char *pszAttr, RFC5245CandidateAttr *pAttr )
|
||||
{
|
||||
if ( pszAttr == nullptr || pAttr == nullptr )
|
||||
@@ -878,9 +867,10 @@ bool ParseRFC5245CandidateAttribute( const char *pszAttr, RFC5245CandidateAttr *
|
||||
pAttr->nPriority = atoi( pPriorityBegin );
|
||||
{
|
||||
std::string connectionAddr( pConnectionAddressBegin, pConnectionAddressEnd - pConnectionAddressBegin );
|
||||
pAttr->sAddress.swap( connectionAddr );
|
||||
if ( !pAttr->address.ParseString( connectionAddr.c_str() ) )
|
||||
return false;
|
||||
}
|
||||
pAttr->nPort = atoi( pPortBegin );
|
||||
pAttr->address.m_port = (uint16)atoi( pPortBegin );
|
||||
{
|
||||
std::string candidateType( pCandidateTypeBegin, pCandidateTypeEnd - pCandidateTypeBegin );
|
||||
pAttr->sType.swap( candidateType );
|
||||
@@ -1146,10 +1136,16 @@ void CSteamNetworkingICESession::SetRemotePassword( const char *pszPassword )
|
||||
SetNextThinkTimeASAP();
|
||||
}
|
||||
|
||||
void CSteamNetworkingICESession::AddPeerCandidate( const ICECandidateBase& candidate, const char* pszFoundation )
|
||||
EICECandidateType CSteamNetworkingICESession::AddPeerCandidate( const RFC5245CandidateAttr& attr )
|
||||
{
|
||||
SteamNetworkingGlobalLock::AssertHeldByCurrentThread();
|
||||
|
||||
ICECandidateBase candidate( attr.nType, attr.address, attr.address );
|
||||
candidate.m_nPriority = attr.nPriority;
|
||||
const char *pszFoundation = attr.sFoundation.c_str();
|
||||
|
||||
EICECandidateType eCandidateType = candidate.CalcType();
|
||||
|
||||
// Do we already have a candidate for this peer? If so, just update the foundation and move on.
|
||||
bool bNeedsNewEntry = true;
|
||||
for ( ICEPeerCandidate& c : m_vecPeerCandidates )
|
||||
@@ -1158,7 +1154,7 @@ void CSteamNetworkingICESession::AddPeerCandidate( const ICECandidateBase& candi
|
||||
{
|
||||
// If the foundation is the same, don't do anything - this is redundant.
|
||||
if ( V_strcmp( c.m_sFoundation.c_str(), pszFoundation ) == 0 )
|
||||
return;
|
||||
return eCandidateType;
|
||||
|
||||
(ICECandidateBase&)c = candidate;
|
||||
c.m_sFoundation = pszFoundation;
|
||||
@@ -1182,6 +1178,7 @@ void CSteamNetworkingICESession::AddPeerCandidate( const ICECandidateBase& candi
|
||||
}
|
||||
m_bCandidatePairsNeedUpdate = true;
|
||||
SetNextThinkTimeASAP();
|
||||
return eCandidateType;
|
||||
}
|
||||
|
||||
void CSteamNetworkingICESession::InvalidateInterfaceList()
|
||||
@@ -2244,23 +2241,19 @@ void CConnectionTransportP2PICE_Valve::RecvRendezvous( const CMsgICERendezvous &
|
||||
{
|
||||
// candidate-attribute from https://datatracker.ietf.org/doc/html/rfc5245#section-15.1
|
||||
const std::string& s = msg.add_candidate().candidate();
|
||||
SpewMsg( "Got remote candidate \'%s\'\n", s.c_str() );
|
||||
RFC5245CandidateAttr attr;
|
||||
if ( ParseRFC5245CandidateAttribute( s.c_str(), &attr ) )
|
||||
if ( !ParseRFC5245CandidateAttribute( s.c_str(), &attr ) )
|
||||
{
|
||||
SteamNetworkingIPAddr candidateAddr;
|
||||
if ( !candidateAddr.ParseString( attr.sAddress.c_str() ) )
|
||||
{
|
||||
SpewMsg( "Failed to parse address \'%s\' as an IP address.", attr.sAddress.c_str() );
|
||||
return;
|
||||
}
|
||||
candidateAddr.m_port = attr.nPort;
|
||||
|
||||
SpewMsg( "Got a rendezvous candidate at \"%s\"\n", SteamNetworkingIPAddrRender( candidateAddr ).c_str() );
|
||||
CSteamNetworkingICESession::ICECandidateBase newCandidate( attr.nType, candidateAddr, candidateAddr );
|
||||
newCandidate.m_nPriority = attr.nPriority;
|
||||
m_pICESession->AddPeerCandidate( newCandidate, attr.sFoundation.c_str() );
|
||||
Connection().m_msgICESessionSummary.set_remote_candidate_types( Connection().m_msgICESessionSummary.remote_candidate_types() | newCandidate.CalcType() );
|
||||
SpewMsg( "[%s] Failed to parse remote candidate \'%s\'\n",
|
||||
Connection().GetDescription(), s.c_str() );
|
||||
}
|
||||
else
|
||||
{
|
||||
SpewMsg( "[%s] Got remote candidate \'%s\'\n",
|
||||
Connection().GetDescription(), s.c_str() );
|
||||
EICECandidateType nType = m_pICESession->AddPeerCandidate( attr );
|
||||
Connection().m_msgICESessionSummary.set_remote_candidate_types(
|
||||
Connection().m_msgICESessionSummary.remote_candidate_types() | nType );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
namespace SteamNetworkingSocketsLib {
|
||||
class CSteamNetworkingSocketsSTUNRequest;
|
||||
class CSteamNetworkingICESessionCallbacks;
|
||||
struct RFC5245CandidateAttr;
|
||||
|
||||
/// Represents one local network interface used for ICE candidate gathering.
|
||||
/// Owns its socket and tracks at most one in-flight server-reflexive STUN request.
|
||||
@@ -169,8 +171,6 @@ namespace SteamNetworkingSocketsLib {
|
||||
CSteamNetworkingSocketsSTUNRequest& operator=( const CSteamNetworkingSocketsSTUNRequest& );
|
||||
};
|
||||
|
||||
class CSteamNetworkingICESessionCallbacks;
|
||||
|
||||
/// Main logic of establishing an ICE session with a peer. In real-world
|
||||
/// uses cases this is always associated one-to-one with a CConnectionTransportP2PICE_Valve.
|
||||
/// But breaking it out into a separate object helps with testing.
|
||||
@@ -214,7 +214,7 @@ namespace SteamNetworkingSocketsLib {
|
||||
void CalcCandidateAttribute( char *pszBuffer, size_t nBufferSize ) const;
|
||||
};
|
||||
EICERole GetRole() { return m_role; }
|
||||
void AddPeerCandidate( const ICECandidateBase& peerCandidate, const char* pszFoundation );
|
||||
EICECandidateType AddPeerCandidate( const RFC5245CandidateAttr& attr );
|
||||
void SetRemoteUsername( const char *pszUsername );
|
||||
void SetRemotePassword( const char *pszPassword );
|
||||
|
||||
@@ -389,6 +389,19 @@ namespace SteamNetworkingSocketsLib {
|
||||
static void StaticPacketReceived( const RecvPktInfo_t &info, CSteamNetworkingICESession *pContext );
|
||||
};
|
||||
|
||||
// Parsed representation of an RFC 5245 candidate-attribute line.
|
||||
// https://datatracker.ietf.org/doc/html/rfc5245#section-15.1
|
||||
struct RFC5245CandidateAttr {
|
||||
std::string sFoundation;
|
||||
int nComponent;
|
||||
std::string sTransport;
|
||||
int nPriority;
|
||||
SteamNetworkingIPAddr address;
|
||||
std::string sType;
|
||||
CSteamNetworkingICESession::ICECandidateType nType;
|
||||
CUtlVector< std::pair< std::string, std::string > > vAttrs;
|
||||
};
|
||||
|
||||
class CSteamNetworkingICESessionCallbacks
|
||||
{
|
||||
public:
|
||||
|
||||
Reference in New Issue
Block a user