diff --git a/engine/server/application/LoginServer/src/shared/ClientConnection.cpp b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp index fcab72a2..17c9a9c7 100755 --- a/engine/server/application/LoginServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp @@ -27,247 +27,223 @@ using namespace StellaBellum; //----------------------------------------------------------------------- -ClientConnection::ClientConnection(UdpConnectionMT * u, TcpClient * t) : - ServerConnection(u, t), - m_clientId(0), - m_isValidated(false), - m_isSecure(false), - m_adminLevel(-1), - m_stationId(0), - m_requestedAdminSuid(0), - m_gameBits(0), - m_subscriptionBits(0), - m_waitingForCharacterLoginDeletion(false), - m_waitingForCharacterClusterDeletion(false) -{ +ClientConnection::ClientConnection(UdpConnectionMT *u, TcpClient *t) : + ServerConnection(u, t), + m_clientId(0), + m_isValidated(false), + m_isSecure(false), + m_adminLevel(-1), + m_stationId(0), + m_requestedAdminSuid(0), + m_gameBits(0), + m_subscriptionBits(0), + m_waitingForCharacterLoginDeletion(false), + m_waitingForCharacterClusterDeletion(false) { } //----------------------------------------------------------------------- -ClientConnection::~ClientConnection() -{ +ClientConnection::~ClientConnection() { } //----------------------------------------------------------------------- -void ClientConnection::onConnectionClosed() -{ - // client has disconnected - if (m_stationId) - { - DEBUG_REPORT_LOG(true, ("Client %lu disconnected\n", m_stationId)); - LOG("LoginClientConnection", ("onConnectionClosed() for stationId (%lu) at IP (%s)", m_stationId, getRemoteAddress().c_str())); - } +void ClientConnection::onConnectionClosed() { + // client has disconnected + if (m_stationId) { + 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); + LoginServer::getInstance().removeClient(m_clientId); - if ((ConfigLoginServer::getValidateStationKey() || ConfigLoginServer::getDoSessionLogin()) && !m_isValidated) - { - SessionApiClient *session = LoginServer::getInstance().getSessionApiClient(); - if (session) - { - session->dropClient(this); - } - } + if ((ConfigLoginServer::getValidateStationKey() || ConfigLoginServer::getDoSessionLogin()) && !m_isValidated) { + SessionApiClient *session = LoginServer::getInstance().getSessionApiClient(); + if (session) { + session->dropClient(this); + } + } } //----------------------------------------------------------------------- -void ClientConnection::onConnectionOpened() -{ - m_clientId = LoginServer::getInstance().addClient(*this); - setOverflowLimit(ConfigLoginServer::getClientOverflowLimit()); +void ClientConnection::onConnectionOpened() { + m_clientId = LoginServer::getInstance().addClient(*this); + setOverflowLimit(ConfigLoginServer::getClientOverflowLimit()); - LOG("LoginClientConnection", ("onConnectionOpened() for stationId (%lu) at IP (%s)", m_stationId, getRemoteAddress().c_str())); + LOG("LoginClientConnection", + ("onConnectionOpened() for stationId (%lu) at IP (%s)", m_stationId, getRemoteAddress().c_str())); } //----------------------------------------------------------------------- -void ClientConnection::onReceive(const Archive::ByteStream & message) -{ - try - { - //Handle all client messages here. Do not forward out. - Archive::ReadIterator ri = message.begin(); - GameNetworkMessage m(ri); - ri = message.begin(); - - const uint32 messageType = m.getType(); +void ClientConnection::onReceive(const Archive::ByteStream &message) { + try { + //Handle all client messages here. Do not forward out. + Archive::ReadIterator ri = message.begin(); + GameNetworkMessage m(ri); + ri = message.begin(); - //Validation check - if (!getIsValidated() && messageType != constcrc("LoginClientId")) { - //Receiving message from unvalidated client. Pitch it. - DEBUG_WARNING(true, ("Received %s message from unknown, unvalidated client", m.getCmdName().c_str())); - return; - } + const uint32 messageType = m.getType(); - switch (messageType) { - case constcrc("LoginClientId") : - { - // send the client the server "now" Epoch time so that the - // client has an idea of how much difference there is between - // the client's Epoch time and the server Epoch time - GenericValueTypeMessage const serverNowEpochTime( - "ServerNowEpochTime", static_cast(::time(nullptr))); - send(serverNowEpochTime, true); + //Validation check + if (!getIsValidated() && messageType != constcrc("LoginClientId")) { + //Receiving message from unvalidated client. Pitch it. + DEBUG_WARNING(true, ("Received %s message from unknown, unvalidated client", m.getCmdName().c_str())); + return; + } - LoginClientId id(ri); - - // verify version - #if PRODUCTION == 1 - if(!ConfigLoginServer::getValidateClientVersion() || id.getVersion() == GameNetworkMessage::NetworkVersionId) - { - validateClient(id.getId(), id.getKey()); - } - else - { - LOG("CustomerService", ("Login:LoginServer dropping client (stationId=[%lu], ip=[%s], id=[%s], key=[%s], version=[%s]) because of network version mismatch (required version=[%s])", m_stationId, getRemoteAddress().c_str(), id.getId().c_str(), id.getKey().c_str(), id.getVersion().c_str(), GameNetworkMessage::NetworkVersionId.c_str())); - // disconnect is handled on the client side, as soon as it recieves this message - #if _DEBUG - LoginIncorrectClientId incorrectId(GameNetworkMessage::NetworkVersionId, ApplicationVersion::getInternalVersion()); - #else - LoginIncorrectClientId incorrectId("", ""); - #endif // _DEBUG - send(incorrectId, true); - } - #else - validateClient( id.getId(), id.getKey() ); - #endif // PRODUCTION == 1 - - break; - } - case constcrc("RequestExtendedClusterInfo" ) : - { - LoginServer::getInstance().sendExtendedClusterInfo( *this ); - break; - } - case constcrc("DeleteCharacterMessage") : - { - DeleteCharacterMessage msg(ri); - std::vector::const_iterator f = std::find(m_charactersPendingDeletion.begin(), m_charactersPendingDeletion.end(), msg.getCharacterId()); - if ((m_waitingForCharacterLoginDeletion || m_waitingForCharacterClusterDeletion) && f != m_charactersPendingDeletion.end()) - { - DeleteCharacterReplyMessage reply(DeleteCharacterReplyMessage::rc_ALREADY_IN_PROGRESS); - send(reply,true); - } - else - { - if (LoginServer::getInstance().deleteCharacter(msg.getClusterId(), msg.getCharacterId(), getStationId())) - { - m_waitingForCharacterLoginDeletion=true; - m_waitingForCharacterClusterDeletion=true; - m_charactersPendingDeletion.push_back(msg.getCharacterId()); - } - else - { - DeleteCharacterReplyMessage reply(DeleteCharacterReplyMessage::rc_CLUSTER_DOWN); - send(reply,true); - } - } - break; - } - } - } - catch(const Archive::ReadException & readException) - { - WARNING(true, ("Archive read error (%s) on message from client. Disconnecting client.", readException.what())); - disconnect(); - } + switch (messageType) { + case constcrc("LoginClientId") : { + // send the client the server "now" Epoch time so that the + // client has an idea of how much difference there is between + // the client's Epoch time and the server Epoch time + GenericValueTypeMessage const serverNowEpochTime( + "ServerNowEpochTime", static_cast(::time(nullptr))); + send(serverNowEpochTime, true); + + LoginClientId id(ri); + + // verify version +#if PRODUCTION == 1 + if(!ConfigLoginServer::getValidateClientVersion() || id.getVersion() == GameNetworkMessage::NetworkVersionId) + { + validateClient(id.getId(), id.getKey()); + } + else + { + LOG("CustomerService", ("Login:LoginServer dropping client (stationId=[%lu], ip=[%s], id=[%s], key=[%s], version=[%s]) because of network version mismatch (required version=[%s])", m_stationId, getRemoteAddress().c_str(), id.getId().c_str(), id.getKey().c_str(), id.getVersion().c_str(), GameNetworkMessage::NetworkVersionId.c_str())); + // disconnect is handled on the client side, as soon as it recieves this message +#if _DEBUG + LoginIncorrectClientId incorrectId(GameNetworkMessage::NetworkVersionId, ApplicationVersion::getInternalVersion()); +#else + LoginIncorrectClientId incorrectId("", ""); +#endif // _DEBUG + send(incorrectId, true); + } +#else + validateClient(id.getId(), id.getKey()); +#endif // PRODUCTION == 1 + + break; + } + case constcrc("RequestExtendedClusterInfo") : { + LoginServer::getInstance().sendExtendedClusterInfo(*this); + break; + } + case constcrc("DeleteCharacterMessage") : { + DeleteCharacterMessage msg(ri); + std::vector::const_iterator f = std::find(m_charactersPendingDeletion.begin(), + m_charactersPendingDeletion.end(), + msg.getCharacterId()); + if ((m_waitingForCharacterLoginDeletion || m_waitingForCharacterClusterDeletion) && + f != m_charactersPendingDeletion.end()) { + DeleteCharacterReplyMessage reply(DeleteCharacterReplyMessage::rc_ALREADY_IN_PROGRESS); + send(reply, true); + } else { + if (LoginServer::getInstance().deleteCharacter(msg.getClusterId(), msg.getCharacterId(), + getStationId())) { + m_waitingForCharacterLoginDeletion = true; + m_waitingForCharacterClusterDeletion = true; + m_charactersPendingDeletion.push_back(msg.getCharacterId()); + } else { + DeleteCharacterReplyMessage reply(DeleteCharacterReplyMessage::rc_CLUSTER_DOWN); + send(reply, true); + } + } + break; + } + } + } + catch (const Archive::ReadException &readException) { + WARNING(true, ("Archive read error (%s) on message from client. Disconnecting client.", readException.what())); + disconnect(); + } } //----------------------------------------------------------------------- // originally was used to validate station API credentials, now uses our custom api -void ClientConnection::validateClient(const std::string & id, const std::string & key) -{ - bool authOK = false; - StationId suid = atoi(id.c_str()); - static const std::string authURL(ConfigLoginServer::getExternalAuthUrl()); - std::string uname; +void ClientConnection::validateClient(const std::string &id, const std::string &key) { + bool authOK = false; + StationId suid = atoi(id.c_str()); + static const std::string authURL(ConfigLoginServer::getExternalAuthUrl()); + std::string uname; std::string parentAccount; std::vector childAccounts; - if (!authURL.empty()) - { - // create the object - webAPI api(authURL); // TODO: is loginserver single threaded? if so then let's make this static, and clear/reset it each run - - // add our data - api.addJsonData("user_name", id); - api.addJsonData("user_password", key); - api.addJsonData("ip", getRemoteAddress()); - - if (api.submit()) - { - bool status = api.getNullableValue("status"); - uname = api.getString("username"); + if (!authURL.empty()) { + // create the object + webAPI api( + authURL); // TODO: is loginserver single threaded? if so then let's make this static, and clear/reset it each run - if (status && !uname.empty()) - { - authOK = true; + // add our data + api.addJsonData("user_name", id); + api.addJsonData("user_password", key); + api.addJsonData("ip", getRemoteAddress()); - parentAccount = api.getString("mainAccount"); - childAccounts = api.getStringVector("subAccounts"); - } - else - { - std::string msg = api.getString("message"); - if (msg.empty()) - { - msg = "Invalid username or password."; - } - - ErrorMessage err("Login Failed", msg); - this->send(err, true); - } - } - else - { - ErrorMessage err("Login Failed", "Could not connect to remote."); - this->send(err, true); - } - } - else - { - // test mode - authOK = true; - uname = id; - } + if (api.submit()) { + bool status = api.getNullableValue("status"); + uname = api.getString("username"); - if (authOK) - { - if (suid == 0) - { - if (uname.length() > MAX_ACCOUNT_NAME_LENGTH) - { - uname.resize(MAX_ACCOUNT_NAME_LENGTH); - } + if (status && !uname.empty()) { + authOK = true; - std::hash h; - suid = h(uname.c_str()); - } + parentAccount = api.getString("mainAccount"); + childAccounts = api.getStringVector("subAccounts"); + } else { + std::string msg = api.getString("message"); + if (msg.empty()) { + msg = "Invalid username or password."; + } - std::hash h; - StationId parent = h(parentAccount); + ErrorMessage err("Login Failed", msg); + this->send(err, true); + } + } else { + ErrorMessage err("Login Failed", "Could not connect to remote."); + this->send(err, true); + } + } else { + // test mode + authOK = true; + uname = id; + } - WARNING(true, ("Parent account is %s", parentAccount.c_str())); + if (authOK) { + if (suid == 0) { + if (uname.length() > MAX_ACCOUNT_NAME_LENGTH) { + uname.resize(MAX_ACCOUNT_NAME_LENGTH); + } - for (auto i : childAccounts) { - WARNING(true, ("Found child account %s %llu", i.c_str(), h(i))); + std::hash h; + suid = h(uname.c_str()); + } - if (i.length() > MAX_ACCOUNT_NAME_LENGTH) { - i.resize(MAX_ACCOUNT_NAME_LENGTH); - } + std::hash h; + StationId parent = h(parentAccount); - // insert all related accounts, if not already there, into the db - DatabaseConnection::getInstance().upsertAccountRelationship(parent, h(i)); - } + WARNING(true, ("Parent account is %s", parentAccount.c_str())); - LOG("LoginClientConnection", ("validateClient() for stationId (%lu) at IP (%s), id (%s)", m_stationId, getRemoteAddress().c_str(), uname.c_str())); - - LoginServer::getInstance().onValidateClient(suid, uname, this, true, NULL, 0xFFFFFFFF, 0xFFFFFFFF); - } + for (auto i : childAccounts) { + if (i.length() > MAX_ACCOUNT_NAME_LENGTH) { + i.resize(MAX_ACCOUNT_NAME_LENGTH); + } + + StationId childID = h(i); + printf ("\tFound child account %s (%llu)", i.c_str(), childID); + + // insert all related accounts, if not already there, into the db + DatabaseConnection::getInstance().upsertAccountRelationship(parent, childID); + } + + LOG("LoginClientConnection", + ("validateClient() for stationId (%lu) at IP (%s), id (%s)", m_stationId, getRemoteAddress().c_str(), uname.c_str())); + + LoginServer::getInstance().onValidateClient(suid, uname, this, true, NULL, 0xFFFFFFFF, 0xFFFFFFFF); + } } // ---------------------------------------------------------------------------- @@ -277,49 +253,46 @@ void ClientConnection::validateClient(const std::string & id, const std::string * required for character deletion. If the character has already been deleted * from the cluster, send the reply message to the client. */ -void ClientConnection::onCharacterDeletedFromLoginDatabase(const NetworkId & characterId) -{ - m_waitingForCharacterLoginDeletion = false; - if (!m_waitingForCharacterClusterDeletion) - { - std::vector::iterator f = std::find(m_charactersPendingDeletion.begin(), m_charactersPendingDeletion.end(), characterId); - if(f != m_charactersPendingDeletion.end()) - { - m_charactersPendingDeletion.erase(f); - } - - DeleteCharacterReplyMessage reply(DeleteCharacterReplyMessage::rc_OK); - send(reply,true); - LOG("CustomerService", ("Player:deleted character %s for stationId %u at IP: %s", characterId.getValueString().c_str(), m_stationId, getRemoteAddress().c_str())); - } +void ClientConnection::onCharacterDeletedFromLoginDatabase(const NetworkId &characterId) { + m_waitingForCharacterLoginDeletion = false; + if (!m_waitingForCharacterClusterDeletion) { + std::vector::iterator f = std::find(m_charactersPendingDeletion.begin(), + m_charactersPendingDeletion.end(), characterId); + if (f != m_charactersPendingDeletion.end()) { + m_charactersPendingDeletion.erase(f); + } + + DeleteCharacterReplyMessage reply(DeleteCharacterReplyMessage::rc_OK); + send(reply, true); + LOG("CustomerService", + ("Player:deleted character %s for stationId %u at IP: %s", characterId.getValueString().c_str(), m_stationId, getRemoteAddress().c_str())); + } } // ---------------------------------------------------------------------- -void ClientConnection::onCharacterDeletedFromCluster(const NetworkId & characterId) -{ - m_waitingForCharacterClusterDeletion = false; - if (!m_waitingForCharacterLoginDeletion) - { - std::vector::iterator f = std::find(m_charactersPendingDeletion.begin(), m_charactersPendingDeletion.end(), characterId); - if(f != m_charactersPendingDeletion.end()) - { - m_charactersPendingDeletion.erase(f); +void ClientConnection::onCharacterDeletedFromCluster(const NetworkId &characterId) { + m_waitingForCharacterClusterDeletion = false; + if (!m_waitingForCharacterLoginDeletion) { + std::vector::iterator f = std::find(m_charactersPendingDeletion.begin(), + m_charactersPendingDeletion.end(), characterId); + if (f != m_charactersPendingDeletion.end()) { + m_charactersPendingDeletion.erase(f); - // TODO: send api request and decrement # characters on this account/subaccount - } - - DeleteCharacterReplyMessage reply(DeleteCharacterReplyMessage::rc_OK); - send(reply,true); - LOG("CustomerService", ("Player:deleted character %s for stationId %u at IP: %s", characterId.getValueString().c_str(), m_stationId, getRemoteAddress().c_str())); - } + // TODO: send api request and decrement # characters on this account/subaccount + } + + DeleteCharacterReplyMessage reply(DeleteCharacterReplyMessage::rc_OK); + send(reply, true); + LOG("CustomerService", + ("Player:deleted character %s for stationId %u at IP: %s", characterId.getValueString().c_str(), m_stationId, getRemoteAddress().c_str())); + } } // ---------------------------------------------------------------------- -StationId ClientConnection::getRequestedAdminSuid() const -{ - return m_requestedAdminSuid; +StationId ClientConnection::getRequestedAdminSuid() const { + return m_requestedAdminSuid; } // ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/TaskMapAccount.cpp b/engine/server/application/LoginServer/src/shared/TaskMapAccount.cpp index 7fa0f104..368d8131 100644 --- a/engine/server/application/LoginServer/src/shared/TaskMapAccount.cpp +++ b/engine/server/application/LoginServer/src/shared/TaskMapAccount.cpp @@ -54,7 +54,7 @@ TaskMapAccount::MapAccountQuery::MapAccountQuery() : void TaskMapAccount::MapAccountQuery::getSQL(std::string &sql) { - sql = std::string("begin ")+DatabaseConnection::getInstance().getSchemaQualifier()+"select login.upsert_account_map(:parentID, :childID) from dual; end;"; + sql = std::string("begin ")+DatabaseConnection::getInstance().getSchemaQualifier()+"login.upsert_account_map(:parentID, :childID); end;"; } // ----------------------------------------------------------------------