Closed LeventSevgili closed 3 years ago
Okay i implemented as below and it worked quite nicely. We tested a connection from a client to a game server which is behind a VPN, without TURN, it was not working. Now with TURN, it is connected and stable.
Usage:
// comma seperated setting lists
const char *stunList = "stun.123.456.45.456:3478";
const char *turnList = "turn:123.45.45:3478";
const char *userList = "levent";
const char *passList = "pass";
SteamNetworkingUtils()->SetGlobalConfigValueString(k_ESteamNetworkingConfig_P2P_STUN_ServerList, stunList);
SteamNetworkingUtils()->SetGlobalConfigValueString(k_ESteamNetworkingConfig_P2P_TURN_ServerList, turnList);
SteamNetworkingUtils()->SetGlobalConfigValueString(k_ESteamNetworkingConfig_P2P_TURN_UserList, userList);
SteamNetworkingUtils()->SetGlobalConfigValueString(k_ESteamNetworkingConfig_P2P_TURN_PassList, passList);
Implementation: File: steamnetworkingtypes.h Added 3 more configuration for P2P
k_ESteamNetworkingConfig_P2P_TURN_ServerList = 107,
k_ESteamNetworkingConfig_P2P_TURN_UserList = 108,
k_ESteamNetworkingConfig_P2P_TURN_PassList = 109,
File: ice_session.cpp Added break to the switch statement.
bool CICESession::BInitializeOnSocketThread( const ICESessionConfig &cfg )
{
.
switch( pTurn->m_protocolType ) {
case k_EProtocolTypeUDP:
case k_EProtocolTypeTCP:
case k_EProtocolTypeSSLTCP:
case k_EProtocolTypeTLS:
break; // Added this break
default:
m_pDelegate->Log( IICESessionDelegate::k_ELogPriorityError, "Invalid Turn server protocol type '%d'\n", (int) pTurn->m_protocolType );
return false;
}
.
}
File: steamnetworkingsockets_internal.h Added 3 config value for TURN.
#ifdef STEAMNETWORKINGSOCKETS_ENABLE_ICE
.
.
ConfigValue<std::string> m_P2P_TURN_ServerList;
ConfigValue<std::string> m_P2P_TURN_UserList;
ConfigValue<std::string> m_P2P_TURN_PassList;
#endif
File: csteamnetworkingsockets.cpp Add default values for new TURN configs
DEFINE_CONNECTON_DEFAULT_CONFIGVAL( std::string, P2P_TURN_ServerList, "" );
DEFINE_CONNECTON_DEFAULT_CONFIGVAL( std::string, P2P_TURN_UserList, "" );
DEFINE_CONNECTON_DEFAULT_CONFIGVAL( std::string, P2P_TURN_PassList, "" );
File: steamnetworkingsockets_p2p_ice.cpp Updated the Init method of CConnectionTransportP2PICE
void CConnectionTransportP2PICE::Init()
{
.
// Get the TURN server list
std_vector<std::string> vecTurnServers;
std_vector<std::string> vecTurnUsers;
std_vector<std::string> vecTurnPasses;
std_vector<ICESessionConfig::TurnServer*> vecTurnServersPsz;
if ( P2P_Transport_ICE_Enable & k_nSteamNetworkingConfig_P2P_Transport_ICE_Enable_Relay )
{
m_nAllowedCandidateTypes |= k_EICECandidate_Any_HostPublic | k_EICECandidate_Any_Reflexive;
{
CUtlVectorAutoPurge<char*> tempTurnServers;
V_AllocAndSplitString(m_connection.m_connectionConfig.m_P2P_TURN_ServerList.Get().c_str(), ",", tempTurnServers);
for (const char* pszAddress : tempTurnServers)
{
std::string server;
// Add prefix, unless they already supplied it
if (V_strnicmp(pszAddress, "turn:", 5) != 0)
server = "turn:";
server.append(pszAddress);
vecTurnServers.push_back(std::move(server));
}
// populate usernames
CUtlVectorAutoPurge<char*> tempTurnUsers;
V_AllocAndSplitString(m_connection.m_connectionConfig.m_P2P_TURN_UserList.Get().c_str(), ",", tempTurnUsers);
for (const char* user : tempTurnServers)
{
std::string server;
server.append(user);
vecTurnUsers.push_back(std::move(server));
}
// populate passwords
CUtlVectorAutoPurge<char*> tempTurnPasses;
V_AllocAndSplitString(m_connection.m_connectionConfig.m_P2P_TURN_PassList.Get().c_str(), ",", tempTurnPasses);
for (const char* pass : tempTurnPasses)
{
std::string server;
server.append(pass);
vecTurnPasses.push_back(std::move(server));
}
}
if (vecTurnServers.empty())
SpewWarningGroup(LogLevel_P2PRendezvous(), "[%s] Reflexive candidates enabled by P2P_Transport_ICE_Enable, but P2P_STUN_ServerList is empty\n", ConnectionDescription());
else
SpewVerboseGroup(LogLevel_P2PRendezvous(), "[%s] Using STUN server list: %s\n", ConnectionDescription(), m_connection.m_connectionConfig.m_P2P_TURN_ServerList.Get().c_str());
Assert(vecTurnServers.size() == vecTurnUsers.size() == vecTurnPasses.size());
}
else
{
SpewVerboseGroup(LogLevel_P2PRendezvous(), "[%s] Not using STUN servers as per P2P_Transport_ICE_Enable\n", ConnectionDescription());
}
// Populate vecTurnServersPsz
for (int i = 0; i < vecTurnServers.size(); i++)
{
ICESessionConfig::TurnServer* turn = new ICESessionConfig::TurnServer();
turn->m_pszHost = vecTurnServers[i].c_str();
turn->m_pszPwd = vecTurnUsers[i].c_str();
turn->m_pszUsername = vecTurnPasses[i].c_str();
vecTurnServersPsz.push_back(turn);
}
// Set the Turn config
if (vecTurnServers.size() > 0)
{
cfg.m_nTurnServers = len(vecTurnServers);
cfg.m_pTurnServers = *vecTurnServersPsz.data();
}
.
}
It is a pretty straightforward implementation. Working for me. Hope it helps someone :)
That looks like the right approach. Want to submit a PR?
Gladly! I'll submit shortly. Thanks.
PR #192 Thanks!
I pulled #192
Hey,
We already setup a TURN server for test, just wondering if it is straightforward to configure the GNS for Relay Fallback on client? Or any example code? Any help on that would be appreciated. Thank you very much!
[UPDATE] I think the place is already reserved at CConnectionTransportP2PICE class as:
It seems it requires a setting variable at
struct ConnectionConfig
something likek_ESteamNetworkingConfig_P2P_TURN_ServerList = 108
and it needs to be passed to the ICE part withinvoid CConnectionTransportP2PICE::Init()
method at above? Well of course i may be missing something :)