mirror of
https://github.com/SWG-Source/src.git
synced 2026-09-13 00:45:03 -04:00
better oci error reporting
This commit is contained in:
@@ -57,13 +57,16 @@ ClientConnection::~ClientConnection()
|
||||
void ClientConnection::onConnectionClosed()
|
||||
{
|
||||
// client has disconnected
|
||||
DEBUG_REPORT_LOG(true, ("Client %lu disconnected\n", getStationId()));
|
||||
LOG("LoginClientConnection", ("onConnectionClosed() for stationId (%lu) at IP (%s)", m_stationId, getRemoteAddress().c_str()));
|
||||
LoginServer::getInstance().removeClient(m_clientId);
|
||||
|
||||
if (!m_isValidated)
|
||||
if (m_clientId)
|
||||
{
|
||||
SessionApiClient * session = LoginServer::getInstance().getSessionApiClient();
|
||||
// if it is a 0 they are a dos faggot, most likely
|
||||
DEBUG_REPORT_LOG(true, ("Client %lu disconnected\n", m_stationId));
|
||||
LOG("LoginClientConnection", ("onConnectionClosed() for stationId (%lu) at IP (%s)", m_stationId, getRemoteAddress().c_str()));
|
||||
LoginServer::getInstance().removeClient(m_clientId);
|
||||
}
|
||||
|
||||
if (!m_isValidated) {
|
||||
SessionApiClient *session = LoginServer::getInstance().getSessionApiClient();
|
||||
if (session)
|
||||
session->dropClient(this);
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ void ConfigLoginServer::install(void)
|
||||
KEY_INT (centralServicePort, 44452);
|
||||
KEY_INT (clientServicePort, 44453);
|
||||
KEY_INT (clientOverflowLimit, 1024 * 8);
|
||||
KEY_INT (maxClients, 3000);
|
||||
KEY_INT (maxClients, 250);
|
||||
KEY_INT (taskServicePort, 44459);
|
||||
KEY_INT (pingServicePort, 44460);
|
||||
KEY_INT (httpServicePort, 44490);
|
||||
@@ -116,6 +116,7 @@ void ConfigLoginServer::install(void)
|
||||
KEY_BOOL(requireSecureLoginForCsTool, true);
|
||||
KEY_BOOL(useExternalAuth, false);
|
||||
KEY_STRING(externalAuthURL, "");
|
||||
KEY_INT(maxConnectionsPerIP, 2); // assuming 2 people playing in the same household
|
||||
|
||||
int index = 0;
|
||||
char const * result = 0;
|
||||
|
||||
@@ -17,14 +17,14 @@ class ConfigLoginServer
|
||||
int maxClients;
|
||||
int taskServicePort;
|
||||
int pingServicePort;
|
||||
int httpServicePort;
|
||||
int httpServicePort;
|
||||
bool validateClientVersion;
|
||||
bool validateStationKey;
|
||||
bool doSessionLogin;
|
||||
bool doConsumption;
|
||||
bool doConsumption;
|
||||
const char * sessionServers;
|
||||
int sessionType;
|
||||
|
||||
|
||||
const char * DSN;
|
||||
const char * databaseUID;
|
||||
const char * schemaOwner;
|
||||
@@ -54,7 +54,7 @@ class ConfigLoginServer
|
||||
const char * purgeAccountSourceTable;
|
||||
const char * adminAccountDataTable;
|
||||
bool allowSkipTutorialToAll;
|
||||
|
||||
|
||||
bool internalBypassOnlineLimit;
|
||||
|
||||
int populationExtremelyHeavyThresholdPercent;
|
||||
@@ -63,11 +63,13 @@ class ConfigLoginServer
|
||||
int populationMediumThresholdPercent;
|
||||
int populationLightThresholdPercent;
|
||||
int csToolPort;
|
||||
|
||||
bool requireSecureLoginForCsTool;
|
||||
bool useExternalAuth;
|
||||
|
||||
bool requireSecureLoginForCsTool;
|
||||
bool useExternalAuth;
|
||||
|
||||
const char * externalAuthURL;
|
||||
|
||||
int maxConnectionsPerIP;
|
||||
};
|
||||
|
||||
static const uint16 getCentralServicePort();
|
||||
@@ -82,7 +84,7 @@ class ConfigLoginServer
|
||||
static const bool getDoConsumption();
|
||||
static const char * getSessionServers();
|
||||
static const int getSessionType();
|
||||
|
||||
|
||||
static const int getMaxClients ();
|
||||
static const char * getPrivateIpMask();
|
||||
static const char * getDSN();
|
||||
@@ -105,7 +107,7 @@ class ConfigLoginServer
|
||||
static void install ();
|
||||
static void remove ();
|
||||
|
||||
static int getNumberOfSessionServers();
|
||||
static int getNumberOfSessionServers();
|
||||
static char const * getSessionServer(int index);
|
||||
static const int getDisconnectSleepTime (void);
|
||||
static const int getClusterGroup();
|
||||
@@ -118,24 +120,26 @@ class ConfigLoginServer
|
||||
static int getPurgePhaseAdvanceDays(int purgePhase);
|
||||
static const char * getAdminAccountDataTable();
|
||||
static bool getAllowSkipTutorialToAll();
|
||||
|
||||
|
||||
static bool getInternalBypassOnlineLimit();
|
||||
static const int getCSToolPort();
|
||||
|
||||
static bool getRequireSecureLoginForCsTool();
|
||||
static bool getRequireSecureLoginForCsTool();
|
||||
|
||||
static int getPopulationExtremelyHeavyThresholdPercent();
|
||||
static int getPopulationVeryHeavyThresholdPercent();
|
||||
static int getPopulationHeavyThresholdPercent();
|
||||
static int getPopulationMediumThresholdPercent();
|
||||
static int getPopulationLightThresholdPercent();
|
||||
|
||||
static bool getUseExternalAuth();
|
||||
|
||||
static bool getUseExternalAuth();
|
||||
static const char * getExternalAuthUrl();
|
||||
|
||||
// has character creation for this cluster been disabled through config option
|
||||
static bool isCharacterCreationDisabled(std::string const & cluster);
|
||||
static stdset<std::string>::fwd const & getCharacterCreationDisabledClusterList();
|
||||
static stdset<std::string>::fwd const & getCharacterCreationDisabledClusterList();
|
||||
|
||||
static const int getMaxConnectionsPerIP();
|
||||
|
||||
private:
|
||||
static Data * data;
|
||||
@@ -483,6 +487,11 @@ inline const char * ConfigLoginServer::getExternalAuthUrl()
|
||||
{
|
||||
return data->externalAuthURL;
|
||||
}
|
||||
|
||||
inline const int ConfigLoginServer::getMaxConnectionsPerIP()
|
||||
{
|
||||
return data->maxConnectionsPerIP;
|
||||
}
|
||||
// ======================================================================
|
||||
|
||||
#endif // _ConfigLoginServer_H
|
||||
|
||||
@@ -146,11 +146,11 @@ LoginServer::LoginServer() :
|
||||
setup.compress = ConfigLoginServer::getCompressClientNetworkTraffic();
|
||||
setup.useTcp = false;
|
||||
|
||||
clientService = new Service(ConnectionAllocator<ClientConnection>(), setup);
|
||||
clientService = new Service(ConnectionAllocator<ClientConnection>(), setup, ConfigLoginServer::getMaxConnectionsPerIP());
|
||||
setup.compress = false;
|
||||
|
||||
setup.port = ConfigLoginServer::getPingServicePort();
|
||||
pingService = new Service(ConnectionAllocator<PingConnection>(), setup);
|
||||
pingService = new Service(ConnectionAllocator<PingConnection>(), setup, ConfigLoginServer::getMaxConnectionsPerIP());
|
||||
setup.useTcp = true;
|
||||
|
||||
if (ConfigLoginServer::getDevelopmentMode())
|
||||
@@ -246,16 +246,22 @@ ClientConnection* LoginServer::getUnvalidatedClient(int clientId)
|
||||
|
||||
void LoginServer::removeClient(int clientId)
|
||||
{
|
||||
WARNING_STRICT_FATAL(clientId == 0, ("Tried to remove a client with client id == 0"));
|
||||
std::map<int, ClientConnection*>::iterator i = m_clientMap.find(clientId);
|
||||
if (i != m_clientMap.end())
|
||||
{
|
||||
if (i->second->getIsValidated())
|
||||
{
|
||||
IGNORE_RETURN(m_validatedClientMap.erase(i->second->getStationId()));
|
||||
}
|
||||
IGNORE_RETURN(m_clientMap.erase(clientId));
|
||||
}
|
||||
if (clientId) // yeah why bother if it's 0 or null? i realize 0 is a valid int but since previously the warning below fired if it was 0....yeah, no
|
||||
{
|
||||
std::map<int, ClientConnection*>::iterator i = m_clientMap.find(clientId);
|
||||
if (i != m_clientMap.end())
|
||||
{
|
||||
if (i->second->getIsValidated())
|
||||
{
|
||||
IGNORE_RETURN(m_validatedClientMap.erase(i->second->getStationId()));
|
||||
}
|
||||
IGNORE_RETURN(m_clientMap.erase(clientId));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WARNING_STRICT_FATAL(true, ("Tried to remove a client with client id == 0"));
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
@@ -69,25 +69,21 @@ bool DB::OCIServer::checkerr(OCISession const & session, int status)
|
||||
WARNING(true,("Database error: %.*s",512,errbuf));
|
||||
LOG("DatabaseError",("Database error: %.*s",512,errbuf));
|
||||
FATAL(DB::Server::getFatalOnError() || session.getFatalOnError(),("Database error: %.*s",512,errbuf));
|
||||
|
||||
return false;
|
||||
|
||||
/*
|
||||
switch (errcode)
|
||||
|
||||
switch ((int) errcode)
|
||||
{
|
||||
case 1013:
|
||||
FATAL(true,("Cancelled by user request (ctrl-c or kill signal).\n"));
|
||||
break;
|
||||
|
||||
case 12541:
|
||||
REPORT_LOG(true,("Database Error - %.*s\n", 512, errbuf));
|
||||
return false;
|
||||
|
||||
default:
|
||||
FATAL(true,("Unhandled Database Error - %.*s\n", 512, errbuf));
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
case OCI_INVALID_HANDLE:
|
||||
REPORT_LOG(true,("Error - OCI_INVALID_HANDLE\n"));
|
||||
|
||||
@@ -24,10 +24,11 @@ ConnectionAllocatorBase::~ConnectionAllocatorBase()
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
//Service::Service(const ConnectionAllocatorBase & c, const unsigned short port, const int m, const int keepAliveDelay, const std::string & interfaceAddress, const bool compress) :
|
||||
Service::Service(const ConnectionAllocatorBase & c, const NetworkSetupData & setup) :
|
||||
Service::Service(const ConnectionAllocatorBase & c, const NetworkSetupData & setup, const int maxConnectionsPerIP) :
|
||||
connectionAllocator(c.clone()),
|
||||
m_callback(new MessageDispatch::Callback),
|
||||
m_tcpServer(0)
|
||||
m_tcpServer(0),
|
||||
m_maxConnectionsPerIP(maxConnectionsPerIP)
|
||||
{
|
||||
std::string realAddress;
|
||||
if(setup.bindInterface.length() > 0)
|
||||
@@ -165,7 +166,7 @@ m_tcpServer(0)
|
||||
m_maxConnections = setup.maxConnections;
|
||||
newService(this);
|
||||
|
||||
m_callback->connect(*this, &Service::onConnectionClosed);
|
||||
`->connect(*this, &Service::onConnectionClosed);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@@ -214,10 +215,38 @@ void Service::onConnectionOpened(Connection * c)
|
||||
{
|
||||
if (c)
|
||||
{
|
||||
c->setService(this);
|
||||
c->onConnectionOpened();
|
||||
connections.insert(c);
|
||||
WARNING((connections.size() >= static_cast<size_t>(m_maxConnections)), ("Service has reached it's maximum connection count %d", m_maxConnections));
|
||||
if (connections.size() < static_cast<size_t>(m_maxConnections) || m_maxConnections == 0)
|
||||
{
|
||||
std::string remoteIP = c->getRemoteAddress();
|
||||
int numConnections = 0;
|
||||
|
||||
// if we're trying to throttle dos attempts
|
||||
if (m_maxConnectionsPerIP > 0)
|
||||
{
|
||||
// we have to recount each time so that we don't cut off legit users
|
||||
for (auto i = connections.begin(); i != connections.end(); ++i) {
|
||||
if (remoteIP == (*i)->getRemoteAddress()) {
|
||||
numConnections++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_maxConnectionsPerIP == 0 || (numConnections < m_maxConnectionsPerIP))
|
||||
{
|
||||
c->setService(this);
|
||||
c->onConnectionOpened();
|
||||
connections.insert(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
WARNING(true, ("Client at IP %s has attempted more connections than allowed (%i). Potential DoS Attack?", remoteIP.c_str(), m_maxConnectionsPerIP));
|
||||
removeConnection(c); // asshole (probably)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WARNING(true, ("Service has reached it's maximum connection count (%d).", m_maxConnections));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,6 +289,7 @@ int Service::flushAndConfirmAllData()
|
||||
unsigned long startTime = Clock::timeMs();
|
||||
bool needReport = false;
|
||||
unsigned long stallReportDelay = ConfigSharedNetwork::getStallReportDelay();
|
||||
|
||||
do
|
||||
{
|
||||
if(stallReportDelay > 0)
|
||||
|
||||
@@ -59,7 +59,7 @@ class Service : public NetworkHandler
|
||||
{
|
||||
public:
|
||||
//Service(const ConnectionAllocatorBase & connectionAllocator, const unsigned short listenPort, const int maxConnections, const int keepAliveDelay = 1000, const std::string & interfaceAddress = std::string(""), const bool compress=false);
|
||||
Service(const ConnectionAllocatorBase & connectionAllocator, const NetworkSetupData & setupData);
|
||||
Service(const ConnectionAllocatorBase & connectionAllocator, const NetworkSetupData & setupData, const int maxConnectionsPerIP = 0);
|
||||
virtual ~Service();
|
||||
|
||||
void onConnectionOpened(TcpClient * t);
|
||||
@@ -86,6 +86,7 @@ private:
|
||||
const ConnectionAllocatorBase * connectionAllocator;
|
||||
std::set<Connection *> connections;
|
||||
int m_maxConnections;
|
||||
int m_maxConnectionsPerIP; // dos protection for ping and login servers
|
||||
MessageDispatch::Callback * m_callback;
|
||||
TcpServer * m_tcpServer;
|
||||
};
|
||||
|
||||
+22
-22
@@ -992,9 +992,9 @@ void UdpManager::ProcessRawPacket(const PacketHistoryEntry *e)
|
||||
|
||||
if (con == nullptr)
|
||||
{
|
||||
// packet coming from an unknown ip/port
|
||||
// if it is a connection request packet, then establish a new connection object to reply to it
|
||||
// connection establish packet must always be at least 6 bytes long as we must have a version number, no matter how it changes
|
||||
// packet coming from an unknown ip/port
|
||||
// if it is a connection request packet, then establish a new connection object to reply to it
|
||||
// connection establish packet must always be at least 6 bytes long as we must have a version number, no matter how it changes
|
||||
if (e->mBuffer[0] == 0 && e->mBuffer[1] == UdpConnection::cUdpPacketConnect && e->mLen == UdpConnection::cUdpPacketConnectSize)
|
||||
{
|
||||
if (mConnectionListCount >= mParams.maxConnections)
|
||||
@@ -1009,8 +1009,8 @@ void UdpManager::ProcessRawPacket(const PacketHistoryEntry *e)
|
||||
mParams.handler->OnConnectRequest(newcon);
|
||||
if (newcon->GetRefCount() == 1)
|
||||
{
|
||||
// we are going to end up destroying this connection when we release it on this next line
|
||||
// so disconnect it first giving it a reason
|
||||
// we are going to end up destroying this connection when we release it on this next line
|
||||
// so disconnect it first giving it a reason
|
||||
newcon->InternalDisconnect(0, UdpConnection::cDisconnectReasonConnectionRefused);
|
||||
}
|
||||
newcon->Release();
|
||||
@@ -1023,9 +1023,9 @@ void UdpManager::ProcessRawPacket(const PacketHistoryEntry *e)
|
||||
{
|
||||
if (e->mBuffer[0] == 0 && e->mBuffer[1] == UdpConnection::cUdpPacketRequestRemap)
|
||||
{
|
||||
// ok, we got a packet from somebody, that we don't know who they are, but, it appears they are asking
|
||||
// for their address/port to be remapped. If we allow port (and/or address) remapping, then go ahead
|
||||
// an honor their request if possible
|
||||
// ok, we got a packet from somebody, that we don't know who they are, but, it appears they are asking
|
||||
// for their address/port to be remapped. If we allow port (and/or address) remapping, then go ahead
|
||||
// an honor their request if possible
|
||||
uchar *ptr = e->mBuffer + 2;
|
||||
int connectCode = UdpMisc::GetValue32(ptr);
|
||||
ptr += 4;
|
||||
@@ -1036,10 +1036,10 @@ void UdpManager::ProcessRawPacket(const PacketHistoryEntry *e)
|
||||
{
|
||||
if (mParams.allowAddressRemapping || con->mIp == e->mIp)
|
||||
{
|
||||
// one final security check to ensure these are really the same connection, compare encryption codes
|
||||
// one final security check to ensure these are really the same connection, compare encryption codes
|
||||
if (con->mConnectionConfig.encryptCode == encryptCode)
|
||||
{
|
||||
// remapping is allowed, remap ourselves to the address of the incoming request
|
||||
// remapping is allowed, remap ourselves to the address of the incoming request
|
||||
mAddressHashTable->Remove(con, AddressHashValue(con->mIp, con->mPort));
|
||||
con->mIp = e->mIp;
|
||||
con->mPort = e->mPort;
|
||||
@@ -1052,18 +1052,18 @@ void UdpManager::ProcessRawPacket(const PacketHistoryEntry *e)
|
||||
}
|
||||
|
||||
|
||||
// got a packet from somebody and we don't know who they are and the packet we got was not a connection request
|
||||
// just in case they are a previous client who thinks they are still connected, we will send them an internal
|
||||
// packet telling them that we don't know who they are
|
||||
// got a packet from somebody and we don't know who they are and the packet we got was not a connection request
|
||||
// just in case they are a previous client who thinks they are still connected, we will send them an internal
|
||||
// packet telling them that we don't know who they are
|
||||
if (mParams.replyUnreachableConnection)
|
||||
{
|
||||
// do not reply back with unreachable if the packet coming in is a terminate or unreachable packet itself
|
||||
// do not reply back with unreachable if the packet coming in is a terminate or unreachable packet itself
|
||||
if (e->mBuffer[0] != 0 || (e->mBuffer[0] == 0 && e->mBuffer[1] != UdpConnection::cUdpPacketUnreachableConnection && e->mBuffer[1] != UdpConnection::cUdpPacketTerminate))
|
||||
{
|
||||
// since we do not have a connection-object associated with this incoming packet, there is no way we could
|
||||
// encrypt it or add CRC bytes to it, since we have no idea what the other end of the connection is expecting
|
||||
// in this regard. As such, the UnreachableConnection packet (like the connect and confirm packets) is one
|
||||
// of those internal packet types that is designated as not being encrypted or CRC'ed.
|
||||
// since we do not have a connection-object associated with this incoming packet, there is no way we could
|
||||
// encrypt it or add CRC bytes to it, since we have no idea what the other end of the connection is expecting
|
||||
// in this regard. As such, the UnreachableConnection packet (like the connect and confirm packets) is one
|
||||
// of those internal packet types that is designated as not being encrypted or CRC'ed.
|
||||
unsigned char buf[8];
|
||||
buf[0] = 0;
|
||||
buf[1] = UdpConnection::cUdpPacketUnreachableConnection;
|
||||
@@ -1389,10 +1389,10 @@ void UdpConnection::InternalDisconnect(int flushTimeout, DisconnectReason reason
|
||||
return;
|
||||
}
|
||||
|
||||
// send a termination packet to the other side
|
||||
// do not send a termination packet if we are still negotiating (we are not allowed to send any packets while negotiating)
|
||||
// if you attempt to send a packet while negotiating, then it will potentially attempt to encrypt it before an encryption
|
||||
// method is determined, resulting in a function call through an invalid pointer
|
||||
// send a termination packet to the other side
|
||||
// do not send a termination packet if we are still negotiating (we are not allowed to send any packets while negotiating)
|
||||
// if you attempt to send a packet while negotiating, then it will potentially attempt to encrypt it before an encryption
|
||||
// method is determined, resulting in a function call through an invalid pointer
|
||||
if (!mSilentDisconnect)
|
||||
{
|
||||
if (mStatus == cStatusConnected || mStatus == cStatusDisconnectPending)
|
||||
|
||||
Reference in New Issue
Block a user