Skip to content
Permalink
Browse files

Test to fix some connect timeouts #3

  • Loading branch information...
ccw808 committed Jul 17, 2015
1 parent 16f4253 commit eee258494b072c174943f683d9bda26fcadcef23
@@ -130,7 +130,7 @@ bool CConnectManager::Connect ( const char* szHost, unsigned short usPort, const

m_bIsConnecting = true;
m_tConnectStarted = time ( NULL );
m_bHasSentTcpRequest = false;
m_bHasTriedSecondConnect = false;

// Load server password
if ( m_strPassword.empty () )
@@ -141,6 +141,7 @@ bool CConnectManager::Connect ( const char* szHost, unsigned short usPort, const
m_pServerItem = new CServerListItem ( m_Address, m_usPort );
m_pServerItem->m_iTimeoutLength = 2000;
m_bIsDetectingVersion = true;
OpenServerFirewall( m_Address );

// Display the status box
SString strBuffer ( _("Connecting to %s:%u ..."), m_strHost.c_str(), m_usPort );
@@ -248,19 +249,18 @@ void CConnectManager::DoPulse ( void )
}
}

if ( !m_bHasSentTcpRequest )
int iConnectTimeDelta = time ( NULL ) - m_tConnectStarted;

// Try connect again if no response after 4 seconds
if ( iConnectTimeDelta >= 4 && !m_bHasTriedSecondConnect && g_pCore->GetNetwork()->GetExtendedErrorCode() == 0 )
{
if ( time ( NULL ) >= m_tConnectStarted + 2 )
{
// Handle possible IP rejection by proving we exist with a TCP connection
g_pCore->GetNetwork()->GetHTTPDownloadManager( EDownloadMode::CORE_UPDATER )->QueueFile( m_strHost.c_str(), NULL, 0, "", 0, true, NULL, NULL, false, 1, 2000 );
m_bHasSentTcpRequest = true;
AddReportLog( 9401, SString( "ConnectManager sent TCP connection request to %s", m_strHost.c_str() ) );
}
m_bHasTriedSecondConnect = true;
SString strAddress = inet_ntoa ( m_Address );
g_pCore->GetNetwork()->StartNetwork ( strAddress, m_usPort, CVARS_GET_VALUE < bool > ( "packet_tag" ) );
}

// Time to timeout the connection?
if ( time ( NULL ) >= m_tConnectStarted + 8 )
if ( iConnectTimeDelta >= 8 )
{
// Show a message that the connection timed out and abort
g_pCore->ShowNetErrorMessageBox ( _("Error")+_E("CC23"), _("Connection timed out"), "connect-timed-out", true );
@@ -458,3 +458,27 @@ void CConnectManager::OnServerExists ( void )
CServerBrowser::GetSingletonPtr()->NotifyServerExists ( m_Address, m_usPort );
}
}

//
// Some server firewalls block UDP packets unless a TCP connection has previously been established
//
void CConnectManager::OpenServerFirewall( in_addr Address, ushort usHttpPort, bool bHighPriority )
{
if ( usHttpPort == 0 )
usHttpPort = 80;

uint uiTimeOut;
if ( bHighPriority )
{
// Clear previously queued requests if this is high priority
g_pCore->GetNetwork()->GetHTTPDownloadManager( EDownloadMode::CONNECT_TCP_SEND )->Reset();
uiTimeOut = 2000;
}
else
{
uiTimeOut = 1000;
}

SString strDummyUrl( "http://%s:%d/.dummy/", inet_ntoa( Address ), usHttpPort );
g_pCore->GetNetwork()->GetHTTPDownloadManager( EDownloadMode::CONNECT_TCP_SEND )->QueueFile( strDummyUrl, NULL, 0, "", 0, true, NULL, NULL, false, 1, uiTimeOut );
}
@@ -35,6 +35,7 @@ class CConnectManager
void OnServerExists ( void );

bool ShouldUseInternalHTTPServer ( void ) { return m_bForceInternalHTTPServer; }
static void OpenServerFirewall ( in_addr Address, ushort usHttpPort = 80, bool bHighPriority = false );

static bool StaticProcessPacket ( unsigned char ucPacketID, class NetBitStreamInterface& bitStream );

@@ -55,7 +56,7 @@ class CConnectManager
bool m_bSave;
bool m_bForceInternalHTTPServer;
time_t m_tConnectStarted;
bool m_bHasSentTcpRequest;
bool m_bHasTriedSecondConnect;

GUI_CALLBACK* m_pOnCancelClick;

@@ -388,6 +388,8 @@ bool CRemoteMasterServer::ParseListVer2 ( CServerListItemList& itemList )
bool bHasRestrictionFlags = ( uiFlags & ASE_FLAG_RESTRICTIONS ) != 0;
bool bHasSearchIgnoreSections = ( uiFlags & ASE_FLAG_SEARCH_IGNORE_SECTIONS ) != 0;
bool bHasKeepFlag = ( uiFlags & ASE_FLAG_KEEP ) != 0;
bool bHasHttpPort = ( uiFlags & ASE_FLAG_HTTP_PORT ) != 0;
bool bHasSpecialFlags = ( uiFlags & ASE_FLAG_SPECIAL_FLAGS ) != 0;

// Rate quality of data supplied here
uint uiDataQuality = SERVER_INFO_ASE_2;
@@ -496,6 +498,16 @@ bool CRemoteMasterServer::ParseListVer2 ( CServerListItemList& itemList )
pItem->bKeepFlag = ucKeepFlag ? true : false;
}

if ( bHasHttpPort )
{
stream.Read ( pItem->m_usHttpPort );
}

if ( bHasSpecialFlags )
{
stream.Read ( pItem->m_ucSpecialFlags );
}

pItem->PostChange ();

#if MTA_DEBUG
@@ -37,6 +37,8 @@ namespace
CValueInt bPassworded; // Password protected
CValueInt bKeepFlag;
CValueInt uiCacheNoReplyCount;
CValueInt usHttpPort;
CValueInt ucSpecialFlags;
SString strName; // Server name
SString strGameMode; // Game mode
SString strMap; // Map name
@@ -168,6 +170,8 @@ bool CServerCache::LoadServerCache ( void )
if ( const SString* pString = MapFind ( item.attributeMap, "bPassworded" ) ) info.bPassworded.SetFromString ( *pString );
if ( const SString* pString = MapFind ( item.attributeMap, "bKeepFlag" ) ) info.bKeepFlag.SetFromString ( *pString );
if ( const SString* pString = MapFind ( item.attributeMap, "uiNoReplyCount" ) ) info.uiCacheNoReplyCount.SetFromString ( *pString );
if ( const SString* pString = MapFind ( item.attributeMap, "httpPort" ) ) info.usHttpPort.SetFromString ( *pString );
if ( const SString* pString = MapFind ( item.attributeMap, "flags" ) ) info.ucSpecialFlags.SetFromString ( *pString );
if ( const SString* pString = MapFind ( item.attributeMap, "strName" ) ) info.strName = *pString;
if ( const SString* pString = MapFind ( item.attributeMap, "strGameMode" ) ) info.strGameMode = *pString;
if ( const SString* pString = MapFind ( item.attributeMap, "strMap" ) ) info.strMap = *pString;
@@ -281,6 +285,8 @@ void CServerCache::StaticSaveServerCache ( void )
MapSet ( item.attributeMap, "bPassworded", info.bPassworded.ToString () );
MapSet ( item.attributeMap, "bKeepFlag", info.bKeepFlag.ToString () );
MapSet ( item.attributeMap, "uiNoReplyCount", info.uiCacheNoReplyCount.ToString () );
MapSet ( item.attributeMap, "httpPort", info.usHttpPort.ToString () );
MapSet ( item.attributeMap, "flags", info.ucSpecialFlags.ToString () );
MapSet ( item.attributeMap, "strName", info.strName );
MapSet ( item.attributeMap, "strGameMode", info.strGameMode );
MapSet ( item.attributeMap, "strMap", info.strMap );
@@ -324,7 +330,8 @@ void CServerCache::GetServerCachedInfo ( CServerListItem* pItem )
pItem->strMap = pInfo->strMap;
pItem->strVersion = pInfo->strVersion;
pItem->uiCacheNoReplyCount = pInfo->uiCacheNoReplyCount;

pItem->m_usHttpPort = pInfo->usHttpPort;
pItem->m_ucSpecialFlags = pInfo->ucSpecialFlags;
pItem->PostChange ();
}
else
@@ -335,6 +342,8 @@ void CServerCache::GetServerCachedInfo ( CServerListItem* pItem )
if ( pItem->strMap.empty () ) pItem->strMap = pInfo->strMap;
if ( pItem->strVersion.empty () ) pItem->strVersion = pInfo->strVersion;
if ( pItem->nPing == 9999 ) pItem->nPing = pInfo->nPing;
if ( pItem->m_usHttpPort == 0 ) pItem->m_usHttpPort = pInfo->usHttpPort;
if ( pItem->m_ucSpecialFlags == 0 ) pItem->m_ucSpecialFlags = pInfo->ucSpecialFlags;
}
}
}
@@ -370,7 +379,9 @@ void CServerCache::SetServerCachedInfo ( const CServerListItem* pItem )
&& pInfo->strGameMode == pItem->strGameMode
//&& pInfo->strMap == pItem->strMap
&& pInfo->strVersion == pItem->strVersion
&& pInfo->uiCacheNoReplyCount == pItem->uiCacheNoReplyCount )
&& pInfo->uiCacheNoReplyCount == pItem->uiCacheNoReplyCount
&& pInfo->usHttpPort == pItem->m_usHttpPort
&& pInfo->ucSpecialFlags == pItem->m_ucSpecialFlags )
{
return;
}
@@ -386,6 +397,8 @@ void CServerCache::SetServerCachedInfo ( const CServerListItem* pItem )
pInfo->strMap = pItem->strMap;
pInfo->strVersion = pItem->strVersion;
pInfo->uiCacheNoReplyCount = pItem->uiCacheNoReplyCount;
pInfo->usHttpPort = pItem->m_usHttpPort;
pInfo->ucSpecialFlags = pItem->m_ucSpecialFlags;
}


@@ -390,7 +390,34 @@ std::string CServerListItem::Pulse ( bool bCanSendQuery, bool bRemoveNonRespondi
}
}

if ( m_ElapsedTime.Get () > SERVER_LIST_ITEM_TIMEOUT )
/////////////////////////////////////////////////////////////////////////////////////////
// TCP send to servers that the master server can see, but this client can't
uint uiQueryAge = (uint)m_ElapsedTime.Get();
if ( uiQueryAge > 2000 )
{
if ( !m_bDoneTcpSend && GetMaxRetries() > 0 )
{
m_bDoneTcpSend = true;
if ( ( m_ucSpecialFlags & ASE_SPECIAL_FLAG_DENY_TCP_SEND ) == 0 )
{
CConnectManager::OpenServerFirewall( Address, m_usHttpPort, false );
m_bDoPostTcpQuery = 1;
}
}
}
if ( uiQueryAge > 4000 )
{
if ( m_bDoPostTcpQuery )
{
// Do another query if we just tried to open this server's firewall
m_bDoPostTcpQuery = false;
Query ();
return "ResentQuery";
}
}
/////////////////////////////////////////////////////////////////////////////////////////

if ( uiQueryAge > SERVER_LIST_ITEM_TIMEOUT )
{
if ( bKeepFlag )
bRemoveNonResponding = false;
@@ -401,9 +428,8 @@ std::string CServerListItem::Pulse ( bool bCanSendQuery, bool bRemoveNonRespondi
nPlayers = 0; // We don't have player names, so zero this now
}
uiRevision++; // To flag browser gui update
uint uiMaxRetries = GetDataQuality () <= SERVER_INFO_ASE_0 || MaybeWontRespond () ? 0 : 1;

if ( uiQueryRetryCount < uiMaxRetries )
if ( uiQueryRetryCount < GetMaxRetries() )
{
// Try again
uiQueryRetryCount++;
@@ -599,6 +625,13 @@ bool CServerListItem::ParseQuery ( const char * szBuffer, unsigned int nLength )
const SString strPingStatus = strBuildNumber.Right ( strBuildNumber.length () - strlen ( strBuildNumber ) - 1 );
CCore::GetSingleton ().GetNetwork ()->UpdatePingStatus ( *strPingStatus, nPlayers );

// Recover server http port if present
const SString strNetRoute = strPingStatus.Right ( strPingStatus.length () - strlen ( strPingStatus ) - 1 );
const SString strUpTime = strNetRoute.Right ( strNetRoute.length () - strlen ( strNetRoute ) - 1 );
const SString strHttpPort = strUpTime.Right ( strUpTime.length () - strlen ( strUpTime ) - 1 );
if ( !strHttpPort.empty () )
m_usHttpPort = atoi ( strHttpPort );

// Get player nicks
vecPlayers.clear ();
while ( i < nLength )
@@ -769,6 +802,10 @@ CServerListItem::CServerListItem ( in_addr _Address, unsigned short _usGamePort,
Address = _Address;
usGamePort = _usGamePort;
m_pItemList = pItemList;
m_bDoneTcpSend = false;
m_bDoPostTcpQuery = false;
m_usHttpPort = 0;
m_ucSpecialFlags = 0;
Init ();
if ( m_pItemList )
{
@@ -63,6 +63,15 @@ enum
ASE_FLAG_RESTRICTIONS = 0x2000,
ASE_FLAG_SEARCH_IGNORE_SECTIONS = 0x4000,
ASE_FLAG_KEEP = 0x8000,
ASE_FLAG_HTTP_PORT = 0x080000,
ASE_FLAG_SPECIAL_FLAGS = 0x100000,
};

enum
{
ASE_SPECIAL_FLAG_VALID = 0x01,
ASE_SPECIAL_FLAG_DENY_TCP_SEND = 0x02,
ASE_SPECIAL_FLAG_FORCE_KEEP = 0x04,
};

enum
@@ -86,6 +95,10 @@ class CServerListItem
Address.S_un.S_addr = 0;
usGamePort = 0;
m_pItemList = NULL;
m_bDoneTcpSend = false;
m_bDoPostTcpQuery = false;
m_usHttpPort = 0;
m_ucSpecialFlags = 0;
Init ();
}
CServerListItem ( in_addr _Address, unsigned short _usGamePort, CServerListItemList* pItemList = NULL, bool bAtFront = false );
@@ -204,6 +217,8 @@ class CServerListItem

int m_iBuildType; // 9=release
int m_iBuildNumber; // 00000 and up
ushort m_usHttpPort;
uchar m_ucSpecialFlags;

SString strNameSortKey; // Server name as a sortable string
SString strVersionSortKey; // Game version as a sortable string
@@ -300,11 +315,18 @@ class CServerListItem
return m_iDataQuality;
}

uint GetMaxRetries ( void ) const
{
return GetDataQuality () <= SERVER_INFO_ASE_0 || MaybeWontRespond () ? 0 : 1;
}

static bool StaticIsValid ( CServerListItem* pServer )
{
return MapContains ( ms_ValidServerListItemMap, pServer );
}

bool m_bDoneTcpSend;
bool m_bDoPostTcpQuery;
int m_iTimeoutLength;
CServerListItemList* m_pItemList;
protected:
@@ -2121,7 +2121,7 @@ void CVersionUpdater::_ProcessPatchFileQuery ( void )
if ( strNotifyMasterRevision.length () && strNotifyMasterRevision > m_MasterConfig.master.strRevision )
{
// Only do next bit when 'notify revision' increases (prevents superfluous downloads when notify revision is (incorrectly) higher than actual revision)
if ( m_VarConfig.master_highestNotifyRevision.empty () || strNotifyMasterRevision < m_VarConfig.master_highestNotifyRevision )
if ( m_VarConfig.master_highestNotifyRevision.empty () || strNotifyMasterRevision > m_VarConfig.master_highestNotifyRevision )
{
m_VarConfig.master_highestNotifyRevision = strNotifyMasterRevision;

@@ -27,6 +27,7 @@ namespace EDownloadMode
RESOURCE_INITIAL_FILES,
RESOURCE_SINGULAR_FILES,
CALL_REMOTE,
CONNECT_TCP_SEND,
};
}
using EDownloadMode::EDownloadModeType;
@@ -34,6 +34,8 @@ class CNetHTTPDownloadManagerInterface

// Limit number of concurrent http client connections
virtual void SetMaxConnections ( int iMaxConnections ) = 0;

virtual void Reset ( void ) = 0;
};

#endif
@@ -75,7 +75,7 @@

#define _ASE_VERSION QUOTE_DEFINE(MTASA_VERSION_MAJOR) "." QUOTE_DEFINE(MTASA_VERSION_MINOR)
#define _NETCODE_VERSION_BRANCH_ID 0x4 // Use 0x1 - 0xF to indicate an incompatible branch is being used (0x0 is reserved, 0x4 is trunk)
#define _CLIENT_NET_MODULE_VERSION 0x08E // (0x000 - 0xfff) Lvl9 wizards only
#define _CLIENT_NET_MODULE_VERSION 0x093 // (0x000 - 0xfff) Lvl9 wizards only
#define _NETCODE_VERSION 0x1D8 // (0x000 - 0xfff) Increment when net messages change (pre-release)
#define MTA_DM_BITSTREAM_VERSION 0x063 // (0x000 - 0xfff) Increment when net messages change (post-release). (Changing will also require additional backward compatibility code).

@@ -412,6 +412,11 @@ std::string ASE::QueryLight ( void )
SString strPingStatus = (const char*)strPingStatusFixed;
SString strNetRoute = (const char*)strNetRouteFixed;
SString strUpTime( "%d", (uint)( time( NULL ) - m_tStartTime ) );
SString strHttpPort( "%d", m_pMainConfig->GetHTTPPort() );

uint uiExtraDataLength = ( strPlayerCount.length () + 1 + strBuildType.length () + 1 + strBuildNumber.length () + 1 + strPingStatus.length () + 1 + strNetRoute.length () + 1 + strUpTime.length() + 1 + strHttpPort.length() + 1 );
uint uiMaxMapNameLength = 250 - uiExtraDataLength;
m_strMapName = m_strMapName.Left( uiMaxMapNameLength );

reply << "EYE2";
// game
@@ -427,7 +432,7 @@ std::string ASE::QueryLight ( void )
reply << ( unsigned char ) ( m_strGameType.length() + 1 );
reply << m_strGameType;
// map name with backwardly compatible large player count, build type and build number
reply << ( unsigned char ) ( m_strMapName.length() + 1 + strPlayerCount.length () + 1 + strBuildType.length () + 1 + strBuildNumber.length () + 1 + strPingStatus.length () + 1 + strNetRoute.length () + 1 + strUpTime.length() + 1 );
reply << ( unsigned char ) ( m_strMapName.length() + 1 + uiExtraDataLength );
reply << m_strMapName;
reply << ( unsigned char ) 0;
reply << strPlayerCount;
@@ -441,6 +446,8 @@ std::string ASE::QueryLight ( void )
reply << strNetRoute;
reply << ( unsigned char ) 0;
reply << strUpTime;
reply << ( unsigned char ) 0;
reply << strHttpPort;
// version
std::string temp = MTA_DM_ASE_VERSION;
reply << ( unsigned char ) ( temp.length() + 1 );
@@ -96,7 +96,7 @@ class ASE
CPlayerManager* m_pPlayerManager;

std::string m_strGameType;
std::string m_strMapName;
SString m_strMapName;
std::string m_strIP;
std::string m_strPort;

0 comments on commit eee2584

Please sign in to comment.
You can’t perform that action at this time.