Skip to content

Commit

Permalink
Added better support for multiple server IPs.
Browse files Browse the repository at this point in the history
  • Loading branch information
ccw808 committed Jul 8, 2015
1 parent 96e52d8 commit 6c608a6
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 96 deletions.
7 changes: 4 additions & 3 deletions MTA10/core/CServerList.cpp
Expand Up @@ -462,7 +462,7 @@ void CServerListItem::Query ( void )
ioctlsocket ( m_Socket, FIONBIO, &flag );
}

sendto ( m_Socket, "r", 1, 0, (sockaddr *) &addr, sizeof(addr) );
g_pCore->GetNetwork()->SendTo ( m_Socket, "r", 1, 0, (sockaddr *) &addr, sizeof(addr) );
m_ElapsedTime.Reset ();
}

Expand Down Expand Up @@ -518,8 +518,9 @@ bool CServerListItem::ParseQuery ( const char * szBuffer, unsigned int nLength )
// Port
if ( !ReadString ( strTemp, szBuffer, i, nLength ) )
return false;
if ( ( uiMasterServerSaysRestrictions & ASE_FLAG_PORT ) == false )
ChangeAddress( Address, atoi ( strTemp.c_str () ) );
// Don't update port here. We must already have the correct value.
//if ( ( uiMasterServerSaysRestrictions & ASE_FLAG_PORT ) == false )
// ChangeAddress( Address, atoi ( strTemp.c_str () ) );

// Server name
if ( !ReadString ( strTemp, szBuffer, i, nLength ) )
Expand Down
1 change: 1 addition & 0 deletions MTA10/sdk/net/CNet.h
Expand Up @@ -128,6 +128,7 @@ class CNet
virtual bool EncryptDumpfile ( const char* szClearPathFilename, const char* szEncryptedPathFilename ) = 0;
virtual bool DecryptScript ( const char* cpInBuffer, uint uiInSize, const char** pcpOutBuffer, uint* puiOutSize, const char* szScriptName ) = 0;
virtual void PostCrash ( void ) = 0;
virtual int SendTo ( SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen ) = 0;
};

#endif
2 changes: 1 addition & 1 deletion MTA10/version.h
Expand Up @@ -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 0x092 // (0x000 - 0xfff) Lvl9 wizards only
#define _NETCODE_VERSION 0x1DA // (0x000 - 0xfff) Increment when net messages change (pre-release)
#define MTA_DM_BITSTREAM_VERSION 0x062 // (0x000 - 0xfff) Increment when net messages change (post-release). (Changing will also require additional backward compatibility code).

Expand Down
180 changes: 96 additions & 84 deletions MTA10_Server/mods/deathmatch/logic/ASE.cpp
Expand Up @@ -23,7 +23,7 @@ extern "C"

ASE* ASE::_instance = NULL;

ASE::ASE ( CMainConfig* pMainConfig, CPlayerManager* pPlayerManager, unsigned short usPort, const char* szServerIP/*, bool bLan*/ )
ASE::ASE ( CMainConfig* pMainConfig, CPlayerManager* pPlayerManager, unsigned short usPort, const SString& strServerIPList/*, bool bLan*/ )
: m_QueryDosProtect( 5, 6000, 7000 ) // Max of 5 queries per 6 seconds, then 7 second ignore
{
_instance = this;
Expand Down Expand Up @@ -53,12 +53,10 @@ ASE::ASE ( CMainConfig* pMainConfig, CPlayerManager* pPlayerManager, unsigned sh

m_strGameType = "MTA:SA";
m_strMapName = "None";
if ( szServerIP )
m_strIP = szServerIP;
m_strIPList = strServerIPList;
std::stringstream ss;
ss << usPort;
m_strPort = ss.str();
m_Socket = INVALID_SOCKET;

m_strMtaAseVersion = MTA_DM_ASE_VERSION;
}
Expand All @@ -79,63 +77,72 @@ bool ASE::SetPortEnabled ( bool bInternetEnabled, bool bLanEnabled )
ushort usPortReq = m_usPortBase + SERVER_LIST_QUERY_PORT_OFFSET;

// Any change?
if ( ( m_Socket != INVALID_SOCKET ) == bPortEnableReq && m_usPort == usPortReq )
if ( ( !m_SocketList.empty() ) == bPortEnableReq && m_usPort == usPortReq )
return true;

m_usPort = usPortReq;

// Remove current thingmy
if ( m_Socket != INVALID_SOCKET )
for ( uint s = 0 ; s < m_SocketList.size() ; s++ )
{
closesocket( m_Socket );
m_Socket = INVALID_SOCKET;
closesocket( m_SocketList[s] );
}
m_SocketList.clear();

if ( !bPortEnableReq )
return true;

// Start new thingmy
m_SockAddr.sin_family = AF_INET;
m_SockAddr.sin_port = htons ( m_usPort );
// If a local IP has been specified, ensure it is used for sending
if ( m_strIP.length () )
m_SockAddr.sin_addr.s_addr = inet_addr( m_strIP.c_str () );
else
m_SockAddr.sin_addr.s_addr = INADDR_ANY;
std::vector < SString > ipList;
m_strIPList.Split( ",", ipList );
for ( uint i = 0 ; i < ipList.size() ; i++ )
{
const SString& strIP = ipList[i];
sockaddr_in sockAddr;
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons ( m_usPort );
if ( !strIP.empty() )
sockAddr.sin_addr.s_addr = inet_addr( strIP );
else
sockAddr.sin_addr.s_addr = INADDR_ANY;

// Initialize socket
SOCKET newSocket = socket ( AF_INET, SOCK_DGRAM, 0 );

// If we are in lan only mode, reuse addr to avoid possible conflicts
if ( bLanOnly )
{
const int Flags = 1;
setsockopt ( newSocket, SOL_SOCKET, SO_REUSEADDR, (const char *)&Flags, sizeof ( Flags ) );
}

// Initialize socket
m_Socket = socket ( AF_INET, SOCK_DGRAM, 0 );
// Bind the socket
if ( ::bind ( newSocket, ( sockaddr* ) &sockAddr, sizeof ( sockAddr ) ) != 0 )
{
sockclose ( newSocket );
newSocket = INVALID_SOCKET;
return false;
}

// If we are in lan only mode, reuse addr to avoid possible conflicts
if ( bLanOnly )
{
const int Flags = 1;
setsockopt ( m_Socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&Flags, sizeof ( Flags ) );
}
// Set it to non blocking, so we dont have to wait for a packet
#ifdef WIN32
unsigned long ulNonBlock = 1;
ioctlsocket ( newSocket, FIONBIO, &ulNonBlock );
#else
fcntl ( newSocket, F_SETFL, fcntl( newSocket, F_GETFL ) | O_NONBLOCK );
#endif

// Bind the socket
if ( ::bind ( m_Socket, ( sockaddr* ) &m_SockAddr, sizeof ( m_SockAddr ) ) != 0 )
{
sockclose ( m_Socket );
m_Socket = INVALID_SOCKET;
return false;
m_SocketList.push_back( newSocket );
}

// Set it to non blocking, so we dont have to wait for a packet
#ifdef WIN32
unsigned long ulNonBlock = 1;
ioctlsocket ( m_Socket, FIONBIO, &ulNonBlock );
#else
fcntl ( m_Socket, F_SETFL, fcntl( m_Socket, F_GETFL ) | O_NONBLOCK );
#endif

return true;
}


void ASE::DoPulse ( void )
{
if ( m_Socket == INVALID_SOCKET )
if ( m_SocketList.empty() )
return;

sockaddr_in SockAddr;
Expand All @@ -150,60 +157,65 @@ void ASE::DoPulse ( void )

char szBuffer[100]; // Extra bytes for future use

for ( uint i = 0 ; i < 100 ; i++ )
for ( uint s = 0 ; s < m_SocketList.size() ; s++ )
{
// We set the socket to non-blocking so we can just keep reading
int iBuffer = recvfrom ( m_Socket, szBuffer, sizeof( szBuffer ), 0, (sockaddr*)&SockAddr, &nLen );
if ( iBuffer < 1 )
break;
SOCKET aseSocket = m_SocketList[s];

m_uiNumQueriesTotal++;
for ( uint i = 0 ; i < 100 ; i++ )
{
// We set the socket to non-blocking so we can just keep reading
int iBuffer = recvfrom ( aseSocket, szBuffer, sizeof( szBuffer ), 0, (sockaddr*)&SockAddr, &nLen );
if ( iBuffer < 1 )
break;

if ( m_QueryDosProtect.GetTotalFloodingCount () < 100 )
if ( m_QueryDosProtect.AddConnect ( inet_ntoa ( SockAddr.sin_addr ) ) )
continue;
m_uiNumQueriesTotal++;

const std::string* strReply = NULL;
if ( m_QueryDosProtect.GetTotalFloodingCount () < 100 )
if ( m_QueryDosProtect.AddConnect ( inet_ntoa ( SockAddr.sin_addr ) ) )
continue;

switch ( szBuffer[0] )
{
case 's':
{ // ASE protocol query
m_ulMasterServerQueryCount++;
strReply = QueryFullCached ();
break;
}
case 'b':
{ // Our own lighter query for ingame browser
strReply = QueryLightCached ();
break;
}
case 'r':
{ // Our own lighter query for ingame browser - Release version only
strReply = QueryLightCached ();
break;
}
case 'x':
{ // Our own lighter query for xfire updates
strReply = QueryXfireLightCached ();
break;
}
case 'v':
{ // MTA Version (For further possibilities to quick ping, in case we do multiply master servers)
strReply = &m_strMtaAseVersion;
break;
const std::string* strReply = NULL;

switch ( szBuffer[0] )
{
case 's':
{ // ASE protocol query
m_ulMasterServerQueryCount++;
strReply = QueryFullCached ();
break;
}
case 'b':
{ // Our own lighter query for ingame browser
strReply = QueryLightCached ();
break;
}
case 'r':
{ // Our own lighter query for ingame browser - Release version only
strReply = QueryLightCached ();
break;
}
case 'x':
{ // Our own lighter query for xfire updates
strReply = QueryXfireLightCached ();
break;
}
case 'v':
{ // MTA Version (For further possibilities to quick ping, in case we do multiply master servers)
strReply = &m_strMtaAseVersion;
break;
}
}
}

// If our reply buffer isn't empty, send it
if ( strReply && !strReply->empty() )
{
/*int sent =*/ sendto ( m_Socket,
strReply->c_str(),
strReply->length(),
0,
(sockaddr*)&SockAddr,
nLen );
// If our reply buffer isn't empty, send it
if ( strReply && !strReply->empty() )
{
/*int sent =*/ sendto ( aseSocket,
strReply->c_str(),
strReply->length(),
0,
(sockaddr*)&SockAddr,
nLen );
}
}
}

Expand Down
8 changes: 4 additions & 4 deletions MTA10_Server/mods/deathmatch/logic/ASE.h
Expand Up @@ -28,6 +28,7 @@ class ASE;
#include <netinet/in.h>
#include <arpa/inet.h>
#define sockclose close
typedef int SOCKET;
#endif

#include <string.h>
Expand All @@ -51,7 +52,7 @@ class ASE
{
public:
ZERO_ON_NEW
ASE ( CMainConfig* pMainConfig, CPlayerManager* pPlayerManager, unsigned short usPort, const char* szServerIP = NULL );
ASE ( CMainConfig* pMainConfig, CPlayerManager* pPlayerManager, unsigned short usPort, const SString& strServerIPList );
~ASE ( void );

void DoPulse ( void );
Expand Down Expand Up @@ -97,16 +98,15 @@ class ASE

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

static ASE* _instance;
time_t m_tStartTime;

list < CASERule* > m_Rules;

unsigned int m_Socket;
sockaddr_in m_SockAddr;
std::vector < SOCKET > m_SocketList;

unsigned short m_usPortBase;
unsigned short m_usPort;
Expand Down
8 changes: 5 additions & 3 deletions MTA10_Server/mods/deathmatch/logic/CGame.cpp
Expand Up @@ -602,9 +602,11 @@ bool CGame::Start ( int iArgumentCount, char* szArguments [] )
// Enable it if required
if ( m_pMainConfig->IsHTTPEnabled () )
{
if ( !m_pHTTPD->StartHTTPD ( strServerIP, m_pMainConfig->GetHTTPPort () ) )
// Slight hack for internal HTTPD: Listen on all IPs if multiple IPs declared
SString strUseIP = ( strServerIP == strServerIPList ) ? strServerIP : "";
if ( !m_pHTTPD->StartHTTPD ( strUseIP, m_pMainConfig->GetHTTPPort () ) )
{
CLogger::ErrorPrintf ( "Could not start HTTP server on interface '%s' and port '%u'!\n", strServerIP.c_str (), m_pMainConfig->GetHTTPPort () );
CLogger::ErrorPrintf ( "Could not start HTTP server on interface '%s' and port '%u'!\n", strUseIP.c_str (), m_pMainConfig->GetHTTPPort () );
return false;
}
}
Expand Down Expand Up @@ -851,7 +853,7 @@ bool CGame::Start ( int iArgumentCount, char* szArguments [] )
}

// If ASE is enabled
m_pASE = new ASE ( m_pMainConfig, m_pPlayerManager, static_cast < int > ( usServerPort ), strServerIP );
m_pASE = new ASE ( m_pMainConfig, m_pPlayerManager, static_cast < int > ( usServerPort ), strServerIPList );
if ( m_pMainConfig->GetSerialVerificationEnabled () )
m_pASE->SetRuleValue ( "SerialVerification", "yes" );
ApplyAseSetting ();
Expand Down
2 changes: 1 addition & 1 deletion MTA10_Server/version.h
Expand Up @@ -78,7 +78,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 _SERVER_NET_MODULE_VERSION 0x091 // (0x000 - 0xfff) Lvl9 wizards only
#define _SERVER_NET_MODULE_VERSION 0x092 // (0x000 - 0xfff) Lvl9 wizards only
#define _NETCODE_VERSION 0x1DA // (0x000 - 0xfff) Increment when net messages change (pre-release)
#define MTA_DM_BITSTREAM_VERSION 0x062 // (0x000 - 0xfff) Increment when net messages change (post-release). (Changing will also require additional backward compatibility code).

Expand Down

0 comments on commit 6c608a6

Please sign in to comment.