diff --git a/engine/server/application/LoginServer/CMakeLists.txt b/engine/server/application/LoginServer/CMakeLists.txt new file mode 100644 index 00000000..8395072e --- /dev/null +++ b/engine/server/application/LoginServer/CMakeLists.txt @@ -0,0 +1,6 @@ + +cmake_minimum_required(VERSION 2.8) + +project(LoginServer) + +add_subdirectory(src) diff --git a/engine/server/application/LoginServer/src/CMakeLists.txt b/engine/server/application/LoginServer/src/CMakeLists.txt new file mode 100644 index 00000000..969b6216 --- /dev/null +++ b/engine/server/application/LoginServer/src/CMakeLists.txt @@ -0,0 +1,9 @@ + + +add_subdirectory(shared) + +if(WIN32) + add_subdirectory(win32) +else() + add_subdirectory(linux) +endif() \ No newline at end of file diff --git a/engine/server/application/LoginServer/src/linux/CMakeLists.txt b/engine/server/application/LoginServer/src/linux/CMakeLists.txt new file mode 100644 index 00000000..977a8464 --- /dev/null +++ b/engine/server/application/LoginServer/src/linux/CMakeLists.txt @@ -0,0 +1,8 @@ + +add_executable(LoginServer + main.cpp +) + +target_link_libraries(LoginServer + LoginServershared +) \ No newline at end of file diff --git a/engine/server/application/LoginServer/src/linux/main.cpp b/engine/server/application/LoginServer/src/linux/main.cpp new file mode 100644 index 00000000..7b4d7c1b --- /dev/null +++ b/engine/server/application/LoginServer/src/linux/main.cpp @@ -0,0 +1,49 @@ +#include "sharedFoundation/FirstSharedFoundation.h" + +#include "ConfigLoginServer.h" +#include "LoginServer.h" + +#include "sharedCompression/SetupSharedCompression.h" +#include "sharedDebug/SetupSharedDebug.h" +#include "sharedFile/SetupSharedFile.h" +#include "sharedFoundation/ConfigFile.h" +#include "sharedFoundation/Os.h" +#include "sharedFoundation/SetupSharedFoundation.h" +#include "sharedNetworkMessages/SetupSharedNetworkMessages.h" +#include "sharedRandom/SetupSharedRandom.h" +#include "sharedThread/SetupSharedThread.h" + +// ====================================================================== + +int main(int argc, char ** argv) +{ + + SetupSharedThread::install(); + SetupSharedDebug::install(1024); + + //-- setup foundation + SetupSharedFoundation::Data setupFoundationData(SetupSharedFoundation::Data::D_game); + setupFoundationData.lpCmdLine = ConvertCommandLine(argc,argv); + setupFoundationData.configFile = "loginServer.cfg"; + SetupSharedFoundation::install (setupFoundationData); + + if (ConfigFile::isEmpty()) + FATAL(true, ("No config file specified")); + + SetupSharedCompression::install(); + + SetupSharedFile::install(false); + SetupSharedNetworkMessages::install(); + + SetupSharedRandom::install(static_cast(time(NULL))); //lint !e1924 !e64 // NULL is a C-Style cast? + + Os::setProgramName("LoginServer"); + //setup the server + ConfigLoginServer::install(); + + //-- run game + SetupSharedFoundation::callbackWithExceptionHandling(LoginServer::run); + SetupSharedFoundation::remove(); + + return 0; +} diff --git a/engine/server/application/LoginServer/src/shared/CMakeLists.txt b/engine/server/application/LoginServer/src/shared/CMakeLists.txt new file mode 100644 index 00000000..40dfed4f --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/CMakeLists.txt @@ -0,0 +1,68 @@ + +add_library(LoginServershared + CentralServerConnection.cpp + CentralServerConnection.h + ClientConnection.cpp + ClientConnection.h + ConfigLoginServer.cpp + ConfigLoginServer.h + ConsoleCommandParser.cpp + ConsoleCommandParser.h + ConsoleCommandParserLoginServer.cpp + ConsoleCommandParserLoginServer.h + ConsoleManager.cpp + ConsoleManager.h + CSToolConnection.cpp + CSToolConnection.h + DatabaseConnection.cpp + DatabaseConnection.h + FirstLoginServer.h + LoginServer.cpp + LoginServer.h + LoginServerRemoteDebugConnection.cpp + LoginServerRemoteDebugConnection.h + LoginServerRemoteDebugSetup.cpp + LoginServerRemoteDebugSetup.h + PingConnection.cpp + PingConnection.h + PurgeManager.cpp + PurgeManager.h + SessionApiClient.cpp + SessionApiClient.h + TaskChangeStationId.cpp + TaskChangeStationId.h + TaskClaimRewards.cpp + TaskClaimRewards.h + TaskCreateCharacter.cpp + TaskCreateCharacter.h + TaskDeleteCharacter.cpp + TaskDeleteCharacter.h + TaskEnableCharacter.cpp + TaskEnableCharacter.h + TaskGetAccountForPurge.cpp + TaskGetAccountForPurge.h + TaskGetAvatarList.cpp + TaskGetAvatarList.h + TaskGetCharactersForDelete.cpp + TaskGetCharactersForDelete.h + TaskGetClusterList.cpp + TaskGetClusterList.h + TaskGetValidationData.cpp + TaskGetValidationData.h + TaskRegisterNewCluster.cpp + TaskRegisterNewCluster.h + TaskRenameCharacter.cpp + TaskRenameCharacter.h + TaskRestoreCharacter.cpp + TaskRestoreCharacter.h + TaskSetPurgeStatus.cpp + TaskSetPurgeStatus.h + TaskToggleCharacterDisable.cpp + TaskToggleCharacterDisable.h + TaskToggleCompletedTutorial.cpp + TaskToggleCompletedTutorial.h + TaskUpdatePurgeAccountList.cpp + TaskUpdatePurgeAccountList.h + TaskUpgradeAccount.cpp + TaskUpgradeAccount.h +) diff --git a/engine/server/application/LoginServer/src/shared/CSToolConnection.cpp b/engine/server/application/LoginServer/src/shared/CSToolConnection.cpp new file mode 100644 index 00000000..6c663d93 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/CSToolConnection.cpp @@ -0,0 +1,397 @@ +// CSToolConnection.cpp +// copyright 2005 Sony Online Entertainment +// Author: Robert Hanz + +#include "FirstLoginServer.h" + +#include "Archive/ByteStream.h" +#include "ConfigLoginServer.h" +#include "CSToolConnection.h" +#include "serverNetworkMessages/CSToolRequest.h" +#include "serverUtility/AdminAccountManager.h" +#include "Session/LoginAPI/Client.h" +#include "SessionApiClient.h" +#include "sharedLog/Log.h" + +#if defined(WIN32) + #include +#else // for non-windows platforms (linux) + #include +#endif + +namespace CSToolConnectionNamespace +{ + std::map< uint32, CSToolConnection * > toolsByID; +} + +uint32 CSToolConnection::m_curToolID = 0; + +// statics + +CSToolConnection * CSToolConnection::getCSToolConnectionByToolId( uint32 id ) +{ + std::map< uint32, CSToolConnection * >::iterator it = CSToolConnectionNamespace::toolsByID.find( id ); + return it == CSToolConnectionNamespace::toolsByID.end() ? 0 : it->second; +} + +void CSToolConnection::validateCSTool(uint32 toolId, apiResult result, const apiSession& session) +{ + //find the tool + CSToolConnection * p_connection = getCSToolConnectionByToolId(toolId); + if (!p_connection) + return; // no connection, they must have bailed. + + // check the result + if(result == RESULT_SUCCESS) + { + // if we're valid, set to logged in + p_connection->m_bLoggedIn = true; + if (session.GetIsSecure()) + { + p_connection->m_bSecure = true; + } + + // if we have a null session type, then we aren't connected to the + // Session Server and are in debug mode. + // + // if we *do* have a good session, then check the admin table for access level. + int accessLevel = 100; + + bool sessionNull = (session.GetType() == SESSION_TYPE_NULL); + bool isAdmin = AdminAccountManager::isAdminAccount(p_connection->m_sUserName, accessLevel); + bool needSecure = ConfigLoginServer::getRequireSecureLoginForCsTool(); + bool isInternal = AdminAccountManager::isInternalIp(p_connection->getRemoteAddress()); + DEBUG_REPORT_LOG( true, ("CS Tool login for %s, admin=%s, access=%d, internal=%s\n", + p_connection->m_sUserName.c_str(), + isAdmin ? "true" : "false", + accessLevel, + isInternal ? "true" : "false")); + + + bool canLogin = isInternal; // we always have to be internal. + if (sessionNull) + { + // null session means we can skip everything else. + canLogin = canLogin && true; + accessLevel = 100; + } + else + { + // if we don't have a session, we need to be on the admin table + if(isAdmin) + { + // allow login if we either don't need to be secure, or if we are. + if((!needSecure) || p_connection->m_bSecure) + { + canLogin = canLogin && true; + } + else + { + canLogin = false; + } + } + else + { + canLogin = false; + } + } + + if(canLogin) + { + // and inform + std::string response = "Logged in successfully."; + + response += "\r\n"; + p_connection->sendToTool(response); + + p_connection->m_ui32PrivilegeLevel = (uint32)accessLevel; + } + else + { + p_connection->sendToTool("Invalid name/password.\r\n"); + } + + } + // otherwise, give the appropriate response + else if( result == RESULT_INVALID_NAME_OR_PASSWORD ) + { + p_connection->sendToTool("Invalid name/password.\r\n"); + } + else + { + DEBUG_REPORT_LOG(true,("Could not log in CS Tool for user %s, reason %d\n", p_connection->m_sUserName.c_str(), result)); + p_connection->sendToTool("Invalid name/password.\r\n"); + } + +} + +// members + +CSToolConnection::CSToolConnection( UdpConnectionMT * pUdpConn, TcpClient * pTcpConn ) : + Connection( pUdpConn, pTcpConn ), + m_ui32StationID( 0 ), + m_bSecure( false ), + m_bLoggedIn( false ), + m_ui32PrivilegeLevel( 0 ) +{ + if( pTcpConn ) // it'd better be! + setRawTCP( true ); +} + +CSToolConnection::~CSToolConnection() +{ +} + +void CSToolConnection::onReceive( const Archive::ByteStream & message ) +{ + // for testing purposes, just echo back to the user. + + // add to buffer + std::string input; + const unsigned char * uc = message.getBuffer(); + while (uc < message.getBuffer() + message.getSize()) + { + char s = *uc; + input += s; + ++uc; + } + m_sInputBuffer += input; + + + // while we've got an EOL signifier + std::string::size_type pos; + while( ( pos = m_sInputBuffer.find( '\r' ) ) != std::string::npos ) + { + // rebuild message buffer properly. + std::string command = m_sInputBuffer.substr( 0, pos ); + // should dispatch here, for now we're echoing back for debug. + + //command = command + "\r\n"; + //sendToTool( command ); + this->parse( command ); + // then we have additional data. Otherwise, we don't. + if( m_sInputBuffer.size() >= pos + 2 ) + { + m_sInputBuffer = m_sInputBuffer.substr( pos + 2, m_sInputBuffer.length() - ( pos + 2 ) ); + } + else + { + m_sInputBuffer = ""; + } + + } +} + +void CSToolConnection::parse( const std::string command ) +{ + // grab the first word of the command. + std::string first; + std::string args; + std::string::size_type pos; + if( ( pos = command.find( ' ' ) ) == std::string::npos ) + { + first = command; + } + else + { + first = command.substr( 0, pos ); + args = command.substr( pos + 1, command.size() - ( pos + 1 ) ); + } + // test for empty commands. + if( first.length() == 0 || first[ 0 ] == ' ' ) + { + return; + } + + std::string response = "ls:"; + + + if( first == "clusters" ) + { + response += "Active clusters:\r\n"; + std::map< std::string, uint32 > data; + LoginServer::getInstance().getAllClusterNamesAndIDs( data ); + for( std::map< std::string, uint32 >::iterator it = data.begin(); + it != data.end(); + ++it ) + { + response += it->first + "\r\n"; + } + sendToTool( response ); + } + else if ( first == "select" ) + { + // see if we're adding, removing, or exclusive-adding. + if( args[ 0 ] == '+' ) + { + if( args.size() > 1 ) + { + if( args[ 1 ] == '+' ) + { + m_selectedClusters.clear(); + sendToTool( "ls:deselected all servers\r\n" ); + } + pos = args.find_first_not_of( "+" ); + if( pos == std::string::npos ) + { + } + else + { + std::string cluster = args.substr( pos, args.size() - pos ); + response += selectCluster( cluster ); + sendToTool( response ); + } + } + } + else if( args[ 0 ] == '-' ) + { + if( args.size() > 1 ) + { + std::string cluster = args.substr( 1, args.size() - 1 ); + if( m_selectedClusters.find( cluster ) != m_selectedClusters.end() ) + { + response += deselectCluster( cluster ); + sendToTool( response ); + } + } + } + else + { + sendToTool( "Error! Bad select format!\r\n" ); + } + } + else if ( first == "showselected" ) + { + response += "Currently selected clusters:\r\n"; + for( std::set< std::string >::iterator it = m_selectedClusters.begin(); + it != m_selectedClusters.end(); + ++it ) + { + response += *it + "\r\n"; + } + sendToTool( response ); + + } + else if( first == "login" ) + { + // assume name/pw do not have spaces. + std::string name; + std::string pw; + + // split apart + unsigned pos = args.find( " " ); + if( pos != std::string::npos ) + { + name = args.substr( 0, pos ); + pw = args.substr( pos + 1, args.length() - pos - 1 ); + m_sUserName = name; + if( !LoginServer::getInstance().getSessionApiClient() ) + { + apiSession session; + validateCSTool( m_toolID, RESULT_SUCCESS, session ); + return; + } + LoginServer::getInstance().getSessionApiClient()-> + SessionLogin(name.c_str(), + pw.c_str(), + SESSION_TYPE_STARWARS, + inet_addr( getRemoteAddress().c_str() ), + 0, + _defaultNamespace, + ( void * )m_toolID ); + } + + // pass to session. + } + // default command handler. + else + { + if( m_bLoggedIn ) + { + sendToClusters( first, command ); + } + else + { + sendToTool( "Not logged in.\r\n" ); + } + } + +} + +void CSToolConnection::sendToClusters( const std::string & sCommand, const std::string & sCommandLine ) +{ + // build the message + CSToolRequest msg( m_ui32StationID, m_ui32PrivilegeLevel, sCommandLine, sCommand, m_toolID, m_sUserName ); + + // send to all currently selected clusters. + for( std::set< std::string >::iterator it = m_selectedClusters.begin(); + it != m_selectedClusters.end(); + ++it ) + { + LoginServer::getInstance().sendToCluster( LoginServer::getInstance().getClusterIDByName( *it ), msg ); + } +} + +std::string CSToolConnection::selectCluster( const std::string & cluster ) +{ + std::string response; + // see if we have a valid cluster. + uint32 cluster_id = LoginServer::getInstance().getClusterIDByName( cluster ); + if( cluster_id == 0 ) + { + response += "Cluster " + cluster + " does not exist.\r\n"; + } + else + { + m_selectedClusters.insert( cluster ); + response += "Cluster " + cluster + " added to active list\r\n"; + } + return response; +} + +std::string CSToolConnection::deselectCluster( const std::string & cluster ) +{ + std::string response; + + // see if we are currently talking to that cluster. + std::set< std::string >::iterator it = m_selectedClusters.find( cluster ); + if( it == m_selectedClusters.end() ) + { + response += "Cluster " + cluster + " is not currently selected.\r\n"; + } + else + { + m_selectedClusters.erase( it ); + response += "Cluster " + cluster + " removed from active list.\r\n"; + } + return response; + +} + +void CSToolConnection::sendToTool( const std::string & message ) +{ + // convert to ByteStream + std::string temp = message; + temp += "\r\n*\r\n"; + Archive::ByteStream bs; + bs.put( temp.c_str(), temp.size() ); + // send. + this->send( bs, true ); +} + +void CSToolConnection::onConnectionOpened() +{ + LOG( "CSTool", ("Connection opened") ); + // assign an ID, and stick it in our map. + m_curToolID++; + m_toolID = m_curToolID; + CSToolConnectionNamespace::toolsByID[ m_toolID ] = this; + +} + +void CSToolConnection::onConnectionClosed() +{ + LOG( "CSTool", ("Connection closed") ); + CSToolConnectionNamespace::toolsByID.erase( m_toolID ); + +} diff --git a/engine/server/application/LoginServer/src/shared/CSToolConnection.h b/engine/server/application/LoginServer/src/shared/CSToolConnection.h new file mode 100644 index 00000000..08651f09 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/CSToolConnection.h @@ -0,0 +1,59 @@ +// CSToolConnection.h +// copyright 2005 Sony Online Entertainment +// Author: Robert Hanz + +#ifndef _CSToolConnection_h +#define _CSToolConnection_h + +#include "SessionApiClient.h" +#include "sharedFoundation/StationId.h" +#include "sharedNetwork/Connection.h" + +#include + + +class CSToolConnection : public Connection +{ +public: + CSToolConnection(UdpConnectionMT *, TcpClient *); + + CSToolConnection( + const std::string & address, + const unsigned short port); + + virtual ~CSToolConnection(); + + void onReceive(const Archive::ByteStream & message); + void sendToTool(const std::string & message ); + virtual void onConnectionOpened(); + virtual void onConnectionClosed(); + void sendToClusters( const std::string & sCommand, const std::string &sCommandLine ); + + static CSToolConnection * getCSToolConnectionByToolId( uint32 id ); + static void validateCSTool( uint32 toolId, apiResult result, const apiSession & session ); + + // cluster selection interface + std::string selectCluster( const std::string & cluster ); + std::string deselectCluster( const std::string & cluster ); + +protected: + + void parse( const std::string command ); + + uint32 m_ui32StationID; // 0 = not authenticated + std::string m_sAccountLogin; + bool m_bSecure; + bool m_bLoggedIn; + uint32 m_ui32PrivilegeLevel; + std::string m_sInputBuffer; + std::string m_sUserName; + uint32 m_toolID; + static uint32 m_curToolID; + std::set< std::string > m_selectedClusters; + +private: + CSToolConnection(const CSToolConnection& ); + CSToolConnection& operator=(const CSToolConnection& ); +}; + +#endif //_CSToolConnection_h diff --git a/engine/server/application/LoginServer/src/shared/CentralServerConnection.cpp b/engine/server/application/LoginServer/src/shared/CentralServerConnection.cpp new file mode 100644 index 00000000..6b803038 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/CentralServerConnection.cpp @@ -0,0 +1,375 @@ +// CentralServerConnection.cpp +// copyright 2000 Verant Interactive +// Author: Justin Randall + + +//----------------------------------------------------------------------- + +#include "FirstLoginServer.h" +#include "Archive/ByteStream.h" +#include "sharedFoundation/NetworkIdArchive.h" +#include "CentralServerConnection.h" +#include "ConsoleManager.h" +#include "CSToolConnection.h" +#include "ClientConnection.h" +#include "DatabaseConnection.h" +#include "serverNetworkMessages/CSToolResponse.h" +#include "serverNetworkMessages/LoginClusterName.h" +#include "serverNetworkMessages/LoginClusterName2.h" +#include "serverNetworkMessages/ToggleAvatarLoginStatus.h" +#include "serverNetworkMessages/TransferAccountData.h" +#include "serverNetworkMessages/TransferAccountDataArchive.h" +#include "serverNetworkMessages/TransferCharacterData.h" +#include "serverNetworkMessages/TransferCharacterDataArchive.h" +#include "serverNetworkMessages/TransferReplyCharacterList.h" +#include "sharedLog/Log.h" +#include "sharedNetwork/NetworkSetupData.h" +#include "sharedNetworkMessages/ConsoleChannelMessages.h" +#include "sharedNetworkMessages/DeleteCharacterMessage.h" +#include "sharedNetworkMessages/GenericValueTypeMessage.h" +#include "Unicode.h" +#include "UnicodeUtils.h" + +//----------------------------------------------------------------------- + +namespace CentralServerConnectionNamespace +{ + std::map s_centralConnectionsByName; +} + +using namespace CentralServerConnectionNamespace; + +//----------------------------------------------------------------------- + +CentralServerConnection::CentralServerConnection(UdpConnectionMT * u, TcpClient * t) : + ServerConnection(u, t), + m_clusterName(), + m_networkVersion(), + m_clusterId(0) +{ +} + +// ---------------------------------------------------------------------- + +CentralServerConnection::CentralServerConnection( + const std::string & address, + const unsigned short port, + const std::string &clusterName, + const uint32 clusterId) : + ServerConnection(address,port, NetworkSetupData()), + m_clusterName( clusterName ), + m_networkVersion(), + m_clusterId( clusterId ) +{ + s_centralConnectionsByName[m_clusterName] = this; +} + +//----------------------------------------------------------------------- + +CentralServerConnection::~CentralServerConnection() +{ + if(! m_clusterName.empty()) + { + std::map::iterator f = s_centralConnectionsByName.find(m_clusterName); + if(f != s_centralConnectionsByName.end()) + { + s_centralConnectionsByName.erase(f); + } + + LOG("CentralServerConnection", ("Galaxy [%s] disconnected", m_clusterName.c_str())); + } + else + { + LOG("CentralServerConnection", ("Galaxy connection destroyed (never fully connected)")); + } +} + +//----------------------------------------------------------------------- + +void CentralServerConnection::onConnectionOpened() +{ + ServerConnection::onConnectionOpened(); +} + +//----------------------------------------------------------------------- + +void CentralServerConnection::onReceive(const Archive::ByteStream & message) +{ + // emit the message in case someone else wants to use it + ServerConnection::onReceive(message); + + Archive::ReadIterator ri = message.begin(); + GameNetworkMessage m(ri); + ri = message.begin(); + // handle messages the connection object itself may be interested in + if(m.isType("LoginClusterName")) + { + const LoginClusterName c(ri); + ri = message.begin(); + setClusterName(c.getClusterName()); + LOG("CentralServerConnection", ("Galaxy [%s] connected", c.getClusterName().c_str())); + } + else if ( m.isType( "LoginClusterName2" ) ) + { + const LoginClusterName2 c( ri ); + ri = message.begin(); + + const std::string &clusterName = c.getClusterName(); + const std::string &branch = c.getBranch(); + const int changelist = c.getChangelist(); + const std::string &networkVersion = c.getNetworkVersion(); + + DEBUG_REPORT_LOG( true, ( "!!!!!!!!!!!!!!!! name=%s branch=%s changelist=%d net=%s\n", clusterName.c_str(), branch.c_str(), changelist, networkVersion.c_str() ) ); + + setClusterName( clusterName ); + setNetworkVersion( c.getNetworkVersion() ); + LOG("CentralServerConnection", ("Galaxy [%s] connected", getClusterName().c_str())); + + LoginServer::getInstance().setClusterInfoByName( clusterName, branch, changelist, networkVersion ); + + } + else if(m.isType("ToggleAvatarLoginStatus")) + { + const ToggleAvatarLoginStatus t(ri); + if(t.getEnabled()) + { + LOG("CustomerService", ("CharacterTransfer: ToggleAvatarLoginStatus(%s, %d, %s, true)", t.getClusterName().c_str(), t.getStationId(), t.getCharacterId().getValueString().c_str())); + } + else + { + // send message to the cluster to drop connected clients for the + // station id in case the avatar being disabled is currently logged in + GenericValueTypeMessage const closeRequest("TransferCloseClientConnection", t.getStationId()); + LoginServer::getInstance().sendToCluster(LoginServer::getInstance().getClusterIDByName(t.getClusterName()), closeRequest); + + LOG("CustomerService", ("CharacterTransfer: ToggleAvatarLoginStatus(%s, %d, %s, false)\n", t.getClusterName().c_str(), t.getStationId(), t.getCharacterId().getValueString().c_str())); + } + DatabaseConnection::getInstance().toggleDisableCharacter(LoginServer::getInstance().getClusterIDByName(t.getClusterName()), t.getCharacterId(), t.getStationId(), t.getEnabled()); + } + else if(m.isType("CtsCompletedForcharacter")) + { + const GenericValueTypeMessage > msg(ri); + LoginServer::getInstance().sendToCluster(LoginServer::getInstance().getClusterIDByName(msg.getValue().first), msg); + } + else if(m.isType("TransferRequestCharacterList")) + { + const GenericValueTypeMessage request(ri); + const TransferCharacterData & d = request.getValue(); + DatabaseConnection::getInstance().requestAvatarListForAccount(d.getSourceStationId(), &d); + } + else if(m.isType("TransferReplyLoginLocationData")) + { + const GenericValueTypeMessage reply(ri); + const TransferCharacterData & d = reply.getValue(); + LOG("CustomerService", ("CharacterTransfer: Received login location data. %s", d.toString().c_str())); + } + else if(m.isType("TransferGetCharacterDataFromLoginServer")) + { + // the TransferServer sent a request to the central server + // to retrieve a character ID from the login database given + // a source station ID and a source character name. Retrieve + // this data from the login database. + const GenericValueTypeMessage request(ri); + TransferCharacterData d = request.getValue(); + DatabaseConnection::getInstance().requestAvatarListForAccount(d.getSourceStationId(), &d); + LOG("CustomerService", ("CharacterTransfer: Received TransferGetCharactetrDataFromLoginServer from CentralServer. %s", d.toString().c_str())); + } + else if(m.isType("TransferRenameCharacterInLoginDatabase")) + { + const GenericValueTypeMessage request(ri); + LOG("CustomerService", ("CharacterTransfer: Received TransferRenameCharacterInLoginDatabase : %s", request.getValue().toString().c_str())); + const TransferCharacterData & requestData = request.getValue(); + DatabaseConnection::getInstance().renameCharacter(getClusterId(), requestData.getCharacterId(), Unicode::narrowToWide(requestData.getDestinationCharacterName()), &requestData); + } + else if(m.isType("TransferKickConnectedClients")) + { + const GenericValueTypeMessage kick(ri); + ClientConnection * clientConnection = LoginServer::getInstance().getValidatedClient(kick.getValue()); + if(! clientConnection) + { + clientConnection = LoginServer::getInstance().getUnvalidatedClient(kick.getValue()); + } + + if(clientConnection) + { + clientConnection->disconnect(); + } + } + else if(m.isType("TransferAccountRequestLoginServer")) + { + const GenericValueTypeMessage request(ri); + LOG("CustomerService", ("CharacterTransfer: Received TransferAccountRequestLoginServer from station ID %d to from station ID %d", request.getValue().getSourceStationId(), request.getValue().getDestinationStationId())); + const TransferAccountData requestData = request.getValue(); + DatabaseConnection::getInstance().requestAvatarListAccountTransfer(&requestData); + } + else if(m.isType("EnableCharacterMessage")) + { + const GenericValueTypeMessage, std::string> > msg(ri); + + LOG("LoginServer", ("EnableCharacter %d, %s request from %s\n", msg.getValue().first.first, msg.getValue().first.second.getValueString().c_str(), msg.getValue().second.c_str())); + + DatabaseConnection::getInstance().enableCharacter(msg.getValue().first.first, msg.getValue().first.second, msg.getValue().second, true, m_clusterId); + } + else if(m.isType("DisableCharacterMessage")) + { + const GenericValueTypeMessage, std::string> > msg(ri); + + LOG("LoginServer", ("DisableCharacter %d, %s request from %s\n", msg.getValue().first.first, msg.getValue().first.second.getValueString().c_str(), msg.getValue().second.c_str())); + + DatabaseConnection::getInstance().enableCharacter(msg.getValue().first.first, msg.getValue().first.second, msg.getValue().second, false, m_clusterId); + } + else if(m.isType("DeleteFailedTransfer")) + { + GenericValueTypeMessage deleteCharacter(ri); + LOG("CustomerService", ("CharacterTransfer: LoginServer received request to delete a character for a failed transfer. %s", deleteCharacter.getValue().toString().c_str())); + LoginServer::getInstance().deleteCharacter(m_clusterId, deleteCharacter.getValue().getDestinationCharacterId(), deleteCharacter.getValue().getDestinationStationId()); + } + else if(m.isType("RequestTransferClosePseudoClientConnection")) + { + GenericValueTypeMessage > const request(ri); + GenericValueTypeMessage const closeRequest("TransferClosePseudoClientConnection", request.getValue().second); + LoginServer::getInstance().sendToCluster(LoginServer::getInstance().getClusterIDByName(request.getValue().first), closeRequest); + } + else if(m.isType("CSToolResponse" ) ) + { + CSToolResponse response(ri); + // find the connection, if it still exists + CSToolConnection * con = CSToolConnection::getCSToolConnectionByToolId( response.getToolId() ); + + // send the response + if( con ) + { + std::string message; + message = m_clusterName + ":" + response.getResult(); + + if( message[ message.length() -1 ] == '\n' && message[ message.length() - 2 ] != '\r' ) + { + message[ message.length() - 1 ] = '\r'; + message += '\n'; + } + + con->sendToTool( message ); + } + } + else if(m.isType("ConGenericMessage")) + { + ConGenericMessage con(ri); + parseCommand(con.getMsg(), con.getMsgId()); + } + else if(m.isType("LoginToggleCompletedTutorial")) + { + GenericValueTypeMessage< std::pair > const request(ri); + std::pair values = request.getValue(); + DatabaseConnection::getInstance().toggleCompletedTutorial(values.first, values.second); + } + + else if(m.isType("AllCluserGlobalChannel")) + { + typedef std::pair, bool> PayloadType; + GenericValueTypeMessage msg(ri); + + PayloadType const & payload = msg.getValue(); + std::string const & channelName = payload.first.first; + std::string const & messageText = payload.first.second; + bool const & isRemove = payload.second; + + LOG("CustomerService", ("BroadcastVoiceChannel: LoginServer sending AllCluserGlobalChannel to all clusters chan(%s) text(%s) remove(%d)", + channelName.c_str(), messageText.c_str(), (isRemove?1:0) )); + + LoginServer::getInstance().sendToAllClusters(msg); + } + + else if(m.isType("GcwScoreStatRaw")) + { + GenericValueTypeMessage >, std::map > > > > const msg(ri); + LoginServer::getInstance().sendToAllClusters(msg, NULL, 0, msg.getValue().first.c_str()); + } + + else if(m.isType("GcwScoreStatPct")) + { + GenericValueTypeMessage, std::map > > > const msg(ri); + LoginServer::getInstance().sendToAllClusters(msg, NULL, 0, msg.getValue().first.c_str()); + } +} + +//----------------------------------------------------------------------- + +bool CentralServerConnection::sendCharacterListResponse(unsigned int stationId, const AvatarList & avatarList, const TransferCharacterData & characterData) +{ + bool result = false; + // find proper central connection + std::map::iterator f = s_centralConnectionsByName.find(characterData.getSourceGalaxy()); + if(f != s_centralConnectionsByName.end()) + { + // cull characters not associated with this server + CentralServerConnection * connection = f->second; + AvatarList::const_iterator i; + AvatarList replyCharacters; + for(i = avatarList.begin(); i != avatarList.end(); ++i) + { + if(i->m_clusterId == connection->m_clusterId) + replyCharacters.push_back(*i); + } + TransferReplyCharacterList reply(characterData.getTrack(), stationId, replyCharacters); + connection->send(reply, true); + result = true; + } + else + { + LOG("Connection", ("Could not find a connection server to send character list response to for character %d\n", stationId)); + } + return result; +} + +//----------------------------------------------------------------------- + +void CentralServerConnection::sendToCentralServer(const std::string & galaxyName, const GameNetworkMessage & message) +{ + std::map::iterator f = s_centralConnectionsByName.find(galaxyName); + if(f != s_centralConnectionsByName.end()) + { + CentralServerConnection * connection = f->second; + connection->send(message, true); + } +} + +//----------------------------------------------------------------------- + +void CentralServerConnection::setClusterName(const std::string & newClusterName) +{ + DEBUG_REPORT_LOG( true, ( "setClusterName %s\n", newClusterName.c_str() ) ); + + m_clusterName = newClusterName; + s_centralConnectionsByName[m_clusterName] = this; +} + +//----------------------------------------------------------------------- + +void CentralServerConnection::setClusterId(uint32 clusterId) +{ + m_clusterId = clusterId; +} + +//----------------------------------------------------------------------- + +void CentralServerConnection::parseCommand(const std::string & cmd, int track) +{ +// int i = s_track; +// s_resultsMap[i] = this; +// ++s_track; + std::string result; + /*CommandParser::ErrorType err =*/ ConsoleManager::processString(cmd, track, result); + ConGenericMessage con(result, track); + send(con, true); +/* if(err == CommandParser::ERR_CMD_NOT_FOUND) + { + onCommandComplete(result, track); + } + else if(!result.empty() && err == CommandParser::ERR_SUCCESS) + { + onCommandComplete(result, track); + } +*/ +} + +//----------------------------------------------------------------------- diff --git a/engine/server/application/LoginServer/src/shared/CentralServerConnection.h b/engine/server/application/LoginServer/src/shared/CentralServerConnection.h new file mode 100644 index 00000000..75d657b2 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/CentralServerConnection.h @@ -0,0 +1,83 @@ +// CentralServerConnection.h +// copyright 2000 Verant Interactive +// Author: Justin Randall + +#ifndef _CentralServerConnection_H +#define _CentralServerConnection_H + +//----------------------------------------------------------------------- + +#include "serverNetworkMessages/AvatarList.h" +#include "serverUtility/ServerConnection.h" + +class CentralServerCommandChannel; +class TransferCharacterData; + +//----------------------------------------------------------------------- + +class CentralServerConnection : public ServerConnection +{ +public: + CentralServerConnection(UdpConnectionMT *, TcpClient *); + + CentralServerConnection( + const std::string & address, + const unsigned short port, + const std::string &clusterName, + const uint32 clusterId); + + ~CentralServerConnection(); + + const std::string & getClusterName(void) const; + uint32 getClusterId() const; + const std::string & getNetworkVersion() const; + void onConnectionOpened(); + void onReceive(const Archive::ByteStream & message); + void setClusterName(const std::string & newClusterName); + void setClusterId(uint32 clusterId); + void setNetworkVersion( const std::string &networkVersion ); + static bool sendCharacterListResponse(unsigned int, const AvatarList &, const TransferCharacterData &); + static void sendToCentralServer(const std::string &, const GameNetworkMessage &); + +private: + std::string m_clusterName; + std::string m_networkVersion; + uint32 m_clusterId; + +private: + CentralServerConnection(const CentralServerConnection&); + CentralServerConnection& operator=(const CentralServerConnection&); + void parseCommand (const std::string & cmd, int trackId); +}; //lint !e1712 // default constructor not defined + +//----------------------------------------------------------------------- + +inline const std::string & CentralServerConnection::getClusterName(void) const +{ + return m_clusterName; +} + +// ---------------------------------------------------------------------- + +inline uint32 CentralServerConnection::getClusterId() const +{ + return m_clusterId; +} + +//----------------------------------------------------------------------- + +inline void CentralServerConnection::setNetworkVersion( const std::string &version ) +{ + m_networkVersion = version; +} + +//----------------------------------------------------------------------- + +inline const std::string &CentralServerConnection::getNetworkVersion() const +{ + return m_networkVersion; +} + +// ====================================================================== + +#endif // _CentralServerConnection_H diff --git a/engine/server/application/LoginServer/src/shared/ClientConnection.cpp b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp new file mode 100644 index 00000000..e18508ee --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp @@ -0,0 +1,258 @@ +// ClientConnection.cpp +// copyright 2000 Verant Interactive +// Author: Justin Randall + + +//----------------------------------------------------------------------- + +#include "FirstLoginServer.h" +#include "ClientConnection.h" + +#include "Archive/ByteStream.h" +#include "ConfigLoginServer.h" +#include "DatabaseConnection.h" +#include "LoginServer.h" +#include "SessionApiClient.h" +#include "serverKeyShare/KeyShare.h" +#include "sharedFoundation/ApplicationVersion.h" +#include "sharedLog/Log.h" +#include "sharedNetworkMessages/ClientLoginMessages.h" +#include "sharedNetworkMessages/DeleteCharacterMessage.h" +#include "sharedNetworkMessages/DeleteCharacterReplyMessage.h" +#include "sharedNetworkMessages/ErrorMessage.h" +#include "sharedNetworkMessages/GenericValueTypeMessage.h" +#include "sharedNetworkMessages/LoginEnumCluster.h" + +//----------------------------------------------------------------------- + +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() +{ +} + +//----------------------------------------------------------------------- + +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) + { + SessionApiClient * session = LoginServer::getInstance().getSessionApiClient(); + if (session) + session->dropClient(this); + } +} + +//----------------------------------------------------------------------- + +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())); +} + +//----------------------------------------------------------------------- + +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() && !m.isType("LoginClientId")) + { + //Receiving message from unvalidated client. Pitch it. + DEBUG_WARNING(true, ("Received %s message from unknown, unvalidated client", m.getCmdName().c_str())); + return; + } + + if(m.isType("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(NULL))); + 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 + + } + else if ( m.isType( "RequestExtendedClusterInfo" ) ) + { + LoginServer::getInstance().sendExtendedClusterInfo( *this ); + } + else if (m.isType("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); + } + } + } + } + catch(const Archive::ReadException & readException) + { + WARNING(true, ("Archive read error (%s) on message from client. Disconnecting client.", readException.what())); + disconnect(); + } +} + +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +// Stub routine for station API account validation. +// Grab a challenge key from the list and send it back to the client. +void ClientConnection::validateClient(const std::string & id, const std::string & key) +{ + + if (ConfigLoginServer::getValidateStationKey()) + { + m_requestedAdminSuid = atoi(id.c_str()); // for normal logins, this will be set to 0 + + SessionApiClient * sessionApiClient = LoginServer::getInstance().getSessionApiClient(); + DEBUG_FATAL(!sessionApiClient, ("Config file says to validate with session, but no session api is installed")); + if(sessionApiClient) //lint !e774 //(Boolean within 'if' always evaluates to True) the previous DEBUG_FATAL probably causes this warning + sessionApiClient->validateClient(this, key); + } + else if (ConfigLoginServer::getDoSessionLogin()) + { + SessionApiClient * sessionApiClient = LoginServer::getInstance().getSessionApiClient(); + DEBUG_FATAL(!sessionApiClient, ("Config file says to do session login, but no session api is installed")); + if(sessionApiClient) //lint !e774 //(Boolean within 'if' always evaluates to True) the previous DEBUG_FATAL probably causes this warning + sessionApiClient->loginClient(this, id, key); + } + else + { + StationId suid = atoi(id.c_str()); + + if (suid==0) + { + std::hash h; + suid = h(id); //lint !e603 // Symbol 'h' not initialized (it's a functor) + } + + LOG("LoginClientConnection", ("validateClient() for stationId (%lu) at IP (%s), id (%s) key (%s), skipping validating session", m_stationId, getRemoteAddress().c_str(), id.c_str(), key.c_str())); + + LoginServer::getInstance().onValidateClient(suid, id, this, true, NULL, 0xFFFFFFFF, 0xFFFFFFFF); + } +} + +// ---------------------------------------------------------------------------- + +/** + * The character has been deleted from the login database. 1/2 of what is + * 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::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); + } + + 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; +} + +// ====================================================================== + diff --git a/engine/server/application/LoginServer/src/shared/ClientConnection.h b/engine/server/application/LoginServer/src/shared/ClientConnection.h new file mode 100644 index 00000000..432e875f --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/ClientConnection.h @@ -0,0 +1,158 @@ +// ClientConnection.h +// copyright 2000 Verant Interactive +// Author: Justin Randall + +#ifndef _ClientConnection_H +#define _ClientConnection_H + +//----------------------------------------------------------------------- + +#include "serverUtility/ServerConnection.h" +#include "sharedFoundation/StationId.h" + +class ClientCommandChannel; +class NetworkId; + +//----------------------------------------------------------------------- + +class ClientConnection : public ServerConnection +{ +public: + ClientConnection(UdpConnectionMT *, TcpClient *); + ~ClientConnection(); + + bool getIsValidated() const; + void setIsValidated(bool); + + bool getIsSecure() const; + void setIsSecure(bool); + + int getAdminLevel() const; + void setAdminLevel(int); + + const StationId getStationId() const; + void setStationId(StationId newValue) const; + StationId getRequestedAdminSuid() const; + + const uint32 getGameBits() const; + const uint32 getSubscriptionBits() const; + void setGameBits(uint32 gameBits) const; + void setSubscriptionBits(uint32 subscriptionBits) const; + + virtual void onConnectionClosed (); + virtual void onConnectionOpened (); + virtual void onReceive (const Archive::ByteStream & message); + + void onCharacterDeletedFromLoginDatabase (const NetworkId & characterId); + void onCharacterDeletedFromCluster (const NetworkId & characterId); + +private: + ClientConnection(const ClientConnection&); + ClientConnection& operator=( const ClientConnection&); + + void validateClient(const std::string & id, const std::string & key); + +private: + int m_clientId; + bool m_isValidated; + bool m_isSecure; // player logged in using a SecureId + int m_adminLevel; // admin level of the player in the admin file (-1 if not in the admin file) + mutable StationId m_stationId; + StationId m_requestedAdminSuid; + mutable uint32 m_gameBits; + mutable uint32 m_subscriptionBits; + + bool m_waitingForCharacterLoginDeletion; + bool m_waitingForCharacterClusterDeletion; + std::vector m_charactersPendingDeletion; + +}; //lint !e1712 // default constructor not defined + +//----------------------------------------------------------------------- + +inline const StationId ClientConnection::getStationId() const +{ + return m_stationId; +} + +// ---------------------------------------------------------------------- + +inline void ClientConnection::setStationId(StationId newValue) const +{ + m_stationId = newValue; +} + +//----------------------------------------------------------------------- + +inline bool ClientConnection::getIsValidated() const +{ + return m_isValidated; +} + +// ---------------------------------------------------------------------- + +inline void ClientConnection::setIsValidated(bool newValue) +{ + m_isValidated = newValue; +} + +// ---------------------------------------------------------------------- + +inline bool ClientConnection::getIsSecure() const +{ + return m_isSecure; +} + +// ---------------------------------------------------------------------- + +inline void ClientConnection::setIsSecure(bool newValue) +{ + m_isSecure = newValue; +} + +// ---------------------------------------------------------------------- + +inline int ClientConnection::getAdminLevel()const +{ + return m_adminLevel; +} + +// ---------------------------------------------------------------------- + +inline void ClientConnection::setAdminLevel(int newValue) +{ + m_adminLevel = newValue; +} + +//----------------------------------------------------------------------- + +inline const uint32 ClientConnection::getGameBits() const +{ + return m_gameBits; +} + +// ---------------------------------------------------------------------- + +inline void ClientConnection::setGameBits(uint32 gameBits) const +{ + m_gameBits = gameBits; +} + +//----------------------------------------------------------------------- + +inline const uint32 ClientConnection::getSubscriptionBits() const +{ + return m_subscriptionBits; +} + +// ---------------------------------------------------------------------- + +inline void ClientConnection::setSubscriptionBits(uint32 subscriptionBits) const +{ + m_subscriptionBits = subscriptionBits; +} + +//----------------------------------------------------------------------- + + +#endif // _ClientConnection_H diff --git a/engine/server/application/LoginServer/src/shared/ConfigLoginServer.cpp b/engine/server/application/LoginServer/src/shared/ConfigLoginServer.cpp new file mode 100644 index 00000000..9823533d --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/ConfigLoginServer.cpp @@ -0,0 +1,204 @@ +// ConfigLoginServer.cpp +// copyright 2000 Verant Interactive +// Author: Justin Randall + + +//----------------------------------------------------------------------- + +#include "FirstLoginServer.h" +#include "serverUtility/ConfigServerUtility.h" +#include "Session/LoginAPI/Client.h" +#include "sharedFoundation/ConfigFile.h" +#include "sharedNetwork/SetupSharedNetwork.h" +#include "ConfigLoginServer.h" + +//----------------------------------------------------------------------- + +ConfigLoginServer::Data * ConfigLoginServer::data = 0; + +#define KEY_INT(a,b) (data->a = ConfigFile::getKeyInt("LoginServer", #a, b)) +#define KEY_BOOL(a,b) (data->a = ConfigFile::getKeyBool("LoginServer", #a, b)) +// #define KEY_REAL(a,b) (data->a = ConfigFile::getKeyReal("LoginServer", #a, b)) +#define KEY_FLOAT(a,b) (data->a = ConfigFile::getKeyFloat("LoginServer", #a, b)) +#define KEY_STRING(a,b) (data->a = ConfigFile::getKeyString("LoginServer", #a, b)) + +//----------------------------------------------------------------------- + +namespace ConfigLoginServerNamespace +{ + typedef std::vector StringPtrArray; + StringPtrArray ms_privateIpMasks; // ConfigFile owns the pointer + StringPtrArray ms_sessionServer; // ConfigFile owns the pointer + + int const ms_numPurgePhases=5; + int ms_purgePhaseAdvanceDays[ms_numPurgePhases]={0,30,60,90,120}; + + // disable character creation for these clusters through config option + std::set ms_clusterCharacterCreationDisable; +} + +using namespace ConfigLoginServerNamespace; + +// ====================================================================== + +int ConfigLoginServer::getNumberOfSessionServers() +{ + return static_cast(ms_sessionServer.size()); +} + +// ---------------------------------------------------------------------- + +char const * ConfigLoginServer::getSessionServer(int index) +{ + VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(0, index, getNumberOfSessionServers()); + return ms_sessionServer[static_cast(index)]; +} + +// ---------------------------------------------------------------------- + +void ConfigLoginServer::install(void) +{ + ConfigServerUtility::install(); + + SetupSharedNetwork::SetupData networkSetupData; + SetupSharedNetwork::getDefaultServerSetupData(networkSetupData); + SetupSharedNetwork::install(networkSetupData); + + data = new ConfigLoginServer::Data; + + KEY_INT (centralServicePort, 44452); + KEY_INT (clientServicePort, 44453); + KEY_INT (clientOverflowLimit, 1024 * 8); + KEY_INT (maxClients, 250); + KEY_INT (taskServicePort, 44459); + KEY_INT (pingServicePort, 44460); + KEY_INT (httpServicePort, 44490); + KEY_STRING (DSN, "loginserver"); + KEY_STRING (privateIpMask, "127.0.0.1"); + KEY_STRING (databaseUID, "loginserver"); + KEY_STRING (schemaOwner, ""); + KEY_STRING (databasePWD, "loginserver"); + KEY_STRING (databaseProtocol, "OCI"); + KEY_BOOL (enableQueryProfile,false); + KEY_BOOL (verboseQueryMode,false); + KEY_BOOL(logWorkerThreads, false); + KEY_INT (maxPlayersPerCluster, 2500); + KEY_INT (maxCharactersPerCluster, 10000); + KEY_INT (maxCharactersPerAccount, 20); + KEY_BOOL (validateClientVersion, true); + KEY_BOOL (validateStationKey, false); + KEY_BOOL (doSessionLogin, false); + KEY_BOOL (doConsumption, false); + KEY_STRING (sessionServers, "sdlogin-test:3004"); + KEY_INT (sessionType, SESSION_TYPE_STARWARS); + KEY_BOOL (developmentMode, true); + KEY_INT (databaseThreads, 1); + KEY_BOOL (compressClientNetworkTraffic, true); + KEY_INT (metricsListenerPort, 2201); + KEY_FLOAT (defaultDBQueueUpdateTimeLimit, 0.25f); + KEY_INT (disconnectSleepTime, 30000); + KEY_INT (clusterGroup,1); + KEY_INT(maxSimultaneousPurgeAccounts,1000); + KEY_INT(purgeSleepTime,600); + KEY_BOOL(enableStructurePurge,false); + KEY_BOOL(enableCharacterPurge,false); + KEY_INT (updatePurgeAccountListTime, 0); + KEY_STRING (purgeAccountSourceTable,"account_extract"); + KEY_STRING (adminAccountDataTable, "datatables/admin/us_admin.iff"); + KEY_BOOL(allowSkipTutorialToAll,false); + KEY_BOOL(internalBypassOnlineLimit,true); + KEY_INT (populationExtremelyHeavyThresholdPercent, 50); + KEY_INT (populationVeryHeavyThresholdPercent, 40); + KEY_INT (populationHeavyThresholdPercent, 32); + KEY_INT (populationMediumThresholdPercent, 16); + KEY_INT (populationLightThresholdPercent, 8); + KEY_INT (csToolPort, 10666); + KEY_BOOL(requireSecureLoginForCsTool, true); + + int index = 0; + char const * result = 0; + do + { + result = ConfigFile::getKeyString("LoginServer", "privateIpMask", index++, 0); + if (result != 0) + { + ms_privateIpMasks.push_back(result); + } + } + while (result); + + index = 0; + result = 0; + do + { + result = ConfigFile::getKeyString("LoginServer", "sessionServer", index++, 0); + if (result != 0) + { + ms_sessionServer.push_back(result); + } + } + while (result); + + index = 0; + result = 0; + do + { + result = ConfigFile::getKeyString("LoginServer", "disableCharacterCreation", index++, 0); + if (result != 0) + { + ms_clusterCharacterCreationDisable.insert(result); + } + } + while (result); + + if (!ms_clusterCharacterCreationDisable.empty()) + { + for (std::set::const_iterator iter = ms_clusterCharacterCreationDisable.begin(); iter != ms_clusterCharacterCreationDisable.end(); ++iter) + { + DEBUG_REPORT_LOG(true, ("Character creation for cluster (%s) has been disabled through config option.\n", iter->c_str())); + } + } + + { + char keyName[500]; + for (int index=0; index < ms_numPurgePhases; index++) + { + snprintf(keyName,sizeof(keyName),"purgePhaseAdvanceDays%i",index); + ms_purgePhaseAdvanceDays[index] = ConfigFile::getKeyInt("LoginServer", keyName, 0, ms_purgePhaseAdvanceDays[index]); + } + } +} + + +//----------------------------------------------------------------------- + +void ConfigLoginServer::remove(void) +{ + delete data; + data = 0; + ConfigServerUtility::remove(); +} + +// ---------------------------------------------------------------------- + +int ConfigLoginServer::getPurgePhaseAdvanceDays(int purgePhase) +{ + VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(0, purgePhase, ms_numPurgePhases); + return ms_purgePhaseAdvanceDays[purgePhase]; +} + +// ---------------------------------------------------------------------- + +bool ConfigLoginServer::isCharacterCreationDisabled(std::string const & cluster) +{ + return (ms_clusterCharacterCreationDisable.count(cluster) >= 1); +} + +// ---------------------------------------------------------------------- + +std::set const & ConfigLoginServer::getCharacterCreationDisabledClusterList() +{ + return ms_clusterCharacterCreationDisable; +} + +// ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/ConfigLoginServer.h b/engine/server/application/LoginServer/src/shared/ConfigLoginServer.h new file mode 100644 index 00000000..7bd94880 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/ConfigLoginServer.h @@ -0,0 +1,472 @@ +// ConfigLoginServer.h +// copyright 2000 Verant Interactive +// Author: Justin Randall + +#ifndef _ConfigLoginServer_H +#define _ConfigLoginServer_H + +//----------------------------------------------------------------------- + +class ConfigLoginServer +{ + public: + struct Data + { + int centralServicePort; + int clientServicePort; + int maxClients; + int taskServicePort; + int pingServicePort; + int httpServicePort; + bool validateClientVersion; + bool validateStationKey; + bool doSessionLogin; + bool doConsumption; + const char * sessionServers; + int sessionType; + + const char * DSN; + const char * databaseUID; + const char * schemaOwner; + const char * databasePWD; + const char * databaseProtocol; + bool enableQueryProfile; + bool verboseQueryMode; + bool logWorkerThreads; + + const char * privateIpMask; + int maxPlayersPerCluster; + int maxCharactersPerCluster; + int maxCharactersPerAccount; + int clientOverflowLimit; + bool developmentMode; + int databaseThreads; + bool compressClientNetworkTraffic; + int metricsListenerPort; + float defaultDBQueueUpdateTimeLimit; + int disconnectSleepTime; + int clusterGroup; + int maxSimultaneousPurgeAccounts; + int purgeSleepTime; + bool enableStructurePurge; + bool enableCharacterPurge; + int updatePurgeAccountListTime; + const char * purgeAccountSourceTable; + const char * adminAccountDataTable; + bool allowSkipTutorialToAll; + + bool internalBypassOnlineLimit; + + int populationExtremelyHeavyThresholdPercent; + int populationVeryHeavyThresholdPercent; + int populationHeavyThresholdPercent; + int populationMediumThresholdPercent; + int populationLightThresholdPercent; + int csToolPort; + + bool requireSecureLoginForCsTool; + }; + + static const uint16 getCentralServicePort(); + static const uint16 getClientServicePort(); + static const int getClientOverflowLimit(); + static const uint16 getTaskServicePort(); + static const uint16 getPingServicePort(); + static const uint16 getHttpServicePort(); + static const bool getValidateClientVersion(); + static const bool getValidateStationKey(); + static const bool getDoSessionLogin(); + static const bool getDoConsumption(); + static const char * getSessionServers(); + static const int getSessionType(); + + static const int getMaxClients (); + static const char * getPrivateIpMask(); + static const char * getDSN(); + static const char * getDatabaseUID(); + static const char * getSchemaOwner(); + static const char * getDatabasePWD(); + static const char * getDatabaseProtocol(); + static const bool getEnableQueryProfile(); + static const bool getVerboseQueryMode(); + static const bool getLogWorkerThreads(); + static int getMaxPlayersPerCluster(); + static int getMaxCharactersPerCluster(); + static int getMaxCharactersPerAccount(); + //static int getMaxCharactersPerAccountPerCluster(); + static const bool getDevelopmentMode(); + static int getDatabaseThreads(); + static bool getCompressClientNetworkTraffic(); + static uint16 getMetricsListenerPort(); + static float getDefaultDBQueueUpdateTimeLimit(); + static void install (); + static void remove (); + + static int getNumberOfSessionServers(); + static char const * getSessionServer(int index); + static const int getDisconnectSleepTime (void); + static const int getClusterGroup(); + static int getMaxSimultaneousPurgeAccounts(); + static int getPurgeSleepTime(); + static bool getEnableStructurePurge(); + static bool getEnableCharacterPurge(); + static int getUpdatePurgeAccountListTime(); + static const char * getPurgeAccountSourceTable(); + static int getPurgePhaseAdvanceDays(int purgePhase); + static const char * getAdminAccountDataTable(); + static bool getAllowSkipTutorialToAll(); + + static bool getInternalBypassOnlineLimit(); + static const int getCSToolPort(); + + static bool getRequireSecureLoginForCsTool(); + + static int getPopulationExtremelyHeavyThresholdPercent(); + static int getPopulationVeryHeavyThresholdPercent(); + static int getPopulationHeavyThresholdPercent(); + static int getPopulationMediumThresholdPercent(); + static int getPopulationLightThresholdPercent(); + + // has character creation for this cluster been disabled through config option + static bool isCharacterCreationDisabled(std::string const & cluster); + static stdset::fwd const & getCharacterCreationDisabledClusterList(); + +private: + static Data * data; +}; + +//----------------------------------------------------------------------- + +inline const uint16 ConfigLoginServer::getCentralServicePort() +{ + return static_cast(data->centralServicePort); +} + +//----------------------------------------------------------------------- + +inline const uint16 ConfigLoginServer::getHttpServicePort() +{ + return static_cast(data->httpServicePort); +} + +//----------------------------------------------------------------------- + +inline const uint16 ConfigLoginServer::getClientServicePort() +{ + return static_cast(data->clientServicePort); +} + +//----------------------------------------------------------------------- + +inline const int ConfigLoginServer::getClientOverflowLimit() +{ + return data->clientOverflowLimit; +} + +//----------------------------------------------------------------------- + + +inline const int ConfigLoginServer::getMaxClients() +{ + return data->maxClients; +} + +//----------------------------------------------------------------------- + +inline const char * ConfigLoginServer::getPrivateIpMask() +{ + return data->privateIpMask; +} + +//----------------------------------------------------------------------- + +inline const uint16 ConfigLoginServer::getTaskServicePort() +{ + return static_cast(data->taskServicePort); +} + +//----------------------------------------------------------------------- + +inline const uint16 ConfigLoginServer::getPingServicePort() +{ + return static_cast(data->pingServicePort); +} + +// ---------------------------------------------------------------------- + +inline const bool ConfigLoginServer::getValidateClientVersion() +{ + return (data->validateClientVersion); +} + +// ---------------------------------------------------------------------- + +inline const bool ConfigLoginServer::getValidateStationKey() +{ + return (data->validateStationKey); +} + +// ---------------------------------------------------------------------- + +inline const bool ConfigLoginServer::getDoSessionLogin() +{ + return (data->doSessionLogin); +} + +// ---------------------------------------------------------------------- + +inline const bool ConfigLoginServer::getDoConsumption() +{ + return (data->doConsumption); +} + +// ---------------------------------------------------------------------- + +inline const char * ConfigLoginServer::getSessionServers() +{ + return (data->sessionServers); +} + +//------------------------------------------------------------------------------------------ + +inline const int ConfigLoginServer::getSessionType() +{ + return data->sessionType; +} + +// ---------------------------------------------------------------------- + +inline const char * ConfigLoginServer::getDSN() +{ + return (data->DSN); +} + +// ---------------------------------------------------------------------- + +inline const char * ConfigLoginServer::getDatabaseUID() +{ + return (data->databaseUID); +} + +// ---------------------------------------------------------------------- + +inline const char * ConfigLoginServer::getDatabasePWD() +{ + return (data->databasePWD); +} + +// ---------------------------------------------------------------------- + +inline const char * ConfigLoginServer::getDatabaseProtocol() +{ + return (data->databaseProtocol); +} + +//----------------------------------------------------------------------- + +inline int ConfigLoginServer::getMaxPlayersPerCluster() +{ + return (data->maxPlayersPerCluster); +} + +// ---------------------------------------------------------------------- + +inline int ConfigLoginServer::getMaxCharactersPerCluster() +{ + return (data->maxCharactersPerCluster); +} + +// ---------------------------------------------------------------------- + +inline int ConfigLoginServer::getMaxCharactersPerAccount() +{ + return (data->maxCharactersPerAccount); +} + +// ---------------------------------------------------------------------- + +inline const bool ConfigLoginServer::getEnableQueryProfile() +{ + return (data->enableQueryProfile); +} + +// ---------------------------------------------------------------------- + +inline const bool ConfigLoginServer::getVerboseQueryMode() +{ + return (data->verboseQueryMode); +} + +// ---------------------------------------------------------------------- + +inline const bool ConfigLoginServer::getLogWorkerThreads() +{ + return data->logWorkerThreads; +} + +// ---------------------------------------------------------------------- + +inline const bool ConfigLoginServer::getDevelopmentMode() +{ + return (data->developmentMode); +} + +// ---------------------------------------------------------------------- + +inline int ConfigLoginServer::getDatabaseThreads() +{ + return (data->databaseThreads); +} + +// ---------------------------------------------------------------------- + +inline bool ConfigLoginServer::getCompressClientNetworkTraffic() +{ + return data->compressClientNetworkTraffic; +} + +// ---------------------------------------------------------------------- + +inline uint16 ConfigLoginServer::getMetricsListenerPort() +{ + return static_cast(data->metricsListenerPort); +} + +// ---------------------------------------------------------------------- + +inline const char *ConfigLoginServer::getSchemaOwner() +{ + return data->schemaOwner; +} + +// ---------------------------------------------------------------------- + +inline float ConfigLoginServer::getDefaultDBQueueUpdateTimeLimit() +{ + return data->defaultDBQueueUpdateTimeLimit; +} + +// ---------------------------------------------------------------------- + +inline const int ConfigLoginServer::getDisconnectSleepTime(void) +{ + return data->disconnectSleepTime; +} + +// ---------------------------------------------------------------------- + +inline const int ConfigLoginServer::getClusterGroup() +{ + return data->clusterGroup; +} + +// ---------------------------------------------------------------------- + +inline int ConfigLoginServer::getMaxSimultaneousPurgeAccounts() +{ + return data->maxSimultaneousPurgeAccounts; +} + +//----------------------------------------------------------------------- + +inline int ConfigLoginServer::getPurgeSleepTime() +{ + return data->purgeSleepTime; +} + +// ---------------------------------------------------------------------- + +inline bool ConfigLoginServer::getEnableStructurePurge() +{ + return data->enableStructurePurge; +} + +// ---------------------------------------------------------------------- + +inline bool ConfigLoginServer::getEnableCharacterPurge() +{ + return data->enableCharacterPurge; +} + +// ---------------------------------------------------------------------- + +inline int ConfigLoginServer::getUpdatePurgeAccountListTime() +{ + return data->updatePurgeAccountListTime; +} + +// ---------------------------------------------------------------------- + +inline char const * ConfigLoginServer::getPurgeAccountSourceTable() +{ + return data->purgeAccountSourceTable; +} + +// ---------------------------------------------------------------------- + +inline const char * ConfigLoginServer::getAdminAccountDataTable() +{ + return data->adminAccountDataTable; +} + +// ---------------------------------------------------------------------- + +inline bool ConfigLoginServer::getAllowSkipTutorialToAll() +{ + return data->allowSkipTutorialToAll; +} + +// ---------------------------------------------------------------------- + +inline bool ConfigLoginServer::getInternalBypassOnlineLimit() +{ + return data->internalBypassOnlineLimit; +} + +// ---------------------------------------------------------------------- + +inline int ConfigLoginServer::getPopulationExtremelyHeavyThresholdPercent() +{ + return data->populationExtremelyHeavyThresholdPercent; +} + +// ---------------------------------------------------------------------- + +inline int ConfigLoginServer::getPopulationVeryHeavyThresholdPercent() +{ + return data->populationVeryHeavyThresholdPercent; +} + +// ---------------------------------------------------------------------- + +inline int ConfigLoginServer::getPopulationHeavyThresholdPercent() +{ + return data->populationHeavyThresholdPercent; +} + +// ---------------------------------------------------------------------- + +inline int ConfigLoginServer::getPopulationMediumThresholdPercent() +{ + return data->populationMediumThresholdPercent; +} + +// ---------------------------------------------------------------------- + +inline int ConfigLoginServer::getPopulationLightThresholdPercent() +{ + return data->populationLightThresholdPercent; +} + +inline bool ConfigLoginServer::getRequireSecureLoginForCsTool() +{ + return data->requireSecureLoginForCsTool; +} + +inline const int ConfigLoginServer::getCSToolPort() +{ + return data->csToolPort; +} +// ====================================================================== + +#endif // _ConfigLoginServer_H diff --git a/engine/server/application/LoginServer/src/shared/ConsoleCommandParser.cpp b/engine/server/application/LoginServer/src/shared/ConsoleCommandParser.cpp new file mode 100644 index 00000000..fc18677c --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/ConsoleCommandParser.cpp @@ -0,0 +1,56 @@ +// ConsoleCommandParser.cpp +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +//----------------------------------------------------------------------- + +#include "FirstLoginServer.h" +#include "ConsoleCommandParser.h" +#include "UnicodeUtils.h" + +//----------------------------------------------------------------------- + +namespace CommandNames +{ +#define MAKE_COMMAND(a) const char * const a = #a +#undef MAKE_COMMAND +} + +const CommandParser::CmdInfo cmds[] = +{ + {"runState", 0, "", "Return the running state of the CentralServer. It should always return 'running'"}, + {"", 0, "", ""} // this must be last +}; + + +//----------------------------------------------------------------------- + +ConsoleCommandParser::ConsoleCommandParser() : +CommandParser ("", 0, "...", "console commands", this) +{ + createDelegateCommands(cmds); +} + +//----------------------------------------------------------------------- + +ConsoleCommandParser::~ConsoleCommandParser() +{ +} + +//----------------------------------------------------------------------- + +bool ConsoleCommandParser::performParsing(const NetworkId &, const StringVector_t & argv, const String_t &, String_t & result, const CommandParser *) +{ + bool successResult = false; + + if(isCommand(argv[0], "runState")) + { + result += Unicode::narrowToWide("running"); + successResult = true; + } + + return successResult; +} + +//----------------------------------------------------------------------- + diff --git a/engine/server/application/LoginServer/src/shared/ConsoleCommandParser.h b/engine/server/application/LoginServer/src/shared/ConsoleCommandParser.h new file mode 100644 index 00000000..4ebf6387 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/ConsoleCommandParser.h @@ -0,0 +1,29 @@ +// ConsoleCommandParser.h +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +#ifndef _INCLUDED_ConsoleCommandParser_H +#define _INCLUDED_ConsoleCommandParser_H + +//----------------------------------------------------------------------- + +#include "sharedCommandParser/CommandParser.h" + +//----------------------------------------------------------------------- + +class ConsoleCommandParser : public CommandParser +{ +public: + ConsoleCommandParser(); + ~ConsoleCommandParser(); + virtual bool performParsing(const NetworkId & userId, const StringVector_t & argv,const String_t & originalCommand,String_t & result,const CommandParser * node); + +private: + ConsoleCommandParser & operator = (const ConsoleCommandParser & rhs); + ConsoleCommandParser(const ConsoleCommandParser & source); +}; + +//----------------------------------------------------------------------- + +#endif // _INCLUDED_ConsoleCommandParser_H + diff --git a/engine/server/application/LoginServer/src/shared/ConsoleCommandParserLoginServer.cpp b/engine/server/application/LoginServer/src/shared/ConsoleCommandParserLoginServer.cpp new file mode 100644 index 00000000..b1a2dfad --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/ConsoleCommandParserLoginServer.cpp @@ -0,0 +1,73 @@ +// ConsoleCommandParserLoginServer.cpp +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +//----------------------------------------------------------------------- + +#include "FirstLoginServer.h" +#include "ConsoleCommandParserLoginServer.h" +#include "LoginServer.h" +#include "sharedNetworkMessages/ConsoleChannelMessages.h" +#include "sharedNetworkMessages/GenericValueTypeMessage.h" +#include "UnicodeUtils.h" +#include "sharedLog/Log.h" + + +//----------------------------------------------------------------------- + +namespace CommandNames +{ +#define MAKE_COMMAND(a) const char * const a = #a + MAKE_COMMAND(login); +#undef MAKE_COMMAND +} + +const CommandParser::CmdInfo cmds[] = +{ + {"runState", 0, "", "Return the running state of the CentralServer. It should always return 'running'"}, + {"", 0, "", ""} // this must be last +}; + +//----------------------------------------------------------------------- + +ConsoleCommandParserLoginServer::ConsoleCommandParserLoginServer() : +CommandParser ("login", 0, "...", "console commands", 0) +{ +} + +//----------------------------------------------------------------------- + +ConsoleCommandParserLoginServer::~ConsoleCommandParserLoginServer() +{ +} + +//----------------------------------------------------------------------- + +bool ConsoleCommandParserLoginServer::performParsing(const NetworkId & track, const StringVector_t & argv,const String_t & originalCommand,String_t & result,const CommandParser *) +{ + bool successResult = false; + + if(isCommand(argv[0], CommandNames::login)) + { + if(argv.size() > 1) + { + std::string cmd = Unicode::wideToNarrow(argv[1]); + if(cmd == "runState") + { + result += Unicode::narrowToWide("running"); + successResult = true; + } + else if(cmd == "exit") + { + result += Unicode::narrowToWide("exiting"); + LoginServer::getInstance().setDone(true); + successResult = true; + } + } + } + + return successResult; +} + +//----------------------------------------------------------------------- + diff --git a/engine/server/application/LoginServer/src/shared/ConsoleCommandParserLoginServer.h b/engine/server/application/LoginServer/src/shared/ConsoleCommandParserLoginServer.h new file mode 100644 index 00000000..3d96db31 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/ConsoleCommandParserLoginServer.h @@ -0,0 +1,29 @@ +// ConsoleCommandParserGame.h +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +#ifndef _INCLUDED_ConsoleCommandParserLoginServer_H +#define _INCLUDED_ConsoleCommandParserLoginServer_H + +//----------------------------------------------------------------------- + +#include "sharedCommandParser/CommandParser.h" + +//----------------------------------------------------------------------- + +class ConsoleCommandParserLoginServer : public CommandParser +{ +public: + ConsoleCommandParserLoginServer(); + ~ConsoleCommandParserLoginServer(); + virtual bool performParsing(const NetworkId & userId, const StringVector_t & argv,const String_t & originalCommand,String_t & result,const CommandParser * node); + +private: + ConsoleCommandParserLoginServer & operator = (const ConsoleCommandParserLoginServer & rhs); + ConsoleCommandParserLoginServer(const ConsoleCommandParserLoginServer & source); + +}; + +//----------------------------------------------------------------------- + +#endif // _INCLUDED_ConsoleCommandParserLoginServer_H diff --git a/engine/server/application/LoginServer/src/shared/ConsoleManager.cpp b/engine/server/application/LoginServer/src/shared/ConsoleManager.cpp new file mode 100644 index 00000000..ecaaa8fa --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/ConsoleManager.cpp @@ -0,0 +1,61 @@ +// ConsoleManager.cpp +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +//----------------------------------------------------------------------- + +#include "FirstLoginServer.h" +#include "ConsoleCommandParser.h" +#include "ConsoleCommandParserLoginServer.h" +#include "ConsoleManager.h" +#include "UnicodeUtils.h" + +//----------------------------------------------------------------------- + +namespace ConsoleManagerNamespace +{ + ConsoleCommandParser * s_consoleCommandParserRoot = NULL; +} + +using namespace ConsoleManagerNamespace; + +//----------------------------------------------------------------------- + +ConsoleManager::ConsoleManager() +{ +} + +//----------------------------------------------------------------------- + +ConsoleManager::~ConsoleManager() +{ +} + +//----------------------------------------------------------------------- + +void ConsoleManager::install() +{ + s_consoleCommandParserRoot = new ConsoleCommandParser; + IGNORE_RETURN(s_consoleCommandParserRoot->addSubCommand(new ConsoleCommandParserLoginServer)); +} + +//----------------------------------------------------------------------- + +void ConsoleManager::remove() +{ + delete s_consoleCommandParserRoot; +} + +//----------------------------------------------------------------------- + +CommandParser::ErrorType ConsoleManager::processString(const std::string & msg, const int track, std::string & result) +{ + CommandParser::ErrorType parseResult; + Unicode::String wideResult; + parseResult = s_consoleCommandParserRoot->parse(NetworkId(static_cast(track)), Unicode::narrowToWide(msg), wideResult); + result = Unicode::wideToNarrow(wideResult); + return parseResult; +} + +//----------------------------------------------------------------------- + diff --git a/engine/server/application/LoginServer/src/shared/ConsoleManager.h b/engine/server/application/LoginServer/src/shared/ConsoleManager.h new file mode 100644 index 00000000..b2afadb6 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/ConsoleManager.h @@ -0,0 +1,27 @@ +// ConsoleManager.h +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +#ifndef _INCLUDED_ConsoleManager_H +#define _INCLUDED_ConsoleManager_H + +#include "sharedCommandParser/CommandParser.h" + +//----------------------------------------------------------------------- + +class ConsoleManager +{ +public: + static void install(); + static void remove(); + static CommandParser::ErrorType processString(const std::string & msg, const int track, std::string & result); +private: + ConsoleManager & operator = (const ConsoleManager & rhs); + ConsoleManager(const ConsoleManager & source); + ConsoleManager(); + ~ConsoleManager(); +}; + +//----------------------------------------------------------------------- + +#endif // _INCLUDED_ConsoleManager_H diff --git a/engine/server/application/LoginServer/src/shared/DatabaseConnection.cpp b/engine/server/application/LoginServer/src/shared/DatabaseConnection.cpp new file mode 100644 index 00000000..e5b1e584 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/DatabaseConnection.cpp @@ -0,0 +1,351 @@ +// ====================================================================== +// +// DatabaseConnection.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLoginServer.h" +#include "DatabaseConnection.h" + +#include "ConfigLoginServer.h" +#include "LoginServer.h" +#include "TaskClaimRewards.h" +#include "TaskChangeStationId.h" +#include "TaskCreateCharacter.h" +#include "TaskDeleteCharacter.h" +#include "TaskEnableCharacter.h" +#include "TaskGetAccountForPurge.h" +#include "TaskGetAvatarList.h" +#include "TaskGetCharactersForDelete.h" +#include "TaskGetClusterList.h" +#include "TaskGetValidationData.h" +#include "TaskRegisterNewCluster.h" +#include "TaskRenameCharacter.h" +#include "TaskRestoreCharacter.h" +#include "TaskSetPurgeStatus.h" +#include "TaskToggleCharacterDisable.h" +#include "TaskToggleCompletedTutorial.h" +#include "TaskUpdatePurgeAccountList.h" +#include "TaskUpgradeAccount.h" +#include "serverNetworkMessages/AvatarList.h" +#include "serverNetworkMessages/ClaimRewardsReplyMessage.h" +#include "sharedDatabaseInterface/DbServer.h" +#include "sharedDatabaseInterface/DbTaskQueue.h" + +// ====================================================================== + +DatabaseConnection::DatabaseConnection() : + Singleton(), + m_databaseServer(0), + m_taskQueue(0) +{ +} + +// ---------------------------------------------------------------------- + +DatabaseConnection::~DatabaseConnection() +{ + delete m_databaseServer; + delete m_taskQueue; + + m_databaseServer=0; + m_taskQueue=0; +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::connect() +{ + DEBUG_FATAL(m_databaseServer,("Called DatabaseConnection::connect() when already connected.\n")); + + m_databaseServer = DB::Server::create(ConfigLoginServer::getDSN(), + ConfigLoginServer::getDatabaseUID(), + ConfigLoginServer::getDatabasePWD(), + DB::Server::getProtocolByName(ConfigLoginServer::getDatabaseProtocol()), + true); + DB::Server::setDisconnectSleepTime(ConfigLoginServer::getDisconnectSleepTime()); + m_taskQueue=new DB::TaskQueue(static_cast(ConfigLoginServer::getDatabaseThreads()),m_databaseServer,0); + + if (ConfigLoginServer::getEnableQueryProfile()) + DB::Server::enableProfiling(); + + if (ConfigLoginServer::getVerboseQueryMode()) + DB::Server::enableVerboseMode(); + + DB::TaskQueue::enableWorkerThreadsLogging(ConfigLoginServer::getLogWorkerThreads()); +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::disconnect() +{ + DEBUG_FATAL(!m_databaseServer,("Called DatabaseConnection::disconnect() when not connected.\n")); + + if (ConfigLoginServer::getEnableQueryProfile()) + { + DB::Server::debugOutputProfile(); + DB::Server::endProfiling(); + } + + delete m_taskQueue; + delete m_databaseServer; + + m_taskQueue=0; + m_databaseServer=0; +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::requestAvatarListForAccount(StationId stationId, const TransferCharacterData * characterData) +{ + NOT_NULL(m_taskQueue); + m_taskQueue->asyncRequest(new TaskGetAvatarList(stationId, ConfigLoginServer::getClusterGroup(), characterData)); +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::onAvatarListRetrieved(StationId stationId, int stationIdNumberJediSlot, const AvatarList & avatars, TransferCharacterData * const transferData) const +{ + LoginServer::getInstance().sendAvatarList(stationId, stationIdNumberJediSlot, avatars, transferData); +} + +// ---------------------------------------------------------------------- + +/** + * Retreive the list of all known clusters from the database. + * This list is in the database so that we know about clusters + * that aren't currently running, for character lists, etc. + */ + +void DatabaseConnection::requestClusterList() +{ + NOT_NULL(m_taskQueue); + m_taskQueue->asyncRequest(new TaskGetClusterList(ConfigLoginServer::getClusterGroup())); +} + +// ---------------------------------------------------------------------- + +/** + * Called when a previously unknown cluster connects. Adds the cluster + * to the database and assigns it the next available cluster ID. + */ + +void DatabaseConnection::registerNewCluster(const std::string &clusterName, const std::string &remoteAddress) +{ + NOT_NULL(m_taskQueue); + m_taskQueue->asyncRequest(new TaskRegisterNewCluster(clusterName, remoteAddress)); +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::update() +{ + NOT_NULL(m_taskQueue); + m_taskQueue->update(ConfigLoginServer::getDefaultDBQueueUpdateTimeLimit()); +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::getAccountValidationData(StationId stationId, uint32 clusterId, unsigned int track, uint32 subscriptionBits) +{ + NOT_NULL(m_taskQueue); + m_taskQueue->asyncRequest(new TaskGetValidationData(stationId, ConfigLoginServer::getClusterGroup(), clusterId, track, subscriptionBits)); +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::getAccountValidationData(const TransferRequestMoveValidation & request, uint32 clusterId) +{ + NOT_NULL(m_taskQueue); + m_taskQueue->asyncRequest(new TaskGetValidationData(request, ConfigLoginServer::getClusterGroup(), clusterId)); +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::deleteCharacter(uint32 clusterId, const NetworkId &characterId, StationId stationId) +{ + NOT_NULL(m_taskQueue); + m_taskQueue->asyncRequest(new TaskDeleteCharacter(clusterId,characterId,stationId)); +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::deleteAllCharacters(StationId stationId) +{ + NON_NULL(m_taskQueue)->asyncRequest(new TaskGetCharactersForDelete(stationId,ConfigLoginServer::getClusterGroup())); +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::renameCharacter(uint32 clusterId, const NetworkId &characterId, const Unicode::String &newName, const TransferCharacterData * requestData) +{ + NOT_NULL(m_taskQueue); + m_taskQueue->asyncRequest(new TaskRenameCharacter(clusterId, characterId, newName, requestData)); +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::requestAvatarListAccountTransfer(const TransferAccountData * requestData) +{ + NOT_NULL(m_taskQueue); + m_taskQueue->asyncRequest(new TaskGetAvatarList(ConfigLoginServer::getClusterGroup(), requestData)); +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::onAvatarListRetrievedAccountTransfer(const AvatarList &avatars, TransferAccountData * transferAccountData) +{ + NOT_NULL(m_taskQueue); + LoginServer::getInstance().performAccountTransfer(avatars, transferAccountData); +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::changeStationId(StationId sourceStationId, StationId destinationStationId, const TransferAccountData * const transferAccountData) +{ + NOT_NULL(m_taskQueue); + m_taskQueue->asyncRequest(new TaskChangeStationId(sourceStationId, destinationStationId, transferAccountData)); +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::createCharacter(uint32 clusterId, StationId stationId, const Unicode::String &characterName, const NetworkId &characterObjectId, int templateId, bool jedi) +{ + NOT_NULL(m_taskQueue); + m_taskQueue->asyncRequest(new TaskCreateCharacter(clusterId, stationId, characterName, characterObjectId, templateId, jedi)); +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::restoreCharacter(uint32 clusterId, const std::string &whoRequested, StationId stationId, const Unicode::String &characterName, const NetworkId &characterObjectId, int templateId, bool jedi) +{ + NOT_NULL(m_taskQueue); + m_taskQueue->asyncRequest(new TaskRestoreCharacter(clusterId, whoRequested, stationId, characterName, characterObjectId, templateId, jedi)); +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::enableCharacter(StationId stationId, const NetworkId &characterId, const std::string &whoRequested, bool enabled, uint32 clusterId) +{ + NOT_NULL(m_taskQueue); + m_taskQueue->asyncRequest(new TaskEnableCharacter(stationId, characterId, whoRequested, enabled, clusterId)); +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::upgradeAccount(LoginUpgradeAccountMessage *msg, uint32 clusterId) +{ + NOT_NULL(m_taskQueue); + m_taskQueue->asyncRequest(new TaskUpgradeAccount(msg,clusterId)); +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::toggleDisableCharacter(uint32 clusterId, const NetworkId &characterId, StationId stationId, bool enabled) +{ + NOT_NULL(m_taskQueue); + m_taskQueue->asyncRequest(new TaskToggleCharacterDisable(clusterId,characterId,stationId,enabled)); +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::toggleCompletedTutorial(StationId stationId, bool newValue) +{ + NOT_NULL(m_taskQueue); + m_taskQueue->asyncRequest(new TaskToggleCompletedTutorial(stationId, newValue)); +} + +// ---------------------------------------------------------------------- + +const std::string DatabaseConnection::getSchemaQualifier() const +{ + if (ConfigLoginServer::getSchemaOwner()[0]!='\0') + return std::string(ConfigLoginServer::getSchemaOwner())+'.'; + else + return std::string(); +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::claimRewards(uint32 clusterId, uint32 gameServerId, StationId stationId, NetworkId const & playerId, std::string const & rewardEvent, bool consumeEvent, std::string const & rewardItem, bool consumeItem, uint32 accountFeatureId, bool consumeAccountFeatureId, int previousAccountFeatureIdCount, int currentAccountFeatureIdCount) +{ + NOT_NULL(m_taskQueue); + + if (consumeEvent || consumeItem || ((accountFeatureId > 0) && consumeAccountFeatureId)) + { + m_taskQueue->asyncRequest(new TaskClaimRewards(clusterId, gameServerId, stationId, playerId, rewardEvent, consumeEvent, rewardItem, consumeItem, accountFeatureId, consumeAccountFeatureId, previousAccountFeatureIdCount, currentAccountFeatureIdCount)); + } + else + { + ClaimRewardsReplyMessage const msg(gameServerId, stationId, playerId, rewardEvent, rewardItem, accountFeatureId, consumeAccountFeatureId, previousAccountFeatureIdCount, currentAccountFeatureIdCount, true); + LoginServer::getInstance().sendToCluster(clusterId, msg); + } +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::getAccountForPurge(int purgePhase) +{ + NOT_NULL(m_taskQueue); + m_taskQueue->asyncRequest(new TaskGetAccountForPurge(purgePhase)); +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::setPurgeStatusAndRelease(StationId account, int newPurgePhase) +{ + NOT_NULL(m_taskQueue); + m_taskQueue->asyncRequest(new TaskSetPurgeStatus(account, newPurgePhase)); +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::updatePurgeAccountList() +{ + FATAL(ConfigLoginServer::getDatabaseThreads() < 2,("Attempted to run updatePurgeAccountList with only 1 worker thread, which would mean logins would be blocked while the process is running. Either disable updating the purge account list, or add more worker threads.")); + NOT_NULL(m_taskQueue); + m_taskQueue->asyncRequest(new TaskUpdatePurgeAccountList); +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::occupyUnlockedSlot(uint32 clusterId, StationId stationId, NetworkId const & characterId, uint32 replyGameServerId) +{ + NOT_NULL(m_taskQueue); + m_taskQueue->asyncRequest(new TaskOccupyUnlockedSlot(ConfigLoginServer::getClusterGroup(), clusterId, stationId, characterId, replyGameServerId)); +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::vacateUnlockedSlot(uint32 clusterId, StationId stationId, NetworkId const & characterId, uint32 replyGameServerId) +{ + NOT_NULL(m_taskQueue); + m_taskQueue->asyncRequest(new TaskVacateUnlockedSlot(ConfigLoginServer::getClusterGroup(), clusterId, stationId, characterId, replyGameServerId)); +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::swapUnlockedSlot(uint32 clusterId, StationId stationId, NetworkId const & sourceCharacterId, NetworkId const & targetCharacterId, uint32 replyGameServerId) +{ + NOT_NULL(m_taskQueue); + m_taskQueue->asyncRequest(new TaskSwapUnlockedSlot(ConfigLoginServer::getClusterGroup(), clusterId, stationId, sourceCharacterId, targetCharacterId, replyGameServerId)); +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::featureIdTransactionRequest(uint32 clusterId, StationId stationId, NetworkId const & characterId, uint32 replyGameServerId) +{ + NOT_NULL(m_taskQueue); + m_taskQueue->asyncRequest(new TaskFeatureIdTransactionRequest(clusterId, stationId, characterId, replyGameServerId)); +} + +// ---------------------------------------------------------------------- + +void DatabaseConnection::featureIdTransactionSyncUpdate(uint32 clusterId, StationId stationId, NetworkId const & characterId, std::string const & itemId, int adjustment) +{ + NOT_NULL(m_taskQueue); + m_taskQueue->asyncRequest(new TaskFeatureIdTransactionSyncUpdate(clusterId, stationId, characterId, itemId, adjustment)); +} + +// ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/DatabaseConnection.h b/engine/server/application/LoginServer/src/shared/DatabaseConnection.h new file mode 100644 index 00000000..e2ad211e --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/DatabaseConnection.h @@ -0,0 +1,80 @@ +// ====================================================================== +// +// DatabaseConnection.h +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_DatabaseConnection_H +#define INCLUDED_DatabaseConnection_H + +// ====================================================================== + +#include "Singleton/Singleton.h" +#include "serverNetworkMessages/AvatarList.h" +#include "sharedFoundation/NetworkId.h" +#include "sharedFoundation/StationId.h" + +namespace DB +{ + class Server; + class TaskQueue; +} + +class LoginUpgradeAccountMessage; +class TransferAccountData; +class TransferCharacterData; +class TransferRequestMoveValidation; + +// ====================================================================== + +/** + * A class to manage the LoginServer's connection to the database. + */ + +class DatabaseConnection : public Singleton +{ + public: + DatabaseConnection(); + ~DatabaseConnection(); + + void connect (); + void disconnect (); + void requestAvatarListForAccount (StationId stationId, const TransferCharacterData *); + void requestClusterList (); + void registerNewCluster (const std::string &clusterName, const std::string &remoteAddress); + void onAvatarListRetrieved (StationId stationId, int stationIdNumberJediSlot, const AvatarList &avatars, TransferCharacterData * const transferCharacterData) const; + void update (); + void getAccountValidationData (StationId stationId, uint32 clusterId, unsigned int track, uint32 subscriptionBits); + void getAccountValidationData (const TransferRequestMoveValidation & request, uint32 clusterId); + void deleteCharacter (uint32 clusterId, const NetworkId &characterId, StationId stationId); + void deleteAllCharacters (StationId stationId); + void renameCharacter (uint32 clusterId, const NetworkId &characterId, const Unicode::String &newName, const TransferCharacterData * requestData); + void requestAvatarListAccountTransfer (const TransferAccountData * requestData); + void onAvatarListRetrievedAccountTransfer (const AvatarList &avatars, TransferAccountData * transferAccountData); + void changeStationId (StationId sourceStationId, StationId destinationStationId, const TransferAccountData * const transferAccountData); + void createCharacter (uint32 clusterId, StationId stationId, const Unicode::String &characterName, const NetworkId &characterObjectId, int templateId, bool jedi); + void restoreCharacter (uint32 clusterId, const std::string &whoRequested, StationId stationId, const Unicode::String &characterName, const NetworkId &characterObjectId, int templateId, bool jedi); + void enableCharacter (StationId stationId, const NetworkId &characterId, const std::string &whoRequested, bool enabled, uint32 clusterId); + void upgradeAccount (LoginUpgradeAccountMessage *msg, uint32 clusterId); + void toggleDisableCharacter (uint32 clusterId, const NetworkId &characterId, StationId stationId, bool enabled); + void toggleCompletedTutorial (StationId stationId, bool newValue); + const std::string getSchemaQualifier() const; + void claimRewards (uint32 clusterId, uint32 gameServerId, StationId stationId, NetworkId const & playerId, std::string const & rewardEvent, bool consumeEvent, std::string const & rewardItem, bool consumeItem, uint32 accountFeatureId, bool consumeAccountFeatureId, int previousAccountFeatureIdCount, int currentAccountFeatureIdCount); + void getAccountForPurge (int purgePhase); + void setPurgeStatusAndRelease (StationId account, int newPurgePhase); + void updatePurgeAccountList (); + void occupyUnlockedSlot (uint32 clusterId, StationId stationId, NetworkId const & characterId, uint32 replyGameServerId); + void vacateUnlockedSlot (uint32 clusterId, StationId stationId, NetworkId const & characterId, uint32 replyGameServerId); + void swapUnlockedSlot (uint32 clusterId, StationId stationId, NetworkId const & sourceCharacterId, NetworkId const & targetCharacterId, uint32 replyGameServerId); + void featureIdTransactionRequest (uint32 clusterId, StationId stationId, NetworkId const & characterId, uint32 replyGameServerId); + void featureIdTransactionSyncUpdate(uint32 clusterId, StationId stationId, NetworkId const & characterId, std::string const & itemId, int adjustment); + + private: + DB::Server *m_databaseServer; + DB::TaskQueue *m_taskQueue; +}; + +// ====================================================================== + +#endif diff --git a/engine/server/application/LoginServer/src/shared/FirstLoginServer.h b/engine/server/application/LoginServer/src/shared/FirstLoginServer.h new file mode 100644 index 00000000..76cd4a1e --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/FirstLoginServer.h @@ -0,0 +1,24 @@ +// ====================================================================== +// +// FirstLoginServer.h +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_FirstLoginServer_H +#define INCLUDED_FirstLoginServer_H + +// ====================================================================== + +#pragma warning ( disable : 4702 ) // unreachable code (STL vector) +#include "sharedFoundation/FirstSharedFoundation.h" +#include "Archive/ByteStream.h" +#include "serverUtility/ServerConnection.h" +#include "sharedDebug/FirstSharedDebug.h" +#include "sharedMemoryManager/FirstSharedMemoryManager.h" +#include "LoginServer.h" +#include "sharedNetworkMessages/GameNetworkMessage.h" +// ====================================================================== + +#endif + diff --git a/engine/server/application/LoginServer/src/shared/LoginServer.cpp b/engine/server/application/LoginServer/src/shared/LoginServer.cpp new file mode 100644 index 00000000..7b593fa5 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/LoginServer.cpp @@ -0,0 +1,1977 @@ +// LoginServer.cpp +// copyright 2000 Verant Interactive +// Author: Justin Randall + + +//----------------------------------------------------------------------- + +#include "FirstLoginServer.h" +#include "LoginServer.h" + +#include "Archive/ByteStream.h" +#include "CentralServerConnection.h" +#include "ClientConnection.h" +#include "ConfigLoginServer.h" +#include "ConsoleManager.h" +#include "CSToolConnection.h" +#include "DatabaseConnection.h" +#include "LoginServerRemoteDebugSetup.h" +#include "MonAPI2/MonitorAPI.h" +#include "PingConnection.h" +#include "PurgeManager.h" +#include "SessionApiClient.h" +#include "UnicodeUtils.h" +#include "serverKeyShare/KeyServer.h" +#include "serverNetworkMessages/AccountFeatureIdRequest.h" +#include "serverNetworkMessages/AccountFeatureIdResponse.h" +#include "serverNetworkMessages/AdjustAccountFeatureIdRequest.h" +#include "serverNetworkMessages/AdjustAccountFeatureIdResponse.h" +#include "serverNetworkMessages/ClaimRewardsMessage.h" +#include "serverNetworkMessages/ClaimRewardsReplyMessage.h" +#include "serverNetworkMessages/ConnectionServerDown.h" +#include "serverNetworkMessages/FeatureIdTransactionRequest.h" +#include "serverNetworkMessages/FeatureIdTransactionSyncUpdate.h" +#include "serverNetworkMessages/LoginClusterName.h" +#include "serverNetworkMessages/LoginConnectionServerAddress.h" +#include "serverNetworkMessages/LoginCreateCharacterMessage.h" +#include "serverNetworkMessages/LoginKeyPush.h" +#include "serverNetworkMessages/LoginRestoreCharacterMessage.h" +#include "serverNetworkMessages/LoginUpgradeAccountMessage.h" +#include "serverNetworkMessages/PreloadFinishedMessage.h" +#include "serverNetworkMessages/RenameCharacterMessage.h" +#include "serverNetworkMessages/ServerDeleteCharacterMessage.h" +#include "serverNetworkMessages/TransferAccountData.h" +#include "serverNetworkMessages/TransferAccountDataArchive.h" +#include "serverNetworkMessages/TransferCharacterData.h" +#include "serverNetworkMessages/TransferCharacterDataArchive.h" +#include "serverNetworkMessages/TransferReplyMoveValidation.h" +#include "serverNetworkMessages/TransferRequestMoveValidation.h" +#include "serverNetworkMessages/UpdateLoginConnectionServerStatus.h" +#include "serverNetworkMessages/UpdatePlayerCountMessage.h" +#include "serverNetworkMessages/ValidateAccountMessage.h" +#include "serverNetworkMessages/ValidateAccountReplyMessage.h" +#include "serverUtility/AdminAccountManager.h" +#include "sharedFoundation/ApplicationVersion.h" +#include "sharedFoundation/Clock.h" +#include "sharedFoundation/Os.h" +#include "sharedGame/PlatformFeatureBits.h" +#include "sharedLog/Log.h" +#include "sharedLog/SetupSharedLog.h" +#include "sharedMemoryManager/MemoryManager.h" +#include "sharedNetwork/Address.h" +#include "sharedNetwork/NetworkSetupData.h" +#include "sharedNetworkMessages/ClientCentralMessages.h" +#include "sharedNetworkMessages/ClientLoginMessages.h" +#include "sharedNetworkMessages/DeleteCharacterMessage.h" +#include "sharedNetworkMessages/GenericValueTypeMessage.h" +#include "sharedNetworkMessages/LoginClusterStatus.h" +#include "sharedNetworkMessages/LoginClusterStatusEx.h" +#include "sharedNetworkMessages/LoginEnumCluster.h" +#include "sharedUtility/DataTableManager.h" + +#include + +//----------------------------------------------------------------------- + +namespace LoginServerNamespace +{ + struct ConnectionServerEntryLessThan : public std::binary_function + { + bool operator()(const LoginServer::ConnectionServerEntry & x, const LoginServer::ConnectionServerEntry & y) const; + }; //lint !e1509 // (base class destructor for class 'binary_function' is not virtual -- Effective C++ #14) // binary_function defines 3 typedefs required for the Adaptable Binary Function concept, The destructor is generated by the compiler and beyond our control + + enum + { + WORLD_COUNT_CHANNEL, + CLUSTER_COUNT_CHANNEL + }; + + // Very simple function to determine if a "threshold" has been crossed + bool hasCrossedThreshold(int thresholdValue, int oldValue, int newValue) + { + bool result = false; + + if ((oldValue < thresholdValue) && (newValue >= thresholdValue)) + { + // Crossed over the threshold + result = true; + } + else if ((oldValue >= thresholdValue) && (newValue < thresholdValue)) + { + // Crossed back down under the threshold + result = true; + } + + return result; + } + + // for testing purpose when not using session authentication, store + // the account feature Ids here, which will get cleared (obviously) + // when the LoginServer is restarted + std::map > s_nonSessionTestingAccountSwgFeatureIds; + std::map > s_nonSessionTestingAccountSwgTcgFeatureIds; +} + +//----------------------------------------------------------------------- + +using namespace LoginServerNamespace; + +//----------------------------------------------------------------------- + +bool ConnectionServerEntryLessThan::operator()(const LoginServer::ConnectionServerEntry &x, const LoginServer::ConnectionServerEntry &y) const +{ + return x.numClients < y.numClients; +} + + +//----------------------------------------------------------------------- + +LoginServer::LoginServer() : +Singleton(), +MessageDispatch::Receiver(), +done(false), +m_centralService(NULL), +clientService(0), +pingService(0), +keyServer(0), +m_clientMap(), +m_clusterList(), +m_sessionApiClient(0), +m_validatedClientMap(), +m_clusterStatusChanged(false), +m_soeMonitor(0) +{ + NetworkSetupData setup; + setup.port = ConfigLoginServer::getClientServicePort(); + setup.maxConnections = ConfigLoginServer::getMaxClients(); + setup.keepAliveDelay = 45000; + setup.compress = ConfigLoginServer::getCompressClientNetworkTraffic(); + setup.useTcp = false; + + clientService = new Service(ConnectionAllocator(), setup); + setup.compress = false; + + setup.port = ConfigLoginServer::getPingServicePort(); + pingService = new Service(ConnectionAllocator(), setup); + setup.useTcp = true; + + if (ConfigLoginServer::getDevelopmentMode()) + { + setup.port = ConfigLoginServer::getCentralServicePort(); + setup.maxConnections = 100; + m_centralService = new Service(ConnectionAllocator(), setup); + } + + setup.port = ConfigLoginServer::getCSToolPort(); + m_CSService = new Service(ConnectionAllocator(), setup ); + + // set up message connections + connectToMessage("ClaimRewardsMessage"); + connectToMessage("ConnectionClosed"); + connectToMessage("ConnectionServerDown"); //Sent to login from central when connection server goes down + connectToMessage("LoginClusterName"); + connectToMessage("LoginClusterName2"); + connectToMessage("LoginConnectionServerAddress"); //Sent to login from central after reconnecting. + connectToMessage("LoginCreateCharacterMessage"); + connectToMessage("LoginRestoreCharacterMessage"); + connectToMessage("LoginUpgradeAccountMessage"); + connectToMessage("PreloadFinishedMessage"); + connectToMessage("PurgeCompleteMessage"); + connectToMessage("RenameCharacterMessage"); + connectToMessage("TransferRequestMoveValidation"); + connectToMessage("TransferReplyNameValidation"); + connectToMessage("TransferLoginCharacterToDestinationServer"); + connectToMessage("UpdateLoginConnectionServerStatus"); + connectToMessage("UpdatePlayerCountMessage"); + connectToMessage("ValidateAccountMessage"); + connectToMessage("CntrlSrvDropDupeConns"); + connectToMessage("OccupyUnlockedSlotReq"); + connectToMessage("VacateUnlockedSlotReq"); + connectToMessage("SwapUnlockedSlotReq"); + connectToMessage("AdjustAccountFeatureIdRequest"); + connectToMessage("AccountFeatureIdRequest"); + connectToMessage("FeatureIdTransactionRequest"); + connectToMessage("FeatureIdTransactionSyncUpdate"); + keyServer = new KeyServer; + + if (ConfigLoginServer::getValidateStationKey() || ConfigLoginServer::getDoSessionLogin()) + { + installSessionValidation(); + } +} + +//----------------------------------------------------------------------- + +LoginServer::~LoginServer() +{ + delete keyServer; +} + +//----------------------------------------------------------------------- + +int LoginServer::addClient (ClientConnection & client) +{ + DEBUG_FATAL(client.getIsValidated(), ("Tried to add an already validated client?!")); + //Perhaps add a debug only check to make sure a client connection isn't in twice...I'm not sure how that could happen. + static int nextClientId = 0; + int tmp = ++nextClientId; + m_clientMap[tmp] = &client; + return tmp; +} + +//----------------------------------------------------------------------- + +ClientConnection* LoginServer::getValidatedClient (const StationId& clientId) +{ + std::map::iterator i = m_validatedClientMap.find(clientId); + if (i == m_validatedClientMap.end()) + return 0; + return i->second; + +} + +//----------------------------------------------------------------------- + +ClientConnection* LoginServer::getUnvalidatedClient (int clientId) +{ + WARNING_STRICT_FATAL(clientId == 0, ("Tried to get an unvalidated client with client id == 0")); + std::map::iterator i = m_clientMap.find(clientId); + if (i == m_clientMap.end()) + return 0; + WARNING_STRICT_FATAL(i->second->getIsValidated(), ("Returning validated client from call to getUnvalidatedClient()")); + return i->second; +} +//----------------------------------------------------------------------- + +void LoginServer::removeClient (int clientId) +{ + WARNING_STRICT_FATAL(clientId == 0, ("Tried to remove a client with client id == 0")); + std::map::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)); + } +} + +//----------------------------------------------------------------------- + +void LoginServer::installSessionValidation() +{ + int i = 0; + std::vector sessionServers; + + int numberOfSessionServers = ConfigLoginServer::getNumberOfSessionServers(); + for (i = 0; i < numberOfSessionServers; ++i) + { + char const * const p = ConfigLoginServer::getSessionServer(i); + if(p) + { + REPORT_LOG(true, ("Using session server %s\n", p)); + sessionServers.push_back(p); + } + } + + // if there were none specified, use defaults + FATAL(i == 0, ("No session servers specified for session API")); + + m_sessionApiClient = new SessionApiClient(&sessionServers[0], i); +} + +//----------------------------------------------------------------------- + +bool LoginServer::deleteCharacter(uint32 clusterId, NetworkId const & characterId, StationId suid) +{ + const ClusterListEntry *cle = findClusterById(clusterId); + if (cle) + { + if (cle->m_centralServerConnection) + { + ServerDeleteCharacterMessage smsg(suid, characterId, 0); + cle->m_centralServerConnection->send(smsg,true); + + ClientConnection* target = getValidatedClient(suid); + if (target) + { + target->onCharacterDeletedFromCluster(characterId); + } + + DatabaseConnection::getInstance().deleteCharacter(clusterId, characterId, suid); + return true; + } + else + { + DEBUG_REPORT_LOG(true,("User %lu requested deleting character %s on cluster %lu, but the cluster is not currently connected.\n",suid , characterId.getValueString().c_str(), clusterId)); + return false; + } + } + else + { + DEBUG_REPORT_LOG(true,("User %lu requested deleting character %s on cluster %lu, but we have no cluster with that number.\n", suid, characterId.getValueString().c_str(), clusterId)); + return false; + } +} + + +//----------------------------------------------------------------------- + +const KeyShare::Key & LoginServer::getCurrentKey(void) const +{ + return keyServer->getKey(0); +} + +//----------------------------------------------------------------------- + +SessionApiClient * LoginServer::getSessionApiClient() +{ + return m_sessionApiClient; +} + + +//----------------------------------------------------------------------- + +KeyShare::Token LoginServer::makeToken(const unsigned char * const data, const uint32 dataLen) const +{ + return keyServer->makeToken(data, dataLen); +} + +//----------------------------------------------------------------------- + +void LoginServer::pushAllKeys(CentralServerConnection * targetGameServer) const +{ + for(int i = static_cast(keyServer->getKeyCount()) - 1; i >=0 ; i --) + { + LoginKeyPush pk(keyServer->getKey(static_cast(i))); + targetGameServer->send(pk, true); + } +} + +//----------------------------------------------------------------------- + +void LoginServer::pushKeyToAllServers(void) +{ + KeyShare::Key k = keyServer->getKey(0); + CentralServerConnection * c; + + LoginKeyPush msg(k); + + unsigned char s[128]; + memcpy(s, k.value, 16); //lint !e64 !e119 !e534 // not sure where lint is finding a memcpy(void *, int) prototype + DEBUG_REPORT_LOG(true, ("Key Exchange ->: ")); + for(int x = 0; x < 16; x++) + { + DEBUG_REPORT_LOG(true, ("[%3i]", s[x])); + } + DEBUG_REPORT_LOG(true, ("\n")); + + for (ClusterListType::const_iterator i=m_clusterList.begin(); i!=m_clusterList.end(); ++i) + { + c = (*i)->m_centralServerConnection; + if(c) + { + c->send(msg, true); + } + } +} + +// ---------------------------------------------------------------------- + +void LoginServer::receiveMessage(const MessageDispatch::Emitter & source, const MessageDispatch::MessageBase & message) +{ + // determine message type + + if(message.isType("LoginClusterName") || message.isType( "LoginClusterName2" ) ) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + const LoginClusterName msg(ri); + if(msg.getClusterName().length() > 0) + { + CentralServerConnection * connection = const_cast(safe_cast(&source)); + DEBUG_REPORT_LOG(true, ("Cluster connection %s opened\n", msg.getClusterName().c_str())); + ClusterListEntry *cle=NULL; + if (ConfigLoginServer::getDevelopmentMode()) + { + // in this mode, we trust the name sent by the cluster and we dynamically add clusters we don't know about + cle = findClusterByName(msg.getClusterName()); + if (!cle) + cle = addCluster(msg.getClusterName()); + } + else + { + // in this mode, the cluster name has to match what we were expecting + cle = findClusterByConnection(connection); + if (!cle) + DEBUG_FATAL(true,("PROGRAMMER BUG: Got a connection from %s:%hu, which we weren't expecting. Cluster name is \"%s\".\n",connection->getRemoteAddress().c_str(), connection->getRemotePort(), msg.getClusterName().c_str())); + else + if (msg.getClusterName() != cle->m_clusterName) + { + WARNING(true,("Server %i is named \"%s\" in the database. The server at the specified address (%s:%hu) reports its name as \"%s\". It will not be allowed in the service. Either the name in the database or the name in Central's config file should be corrected.\n",cle->m_clusterId, cle->m_clusterName.c_str(), connection->getRemoteAddress().c_str(), connection->getRemotePort(), msg.getClusterName().c_str())); + disconnectCluster(*cle,true,false); + cle=NULL; + } + } + + if (cle) + { + cle->m_timeZone = msg.getTimeZone(); + cle->m_centralServerConnection = connection; + cle->m_connected = true; + pushAllKeys(connection); + + if (cle->m_clusterId == 0) + { + DEBUG_FATAL(!ConfigLoginServer::getDevelopmentMode(),("Programmer bug: cle->m_clusterId was 0 in non-development mode. The code before this line should have prevented this.\n")); + DEBUG_REPORT_LOG(true,("Cluster was not on the list. Adding it to the database.\n")); + DatabaseConnection::getInstance().registerNewCluster(msg.getClusterName(), connection->getRemoteAddress()); + } + else + cle->m_centralServerConnection->setClusterId(cle->m_clusterId); + + m_clusterStatusChanged = true; + + // tell the cluster its cluster id + if (cle->m_clusterId > 0) + { + GenericValueTypeMessage const msgClusterId("ClusterId", cle->m_clusterId); + cle->m_centralServerConnection->send(msgClusterId, true); + } + + // tell the cluster about its locked and secret state + GenericValueTypeMessage > const msgState("UpdateClusterLockedAndSecretState", std::make_pair(cle->m_locked, cle->m_secret)); + cle->m_centralServerConnection->send(msgState,true); + } + } + } + else if (message.isType("LoginConnectionServerAddress")) + { + const CentralServerConnection * cs = safe_cast(&source); + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + + LoginConnectionServerAddress m(ri); //lint !e1774 !e826onServerEntry entry; + ConnectionServerEntry entry; + entry.clientServiceAddress = Address(Address(m.getClientServiceAddress(), 0).getSockAddr4()).getHostAddress(); + entry.clientServicePortPrivate = m.getClientServicePortPrivate(); + entry.clientServicePortPublic = m.getClientServicePortPublic(); + entry.id = m.getId(); + entry.numClients = m.getNumClients(); + entry.pingPort = m.getPingPort (); + + DEBUG_REPORT_LOG(true, ("ConnectionServer Reconnect - address from connection server (%s), address after conversion (%s)\n", m.getClientServiceAddress().c_str(), entry.clientServiceAddress.c_str())); + + ClusterListEntry *cle = findClusterByConnection(cs); + if (cle) + { + WARNING_STRICT_FATAL(!cle->m_centralServerConnection, ("Got reconnect for connection server with no central! Cluster %s\n",cs->getClusterName().c_str())); + std::vector::iterator i = std::find(cle->m_connectionServers.begin(), cle->m_connectionServers.end(), entry); + if (i == cle->m_connectionServers.end()) + { + cle->m_connectionServers.push_back(entry); + m_clusterStatusChanged = true; + } + else + { + *i = entry; + } + + std::sort(cle->m_connectionServers.begin(), cle->m_connectionServers.end(), ConnectionServerEntryLessThan()); + } + else + WARNING_STRICT_FATAL(true,("Programmer bug: Got LoginConnectionServerAddress from a cluster that wasn't on the list. Probably indicates we aren't tracking connections properly.\n")); + } + else if (message.isType("PreloadFinishedMessage")) + { + const CentralServerConnection * cs = safe_cast(&source); + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + PreloadFinishedMessage msg(ri); + + ClusterListEntry *cle = findClusterByConnection(cs); + if (cle) + { + if (msg.getFinished()) + { + DEBUG_REPORT_LOG(true, ("Cluster %s is ready for players.\n",cle->m_clusterName.c_str())); + if (!cle->m_readyForPlayers) + { + cle->m_readyForPlayers = true; + m_clusterStatusChanged = true; + } + } + else + { + DEBUG_REPORT_LOG(true, ("Cluster %s is not ready for players.\n",cle->m_clusterName.c_str())); + if (cle->m_readyForPlayers) + { + cle->m_readyForPlayers = false; + m_clusterStatusChanged = true; + PurgeManager::onClusterNoLongerReady(cle->m_clusterId); + } + } + } + else + WARNING_STRICT_FATAL(true,("Programmer bug: Got PreloadFinishedMessage from a cluster that wasn't on the list. Probably indicates we aren't tracking connections properly.\n")); + } + else if(message.isType("ConnectionServerDown")) + { + + const CentralServerConnection * centralConnection = safe_cast(&source); + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ConnectionServerDown c(ri); //lint !e1774 !e826 + ClusterListEntry *cle = findClusterByConnection(centralConnection); + if (cle) + { + DEBUG_REPORT_LOG(true, ("Lost a connection server %d for %s.\n", c.getId(), cle->m_clusterName.c_str())); + + std::vector::iterator iter = cle->m_connectionServers.begin(); + bool found = false; + for (; iter != cle->m_connectionServers.end(); ++iter) + { + if (iter->id == c.getId()) + { + IGNORE_RETURN(cle->m_connectionServers.erase(iter)); + std::sort(cle->m_connectionServers.begin(), cle->m_connectionServers.end(), ConnectionServerEntryLessThan()); + found = true; + break; + } + } + DEBUG_REPORT_LOG(!found, ("Tried to remove a connection server that wasn't in our list.\n")); + m_clusterStatusChanged = true; + } + else + WARNING_STRICT_FATAL(true,("Programmer bug: Got ConnectionServerDown from a cluster that wasn't on the list. Probably indicates we aren't tracking connections properly.\n")); + } + else if(message.isType("ConnectionClosed")) + { + const CentralServerConnection *c = dynamic_cast(&source); + if (c) + { + ClusterListEntry *cle = findClusterByConnection(c); + if (cle) + { + DEBUG_REPORT_LOG(true, ("Cluster connection %s closed.\n", c->getClusterName().c_str())); + disconnectCluster(*cle,false,true); + } + else + WARNING_STRICT_FATAL(true,("Programmer bug: Cluster disconnected but it wasn't on the list. Probably indicates we aren't tracking connections properly.\n")); + } + } + else if (message.isType("ValidateAccountMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ValidateAccountMessage msg(ri); + + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) + DatabaseConnection::getInstance().getAccountValidationData(msg.getStationId(), conn->getClusterId(), msg.getTrack(), msg.getSubscriptionBits()); + else + WARNING_STRICT_FATAL(true,("Expect ValidateAccountMessage's to only come from CentralServers.\n")); + } + else if (message.isType("CntrlSrvDropDupeConns")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage > const msg(ri); + + sendToAllClusters(msg, dynamic_cast(&source)); + } + else if (message.isType("AdjustAccountFeatureIdRequest")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + AdjustAccountFeatureIdRequest const msg(ri); + + if (m_sessionApiClient) + { + // on a session authenticated cluster, this request should have been serviced by the ConnectionServer + } + else + { + // for testing purpose when not using session authentication, store + // the account feature Ids locally in memory, which will get cleared + // (obviously) when the LoginServer is restarted + std::map > * nonSessionTestingAccountFeatureIds = NULL; + if (msg.getGameCode() == PlatformGameCode::SWG) + nonSessionTestingAccountFeatureIds = &s_nonSessionTestingAccountSwgFeatureIds; + else if (msg.getGameCode() == PlatformGameCode::SWGTCG) + nonSessionTestingAccountFeatureIds = &s_nonSessionTestingAccountSwgTcgFeatureIds; + + int currentFeatureIdCount = 0; + int updatedFeatureIdCount = 0; + if (nonSessionTestingAccountFeatureIds) + { + std::map & accountFeatureIds = (*nonSessionTestingAccountFeatureIds)[msg.getTargetStationId()]; + std::map::const_iterator accountFeatureId = accountFeatureIds.find(msg.getFeatureId()); + if (accountFeatureId != accountFeatureIds.end()) + currentFeatureIdCount = accountFeatureId->second; + + updatedFeatureIdCount = std::max(0, currentFeatureIdCount + msg.getAdjustment()); + if (updatedFeatureIdCount > 0) + { + accountFeatureIds[msg.getFeatureId()] = updatedFeatureIdCount; + } + else + { + IGNORE_RETURN(accountFeatureIds.erase(msg.getFeatureId())); + if (accountFeatureIds.empty()) + IGNORE_RETURN(nonSessionTestingAccountFeatureIds->erase(msg.getTargetStationId())); + } + } + + // CS log SWG TCG account feature grant or SWG account feature grant for reward item trade in + if (nonSessionTestingAccountFeatureIds && !msg.getTargetPlayerDescription().empty() && msg.getTargetItem().isValid() && !msg.getTargetItemDescription().empty()) + { + if (msg.getGameCode() == PlatformGameCode::SWGTCG) + LOG("CustomerService",("TcgRedemption: %s redeemed %s for SWGTCG account feature Id %lu (%d -> %d)", msg.getTargetPlayerDescription().c_str(), msg.getTargetItemDescription().c_str(), msg.getFeatureId(), currentFeatureIdCount, updatedFeatureIdCount)); + else if (msg.getGameCode() == PlatformGameCode::SWG) + LOG("CustomerService",("VeteranRewards: %s traded in %s for SWG account feature Id %lu (%d -> %d)", msg.getTargetPlayerDescription().c_str(), msg.getTargetItemDescription().c_str(), msg.getFeatureId(), currentFeatureIdCount, updatedFeatureIdCount)); + } + + const CentralServerConnection * conn = dynamic_cast(&source); + if (conn) + { + AdjustAccountFeatureIdResponse const rsp(msg.getRequestingPlayer(), msg.getGameServer(), msg.getTargetPlayer(), msg.getTargetPlayerDescription(), msg.getTargetStationId(), msg.getTargetItem(), msg.getTargetItemDescription(), msg.getGameCode(), msg.getFeatureId(), currentFeatureIdCount, updatedFeatureIdCount, (nonSessionTestingAccountFeatureIds ? RESULT_SUCCESS : RESULT_CANCELLED), false); + sendToCluster(conn->getClusterId(), rsp); + } + } + } + else if (message.isType("AccountFeatureIdRequest")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + AccountFeatureIdRequest const msg(ri); + + if (m_sessionApiClient) + { + // on a session authenticated cluster, this request should have been serviced by the ConnectionServer + } + else + { + // for testing purpose when not using session authentication, store + // the account feature Ids locally in memory, which will get cleared + // (obviously) when the LoginServer is restarted + std::map > * nonSessionTestingAccountFeatureIds = NULL; + if (msg.getGameCode() == PlatformGameCode::SWG) + nonSessionTestingAccountFeatureIds = &s_nonSessionTestingAccountSwgFeatureIds; + else if (msg.getGameCode() == PlatformGameCode::SWGTCG) + nonSessionTestingAccountFeatureIds = &s_nonSessionTestingAccountSwgTcgFeatureIds; + + static std::map const empty; + std::map const * accountFeatureIds = ∅ + + if (nonSessionTestingAccountFeatureIds) + { + std::map >::const_iterator iterFind = nonSessionTestingAccountFeatureIds->find(msg.getTargetStationId()); + if (iterFind != nonSessionTestingAccountFeatureIds->end()) + accountFeatureIds = &(iterFind->second); + } + + const CentralServerConnection * conn = dynamic_cast(&source); + if (conn) + { + static std::map const empty; + AccountFeatureIdResponse const rsp(msg.getRequester(), msg.getGameServer(), msg.getTarget(), msg.getTargetStationId(), msg.getGameCode(), msg.getRequestReason(), RESULT_SUCCESS, false, *accountFeatureIds, empty); + sendToCluster(conn->getClusterId(), rsp); + } + } + } + else if (message.isType("FeatureIdTransactionRequest")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + FeatureIdTransactionRequest const fitr(ri); + + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) + DatabaseConnection::getInstance().featureIdTransactionRequest(conn->getClusterId(), fitr.getStationId(), fitr.getPlayer(), fitr.getGameServer()); + } + else if (message.isType("FeatureIdTransactionSyncUpdate")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + FeatureIdTransactionSyncUpdate const fitsu(ri); + + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) + DatabaseConnection::getInstance().featureIdTransactionSyncUpdate(conn->getClusterId(), fitsu.getStationId(), fitsu.getPlayer(), fitsu.getItemId(), fitsu.getAdjustment()); + } + else if (message.isType("TransferRequestMoveValidation")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + const TransferRequestMoveValidation request(ri); + + TransferReplyMoveValidation::TransferReplyMoveValidationResult result = TransferReplyMoveValidation::TRMVR_can_create_regular_character; + + ClusterListEntry * cle = findClusterByName(request.getDestinationGalaxy()); + if (!cle) + { + result = TransferReplyMoveValidation::TRMVR_destination_galaxy_invalid; + } + else if (!cle->m_centralServerConnection) + { + result = TransferReplyMoveValidation::TRMVR_destination_galaxy_not_connected; + } + else if (!cle->m_readyForPlayers) + { + result = TransferReplyMoveValidation::TRMVR_destination_galaxy_in_loading; + } + + if (result == TransferReplyMoveValidation::TRMVR_can_create_regular_character) + { + // check with DB to see if account is allowed to create character on the destination galaxy + LOG("CustomerService", ("CharacterTransfer: Received TransferRequestMoveValidation : %s (character template id %lu) on %s to %s on %s. Forwarding request to Login Database.", request.getSourceCharacter().c_str(), request.getSourceCharacterTemplateId(), request.getSourceGalaxy().c_str(), request.getDestinationCharacter().c_str(), request.getDestinationGalaxy().c_str())); + DatabaseConnection::getInstance().getAccountValidationData(request, cle->m_centralServerConnection->getClusterId()); + } + else + { + // send failure back to originating server + TransferReplyMoveValidation reply(request.getTransferRequestSource(), request.getTrack(), request.getSourceStationId(), request.getDestinationStationId(), request.getSourceGalaxy(), request.getDestinationGalaxy(), request.getSourceCharacter(), request.getSourceCharacterId(), request.getSourceCharacterTemplateId(), request.getDestinationCharacter(), request.getCustomerLocalizedLanguage(), result); + const CentralServerConnection * conn = dynamic_cast(&source); + if(conn) + { + ClusterListEntry * sourceEntry = findClusterById(conn->getClusterId()); + if(sourceEntry && sourceEntry->m_centralServerConnection) + { + sourceEntry->m_centralServerConnection->send(reply, true); + } + } + } + } + else if (message.isType("TransferReplyNameValidation")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage > const replyNameValidation(ri); + + const CentralServerConnection * conn = dynamic_cast(&source); + if (conn) + { + ClusterListEntry * cle = findClusterByName(replyNameValidation.getValue().second.getSourceGalaxy()); + if (cle && cle->m_centralServerConnection) + { + LOG("CustomerService", ("CharacterTransfer: Received TransferReplyNameValidation from destination galaxy CentralServer, forwarding to source galaxy CentralServer : %s", replyNameValidation.getValue().second.toString().c_str())); + cle->m_centralServerConnection->send(replyNameValidation, true); + } + } + } + else if (message.isType("TransferLoginCharacterToDestinationServer")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage const login(ri); + + const CentralServerConnection * conn = dynamic_cast(&source); + if (conn) + { + ClusterListEntry * cle = findClusterByName(login.getValue().getDestinationGalaxy()); + if (cle && cle->m_centralServerConnection) + { + LOG("CustomerService", ("CharacterTransfer: Received TransferLoginCharacterToDestinationServer from source galaxy CentralServer, forwarding to destination galaxy CentralServer : %s", login.getValue().toString().c_str())); + cle->m_centralServerConnection->send(login, true); + } + } + } + else if (message.isType("UpdateLoginConnectionServerStatus")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + UpdateLoginConnectionServerStatus msg(ri); + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) + { + ClusterListEntry *cle = findClusterByConnection(conn); + if (cle) + { + std::vector::iterator i = cle->m_connectionServers.begin(); + for (; i!= cle->m_connectionServers.end(); ++i) + { + if (i->id == msg.getId()) + { + i->clientServicePortPublic = msg.getPublicPort(); + i->clientServicePortPrivate = msg.getPrivatePort(); + i->numClients = msg.getPlayerCount(); + break; + } + } + std::sort(cle->m_connectionServers.begin(), cle->m_connectionServers.end(), ConnectionServerEntryLessThan()); + } + } + + } + else if (message.isType("UpdatePlayerCountMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + UpdatePlayerCountMessage msg(ri); + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) + { + ClusterListEntry *cle = findClusterByConnection(conn); + if (cle) + { + const int tutorialPlayerCount = (msg.getEmptySceneCount() + msg.getTutorialSceneCount() + msg.getFalconSceneCount()); + + // We only want to update the clients if some "threshold" has been crossed + if ((cle->m_notRecommendedCentral != msg.getLoadedRecently()) + || hasCrossedThreshold(cle->m_onlineTutorialLimit, cle->m_numTutorialPlayers, tutorialPlayerCount) + || hasCrossedThreshold(cle->m_onlineFreeTrialLimit, cle->m_numFreeTrialPlayers, msg.getFreeTrialCount()) + || hasCrossedThreshold(cle->m_onlinePlayerLimit, cle->m_numPlayers, msg.getCount())) + { + m_clusterStatusChanged = true; + } + + cle->m_numPlayers = msg.getCount(); + cle->m_numFreeTrialPlayers = msg.getFreeTrialCount(); + cle->m_notRecommendedCentral = msg.getLoadedRecently(); + cle->m_numTutorialPlayers = tutorialPlayerCount; + } + } + } + else if (message.isType("RenameCharacterMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + RenameCharacterMessage msg(ri); + + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) + DatabaseConnection::getInstance().renameCharacter(conn->getClusterId(), msg.getCharacterId(), msg.getNewName(), NULL); + else + WARNING_STRICT_FATAL(true,("Got RenameCharacterMessage from something other than CentralServerConnection.\n")); + } + else if (message.isType("LoginCreateCharacterMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + LoginCreateCharacterMessage msg(ri); + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) + DatabaseConnection::getInstance().createCharacter(conn->getClusterId(),msg.getStationId(),msg.getCharacterName(),msg.getCharacterObjectId(),msg.getTemplateId(), msg.getJedi()); + } + else if (message.isType("LoginRestoreCharacterMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + LoginRestoreCharacterMessage msg(ri); + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) + DatabaseConnection::getInstance().restoreCharacter(conn->getClusterId(),msg.getWhoRequested(),msg.getAccount(),msg.getCharacterName(),msg.getCharacterId(),msg.getTemplateId(), msg.getJedi()); + } + else if (message.isType("LoginUpgradeAccountMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + LoginUpgradeAccountMessage *msg = new LoginUpgradeAccountMessage(ri); + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) + DatabaseConnection::getInstance().upgradeAccount(msg,conn->getClusterId()); + } + else if (message.isType("ClaimRewardsMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + ClaimRewardsMessage const * msg = new ClaimRewardsMessage(ri); + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) + { + // current restriction is that once per account event or item cannot require a "consuming" account feature id + uint32 const requiredAccountFeatureId = msg->getAccountFeatureId(); + bool const consumeAccountFeatureId = msg->getConsumeAccountFeatureId(); + if ((msg->getConsumeEvent() || msg->getConsumeItem()) && (requiredAccountFeatureId > 0) && consumeAccountFeatureId) + { + ClaimRewardsReplyMessage const rsp(msg->getGameServer(), msg->getStationId(), msg->getPlayer(), msg->getRewardEvent(), msg->getRewardItem(), requiredAccountFeatureId, consumeAccountFeatureId, 0, 0, false); + sendToCluster(conn->getClusterId(), rsp); + delete msg; + } + else if (requiredAccountFeatureId > 0) + { + if (m_sessionApiClient) + { + if (consumeAccountFeatureId) + { + // request session/Platform to update the account feature id + // SessionApiClient will own (and delete) msg + m_sessionApiClient->handleClaimRewardsMessage(conn->getClusterId(), msg); + } + else + { + LoginAPI::Feature oldFeature; + oldFeature.SetID(requiredAccountFeatureId); + oldFeature.SetData(msg->getAccountFeatureIdOldValue()); + + LoginAPI::Feature newFeature; + newFeature.SetID(requiredAccountFeatureId); + newFeature.SetData(msg->getAccountFeatureIdNewValue()); + + DatabaseConnection::getInstance().claimRewards(conn->getClusterId(), msg->getGameServer(), msg->getStationId(), msg->getPlayer(), msg->getRewardEvent(), msg->getConsumeEvent(), msg->getRewardItem(), msg->getConsumeItem(), requiredAccountFeatureId, false, oldFeature.GetConsumeCount(), newFeature.GetConsumeCount()); + delete msg; + } + } + else + { + // for testing purpose when not using session authentication, store + // the account feature Ids locally in memory, which will get cleared + // (obviously) when the LoginServer is restarted + std::map & accountFeatureIds = s_nonSessionTestingAccountSwgFeatureIds[msg->getStationId()]; + std::map::const_iterator accountFeatureId = accountFeatureIds.find(requiredAccountFeatureId); + int currentFeatureIdCount = 0; + if (accountFeatureId != accountFeatureIds.end()) + currentFeatureIdCount = accountFeatureId->second; + + if (currentFeatureIdCount <= 0) + { + // fail because account doesn't have required feature id + IGNORE_RETURN(accountFeatureIds.erase(requiredAccountFeatureId)); + if (accountFeatureIds.empty()) + IGNORE_RETURN(s_nonSessionTestingAccountSwgFeatureIds.erase(msg->getStationId())); + + ClaimRewardsReplyMessage rsp(msg->getGameServer(), msg->getStationId(), msg->getPlayer(), msg->getRewardEvent(), msg->getRewardItem(), requiredAccountFeatureId, consumeAccountFeatureId, 0, 0, false); + sendToCluster(conn->getClusterId(), rsp); + } + else + { + // account has required feature id so claim is success, so update feature id for claim + int const updatedFeatureIdCount = (consumeAccountFeatureId ? std::max(0, currentFeatureIdCount - 1) : currentFeatureIdCount); + + if (consumeAccountFeatureId) + { + if (updatedFeatureIdCount > 0) + { + accountFeatureIds[requiredAccountFeatureId] = updatedFeatureIdCount; + } + else + { + IGNORE_RETURN(accountFeatureIds.erase(requiredAccountFeatureId)); + if (accountFeatureIds.empty()) + IGNORE_RETURN(s_nonSessionTestingAccountSwgFeatureIds.erase(msg->getStationId())); + } + } + + // if feature id updated successfully, record transaction + DatabaseConnection::getInstance().claimRewards(conn->getClusterId(), msg->getGameServer(), msg->getStationId(), msg->getPlayer(), msg->getRewardEvent(), msg->getConsumeEvent(), msg->getRewardItem(), msg->getConsumeItem(), requiredAccountFeatureId, consumeAccountFeatureId, currentFeatureIdCount, updatedFeatureIdCount); + } + + delete msg; + } + } + else + { + DatabaseConnection::getInstance().claimRewards(conn->getClusterId(), msg->getGameServer(), msg->getStationId(), msg->getPlayer(), msg->getRewardEvent(), msg->getConsumeEvent(), msg->getRewardItem(), msg->getConsumeItem(), 0, false, 0, 0); + delete msg; + } + } + else + { + delete msg; + } + } + else if (message.isType("PurgeCompleteMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage msg(ri); + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) + PurgeManager::handlePurgeCompleteOnCluster(msg.getValue(), conn->getClusterId()); + else + WARNING_STRICT_FATAL(true,("Programmer bug: got PurgeCompleteMessage from something that couldn't be cast to a CentralServerConnection")); + } + else if (message.isType("OccupyUnlockedSlotReq")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage, uint32> > const occupyUnlockedSlotReq(ri); + + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) + DatabaseConnection::getInstance().occupyUnlockedSlot(conn->getClusterId(), static_cast(occupyUnlockedSlotReq.getValue().first.first), occupyUnlockedSlotReq.getValue().first.second, occupyUnlockedSlotReq.getValue().second); + } + else if (message.isType("VacateUnlockedSlotReq")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage, uint32> > const vacateUnlockedSlotReq(ri); + + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) + DatabaseConnection::getInstance().vacateUnlockedSlot(conn->getClusterId(), static_cast(vacateUnlockedSlotReq.getValue().first.first), vacateUnlockedSlotReq.getValue().first.second, vacateUnlockedSlotReq.getValue().second); + } + else if (message.isType("SwapUnlockedSlotReq")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + GenericValueTypeMessage, std::pair > > const swapUnlockedSlotReq(ri); + + const CentralServerConnection *conn = dynamic_cast(&source); + if (conn) + DatabaseConnection::getInstance().swapUnlockedSlot(conn->getClusterId(), static_cast(swapUnlockedSlotReq.getValue().first.first), swapUnlockedSlotReq.getValue().first.second, swapUnlockedSlotReq.getValue().second.second, swapUnlockedSlotReq.getValue().second.first); + } +} + +// ---------------------------------------------------------------------- + +/** + * Validate whether a particular account can connect to a particular cluster. + * Also, flag whether character creation is allowed. + * @see DatabaseConnection::getAccountValidationData + */ +void LoginServer::validateAccount(const StationId& stationId, uint32 clusterId, uint32 subscriptionBits, bool canCreateRegular, bool canCreateJedi, bool canSkipTutorial, unsigned int track, std::vector > const & consumedRewardEvents, std::vector > const & claimedRewardItems) +{ + bool canLogin = false; + + ClusterListEntry *cle = findClusterById(clusterId); + if (cle && cle->m_centralServerConnection) + { + // Check login rights + // code to restrict logins based on "internal only", geographic rules, etc., goes here + // allow logins unless the cluster is full + bool clientIsInternal = false; + ClientConnection *conn = getValidatedClient(stationId); + if (conn) + { + clientIsInternal = AdminAccountManager::isInternalIp(conn->getRemoteAddress()); + } + + if (clientIsInternal && ConfigLoginServer::getInternalBypassOnlineLimit()) + { + canLogin = true; + } + else if (cle->m_numPlayers <= cle->m_onlinePlayerLimit) + { + canLogin = true; + + // Check cluster npe user limit + if (cle->m_numTutorialPlayers > cle->m_onlineTutorialLimit) + { + canCreateRegular=false; + canCreateJedi=false; + } + + // limit login/character creation based on subscription feature bits + if ( ((subscriptionBits & ClientSubscriptionFeature::FreeTrial) != 0) + && ((subscriptionBits & ClientSubscriptionFeature::Base) == 0)) + { + // Check cluster free trial user limit + if (cle->m_numFreeTrialPlayers > cle->m_onlineFreeTrialLimit) + { + canLogin = false; + } + // Check cluster free trial character creation + if (!cle->m_freeTrialCanCreateChar) + { + canCreateRegular=false; + canCreateJedi=false; + } + } + } + + if (!canLogin) + { + canCreateRegular=false; + canCreateJedi=false; + canSkipTutorial=false; + } + + // check if we want to allow skip tutorial to all + if (ConfigLoginServer::getAllowSkipTutorialToAll()) + canSkipTutorial=true; + + ValidateAccountReplyMessage msg(stationId, canLogin, canCreateRegular, canCreateJedi, canSkipTutorial, track, consumedRewardEvents, claimedRewardItems); + cle->m_centralServerConnection->send(msg,true); + } +} + +//----------------------------------------------------------------------- + +void LoginServer::validateAccountForTransfer(const TransferRequestMoveValidation & request, uint32 clusterId, uint32 sourceCharacterTemplateId, bool canCreateRegular, bool canCreateJedi) +{ + UNREF(canCreateJedi); + + // if transfer request was made with console god command, always allow + // the character to be created on the destination galaxy; we assume + // the user of the console god command knows that he's doing with regard + // to making sure that the destination galaxy would not end up with too many + // characters on the account on the destination galaxy + if (!canCreateRegular && (request.getTransferRequestSource() == TransferRequestMoveValidation::TRS_console_god_command)) + { + LOG("CustomerService", ("CharacterTransfer: Account Validation request for %s on %s to %s on %s is complete. Even though canCreateRegular=false, we are setting canCreateRegular=true because this request came from the console god command.", request.getSourceCharacter().c_str(), request.getSourceGalaxy().c_str(), request.getDestinationCharacter().c_str(), request.getDestinationGalaxy().c_str())); + canCreateRegular = true; + } + + LOG("CustomerService", ("CharacterTransfer: Account Validation request for %s on %s to %s on %s is complete. Sending response to CentralServer", request.getSourceCharacter().c_str(), request.getSourceGalaxy().c_str(), request.getDestinationCharacter().c_str(), request.getDestinationGalaxy().c_str())); + + // if this request came from a game server and the validation fails, send + // response to the source galaxy so an error message can be displayed to the user + if ((request.getTransferRequestSource() != TransferRequestMoveValidation::TRS_transfer_server) && !canCreateRegular) + { + ClusterListEntry * sourceGalaxyCle = findClusterByName(request.getSourceGalaxy()); + if (sourceGalaxyCle && sourceGalaxyCle->m_centralServerConnection) + { + clusterId = sourceGalaxyCle->m_centralServerConnection->getClusterId(); + } + } + + ClusterListEntry * cle = findClusterById(clusterId); + if(cle && cle->m_centralServerConnection) + { + TransferReplyMoveValidation response(request.getTransferRequestSource(), request.getTrack(), request.getSourceStationId(), request.getDestinationStationId(), request.getSourceGalaxy(), request.getDestinationGalaxy(), request.getSourceCharacter(), request.getSourceCharacterId(), sourceCharacterTemplateId, request.getDestinationCharacter(), request.getCustomerLocalizedLanguage(), (canCreateRegular ? TransferReplyMoveValidation::TRMVR_can_create_regular_character : TransferReplyMoveValidation::TRMVR_cannot_create_regular_character)); + cle->m_centralServerConnection->send(response, true); + } +} + +//----------------------------------------------------------------------- + +void LoginServer::run(void) +{ + NetworkHandler::install(); + LoginServerRemoteDebugSetup::install(); + DatabaseConnection::getInstance().connect(); + DatabaseConnection::getInstance().requestClusterList(); + SetupSharedLog::install("LoginServer"); + ConsoleManager::install(); + DataTableManager::install(); + AdminAccountManager::install(ConfigLoginServer::getAdminAccountDataTable()); + + unsigned long limit = 20; + unsigned long startTime; + unsigned long totalTime = 0; + + // load authentication data and bind the monitor to the port + CMonitorAPI * mon = new CMonitorAPI("metricsAuthentication.cfg", ConfigLoginServer::getMetricsListenerPort()); + getInstance().m_soeMonitor = mon; + const char *masterChannel = "Population"; + mon->add(masterChannel, WORLD_COUNT_CHANNEL); + std::string host = NetworkHandler::getHostName().c_str(); + size_t dotPos = host.find("."); + if(dotPos != host.npos) + { + host = host.substr(0, dotPos - 1); + } + char tmpBuf[1024]; + IGNORE_RETURN(snprintf(tmpBuf, sizeof(tmpBuf), "LoginServer version %s on %s", ApplicationVersion::getInternalVersion(), host.c_str())); + mon->setDescription(WORLD_COUNT_CHANNEL, tmpBuf); + + mon->add("Galaxies", CLUSTER_COUNT_CHANNEL); + + while(!getInstance().done) + { + startTime = Clock::timeMs(); + IGNORE_RETURN(Os::update()); + if(getInstance().keyServer->update()) + { + getInstance().pushKeyToAllServers(); + } + NetworkHandler::dispatch(); + do + { + Os::sleep(1); + NetworkHandler::update(); + } while(Clock::timeMs() - startTime < limit); + + DatabaseConnection::getInstance().update(); + PurgeManager::update(static_cast(limit)/ 1000.0f); + if (getInstance().m_clusterStatusChanged) + { + getInstance().sendClusterStatusToAll(); + getInstance().m_clusterStatusChanged = false; + } + + if (getInstance().m_sessionApiClient) + getInstance().m_sessionApiClient->Process(); + + totalTime += limit; //TODO: make a better way to do this + if (!ConfigLoginServer::getDevelopmentMode() && (totalTime > 10000)) + { + getInstance().refreshConnections(); + DatabaseConnection::getInstance().requestClusterList(); + totalTime = 0; + } + + NetworkHandler::clearBytesThisFrame(); + if(mon) + { + mon->set(WORLD_COUNT_CHANNEL, static_cast(getInstance().m_clientMap.size())); + int count = 0; + ClusterListType::const_iterator i; + for(i = getInstance().m_clusterList.begin(); i != getInstance().m_clusterList.end(); ++i) + { + if((*i)->m_connected) + ++count; + } + mon->set(CLUSTER_COUNT_CHANNEL, count); + mon->Update(); + } + } + + NetworkHandler::update(); + + ConsoleManager::remove(); + DatabaseConnection::getInstance().disconnect(); + LoginServerRemoteDebugSetup::remove(); + + SetupSharedLog::remove(); + NetworkHandler::remove(); +} + + +//----------------------------------------------------------------------- + +void LoginServer::sendAvatarList(const StationId& stationId, int stationIdNumberJediSlot, const AvatarList &avatars, TransferCharacterData * const transferData) +{ + std::vector chardata; + chardata.reserve(avatars.size()); + + EnumerateCharacterId::Chardata temp; + for (AvatarList::const_iterator i=avatars.begin(); i!=avatars.end(); ++i) + { + temp.m_name = (*i).m_name; + temp.m_objectTemplateId = (*i).m_objectTemplateId; + temp.m_networkId = (*i).m_networkId; + temp.m_clusterId = (*i).m_clusterId; + temp.m_characterType = (*i).m_characterType; + + chardata.push_back(temp); + } + + EnumerateCharacterId msg(chardata); + + if(transferData) + { + // send this to the appropriate CentralServer + if(transferData->getSourceCharacterName().empty()) + { + // CTS API character list request + bool result = CentralServerConnection::sendCharacterListResponse(transferData->getSourceStationId(), avatars, *transferData); + UNREF(result); + DEBUG_REPORT_LOG(! result,("Could not send avatar list to StationId %lu because connection has been closed.\n",stationId)); + } + else + { + uint32 characterTemplateId = 0; + NetworkId characterId = NetworkId::cms_invalid; + ClusterListEntry const * const cle = findClusterByName(transferData->getSourceGalaxy()); + if (cle) + { + // find associated character ID + for (AvatarList::const_iterator i=avatars.begin(); i!=avatars.end(); ++i) + { + REPORT_LOG(true, ("checking %s == %s\n", Unicode::wideToNarrow(i->m_name).c_str(), transferData->getSourceCharacterName().c_str())); + if(Unicode::wideToNarrow(i->m_name) == transferData->getSourceCharacterName() + && i->m_clusterId == cle->m_clusterId) + { + characterTemplateId = static_cast(i->m_objectTemplateId); + characterId = i->m_networkId; + break; + } + } + } + + LOG("CustomerService", ("CharacterTransfer: sendAvatarList() for stationId=%u, characterName=%s, sourceGalaxy=%s, determined characterId=%s, determined character template id=%lu", transferData->getSourceStationId(), transferData->getSourceCharacterName().c_str(), transferData->getSourceGalaxy().c_str(), characterId.getValueString().c_str(), characterTemplateId)); + + transferData->setCharacterId(characterId); + transferData->setObjectTemplateCrc(characterTemplateId); + + // part of move request for character transfer system + const GenericValueTypeMessage response("TransferReplyCharacterDataFromLoginServer", *transferData); + CentralServerConnection::sendToCentralServer(transferData->getSourceGalaxy(), response); + } + } + else + { + ClientConnection *conn = getValidatedClient(stationId); + if (conn) + { + LOG("LoginClientConnection", ("sendAvatarList() for stationId (%lu) at IP (%s), sending avatar list to client", stationId, conn->getRemoteAddress().c_str())); + + // this message ***MUST*** be sent first, as the client expects to + // receive this information before receiving the avatar list information + GenericValueTypeMessage const msgStationIdHasJediSlot("StationIdHasJediSlot", stationIdNumberJediSlot); + conn->send(msgStationIdHasJediSlot,true); + + conn->send(msg,true); + } + else + { + DEBUG_REPORT_LOG(true,("Could not send avatar list to StationId %lu.\n",stationId)); + LOG("LoginClientConnection", ("sendAvatarList() for stationId (%lu), cannot find connection to client for sending avatar list", stationId)); + } + } +} + +// ---------------------------------------------------------------------- + +void LoginServer::performAccountTransfer (const AvatarList &avatars, TransferAccountData * transferAccountData) +{ + // grab the station ids + StationId sourceStationId = transferAccountData->getSourceStationId(); + StationId destinationStationId = transferAccountData->getDestinationStationId(); + + // we need to get the avatars' cluster and name for use in the chat transfer process + // also send a message to modify the game server databases for each of the clusterIds in transferAccountData + // avatar data is clusterName, avatarName + std::vector avatarData; + for (AvatarList::const_iterator i = avatars.begin(); i != avatars.end(); ++i) + { + ClusterListEntry * cluster = findClusterById(i->m_clusterId); + + if (cluster) + { + std::string clusterName = cluster->m_clusterName; + std::string avatarName = Unicode::wideToNarrow(i->m_name); + + avatarData.push_back(AvatarData(clusterName, avatarName)); + + LOG("CustomerService", ("CharacterTransfer: Sending request to update game db (via cluster: %s) for account transfer from %lu to %lu (avatar: %s)", clusterName.c_str(), sourceStationId, destinationStationId, avatarName.c_str())); + const GenericValueTypeMessage message("TransferAccountRequestCentralDatabase", *transferAccountData); + sendToCluster (i->m_clusterId, message); + } + else + { + LOG("CustomerService", ("CharacterTransfer: Could not connect to cluster id %lu to update game db for account transfer from %lu to %lu (avatar: %s)", i->m_clusterId, sourceStationId, destinationStationId, Unicode::wideToNarrow(i->m_name).c_str())); + const GenericValueTypeMessage response("TransferAccountToAccountFailedToUpdateGameDatabase", *transferAccountData); + CentralServerConnection::sendToCentralServer(transferAccountData->getStartGalaxy(), response); + return; + } + } + + transferAccountData->setSourceAvatarData(avatarData); + + // we also need to modify the station id for all characters for the loginServer - this will contact the centralServer when it is complete to finish the transfer process + DatabaseConnection::getInstance().changeStationId(sourceStationId, destinationStationId, transferAccountData); +} + +// ---------------------------------------------------------------------- + +void LoginServer::onValidateClient(StationId suid, const std::string & username, ClientConnection *conn, bool isSecure, const char* sessionKey, uint32 gameBits, uint32 subscriptionBits) +{ + UNREF(username); + UNREF(gameBits); + UNREF(subscriptionBits); + NOT_NULL(conn); + WARNING_STRICT_FATAL(getValidatedClient(suid), ("Validating an already valid client in onValidateClient(). StationId: %d UserName: %s", suid, username.c_str())); + + int adminLevel=0; + const bool isAdminAccount = AdminAccountManager::isAdminAccount(Unicode::toLower(username), adminLevel); + + if (conn->getRequestedAdminSuid() != 0) + { + //verify internal, secure, is on the god list + bool loginOK=false; + if(!isSecure) + LOG("CustomerService",("AdminLogin: User %s (account %li) attempted to log into account %li, but was not using a SecureID token", username.c_str(),suid, conn->getRequestedAdminSuid())); + else + { + if (!AdminAccountManager::isInternalIp(conn->getRemoteAddress())) + LOG("CustomerService",("AdminLogin: User %s (account %li) attempted to log into account %li, but was not logging in from an internal IP", username.c_str(),suid, conn->getRequestedAdminSuid())); + else + { + if (!isAdminAccount || adminLevel < 10) + LOG("CustomerService",("AdminLogin: User %s (account %li) attempted to log into account %li, but did not have sufficient permissions", username.c_str(),suid, conn->getRequestedAdminSuid())); + else + { + suid = conn->getRequestedAdminSuid(); + loginOK=true; + } + } + } + + if (!loginOK) + { + conn->disconnect(); + return; + } + } + + // encrypt the clients credentials with the key, return + // the cipher text to the client for use as a connection + // token with the central server + + //Also the sizeof(int) is likewise magic from the session api + size_t len = sizeof(uint32) + sizeof(bool) + MAX_ACCOUNT_NAME_LENGTH + 1; + unsigned char * keyBuffer = new unsigned char[len]; + unsigned char * keyBufferPointer = keyBuffer; + NOT_NULL(keyBuffer); + + IGNORE_RETURN(memset(keyBuffer, 0, len)); + + if (ConfigLoginServer::getDoConsumption() || ConfigLoginServer::getDoSessionLogin()) + { + // pass the sessionkey + len = apiSessionIdWidth + sizeof(StationId); + memcpy(keyBufferPointer, sessionKey, apiSessionIdWidth); + keyBufferPointer += apiSessionIdWidth; + memcpy(keyBufferPointer, &suid, sizeof(StationId)); + + // if LoginServer did session login, send the session key back to the client; + // the client normally gets the session key from the LaunchPad, but in this mode + // where the LoginServer does the session login, it will get it from the LoginServer + if (ConfigLoginServer::getDoSessionLogin()) + { + std::string const strSessionKey(sessionKey, apiSessionIdWidth); + GenericValueTypeMessage const msg("SetSessionKey", strSessionKey); + conn->send(msg, true); + } + } + else + { + // If we aren't validating sessions, pack username, security status, and username to connectionserver + memcpy(keyBufferPointer, &suid, sizeof(uint32)); //lint !e64 !e119 !e534 (lint isn't resolving memcpy properly) + keyBufferPointer += sizeof(uint32); + memcpy(keyBufferPointer, &isSecure, sizeof(bool)); //lint !e64 !e119 !e534 + keyBufferPointer += sizeof(bool); + memcpy(keyBufferPointer, username.c_str(), MAX_ACCOUNT_NAME_LENGTH); //lint !e64 !e119 !e534 + } + + KeyShare::Token token = LoginServer::getInstance().makeToken(keyBuffer, len); + Archive::ByteStream a; + token.pack(a); + + const LoginClientToken k(a.getBuffer(), static_cast(a.getSize()), static_cast(suid), username); + conn->send(k, true); + delete [] keyBuffer; + + // send cluster enum + bool clientInternal = AdminAccountManager::isInternalIp(conn->getRemoteAddress()); + + std::vector data; + + for(ClusterListType::const_iterator j = m_clusterList.begin(); j != m_clusterList.end(); ++j) + { + ClusterListEntry *cle = *j; + if (cle && cle->m_clusterId!=0 && cle->m_clusterName.size()!=0 && (clientInternal || !cle->m_secret)) + { + LoginEnumCluster::ClusterData item; + item.m_clusterId = cle->m_clusterId; + item.m_clusterName = cle->m_clusterName; + item.m_timeZone = cle->m_timeZone; + data.push_back(item); + } + } + + LoginEnumCluster e( data, ConfigLoginServer::getMaxCharactersPerAccount() ); + + conn->send(e,true); + + //Send off list of cluster that has character + //creation disabled, even if the list is empty + //***MUST*** be done after sending LoginEnumCluster + GenericValueTypeMessage > const msgCharacterCreationDisabledClusterList("CharacterCreationDisabled", ConfigLoginServer::getCharacterCreationDisabledClusterList()); + conn->send(msgCharacterCreationDisabledClusterList,true); + + //Send off request for the avatar list from the database. + DatabaseConnection::getInstance().requestAvatarListForAccount(suid, 0); + DEBUG_REPORT_LOG(true, ("Client connected. Station Id: %lu, Username: %s\n", suid, username.c_str())); + LOG("LoginClientConnection", ("onValidateClient() for stationId (%lu) at IP (%s), id (%s), requesting avatar list for account", suid, conn->getRemoteAddress().c_str(), username.c_str())); + + //Set up the connection as being validated with this suid. + conn->setIsValidated(true); + conn->setStationId(suid); + conn->setIsSecure(isSecure); + conn->setAdminLevel(isAdminAccount ? adminLevel : -1); + IGNORE_RETURN(m_validatedClientMap.insert(std::pair(suid, conn))); + + //Must be done after setting various information in the connection object above + sendClusterStatus(*conn); +} + +// ---------------------------------------------------------------------- + +LoginServer::ClusterListEntry *LoginServer::findClusterByName(const std::string &clusterName) +{ + ClusterListType::iterator i; + for (i=m_clusterList.begin(); i!=m_clusterList.end(); ++i) + { + NOT_NULL(*i); // not legal to push null pointers on the vector + if ((*i)->m_clusterName == clusterName) + return *i; + } + return NULL; +} + +// ---------------------------------------------------------------------- + +uint32 LoginServer::getClusterIDByName( const std::string &sName ) +{ + ClusterListEntry const * const p_cluster = findClusterByName( sName ); + return p_cluster ? p_cluster->m_clusterId : 0; +} + +// ---------------------------------------------------------------------- + +const std::string & LoginServer::getClusterNameById( uint32 clusterId ) +{ + static std::string const empty; + + ClusterListEntry const * const cle = findClusterById(clusterId); + if (cle) + return cle->m_clusterName; + + return empty; +} + +// ---------------------------------------------------------------------- + +LoginServer::ClusterListEntry *LoginServer::addCluster(const std::string &clusterName) +{ + DEBUG_FATAL(!ConfigLoginServer::getDevelopmentMode(),("Programmer bug: addCluster(std::string&) can only be used in development mode.\n")); + + ClusterListEntry *e = new ClusterListEntry; + e->m_clusterName = clusterName; + m_clusterList.push_back(e); + return e; +} + +// ---------------------------------------------------------------------- + +void LoginServer::sendExtendedClusterInfo( ClientConnection &client ) const +{ + std::vector data; + + for(ClusterListType::const_iterator j = m_clusterList.begin(); j != m_clusterList.end(); ++j) + { + ClusterListEntry *cle = *j; + + if ( cle ) + { + LoginClusterStatusEx::ClusterData item; + item.m_clusterId = cle->m_clusterId; + item.m_branch = cle->m_branch; + item.m_version = cle->m_changelist; + item.m_networkVersion = cle->m_networkVersion; + data.push_back( item ); + } + + } + + client.send( LoginClusterStatusEx( data ), true ); +} + +// ---------------------------------------------------------------------- + +/** + * Send the list of active clusters to a client. + * Also picks a connection server for the client to use. + * @todo We'd like to resend this to all clients whenever the status + * of any servers changes + */ +void LoginServer::sendClusterStatus(ClientConnection &conn) const +{ + const bool clientIsPrivate = AdminAccountManager::isInternalIp(conn.getRemoteAddress()); + const unsigned int subscriptionBits = conn.getSubscriptionBits(); + const bool isFreeTrialAccount = ( ((subscriptionBits & ClientSubscriptionFeature::FreeTrial) != 0) + && ((subscriptionBits & ClientSubscriptionFeature::Base) == 0)); + + std::vector data; + std::vector dataEx; + + for(ClusterListType::const_iterator j = m_clusterList.begin(); j != m_clusterList.end(); ++j) + { + ClusterListEntry *cle = *j; + // Cluster is OK for login if + // 1) We're connected to Central + // 2) We know the cluster Id + // 3) We have at least one Connection Server + // 4) Client is internal or the cluster is not secret + // 5) Cluster has told us its ready for players + if (cle && cle->m_clusterId!=0 && cle->m_connected && !cle->m_connectionServers.empty() && (clientIsPrivate || !cle->m_secret)) + { + DEBUG_FATAL(!cle->m_centralServerConnection,("Programmer bug: m_connected was true but m_centralServerConnection was NULL\n")); + LoginClusterStatus::ClusterData item; + item.m_clusterId = cle->m_clusterId; + item.m_timeZone = cle->m_timeZone; + +// size_t connectionServerChoice = Random::random(cle->m_connectionServers.size() - 1); //lint !e713 !e732 // loss of precision (arg no 1) + ConnectionServerEntry &connServer = cle->m_connectionServers[0]; + + item.m_connectionServerAddress = connServer.clientServiceAddress; + if(clientIsPrivate) + { + item.m_connectionServerPort = connServer.clientServicePortPrivate; + } + else + { + item.m_connectionServerPort = connServer.clientServicePortPublic; + } + if(item.m_connectionServerPort) + { + item.m_connectionServerPingPort = connServer.pingPort; + + // for security/confidential information issue, only report + // population count to secured internal connections with + // admin privilege >= 10 + if (clientIsPrivate && conn.getIsSecure() && (conn.getAdminLevel() >= 10)) + item.m_populationOnline = cle->m_numPlayers; + else + item.m_populationOnline = -1; + + const int percentFull = cle->m_numPlayers * 100 / cle->m_onlinePlayerLimit; + if (percentFull >= 100) + item.m_populationOnlineStatus = LoginClusterStatus::ClusterData::PS_full; + else if (percentFull >= ConfigLoginServer::getPopulationExtremelyHeavyThresholdPercent()) + item.m_populationOnlineStatus = LoginClusterStatus::ClusterData::PS_extremely_heavy; + else if (percentFull >= ConfigLoginServer::getPopulationVeryHeavyThresholdPercent()) + item.m_populationOnlineStatus = LoginClusterStatus::ClusterData::PS_very_heavy; + else if (percentFull >= ConfigLoginServer::getPopulationHeavyThresholdPercent()) + item.m_populationOnlineStatus = LoginClusterStatus::ClusterData::PS_heavy; + else if (percentFull >= ConfigLoginServer::getPopulationMediumThresholdPercent()) + item.m_populationOnlineStatus = LoginClusterStatus::ClusterData::PS_medium; + else if (percentFull >= ConfigLoginServer::getPopulationLightThresholdPercent()) + item.m_populationOnlineStatus = LoginClusterStatus::ClusterData::PS_light; + else + item.m_populationOnlineStatus = LoginClusterStatus::ClusterData::PS_very_light; + + item.m_maxCharactersPerAccount = cle->m_maxCharactersPerAccount; + if (cle->m_readyForPlayers) + { + item.m_status = LoginClusterStatus::ClusterData::S_up; + if (cle->m_numTutorialPlayers >= cle->m_onlineTutorialLimit) + item.m_status = LoginClusterStatus::ClusterData::S_restricted; + if (isFreeTrialAccount && !cle->m_freeTrialCanCreateChar) + { + item.m_status = LoginClusterStatus::ClusterData::S_restricted; + } + if ((cle->m_numPlayers >= cle->m_onlinePlayerLimit) + || (isFreeTrialAccount && (cle->m_numFreeTrialPlayers >= cle->m_onlineFreeTrialLimit))) + { + item.m_status = LoginClusterStatus::ClusterData::S_full; + } + } + else + item.m_status = LoginClusterStatus::ClusterData::S_loading; + if (cle->m_locked && !clientIsPrivate) + item.m_status = LoginClusterStatus::ClusterData::S_locked; // locked takes precedence over up or loading + + item.m_dontRecommend = (cle->m_notRecommendedDatabase || cle->m_notRecommendedCentral); + item.m_onlinePlayerLimit = cle->m_onlinePlayerLimit; + item.m_onlineFreeTrialLimit = cle->m_onlineFreeTrialLimit; + + data.push_back(item); + } + + ++connServer.numClients; + std::sort(cle->m_connectionServers.begin(), cle->m_connectionServers.end(), ConnectionServerEntryLessThan()); + + } + + if ( cle ) + { + LoginClusterStatusEx::ClusterData itemEx; + itemEx.m_clusterId = cle->m_clusterId; + itemEx.m_branch = cle->m_branch; + itemEx.m_version = cle->m_changelist; + dataEx.push_back( itemEx ); + } + } + + LoginClusterStatus msg(data); + conn.send(msg,true); +} + +// ---------------------------------------------------------------------- + +/** + * Send the list of active clusters to all connected clients. + */ +void LoginServer::sendClusterStatusToAll() const +{ + for (std::map::const_iterator i=m_validatedClientMap.begin(); i!=m_validatedClientMap.end(); ++i) + { + if (i->second) + sendClusterStatus(*(i->second)); + } +} + +// ---------------------------------------------------------------------- + +LoginServer::ClusterListEntry::ClusterListEntry() : + m_clusterId(0), + m_clusterName(), + m_centralServerConnection(0), + m_connectionServers(), + m_numPlayers(0), + m_numFreeTrialPlayers(0), + m_numTutorialPlayers(0), + m_maxCharacters(ConfigLoginServer::getMaxCharactersPerCluster()), + m_maxCharactersPerAccount(0), + m_onlinePlayerLimit(0), + m_onlineFreeTrialLimit(0), + m_onlineTutorialLimit(0), + m_freeTrialCanCreateChar(false), + m_timeZone(0), + m_connected(false), + m_address(""), + m_port(0), + m_allowReconnect(true), + m_secret(false), + m_readyForPlayers(false), + m_locked(false), + m_notRecommendedDatabase(false), + m_notRecommendedCentral(false) +{ +} + +// ---------------------------------------------------------------------- + +/** + * Called as we retrieve clusters from the database. If any of the data + * has changed, disconnect and reconnect. + * If we don't know about the cluster already, add it to the list. + */ +void LoginServer::updateClusterData(uint32 clusterId, const std::string &clusterName, const std::string &address, const uint16 port, bool secret, bool locked, bool notRecommended, int maxCharactersPerAccount, int onlinePlayerLimit, int onlineFreeTrialLimit, bool freeTrialCanCreateChar, int onlineTutorialLimit) +{ + ClusterListEntry *cle = findClusterById(clusterId); + + if (ConfigLoginServer::getDevelopmentMode()) + { + if (!cle) + cle = findClusterByName(clusterName); + } + else + { + if (cle) + { + // refreshing data on a cluster we already know about + if ((cle->m_clusterName != clusterName) || (cle->m_address != address) || (cle->m_port != port)) + { + DEBUG_REPORT_LOG(true,("Disconnecting from cluster %lu because its data has changed in the database.\n",clusterId)); + disconnectCluster(*cle,true,true); + } + } + } + + if (!cle) + { + DEBUG_REPORT_LOG(true,("Cluster %lu: %s\n", clusterId, clusterName.c_str())); + + cle = new ClusterListEntry; + m_clusterList.push_back(cle); + } + + if ((cle->m_secret != secret) + || (cle->m_locked != locked) + || (cle->m_onlinePlayerLimit != onlinePlayerLimit) + || (cle->m_onlineFreeTrialLimit != onlineFreeTrialLimit) + || (cle->m_freeTrialCanCreateChar != freeTrialCanCreateChar) + || (cle->m_onlineTutorialLimit != onlineTutorialLimit)) + { + // The cluster may now be locked/unlocked to some players, so let them know + m_clusterStatusChanged = true; + } + + // tell the cluster if its locked or secret state changes + if (((cle->m_locked != locked) || (cle->m_secret != secret)) && cle->m_connected && cle->m_centralServerConnection) + { + GenericValueTypeMessage > const msgState("UpdateClusterLockedAndSecretState", std::make_pair(locked, secret)); + cle->m_centralServerConnection->send(msgState,true); + } + + bool const clusterIdSet = ((cle->m_clusterId == 0) && (clusterId > 0)); + cle->m_clusterId = clusterId; + cle->m_clusterName = clusterName; + cle->m_address = address; + cle->m_port = port; + cle->m_secret = secret; + cle->m_locked = locked; + cle->m_notRecommendedDatabase = notRecommended; + cle->m_maxCharactersPerAccount = maxCharactersPerAccount; + cle->m_onlinePlayerLimit = onlinePlayerLimit; + cle->m_onlineFreeTrialLimit = onlineFreeTrialLimit; + cle->m_freeTrialCanCreateChar = freeTrialCanCreateChar; + cle->m_onlineTutorialLimit = onlineTutorialLimit; + if (cle->m_centralServerConnection) + { + cle->m_centralServerConnection->setClusterId(clusterId); + + // tell the cluster its cluster id + if (clusterIdSet && ConfigLoginServer::getDevelopmentMode()) + { + GenericValueTypeMessage const msgClusterId("ClusterId", cle->m_clusterId); + cle->m_centralServerConnection->send(msgClusterId, true); + } + } +} + +// ---------------------------------------------------------------------- + +/** + * Remove a connection to a cluster. + * @param cle The ClusterListEntry representing the cluster. + * @param forceDisconnect If true, drops the network connection. If false, assumes + * the network connection has already been closed + * @param reconnect If true, will attempt to reestablish connection to the cluster + * (does not apply in development mode) + */ +void LoginServer::disconnectCluster(ClusterListEntry &cle, bool const forceDisconnect, bool const reconnect) +{ + if (cle.m_centralServerConnection && forceDisconnect) + cle.m_centralServerConnection->disconnect(); + + cle.m_centralServerConnection = 0; //TODO: revisit after connection deletion issues are fixed + cle.m_allowReconnect = reconnect; + cle.m_connectionServers.clear(); + + bool statusChange = false; + + if (cle.m_connected || cle.m_readyForPlayers) + statusChange = true; + + cle.m_connected = false; + cle.m_readyForPlayers = false; + + m_clusterStatusChanged = statusChange; + + // for "carousel" cluster, where multiple clusters point to the same address, + // when disconnecting a "carousel" cluster, need to flag the other "carousel" + // clusters to allow reconnect so that another "carousel" cluster can be + // started, and the LoginServer will connect to it + if (!ConfigLoginServer::getDevelopmentMode() && reconnect) + { + for (ClusterListType::iterator i=m_clusterList.begin(); i!=m_clusterList.end(); ++i) + { + NOT_NULL(*i); + if (!(*i)->m_centralServerConnection && !(*i)->m_allowReconnect && ((*i)->m_address == cle.m_address)) + { + (*i)->m_allowReconnect = true; + } + } + } +} + +// ---------------------------------------------------------------------- + +/** + * Called after we've added a new cluster to the database. + */ +void LoginServer::onClusterRegistered(uint32 clusterId, const std::string &clusterName) +{ + DEBUG_FATAL(!ConfigLoginServer::getDevelopmentMode(),("Programmer bug: should not be registering new clusters automatically unless running in development mode.\n")); + static std::string noAddress(""); + updateClusterData(clusterId, clusterName, noAddress, 0, false, false, false, 8, 100, 100, true, 350); +} + +// ---------------------------------------------------------------------- + +/** + * Find a cluster by ID. + */ + +LoginServer::ClusterListEntry * LoginServer::findClusterById(uint32 clusterId) +{ + ClusterListType::const_iterator i; + for (i=m_clusterList.begin(); i!=m_clusterList.end(); ++i) + { + NOT_NULL(*i); // not legal to push null pointers on the vector + if ((*i)->m_clusterId == clusterId) + return *i; + } + + return NULL; +} + +// ---------------------------------------------------------------------- + +/** + * Find a cluster list entry using the connection to Central + */ + +LoginServer::ClusterListEntry * LoginServer::findClusterByConnection(const CentralServerConnection *connection) +{ + ClusterListType::const_iterator i; + for (i=m_clusterList.begin(); i!=m_clusterList.end(); ++i) + { + NOT_NULL(*i); // not legal to push null pointers on the vector + if ((*i)->m_centralServerConnection == connection) + return *i; + } + + return NULL; +} + +// ---------------------------------------------------------------------- + +void LoginServer::refreshConnections() +{ + if (ConfigLoginServer::getDevelopmentMode()) + return; // in development mode, we don't establish any connections + ClusterListType::iterator i; + for (i=m_clusterList.begin(); i!=m_clusterList.end(); ++i) + { + NOT_NULL(*i); + if (!(*i)->m_centralServerConnection && (*i)->m_allowReconnect) + { + (*i)->m_centralServerConnection = new CentralServerConnection( + (*i)->m_address, + (*i)->m_port, + (*i)->m_clusterName, + (*i)->m_clusterId); + } + } +} + +// ---------------------------------------------------------------------- + +void LoginServer::sendToCluster (uint32 clusterId, const GameNetworkMessage &message) +{ + ClusterListEntry *cle = findClusterById(clusterId); + if (cle && cle->m_connected && cle->m_centralServerConnection) + cle->m_centralServerConnection->send(message,true); + else + DEBUG_REPORT_LOG(true,("Could not send message to cluster %lu because it was not connected.\n",clusterId)); +} + +//----------------------------------------------------------------------- + +void LoginServer::setDone(const bool isDone) +{ + done = isDone; +} + +// ---------------------------------------------------------------------- + +void LoginServer::sendToAllClusters(GameNetworkMessage const & message, Connection const * excludeCentralConnection /*= NULL*/, uint32 excludeClusterId /*= 0*/, char const * excludeClusterName /*= NULL*/) +{ + ClusterListType::const_iterator i; + for (i=m_clusterList.begin(); i!=m_clusterList.end(); ++i) + { + if (NON_NULL(*i)->m_connected && (*i)->m_centralServerConnection && ((*i)->m_centralServerConnection != excludeCentralConnection) && ((*i)->m_clusterId != excludeClusterId) && ((excludeClusterName == NULL) || _stricmp(excludeClusterName, (*i)->m_centralServerConnection->getClusterName().c_str()))) + (*i)->m_centralServerConnection->send(message,true); + } +} + +// ---------------------------------------------------------------------- + +bool LoginServer::areAllClustersUp() const +{ + if (m_clusterList.empty()) + return false; + + ClusterListType::const_iterator i; + for (i=m_clusterList.begin(); i!=m_clusterList.end(); ++i) + { + if (!(NON_NULL(*i)->m_readyForPlayers)) + return false; + } + return true; +} + +// ---------------------------------------------------------------------- + +void LoginServer::getAllClusterNamesAndIDs( std::map< std::string, uint32 > &results ) const +{ + results.clear(); + for (ClusterListType::const_iterator i=m_clusterList.begin(); i!=m_clusterList.end(); ++i) + { + if( !*i ) + continue; + results[ (*i)->m_clusterName ] = (*i)->m_clusterId; + } + +} + +// ---------------------------------------------------------------------- + +void LoginServer::getClusterIds(std::vector result) +{ + result.reserve(m_clusterList.size()); + for (ClusterListType::const_iterator i=m_clusterList.begin(); i!=m_clusterList.end(); ++i) + result.push_back(NON_NULL(*i)->m_clusterId); +} + +// ---------------------------------------------------------------------- + +void LoginServer::setClusterInfoByName( const std::string &name, const std::string &branch, int changelist, const std::string &networkVersion ) +{ + ClusterListEntry *entry = findClusterByName( name ); + + if ( entry ) + { + entry->m_branch = branch; + entry->m_changelist = changelist; + entry->m_networkVersion = networkVersion; + } +} + +// ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/LoginServer.h b/engine/server/application/LoginServer/src/shared/LoginServer.h new file mode 100644 index 00000000..00bc5ffa --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/LoginServer.h @@ -0,0 +1,184 @@ +// LoginServer.h +// copyright 2000 Verant Interactive +// Author: Justin Randall + +#ifndef _LoginServer_H +#define _LoginServer_H + +//----------------------------------------------------------------------- + +#include "Singleton/Singleton.h" +#include "serverNetworkMessages/AvatarList.h" +#include "sharedFoundation/StationId.h" +#include "sharedMessageDispatch/Receiver.h" +#include "sharedNetwork/Service.h" +#include +#include +#include + +#include "serverKeyShare/KeyShare.h" + +class CentralServerConnection; +class ClientConnection; +class CMonitorAPI; +class DeleteCharacterMessage; +class GameNetworkMessage; +class KeyServer; +class ServerConnection; +class Service; +class SessionApiClient; +class TransferAccountData; +class TransferCharacterData; +class TransferRequestMoveValidation; + +//----------------------------------------------------------------------- + +class LoginServer : public Singleton, public MessageDispatch::Receiver +{ +public: + + ~LoginServer (); + int addClient (ClientConnection & client); + ClientConnection* getValidatedClient (const StationId& suid); + ClientConnection* getUnvalidatedClient (int clientId); + void removeClient (int clientId); + + const std::hash_map & getCentralServerMap_hide() const; + + bool deleteCharacter (uint32 clusterId, NetworkId const & characterId, StationId suid); + + const KeyShare::Key & getCurrentKey (void) const; + SessionApiClient* getSessionApiClient (); + KeyShare::Token makeToken (const unsigned char * data, const uint32 dataLen) const; + void pushAllKeys (CentralServerConnection * targetCentralServer) const; + void pushKeyToAllServers (void); + void receiveMessage (const MessageDispatch::Emitter & source, const MessageDispatch::MessageBase & message); + + static void run (void); + void onValidateClient (StationId id, const std::string & username, ClientConnection*,bool, const char*, uint32 gameBits, uint32 subscriptionBits); + + void sendAvatarList (const StationId& stationId, int stationIdNumberJediSlot, const AvatarList &avatars, TransferCharacterData * const); + + void updateClusterData (uint32 clusterId, const std::string &clusterName, const std::string &address, const uint16 port, bool secret, bool locked, bool notRecommended, int maxCharactersPerAccount, int onlinePlayerLimit, int onlineFreeTrialLimit, bool freeTrialCanCreateChar, int onlineTutorialLimit); + void onClusterRegistered (uint32 clusterId, const std::string &clusterName); + void validateAccount (const StationId& stationId, uint32 clusterId, uint32 subscriptionBits, bool canCreateRegular, bool canCreateJedi, bool canSkipTutorial, unsigned int track, std::vector > const & consumedRewardEvents, std::vector > const & claimedRewardItems); + void validateAccountForTransfer(const TransferRequestMoveValidation & request, uint32 clusterId, uint32 sourceCharacterTemplateId, bool canCreateRegular, bool canCreateJedi); + void sendToCluster (uint32 clusterId, const GameNetworkMessage &message); + void sendToAllClusters (GameNetworkMessage const & message, Connection const * excludeCentralConnection = NULL, uint32 excludeClusterId = 0, char const * excludeClusterName = NULL); + bool areAllClustersUp () const; + void getClusterIds (stdvector::fwd result); + void performAccountTransfer (const AvatarList &avatars, TransferAccountData * transferAccountData); + void setDone (const bool isDone); + + void setClusterInfoByName( const std::string &name, const std::string &branch, int changelist, const std::string &networkVersion ); + void sendExtendedClusterInfo( ClientConnection &client ) const; + + void getAllClusterNamesAndIDs( std::map< std::string, uint32 > &results ) const; + uint32 getClusterIDByName( const std::string &sName ); + const std::string & getClusterNameById( uint32 clusterId ); + + struct ConnectionServerEntry + { + std::string clientServiceAddress; + uint16 clientServicePortPrivate; + uint16 clientServicePortPublic; + int id; + uint16 pingPort; + int numClients; + + bool operator==(const ConnectionServerEntry &rhs) const; + }; + + +protected: + friend class Singleton; + LoginServer (); + +private: + + /** + * Data structure to track a cluster. + * This may be only partly filled in if the cluster exists + * but isn't connected. + */ + struct ClusterListEntry + { + uint32 m_clusterId; + std::string m_clusterName; + CentralServerConnection * m_centralServerConnection; + std::vector m_connectionServers; + int m_numPlayers; + int m_numFreeTrialPlayers; + int m_numTutorialPlayers; + int m_maxCharacters; + int m_maxCharactersPerAccount; + int m_onlinePlayerLimit; + int m_onlineFreeTrialLimit; + int m_onlineTutorialLimit; + bool m_freeTrialCanCreateChar; + int m_timeZone; + bool m_connected; + std::string m_address; + uint16 m_port; + bool m_allowReconnect; + bool m_secret; + bool m_readyForPlayers; + bool m_locked; + bool m_notRecommendedDatabase; + bool m_notRecommendedCentral; + std::string m_branch; + int m_changelist; + std::string m_networkVersion; + + ClusterListEntry (); + ClusterListEntry (const ClusterListEntry &rhs); + ClusterListEntry & operator= (const ClusterListEntry &rhs); + }; + + typedef std::vector ClusterListType; + typedef std::map ActiveClientsType; + +private: + void installSessionValidation(); + ClusterListEntry * findClusterById (uint32 clusterId); + ClusterListEntry * findClusterByName (const std::string & clusterName); + ClusterListEntry * findClusterByConnection (const CentralServerConnection *connection); + void sendClusterStatus (ClientConnection &conn) const; + void sendClusterStatusToAll () const; + void refreshConnections (); + ClusterListEntry * addCluster (const std::string &clusterName); + void disconnectCluster (ClusterListEntry &cle, bool forceDisconnect, bool reconnect); + +private: + + + bool done; + Service * m_centralService; + Service * clientService; + Service * pingService; + Service * m_CSService; + KeyServer * keyServer; + ActiveClientsType m_clientMap; + ClusterListType m_clusterList; + SessionApiClient* m_sessionApiClient; + std::map m_validatedClientMap; + bool m_clusterStatusChanged; // true if any cluster has changed status and the list should be resent to all clients + CMonitorAPI * m_soeMonitor; + + +private: + LoginServer (const LoginServer & source); + LoginServer & operator=(const LoginServer & rhs); +}; + +// ====================================================================== + +inline bool LoginServer::ConnectionServerEntry::operator==(const ConnectionServerEntry &rhs) const +{ + return (id == rhs.id); +} + + +// ====================================================================== + +#endif // _LoginServer_H diff --git a/engine/server/application/LoginServer/src/shared/LoginServerRemoteDebugConnection.cpp b/engine/server/application/LoginServer/src/shared/LoginServerRemoteDebugConnection.cpp new file mode 100644 index 00000000..0f782021 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/LoginServerRemoteDebugConnection.cpp @@ -0,0 +1,48 @@ +// ====================================================================== +// +// LoginServerRemoteDebugConnection.cpp +// copyright 2001, Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLoginServer.h" +#include "LoginServerRemoteDebugConnection.h" +#include "sharedDebug/RemoteDebug_inner.h" + +//----------------------------------------------------------------------- + +LoginServerRemoteDebugConnection::LoginServerRemoteDebugConnection(UdpConnectionMT * u, TcpClient * t) : +ServerConnection(u, t) +{ +} + +//----------------------------------------------------------------------- + +LoginServerRemoteDebugConnection::~LoginServerRemoteDebugConnection(void) +{ +} + +//----------------------------------------------------------------------- + +void LoginServerRemoteDebugConnection::onConnectionClosed() +{ + RemoteDebugServer::close(); +} + +//----------------------------------------------------------------------- + +void LoginServerRemoteDebugConnection::onConnectionOpened() +{ + RemoteDebugServer::isReady(); +} + +//----------------------------------------------------------------------- + +void LoginServerRemoteDebugConnection::onReceive(const Archive::ByteStream & message) +{ + Archive::ReadIterator ri = message.begin(); + GameNetworkMessage m(ri); + emitMessage(m); +} + +//----------------------------------------------------------------------- diff --git a/engine/server/application/LoginServer/src/shared/LoginServerRemoteDebugConnection.h b/engine/server/application/LoginServer/src/shared/LoginServerRemoteDebugConnection.h new file mode 100644 index 00000000..f0e111bc --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/LoginServerRemoteDebugConnection.h @@ -0,0 +1,33 @@ +// ====================================================================== +// +// LoginServerRemoteDebugConnection.h +// copyright 2001, Sony Online Entertainment +// +// ====================================================================== + +#ifndef _LoginServerRemoteDebugConnection_H +#define _LoginServerRemoteDebugConnection_H + +//----------------------------------------------------------------------- + +#include "serverUtility/ServerConnection.h" + +//----------------------------------------------------------------------- + +class LoginServerRemoteDebugConnection : public ServerConnection +{ +public: + LoginServerRemoteDebugConnection(UdpConnectionMT *, TcpClient *); + virtual ~LoginServerRemoteDebugConnection(); + void onConnectionClosed (); + void onConnectionOpened (); + void onReceive (const Archive::ByteStream & message); + +private: + LoginServerRemoteDebugConnection(const LoginServerRemoteDebugConnection & source); + LoginServerRemoteDebugConnection & operator = (const LoginServerRemoteDebugConnection & rhs); +}; //lint !e1712 default constructor not defined + +//----------------------------------------------------------------------- + +#endif // _ServerConnectionHandler_H diff --git a/engine/server/application/LoginServer/src/shared/LoginServerRemoteDebugSetup.cpp b/engine/server/application/LoginServer/src/shared/LoginServerRemoteDebugSetup.cpp new file mode 100644 index 00000000..fa78a1c2 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/LoginServerRemoteDebugSetup.cpp @@ -0,0 +1,96 @@ +// ====================================================================== +// +// LoginServerRemoteDebugSetup.cpp +// copyright 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLoginServer.h" +#include "Archive/ByteStream.h" +#include "sharedFoundation/ConfigSharedFoundation.h" +#include "LoginServerRemoteDebugSetup.h" +#include "LoginServerRemoteDebugConnection.h" +#include "sharedDebug/RemoteDebug_inner.h" +#include "sharedNetwork/Connection.h" +#include "sharedNetwork/NetworkSetupData.h" +#include "sharedNetwork/Service.h" + +//static definitions +//Network::Address *LoginServerRemoteDebugSetup::ms_remoteDebugService; +bool LoginServerRemoteDebugSetup::ms_installed; +unsigned int LoginServerRemoteDebugSetup::ms_remoteDebugToolChannelID; +Connection *LoginServerRemoteDebugSetup::ms_connection; +Service *LoginServerRemoteDebugSetup::ms_remoteDebugService; + +void LoginServerRemoteDebugSetup::install(void) +{ + if (ms_installed) + { + //TODO bad + return; + } + + if (!ConfigSharedFoundation::getUseRemoteDebug()) + return; + + NetworkSetupData setup; + setup.port = 4446; + setup.maxConnections = 16; + ms_remoteDebugService = new Service(ConnectionAllocator(), setup); + + RemoteDebugServer::install(remove, open, close, send, 0);//, receive); + ms_installed = true; +} + +void LoginServerRemoteDebugSetup::remove(void) +{ + if (!ms_installed) + { + //TODO bad + return; + } + delete ms_remoteDebugService; + + RemoteDebugServer::remove(); + ms_installed = false; +} + +void LoginServerRemoteDebugSetup::open(const char *, uint16) +{ + DEBUG_WARNING(true, ("not implemented! Fix ME!")); + /* + //TODO config file this? + //attempt to auto-connect to a localhost client app (if it's auto-listening) + if (ms_remoteDebugService->getHostPort()) + Network::connect(ms_connection, "127.0.0.1", port); + else + { + //TODO bad + } + */ +} + +void LoginServerRemoteDebugSetup::close(void) +{ + if (!ms_installed) + { + //TODO bad + return; + } +} + +void LoginServerRemoteDebugSetup::send(void *, uint32) +{ + DEBUG_WARNING(true, ("not implemented! Fix ME!")); + /* + if (!ms_installed) + { + //TODO bad + return; + } + //always send on VNL channel 0, send the buffer, it's length, and reliable=1 + NOT_NULL(ms_connection); + static Archive::ByteStream bs(reinterpret_cast(buffer), bufferLen); + ms_connection->send(bs, true); + */ +}//lint !e818 // parameter bufffer could be declared as pointint to const (but the function prototype beyond this class cannot) diff --git a/engine/server/application/LoginServer/src/shared/LoginServerRemoteDebugSetup.h b/engine/server/application/LoginServer/src/shared/LoginServerRemoteDebugSetup.h new file mode 100644 index 00000000..c5b1fe78 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/LoginServerRemoteDebugSetup.h @@ -0,0 +1,32 @@ +// ====================================================================== +// +// LoginServerRemoteDebugSetup.h +// copyright 2001 Sony Online Entertainment +// +// ====================================================================== + +class Connection; +class LoginServerRemoteDebugConnection; +class Service; + +class LoginServerRemoteDebugSetup +{ +friend class LoginServerRemoteDebugConnection; + +public: + static void install(void); + static void remove(void); + +private: + ///The client-specific network service data instance + ///true if system has been installed, false otherwise + static bool ms_installed; + + static unsigned int ms_remoteDebugToolChannelID; + static Connection * ms_connection; + static Service * ms_remoteDebugService; + static void open(const char *server, uint16 port); + static void close(void); + static void send(void *buffer, uint32 bufferLen); + static void receive(void *buffer, uint32 bufferLen); +}; diff --git a/engine/server/application/LoginServer/src/shared/PingConnection.cpp b/engine/server/application/LoginServer/src/shared/PingConnection.cpp new file mode 100644 index 00000000..afe06c24 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/PingConnection.cpp @@ -0,0 +1,45 @@ +// PingConnection.cpp +// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved. + +//----------------------------------------------------------------------- + +#include "FirstLoginServer.h" +#include "CentralServerConnection.h" +#include "LoginServer.h" +#include "PingConnection.h" +#include "Archive/ByteStream.h" + +//----------------------------------------------------------------------- + +PingConnection::PingConnection(UdpConnectionMT * u, TcpClient * t) : +ServerConnection(u, t) +{ +} + +//----------------------------------------------------------------------- + +PingConnection::~PingConnection() +{ +} + +//----------------------------------------------------------------------- + +void PingConnection::onConnectionOpened() +{ +} + +//----------------------------------------------------------------------- + +void PingConnection::onReceive(const Archive::ByteStream &message ) +{ + Archive::ReadIterator r(message); + GameNetworkMessage g(r); + + if (g.isType("LoginPingMessage")) + { + send(g, true); + } +} + +//----------------------------------------------------------------------- + diff --git a/engine/server/application/LoginServer/src/shared/PingConnection.h b/engine/server/application/LoginServer/src/shared/PingConnection.h new file mode 100644 index 00000000..3fc11309 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/PingConnection.h @@ -0,0 +1,29 @@ +// PingConnection.h +// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved. + +#ifndef _INCLUDED_PingConnection_H +#define _INCLUDED_PingConnection_H + +//----------------------------------------------------------------------- + +#include "serverUtility/ServerConnection.h" + +//----------------------------------------------------------------------- + +class PingConnection : public ServerConnection +{ +public: + PingConnection(UdpConnectionMT *, TcpClient *); + ~PingConnection(); + void onConnectionOpened(); + void onReceive(const Archive::ByteStream & message); + +private: + PingConnection & operator = (const PingConnection & rhs); + PingConnection(const PingConnection & source); + +};//lint !e1712 default constructor not defined + +//----------------------------------------------------------------------- + +#endif // _INCLUDED_PingConnection_H diff --git a/engine/server/application/LoginServer/src/shared/PurgeManager.cpp b/engine/server/application/LoginServer/src/shared/PurgeManager.cpp new file mode 100644 index 00000000..2d649c52 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/PurgeManager.cpp @@ -0,0 +1,385 @@ +// ====================================================================== +// +// PurgeManager.cpp +// copyright (c) 2005 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLoginServer.h" +#include "PurgeManager.h" + +#include "ConfigLoginServer.h" +#include "DatabaseConnection.h" +#include "LoginServer.h" +#include "SessionApiClient.h" +#include "sharedFoundation/Timer.h" +#include "sharedLog/Log.h" +#include "sharedNetworkMessages/GenericValueTypeMessage.h" + +// ====================================================================== + +namespace PurgeManagerNamespace +{ + enum PurgePhase + { + ppNoPurge, ppNotWarned, ppStructureWarningSent, ppStructuresPurged, ppCharacterWarningSent, ppPurged + }; + bool m_gettingAccount=false; + + void removeFromPurgeList(StationId account); + void releaseAccount(StationId account); + PurgePhase getNextPurgePhase(PurgePhase previousPurgePhase); + + class PurgeRecord + { + public: + PurgeRecord(StationId stationId, PurgePhase purgePhase); + StationId getStationId() const; + PurgePhase getPurgePhase() const; + void grabClusterList(); + bool hasCluster(uint32 clusterId) const; + void removeCluster(uint32 clusterId); + bool hasClusters() const; + void advancePurgePhase(); + + private: + StationId m_stationId; + PurgePhase m_purgePhase; + std::set m_clusters; + }; + + typedef std::map PurgeRecordsType; + + PurgeRecordsType m_purgeRecords; + PurgePhase m_currentPurgePhase = ppNotWarned; +} + +using namespace PurgeManagerNamespace; + +// ====================================================================== + +/** + * The PurgeManager picks a purge phase and finds accounts for that phase. + * If no accounts can be found for that phase, it moves on to the next phase. + * Once it has tried all purge phases without finding any accounts, it will + * sleep for a while before starting again. + */ +void PurgeManager::update(float time) +{ + if (!(ConfigLoginServer::getEnableStructurePurge())||(ConfigLoginServer::getEnableCharacterPurge())) + return; + + static Timer retryAccountsTimer(ConfigLoginServer::getPurgeSleepTime()); + + if ((m_currentPurgePhase==ppPurged) || // last purge phase, so wait a while then start over + ((m_currentPurgePhase>=ppStructuresPurged) && (!ConfigLoginServer::getEnableCharacterPurge()))) + { + if (retryAccountsTimer.updateZero(time)) + m_currentPurgePhase=ppNotWarned; + } + else + { + if (LoginServer::getInstance().areAllClustersUp() && (!m_gettingAccount && m_purgeRecords.size() < static_cast(ConfigLoginServer::getMaxSimultaneousPurgeAccounts()))) + { + m_gettingAccount=true; + DatabaseConnection::getInstance().getAccountForPurge(m_currentPurgePhase); + } + } + + if (ConfigLoginServer::getUpdatePurgeAccountListTime() != 0) + { + static Timer updateAccountListTimer(ConfigLoginServer::getUpdatePurgeAccountListTime()); + if (updateAccountListTimer.updateZero(time)) + DatabaseConnection::getInstance().updatePurgeAccountList(); + } +} + +// ---------------------------------------------------------------------- + +void PurgeManager::onGetAccountForPurge(StationId account, int purgePhase) +{ + m_gettingAccount=false; + if (account==0) + { + // No remaining accounts in the DB + m_currentPurgePhase=getNextPurgePhase(m_currentPurgePhase); + } + else + { + if (purgePhase == ppNoPurge) + { + WARNING_DEBUG_FATAL(true,("Programmer bug: onGetAccountForPurge(%i) -- account was in the \"No Purge\" phase. The DB query shouldn't return accounts in this phase.", account)); + return; + } + if (purgePhase == ppPurged) + { + WARNING_DEBUG_FATAL(true,("Programmer bug: onGetAccountForPurge(%i) -- account was in the \"Purged\" phase. The DB query shouldn't return accounts in this phase.", account)); + return; + } + + PurgeRecord record(account, static_cast(purgePhase)); + m_purgeRecords.insert(std::make_pair(account,record)); + + if (ConfigLoginServer::getValidateStationKey()) + NON_NULL(LoginServer::getInstance().getSessionApiClient())->checkStatusForPurge(account); + else + onCheckStatusForPurge(account, false); + } +} + +// ---------------------------------------------------------------------- + +void PurgeManager::onCheckStatusForPurge(StationId account, bool isActive) +{ + DEBUG_REPORT_LOG(true,("onCheckStatusForPurge(%li, %s)\n",account, isActive ? "true" : "false")); + PurgeRecordsType::iterator i=m_purgeRecords.find(account); + if (i==m_purgeRecords.end()) + { + WARNING_DEBUG_FATAL(true,("Programmer bug: onCheckStatusForPurge(%i) -- account was not in m_purgeRecords", account)); + return; + } + PurgeRecord & record = i->second; + + + if (isActive) + { + removeFromPurgeList(account); + } + else + { + if (!LoginServer::getInstance().areAllClustersUp()) + { + // Don't try to process any purges while clusters are down + releaseAccount(account); + return; + } + + switch (record.getPurgePhase()) + { + case ppNoPurge: + WARNING_DEBUG_FATAL(true,("Programmer bug: onCheckStatusForPurge(%i) -- account was in the \"No Purge\" phase.", account)); + break; + case ppNotWarned: + { + LOG("CustomerService",( "Purge: Sending structure purge warning emails for account %i", account)); + //TODO: send to platform somehow for warning emails + record.grabClusterList(); + GenericValueTypeMessage msg("WarnStructuresAboutPurgeMessage",account); + LoginServer::getInstance().sendToAllClusters(msg); + + break; + } + case ppStructureWarningSent: + { + LOG("CustomerService",( "Purge: Starting structure and vendor purge for account %i", account)); + record.grabClusterList(); + GenericValueTypeMessage msg("PurgeStructuresForAccountMessage",account); + LoginServer::getInstance().sendToAllClusters(msg); + break; + } + case ppStructuresPurged: + LOG("CustomerService",( "Purge: Sending character purge warning emails for account %i", account)); + //TODO: send to platform somehow for warning emails + record.advancePurgePhase(); + releaseAccount(record.getStationId()); + break; + case ppCharacterWarningSent: + LOG("CustomerService",( "Purge: Deleting all characters for account %i", account)); + DatabaseConnection::getInstance().deleteAllCharacters(account); + break; + case ppPurged: + WARNING_DEBUG_FATAL(true,("Programmer bug: onCheckStatusForPurge(%i) -- account was in the \"Purged\" phase. This should not be possible.", account)); + break; + default: + WARNING_DEBUG_FATAL(true,("Programmer bug: onCheckStatusForPurge(%i) -- account was in an unhandled purge phase", account)); + } + } +} + +// ---------------------------------------------------------------------- + +void PurgeManagerNamespace::removeFromPurgeList(StationId account) +{ + DatabaseConnection::getInstance().setPurgeStatusAndRelease(account, ppNoPurge); + m_purgeRecords.erase(account); +} + +// ---------------------------------------------------------------------- + +void PurgeManagerNamespace::releaseAccount(StationId account) +{ + PurgeRecordsType::iterator record=m_purgeRecords.find(account); + if (record==m_purgeRecords.end()) + { + WARNING_DEBUG_FATAL(true,("Programmer bug: releaseAccount(%i) -- account was not in m_purgeRecords", account)); + return; + } + + DatabaseConnection::getInstance().setPurgeStatusAndRelease(account, record->second.getPurgePhase()); + m_purgeRecords.erase(record); +} + +// ---------------------------------------------------------------------- + +/** + * The specified cluster is no longer ready for players. Indicates + * a game server crashed or some other problem. Assume any pending purges + * on this cluster did not go through, retry them later. + */ +void PurgeManager::onClusterNoLongerReady(uint32 clusterId) +{ + for (PurgeRecordsType::iterator record=m_purgeRecords.begin(); record!=m_purgeRecords.end(); ) + { + if (record->second.hasCluster(clusterId)) + { + PurgeRecordsType::iterator nextRecord=record; + ++nextRecord; + releaseAccount(record->second.getStationId()); + record=nextRecord; + } + else + ++record; + } +} + +// ---------------------------------------------------------------------- + +/** + * Called when a cluster indicates it has done the purge for a particular + * account and saved the results. + */ +void PurgeManager::handlePurgeCompleteOnCluster(StationId account, uint32 clusterId) +{ + PurgeRecordsType::iterator i=m_purgeRecords.find(account); + if (i==m_purgeRecords.end()) + { + DEBUG_REPORT_LOG(true,("Purge record could not be found in handlePurgeCompleteOnCluster(%li, %li). Probably indicates the cluster and/or the login server were restarted while a purge was in progress. The purge will be retried later.\n",account,clusterId)); + return; + } + + PurgeRecord & record = i->second; + record.removeCluster(clusterId); + if (!record.hasClusters()) + { + // No more clusters remaining. Purge was a success + record.advancePurgePhase(); + releaseAccount(record.getStationId()); + } +} + +// ---------------------------------------------------------------------- + +void PurgeManager::onAllCharactersDeleted(StationId account, bool success) +{ + PurgeRecordsType::iterator i=m_purgeRecords.find(account); + if (i==m_purgeRecords.end()) + { + WARNING_DEBUG_FATAL(true,("Programmer bug: onAllCharactersDeleted(%li) called with an account that wasn't in m_purgeRecords",account)); + return; + } + + PurgeRecord & record = i->second; + if (record.getPurgePhase()!=ppCharacterWarningSent) + { + WARNING_DEBUG_FATAL(true,("Programmer bug: onAllCharactersDeleted(%li) called with an account that wasn't in the ppCharacterWarningSent phase",account)); + releaseAccount(record.getStationId()); + return; + } + + if (success) + record.advancePurgePhase(); + + releaseAccount(record.getStationId()); +} + +// ---------------------------------------------------------------------- + +PurgePhase PurgeManagerNamespace::getNextPurgePhase(PurgePhase previousPurgePhase) +{ + switch (previousPurgePhase) + { + case ppNoPurge: + return ppNoPurge; + case ppNotWarned: + return ppStructureWarningSent; + break; + case ppStructureWarningSent: + return ppStructuresPurged; + break; + case ppStructuresPurged: + return ppCharacterWarningSent; + break; + case ppCharacterWarningSent: + return ppPurged; + break; + case ppPurged: + return ppPurged; + default: + // This needs to FATAL, not WARN, because if the purge phase is fried it might mean we're going to purge accounts that aren't in the right phase + FATAL(true,("Programmer bug: getNextPurgePhase called with invalid purge phase %i",static_cast(previousPurgePhase))); + return ppNoPurge; + } +} + +// ====================================================================== + +PurgeRecord::PurgeRecord(StationId stationId, PurgePhase purgePhase) : + m_stationId(stationId), + m_purgePhase(purgePhase) +{ +} +// ---------------------------------------------------------------------- + +StationId PurgeRecord::getStationId() const +{ + return m_stationId; +} + +// ---------------------------------------------------------------------- + +PurgePhase PurgeRecord::getPurgePhase() const +{ + return m_purgePhase; +} + +// ---------------------------------------------------------------------- + +void PurgeRecord::grabClusterList() +{ + std::vector clusterList; + LoginServer::getInstance().getClusterIds(clusterList); + m_clusters.insert(clusterList.begin(), clusterList.end()); +} + +// ---------------------------------------------------------------------- + +bool PurgeRecord::hasCluster(uint32 clusterId) const +{ + return (m_clusters.find(clusterId)!=m_clusters.end()); +} + +// ---------------------------------------------------------------------- + +void PurgeRecord::removeCluster(uint32 clusterId) +{ + m_clusters.erase(clusterId); +} + +// ---------------------------------------------------------------------- + +bool PurgeRecord::hasClusters() const +{ + return (!m_clusters.empty()); +} + +// ---------------------------------------------------------------------- + +/** + * Move to the next phase in the purge sequence. + */ +void PurgeRecord::advancePurgePhase() +{ + m_purgePhase=getNextPurgePhase(m_purgePhase); +} + +// ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/PurgeManager.h b/engine/server/application/LoginServer/src/shared/PurgeManager.h new file mode 100644 index 00000000..7c684a07 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/PurgeManager.h @@ -0,0 +1,26 @@ +// ====================================================================== +// +// PurgeManager.h +// copyright (c) 2005 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_PurgeManager_H +#define INCLUDED_PurgeManager_H + +// ====================================================================== + +class PurgeManager +{ + public: + static void update(float time); + static void onCheckStatusForPurge(StationId account, bool isActive); + static void onGetAccountForPurge(StationId account, int purgePhase); + static void onClusterNoLongerReady(uint32 clusterId); + static void handlePurgeCompleteOnCluster(StationId account, uint32 clusterId); + static void onAllCharactersDeleted(StationId account, bool success); +}; + +// ====================================================================== + +#endif diff --git a/engine/server/application/LoginServer/src/shared/SessionApiClient.cpp b/engine/server/application/LoginServer/src/shared/SessionApiClient.cpp new file mode 100644 index 00000000..f130d691 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/SessionApiClient.cpp @@ -0,0 +1,456 @@ +// SessionApiClient.cpp +// copyright 2002 Sony Online Entertainment + + +#include "FirstLoginServer.h" +#include "SessionApiClient.h" + +#include "ClientConnection.h" +#include "ConfigLoginServer.h" +#include "CSToolConnection.h" +#include "DatabaseConnection.h" +#include "LoginServer.h" +#include "PurgeManager.h" +#include "serverNetworkMessages/ClaimRewardsMessage.h" +#include "serverNetworkMessages/ClaimRewardsReplyMessage.h" +#include "Session/CommonAPI/CommonAPIStrings.h" +#include "sharedGame/PlatformFeatureBits.h" +#include "sharedLog/Log.h" +#include "sharedNetworkMessages/ErrorMessage.h" +#include "sharedSynchronization/Mutex.h" + +#include + +//------------------------------------------------------------------------------------------ + +std::map SessionApiClient::m_validationMap; + +//------------------------------------------------------------------------------------------ + +namespace SessionApiClientNamespace +{ + std::map > ms_modifyFeatureTrackingNumberMap; +}; + +using namespace SessionApiClientNamespace; + +//------------------------------------------------------------ + +SessionApiClient::SessionApiClient(const char ** serverList, int serverCount) : + Client(serverList, static_cast(serverCount), "Starwars Login Server") +{ +} + +//------------------------------------------------------------ + +SessionApiClient::~SessionApiClient() +{ +} + +//------------------------------------------------------------ + +void SessionApiClient::OnSessionLogin(const apiTrackingNumber trackingNumber, + const apiResult result, + const apiAccount & account, + const apiSubscription & subscription, + const apiSession & session, + const LoginAPI::UsageLimit & usageLimit, + const LoginAPI::Entitlement & entitlement, + void * userData) +{ + OnSessionValidate(trackingNumber, result, account, subscription, session, usageLimit, entitlement, userData); + + +} + +//--------------------------------------------------------------------- + +void SessionApiClient::OnSessionLoginInternal(const apiTrackingNumber trackingNumber, + const apiResult result, + const apiAccount & account, + const apiSubscription & subscription, + const apiSession & session, + const LoginAPI::UsageLimit & usageLimit, + const LoginAPI::Entitlement & entitlement, + void * userData) +{ + UNREF(trackingNumber); + UNREF(result); + UNREF(account); + UNREF(subscription); + UNREF(session); + UNREF(usageLimit); + UNREF(entitlement); + UNREF(userData); +// DEBUG_REPORT_LOG(true, ("Session login internal.\n")); +} + +//--------------------------------------------------------------------- +void SessionApiClient::OnSessionValidate(const apiTrackingNumber trackingNumber, + const apiResult result, + const apiAccount & account, + const apiSubscription & subscription, + const apiSession & session, + const LoginAPI::UsageLimit & usageLimit, + const LoginAPI::Entitlement & entitlement, + void * userData) +{ + UNREF(usageLimit); + UNREF(userData); + + std::map::iterator i = m_validationMap.find(trackingNumber); + DEBUG_REPORT_LOG(true, ("OnSessionValidate result: %d for suid: %d (entitlement total: %u/%u, since last login: %u/%u, reason unentitled: %d)\n", result, account.GetId(), entitlement.GetEntitledTime(), entitlement.GetTotalTime(), entitlement.GetEntitledTimeSinceLastLogin(), entitlement.GetTotalTimeSinceLastLogin(), static_cast(entitlement.GetReasonUnentitled()))); + + if (i != m_validationMap.end()) + { + if (result == RESULT_SUCCESS) + { + LOG("LoginClientConnection", ("OnSessionValidate() for stationId (%u) at IP (%s), id (%s), apiTrackingNumber (%u), SUCCESS", account.GetId(), i->second->getRemoteAddress().c_str(), account.GetName(), trackingNumber)); + LoginServer::getInstance().onValidateClient(account.GetId(), account.GetName(), i->second, session.GetIsSecure(), session.GetId(), subscription.GetGameFeatures(), subscription.GetSubscriptionFeatures()); + m_validationMap.erase(i); + } + else + { + LOG("LoginClientConnection", ("OnSessionValidate() for stationId (%u) at IP (%s), id (%s), apiTrackingNumber (%u), VALIDATION FAILED (%u)", account.GetId(), i->second->getRemoteAddress().c_str(), account.GetName(), trackingNumber, result)); + ErrorMessage err("VALIDATION FAILED", "Your station Id was not valid. Wrong password? Account closed?"); + i->second->send(err, true); + i->second->disconnect(); + } + } + else + { + // attempt to validate a CS Tool associated with this request. + CSToolConnection::validateCSTool( ( uint32 )userData, result, session ); + } + +} + +//--------------------------------------------------------------------- + +void SessionApiClient::OnSessionConsume(const apiTrackingNumber trackingNumber, + const apiResult result, + const apiAccount & account, + const apiSubscription & subscription, + const apiSession & session, + const LoginAPI::UsageLimit & usageLimit, + const LoginAPI::Entitlement & entitlement, + void * userData) +{ + UNREF(trackingNumber); + UNREF(result); + UNREF(account); + UNREF(subscription); + UNREF(session); + UNREF(usageLimit); + UNREF(entitlement); + UNREF(userData); +// DEBUG_REPORT_LOG(true, ("Session consume.\n")); +} + +//--------------------------------------------------------------------- + +void SessionApiClient::OnSessionStartPlay(const apiTrackingNumber trackingNumber, + const apiResult result, + void * userData) +{ + UNREF(trackingNumber); + UNREF(result); + UNREF(userData); +// DEBUG_REPORT_LOG(true, ("Session start play.\n")); +} + +//--------------------------------------------------------------------- + +void SessionApiClient::OnSessionStopPlay(const apiTrackingNumber trackingNumber, + const apiResult result, + void * userData) +{ + UNREF(trackingNumber); + UNREF(result); + UNREF(userData); +// DEBUG_REPORT_LOG(true, ("Session stop play.\n")); +} + +//--------------------------------------------------------------------- + +void SessionApiClient::OnSessionKick(const apiTrackingNumber trackingNumber, + const apiResult result, + void * userData) +{ + UNREF(trackingNumber); + UNREF(result); + UNREF(userData); +// DEBUG_REPORT_LOG(true, ("Session kick.\n")); +} + +//--------------------------------------------------------------------- + +void SessionApiClient::OnGetSessions(const apiTrackingNumber trackingNumber, + const apiResult result, + const unsigned count, + const apiSession session[], + const apiSubscription subscription[], + const LoginAPI::UsageLimit usageLimit[], + const unsigned timeCreated[], + const unsigned timeTouched[], + void * userData) +{ + UNREF(trackingNumber); + UNREF(result); + UNREF(count); + UNREF(session); + UNREF(subscription); + UNREF(usageLimit); + UNREF(timeCreated); + UNREF(timeTouched); + UNREF(userData); +// DEBUG_REPORT_LOG(true, ("Get sessions.\n")); +} + +//------------------------------------------------------------ + +void SessionApiClient::OnGetFeatures(const apiTrackingNumber trackingNumber, + const apiResult result, + const unsigned featureCount, + const LoginAPI::Feature featureArray[], + const void * userData) +{ + UNREF(trackingNumber); + UNREF(result); + UNREF(featureCount); + UNREF(featureArray); + UNREF(userData); +// DEBUG_REPORT_LOG(true, ("Get features.\n")); +} + +//------------------------------------------------------------ + +void SessionApiClient::OnGrantFeature(const apiTrackingNumber trackingNumber, + const apiResult result, + void * userData) +{ + UNREF(trackingNumber); + UNREF(result); + UNREF(userData); +// DEBUG_REPORT_LOG(true, ("Grant feature.\n")); +} + +//------------------------------------------------------------ + +void SessionApiClient::OnModifyFeature(const apiTrackingNumber trackingNumber, + const apiResult result, + void * userData) +{ + UNREF(trackingNumber); + UNREF(result); + UNREF(userData); +// DEBUG_REPORT_LOG(true, ("Modify feature.\n")); +} + +//------------------------------------------------------------ + +void SessionApiClient::OnModifyFeature_v2(const apiTrackingNumber trackingNumber, + const apiResult result, + const LoginAPI::Feature & currentFeature, + void * userData) +{ + UNREF(currentFeature); + UNREF(userData); + + std::map >::iterator i = ms_modifyFeatureTrackingNumberMap.find(trackingNumber); + if (i != ms_modifyFeatureTrackingNumberMap.end()) + { + if (result != RESULT_SUCCESS) + { + // if failed to update feature id, send failure message + LOG("CustomerService",("VeteranRewards: received non-success result code (%u) from session to adjust feature id %lu (%s -> %s) for account (%lu), character (%s), reward event (%s), reward item (%s), session tracking number (%u)", result, i->second.second->getAccountFeatureId(), i->second.second->getAccountFeatureIdOldValue().c_str(), i->second.second->getAccountFeatureIdNewValue().c_str(), i->second.second->getStationId(), i->second.second->getPlayer().getValueString().c_str(), i->second.second->getRewardEvent().c_str(), i->second.second->getRewardItem().c_str(), trackingNumber)); + + ClaimRewardsReplyMessage const rsp(i->second.second->getGameServer(), i->second.second->getStationId(), i->second.second->getPlayer(), i->second.second->getRewardEvent(), i->second.second->getRewardItem(), i->second.second->getAccountFeatureId(), true, 0, 0, false); + LoginServer::getInstance().sendToCluster(i->second.first, rsp); + } + else + { + // if feature id updated successfully, record transaction + LoginAPI::Feature oldFeature; + oldFeature.SetID(i->second.second->getAccountFeatureId()); + oldFeature.SetData(i->second.second->getAccountFeatureIdOldValue()); + + LoginAPI::Feature newFeature; + newFeature.SetID(i->second.second->getAccountFeatureId()); + newFeature.SetData(i->second.second->getAccountFeatureIdNewValue()); + + DatabaseConnection::getInstance().claimRewards(i->second.first, i->second.second->getGameServer(), i->second.second->getStationId(), i->second.second->getPlayer(), i->second.second->getRewardEvent(), i->second.second->getConsumeEvent(), i->second.second->getRewardItem(), i->second.second->getConsumeItem(), i->second.second->getAccountFeatureId(), true, oldFeature.GetConsumeCount(), newFeature.GetConsumeCount()); + } + + delete i->second.second; + ms_modifyFeatureTrackingNumberMap.erase(i); + } +} + +//------------------------------------------------------------ + +void SessionApiClient::OnRevokeFeature(const apiTrackingNumber trackingNumber, + const apiResult result, + void * userData) +{ + UNREF(trackingNumber); + UNREF(result); + UNREF(userData); +// DEBUG_REPORT_LOG(true, ("Revoke feature.\n")); +} + +//------------------------------------------------------------ + +void SessionApiClient::OnEnumerateFeatures(const apiTrackingNumber trackingNumber, + const apiResult result, + const unsigned featureCount, + const LoginAPI::FeatureDescription featureArray[], + const void * userData) +{ + UNREF(trackingNumber); + UNREF(result); + UNREF(featureCount); + UNREF(featureArray); + UNREF(userData); +// DEBUG_REPORT_LOG(true, ("Enumerate features.\n")); +} + +//------------------------------------------------------------ + +void SessionApiClient::handleClaimRewardsMessage(uint32 clusterId, ClaimRewardsMessage const * msg) +{ + UNREF(AccountStatusString); + UNREF(SessionTypeString); + UNREF(GamecodeString); + UNREF(SubscriptionStatusString); + + if (!msg) + return; + + LoginAPI::Feature oldFeature; + oldFeature.SetID(msg->getAccountFeatureId()); + oldFeature.SetData(msg->getAccountFeatureIdOldValue()); + + LoginAPI::Feature newFeature; + newFeature.SetID(msg->getAccountFeatureId()); + newFeature.SetData(msg->getAccountFeatureIdNewValue()); + + apiTrackingNumber const tn = ModifyFeature_v2(msg->getStationId(), PlatformGameCode::getGamecodeName(PlatformGameCode::SWG).c_str(), oldFeature, newFeature); + LOG("CustomerService",("VeteranRewards: requesting session to adjust feature id %lu (%s -> %s) for account (%lu), character (%s), reward event (%s), reward item (%s), session tracking number (%u)", msg->getAccountFeatureId(), msg->getAccountFeatureIdOldValue().c_str(), msg->getAccountFeatureIdNewValue().c_str(), msg->getStationId(), msg->getPlayer().getValueString().c_str(), msg->getRewardEvent().c_str(), msg->getRewardItem().c_str(), tn)); + ms_modifyFeatureTrackingNumberMap[tn] = std::make_pair(clusterId, msg); +} + +//------------------------------------------------------------ + +void SessionApiClient::dropClient(const ClientConnection* client) const +{ + std::map::iterator i = m_validationMap.begin(); + for (;i != m_validationMap.end(); ++i) + { + if (i->second == client) + { + m_validationMap.erase(i); + break; + } + } + +} + +//------------------------------------------------------------ + +void SessionApiClient::validateClient (ClientConnection* client, const std::string & key) +{ + + //Key will be the real session key + //We will only use id if we aren't validating. + //The key will provide a username and an id from the station. + + //We call SessionValidate(key, type) on the Session client + //It will callback with OnSessionValidate(trackingNumber, result, account, subscription, userdata); + + //type will be ConfigLoginServer::getSessionType() + //result is hopefully RESULT_SUCCESS + //acount is struct (name, id, status) where status is ACCOUNT_STATUS_ACTIVE and id is unsigned + //subscription is hopefully SUBSCRIPTION_STATUS_ACTIVE could be trial + //user data is a void* and I think un-used. + + //Then store the client in a map based on the key. + + apiTrackingNumber track = SessionValidate(key.c_str(), static_cast(ConfigLoginServer::getSessionType())); + //apiTrackingNumber track = SessionConsume(key.c_str(), static_cast(ConfigLoginServer::getSessionType())); + + LOG("LoginClientConnection", ("validateClient() for stationId (%lu) at IP (%s), key (%s), apiTrackingNumber (%u), validating session", client->getStationId(), client->getRemoteAddress().c_str(), key.c_str(), track)); + + //Ok to overwrite old or add new here. + m_validationMap[track] = client; +} + +//------------------------------------------------------------ + +void SessionApiClient::loginClient (ClientConnection* client, const std::string& username, const std::string & password) +{ + apiTrackingNumber track = SessionLogin(username.c_str(), password.c_str(), static_cast(ConfigLoginServer::getSessionType()), 0, 0); + + LOG("LoginClientConnection", ("loginClient() for stationId (%lu) at IP (%s), key (%s), apiTrackingNumber (%u), validating session", client->getStationId(), client->getRemoteAddress().c_str(), password.c_str(), track)); + + //Ok to overwrite old or add new here. + m_validationMap[track] = client; +} + +//------------------------------------------------------------ +void SessionApiClient::OnConnectionOpened(const char * address, unsigned port) +{ + UNREF(address); + UNREF(port); +// DEBUG_REPORT_LOG(true, ("Connection success\n")); +} +void SessionApiClient::OnConnectionClosed(const char * address, unsigned port) +{ + UNREF(address); + UNREF(port); +// DEBUG_REPORT_LOG(true, ("Connection closed.\n")); +} +void SessionApiClient::OnConnectionFailed(const char * address, unsigned port) +{ + UNREF(address); + UNREF(port); +// DEBUG_FATAL(true, ("Connection failed")); +} +void SessionApiClient::OnException() +{ +// DEBUG_REPORT_LOG(true, ("Connection exception.\n")); +} + +//------------------------------------------------------------------------------------------ + +void SessionApiClient::NotifySessionKick(const char ** sessionList, + const unsigned sessionCount) +{ + UNREF(sessionList); + UNREF(sessionCount); +// DEBUG_REPORT_LOG(true, ("Session kick.\n")); +} + +// ---------------------------------------------------------------------- + +void SessionApiClient::checkStatusForPurge(StationId account) +{ + GetAccountSubscription(account, PlatformGameCode::SWG, NULL); +} + +//------------------------------------------------------------------------------------------ + +void SessionApiClient::OnGetAccountSubscription(const apiTrackingNumber trackingNumber, + const apiResult result, + const apiAccount & account, + const apiSubscription & subscription, + void * userData) +{ + // This assumes that the only reason this would be called would be to check the status + // for the purge process. If something else ever uses getAccountSubscription, this will + // need to be changed. + if (result==RESULT_SUCCESS) + PurgeManager::onCheckStatusForPurge(account.GetId(), (account.GetStatus()==ACCOUNT_STATUS_ACTIVE)); +} + +// ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/SessionApiClient.h b/engine/server/application/LoginServer/src/shared/SessionApiClient.h new file mode 100644 index 00000000..00c38278 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/SessionApiClient.h @@ -0,0 +1,136 @@ +// SessionApiClient.h +// copyright 2002 Sony Online Entertainment + +#ifndef _SessionApiClient_H +#define _SessionApiClient_H + +#include +#include "Session/LoginAPI/Client.h" + +class ClaimRewardsMessage; +class ClientConnection; + +class SessionApiClient : public LoginAPI::Client +{ +public: + + SessionApiClient(const char ** serverList, int serverCount); + ~SessionApiClient(); + + virtual void OnSessionLogin(const apiTrackingNumber trackingNumber, + const apiResult result, + const apiAccount & account, + const apiSubscription & subscription, + const apiSession & session, + const LoginAPI::UsageLimit & usageLimit, + const LoginAPI::Entitlement & entitlement, + void * userData); + + virtual void OnSessionLoginInternal(const apiTrackingNumber trackingNumber, + const apiResult result, + const apiAccount & account, + const apiSubscription & subscription, + const apiSession & session, + const LoginAPI::UsageLimit & usageLimit, + const LoginAPI::Entitlement & entitlement, + void * userData); + + virtual void OnSessionValidate(const apiTrackingNumber trackingNumber, + const apiResult result, + const apiAccount & account, + const apiSubscription & subscription, + const apiSession & session, + const LoginAPI::UsageLimit & usageLimit, + const LoginAPI::Entitlement & entitlement, + void * userData); + + virtual void OnSessionConsume(const apiTrackingNumber trackingNumber, + const apiResult result, + const apiAccount & account, + const apiSubscription & subscription, + const apiSession & session, + const LoginAPI::UsageLimit & usageLimit, + const LoginAPI::Entitlement & entitlement, + void * userData); + + virtual void OnSessionStartPlay(const apiTrackingNumber trackingNumber, + const apiResult result, + void * userData); + + virtual void OnSessionStopPlay(const apiTrackingNumber trackingNumber, + const apiResult result, + void * userData); + + virtual void OnSessionKick(const unsigned trackingNumber, + const apiResult result, + void * userData); + + virtual void OnGetSessions(const apiTrackingNumber trackingNumber, + const apiResult result, + const unsigned count, + const apiSession session[], + const apiSubscription subscription[], + const LoginAPI::UsageLimit usageLimit[], + const unsigned timeCreated[], + const unsigned timeTouched[], + void * userData); + + virtual void OnGetFeatures(const apiTrackingNumber trackingNumber, + const apiResult result, + const unsigned featureCount, + const LoginAPI::Feature featureArray[], + const void * userData = 0); + + virtual void OnGrantFeature(const apiTrackingNumber trackingNumber, + const apiResult result, + void * userData); + + virtual void OnModifyFeature(const apiTrackingNumber trackingNumber, + const apiResult result, + void * userData); + + virtual void OnModifyFeature_v2(const apiTrackingNumber trackingNumber, + const apiResult result, + const LoginAPI::Feature & currentFeature, + void * userData); + + virtual void OnRevokeFeature(const apiTrackingNumber trackingNumber, + const apiResult result, + void * userData); + + virtual void OnEnumerateFeatures(const apiTrackingNumber trackingNumber, + const apiResult result, + const unsigned featureCount, + const LoginAPI::FeatureDescription featureArray[], + const void * userData = 0); + + virtual void OnGetAccountSubscription(const apiTrackingNumber trackingNumber, + const apiResult result, + const apiAccount & account, + const apiSubscription & subscription, + void * userData); + + virtual void OnConnectionOpened(const char * address, unsigned port); + virtual void OnConnectionClosed(const char * address, unsigned port); + virtual void OnConnectionFailed(const char * address, unsigned port); + virtual void OnException(); + + virtual void NotifySessionKick(const char ** sessionList, + const unsigned sessionCount); + + void handleClaimRewardsMessage(uint32 clusterId, ClaimRewardsMessage const * msg); + void dropClient(const ClientConnection* client) const; + void validateClient (ClientConnection* client, const std::string & key); + void loginClient(ClientConnection* client, const std::string & username, const std::string & password); + void checkStatusForPurge (StationId account); + + static void FlushSessionQueue(); + +private: + + static std::map m_validationMap; + SessionApiClient(); +}; + + +#endif diff --git a/engine/server/application/LoginServer/src/shared/TaskChangeStationId.cpp b/engine/server/application/LoginServer/src/shared/TaskChangeStationId.cpp new file mode 100644 index 00000000..e466d630 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskChangeStationId.cpp @@ -0,0 +1,113 @@ +// ====================================================================== +// +// TaskChangeStationId.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLoginServer.h" +#include "TaskChangeStationId.h" + +#include "CentralServerConnection.h" +#include "DatabaseConnection.h" +#include "sharedLog/Log.h" +#include "serverNetworkMessages/TransferAccountData.h" +#include "serverNetworkMessages/TransferAccountDataArchive.h" +#include "sharedDatabaseInterface/DbSession.h" +#include "sharedNetworkMessages/GenericValueTypeMessage.h" + +// ====================================================================== + +TaskChangeStationId::TaskChangeStationId(StationId sourceStationId, StationId destinationStationId, const TransferAccountData *requestData) : + TaskRequest(), + m_sourceStationId(sourceStationId), + m_destinationStationId(destinationStationId), + m_requestData(0), + m_success(false) +{ + if(requestData) + { + m_requestData = new TransferAccountData(*requestData); + } +} + +// ---------------------------------------------------------------------- + +TaskChangeStationId::~TaskChangeStationId() +{ + delete m_requestData; + m_requestData = 0; +} + +// ---------------------------------------------------------------------- + +bool TaskChangeStationId::process(DB::Session *session) +{ + ChangeStationIdQuery qry; + qry.source_station_id = m_sourceStationId; + qry.destination_station_id = m_destinationStationId; + + m_success = session->exec(&qry); + + qry.done(); + return m_success; +} + +// ---------------------------------------------------------------------- + +void TaskChangeStationId::onComplete() +{ + // part of account to account move request for character transfer system + LOG("CustomerService", ("CharacterTransfer: Completed database change for account transfer from %lu to %lu: sending reply back to transfer server on %s", m_sourceStationId, m_destinationStationId, m_requestData->getStartGalaxy().c_str())); + const GenericValueTypeMessage response("TransferAccountReplySuccessTransferServer", *m_requestData); + CentralServerConnection::sendToCentralServer(m_requestData->getStartGalaxy(), response); +} + +// ====================================================================== + +TaskChangeStationId::ChangeStationIdQuery::ChangeStationIdQuery() : + Query(), + destination_station_id(0), + source_station_id(0) +{ +} + +// ---------------------------------------------------------------------- + +void TaskChangeStationId::ChangeStationIdQuery::getSQL(std::string &sql) +{ + sql = + std::string("begin ")+ + DatabaseConnection::getInstance().getSchemaQualifier()+"\n\ + Update swg_characters Set station_id = :destination_station_id Where station_id = :source_station_id;\n\ + Update account_reward_events Set station_id = :destination_station_id Where station_id = :source_station_id;\n\ + Update account_reward_items Set station_id = :destination_station_id Where station_id = :source_station_id;\n\ + end;"; + +// DEBUG_REPORT_LOG(true, ("TaskChangeStationId SQL: %s\n", sql.c_str())); +} + +// ---------------------------------------------------------------------- + +bool TaskChangeStationId::ChangeStationIdQuery::bindParameters() +{ + if (!bindParameter(destination_station_id)) return false; + if (!bindParameter(source_station_id)) return false; + return true; +} + +// ---------------------------------------------------------------------- + +bool TaskChangeStationId::ChangeStationIdQuery::bindColumns() +{ + return true; +} + +// ---------------------------------------------------------------------- + +DB::Query::QueryMode TaskChangeStationId::ChangeStationIdQuery::getExecutionMode() const +{ + return MODE_PROCEXEC; +} + +// ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/TaskChangeStationId.h b/engine/server/application/LoginServer/src/shared/TaskChangeStationId.h new file mode 100644 index 00000000..6ed1dad4 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskChangeStationId.h @@ -0,0 +1,61 @@ +// ====================================================================== +// +// TaskChangeStationId.h +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_TaskChangeStationId_H +#define INCLUDED_TaskChangeStationId_H + +// ====================================================================== + +#include "sharedDatabaseInterface/Bindable.h" +#include "sharedDatabaseInterface/BindableNetworkId.h" +#include "sharedDatabaseInterface/DbQuery.h" +#include "sharedDatabaseInterface/DbTaskRequest.h" +#include "sharedFoundation/StationId.h" + +class TransferAccountData; + +// ====================================================================== + +class TaskChangeStationId : public DB::TaskRequest +{ + public: + TaskChangeStationId(StationId sourceStationId, StationId destinationStationId, const TransferAccountData * requestData); + ~TaskChangeStationId(); + public: + virtual bool process (DB::Session *session); + virtual void onComplete (); + + private: + TaskChangeStationId(); // disabled default constructor + class ChangeStationIdQuery : public DB::Query + { + public: + ChangeStationIdQuery(); + + DB::BindableLong destination_station_id; //lint !e1925 // public data member + DB::BindableLong source_station_id; //lint !e1925 // public data member + + virtual void getSQL (std::string &sql); + virtual bool bindParameters (); + virtual bool bindColumns (); + virtual QueryMode getExecutionMode () const; + + private: //disable + ChangeStationIdQuery (const ChangeStationIdQuery&); + ChangeStationIdQuery &operator= (const ChangeStationIdQuery&); + }; + + private: + StationId m_sourceStationId; + StationId m_destinationStationId; + TransferAccountData *m_requestData; + bool m_success; +}; + +// ====================================================================== + +#endif diff --git a/engine/server/application/LoginServer/src/shared/TaskClaimRewards.cpp b/engine/server/application/LoginServer/src/shared/TaskClaimRewards.cpp new file mode 100644 index 00000000..ef741b01 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskClaimRewards.cpp @@ -0,0 +1,485 @@ +// ====================================================================== +// +// TaskClaimRewards.cpp +// copyright (c) 2004 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLoginServer.h" +#include "TaskClaimRewards.h" + +#include "DatabaseConnection.h" +#include "serverNetworkMessages/ClaimRewardsReplyMessage.h" +#include "serverNetworkMessages/FeatureIdTransactionResponse.h" +#include "sharedDatabaseInterface/Bindable.h" +#include "sharedDatabaseInterface/BindableNetworkId.h" +#include "sharedDatabaseInterface/DbQuery.h" +#include "sharedDatabaseInterface/DbSession.h" + +// ====================================================================== + +namespace TaskClaimRewardsNamespace +{ + class ConsumeEventQuery : public DB::Query + { + public: + ConsumeEventQuery(StationId stationId, NetworkId const & characterId, uint32 clusterId, std::string const & eventId); + + virtual void getSQL(std::string &sql); + virtual bool bindParameters(); + virtual bool bindColumns(); + virtual QueryMode getExecutionMode() const; + + bool getResult() const; + + private: + DB::BindableLong station_id; + DB::BindableNetworkId character_id; + DB::BindableLong cluster_id; + DB::BindableString<255> event_id; + DB::BindableLong result; + + private: //disable + ConsumeEventQuery(); + ConsumeEventQuery(const ConsumeEventQuery&); + ConsumeEventQuery &operator=(const ConsumeEventQuery&); + }; + + class ClaimItemQuery : public DB::Query + { + public: + ClaimItemQuery(StationId stationId, NetworkId const & characterId, uint32 clusterId, std::string const & itemId); + + virtual void getSQL(std::string &sql); + virtual bool bindParameters(); + virtual bool bindColumns(); + virtual QueryMode getExecutionMode() const; + + bool getResult() const; + + private: + DB::BindableLong station_id; + DB::BindableNetworkId character_id; + DB::BindableLong cluster_id; + DB::BindableString<255> item_id; + DB::BindableLong result; + + private: //disable + ClaimItemQuery(); + ClaimItemQuery(const ClaimItemQuery&); + ClaimItemQuery &operator=(const ClaimItemQuery&); + }; + + class UpdateFeatureIdTransactionQuery : public DB::Query + { + public: + UpdateFeatureIdTransactionQuery(StationId stationId, NetworkId const & characterId, uint32 clusterId, std::string const & itemId, int countAdjustment); + + virtual void getSQL(std::string &sql); + virtual bool bindParameters(); + virtual bool bindColumns(); + virtual QueryMode getExecutionMode() const; + + bool getResult() const; + + private: + DB::BindableLong station_id; + DB::BindableNetworkId character_id; + DB::BindableLong cluster_id; + DB::BindableString<255> item_id; + DB::BindableLong count_adjustment; + DB::BindableLong result; + + private: //disable + UpdateFeatureIdTransactionQuery(); + UpdateFeatureIdTransactionQuery(const UpdateFeatureIdTransactionQuery&); + UpdateFeatureIdTransactionQuery &operator=(const UpdateFeatureIdTransactionQuery&); + }; + + class GetFeatureIdTransactionsQuery : public DB::Query + { + public: + GetFeatureIdTransactionsQuery(StationId stationId, NetworkId const & characterId, uint32 clusterId); + + DB::BindableString<255> item_id; + DB::BindableLong count; + + virtual void getSQL(std::string &sql); + virtual bool bindParameters(); + virtual bool bindColumns(); + virtual QueryMode getExecutionMode() const; + + private: + DB::BindableLong station_id; + DB::BindableNetworkId character_id; + DB::BindableLong cluster_id; + + private: //disable + GetFeatureIdTransactionsQuery(const GetFeatureIdTransactionsQuery&); + GetFeatureIdTransactionsQuery& operator=(const GetFeatureIdTransactionsQuery&); + }; +} + +using namespace TaskClaimRewardsNamespace; + +// ====================================================================== + +TaskClaimRewards::TaskClaimRewards(uint32 clusterId, uint32 gameServerId, StationId stationId, NetworkId const & playerId, std::string const & rewardEvent, bool consumeEvent, std::string const & rewardItem, bool consumeItem, uint32 accountFeatureId, bool consumeAccountFeatureId, int previousAccountFeatureIdCount, int currentAccountFeatureIdCount) : + DB::TaskRequest(), + m_clusterId(clusterId), + m_gameServerId(gameServerId), + m_stationId(stationId), + m_playerId(playerId), + m_rewardEvent(rewardEvent), + m_consumeEvent(consumeEvent), + m_rewardItem(rewardItem), + m_consumeItem(consumeItem), + m_accountFeatureId(accountFeatureId), + m_consumeAccountFeatureId(consumeAccountFeatureId), + m_previousAccountFeatureIdCount(previousAccountFeatureIdCount), + m_currentAccountFeatureIdCount(currentAccountFeatureIdCount), + m_result(false) +{ +} + +// ---------------------------------------------------------------------- + +bool TaskClaimRewards::process(DB::Session *session) +{ + if (!session->setAutoCommitMode(false)) + return false; + + // record the account feature id transaction + if ((m_accountFeatureId > 0) && m_consumeAccountFeatureId) + { + UpdateFeatureIdTransactionQuery featureIdQry(m_stationId, m_playerId, m_clusterId, m_rewardItem, 1); + if (!session->exec(&featureIdQry)) + return false; + if (!featureIdQry.getResult()) + { + if (!session->rollbackTransaction()) + return false; + m_result = false; + return true; + } + } + else + { + // consume the event + if (m_consumeEvent) + { + ConsumeEventQuery eventQry(m_stationId, m_playerId, m_clusterId, m_rewardEvent); + if (!session->exec(&eventQry)) + return false; + if (!eventQry.getResult()) + { + if (!session->rollbackTransaction()) + return false; + m_result = false; + return true; + } + } + + // consume the item + if (m_consumeItem) + { + ClaimItemQuery itemQuery(m_stationId, m_playerId, m_clusterId, m_rewardItem); + if (!session->exec(&itemQuery)) + return false; + if (!itemQuery.getResult()) + { + if (!session->rollbackTransaction()) + return false; + m_result = false; + return true; + } + } + } + + if (!session->commitTransaction()) + return false; + m_result = true; + return true; +} + +// ---------------------------------------------------------------------- + +void TaskClaimRewards::onComplete() +{ + // if the reward used an account feature id, we have already updated the account feature id + // on session/Platform, so regardless if whether we were able to record the transaction + // in the LoginServer DB or not, always send SUCCESS back to the game server for the item + // to be granted + ClaimRewardsReplyMessage msg(m_gameServerId, m_stationId, m_playerId, m_rewardEvent, m_rewardItem, m_accountFeatureId, m_consumeAccountFeatureId, m_previousAccountFeatureIdCount, m_currentAccountFeatureIdCount, (((m_accountFeatureId > 0) && m_consumeAccountFeatureId) ? true : m_result)); + LoginServer::getInstance().sendToCluster(m_clusterId, msg); +} + +// ====================================================================== + +TaskFeatureIdTransactionRequest::TaskFeatureIdTransactionRequest(uint32 clusterId, StationId stationId, NetworkId const & playerId, uint32 gameServerId) : +DB::TaskRequest(), +m_clusterId(clusterId), +m_stationId(stationId), +m_playerId(playerId), +m_gameServerId(gameServerId), +m_transactions() +{ +} + +// ---------------------------------------------------------------------- + +bool TaskFeatureIdTransactionRequest::process(DB::Session *session) +{ + GetFeatureIdTransactionsQuery qry(m_stationId, m_playerId, m_clusterId); + if (!(session->exec(&qry))) + return false; + + int rowsFetched; + while ((rowsFetched = qry.fetch()) > 0) + m_transactions[qry.item_id.getValueASCII()] = static_cast(qry.count.getValue()); + + return (rowsFetched >= 0); +} + +// ---------------------------------------------------------------------- + +void TaskFeatureIdTransactionRequest::onComplete() +{ + FeatureIdTransactionResponse const fitr(m_gameServerId, m_playerId, m_transactions); + LoginServer::getInstance().sendToCluster(m_clusterId, fitr); +} + +// ====================================================================== + +TaskFeatureIdTransactionSyncUpdate::TaskFeatureIdTransactionSyncUpdate(uint32 clusterId, StationId stationId, NetworkId const & playerId, std::string const & itemId, int adjustment) : +DB::TaskRequest(), +m_clusterId(clusterId), +m_stationId(stationId), +m_playerId(playerId), +m_itemId(itemId), +m_adjustment(adjustment) +{ +} + +// ---------------------------------------------------------------------- + +bool TaskFeatureIdTransactionSyncUpdate::process(DB::Session *session) +{ + UpdateFeatureIdTransactionQuery featureIdQry(m_stationId, m_playerId, m_clusterId, m_itemId, m_adjustment); + if (!session->exec(&featureIdQry)) + return false; + + return true; +} + +// ---------------------------------------------------------------------- + +void TaskFeatureIdTransactionSyncUpdate::onComplete() +{ +} + +// ====================================================================== + +TaskClaimRewardsNamespace::ConsumeEventQuery::ConsumeEventQuery(StationId stationId, NetworkId const & characterId, uint32 clusterId, std::string const & eventId) : + DB::Query(), + station_id(static_cast(stationId)), + character_id(characterId), + cluster_id(static_cast(clusterId)), + event_id(eventId), + result(0) +{ +} + +// ---------------------------------------------------------------------- + +void TaskClaimRewardsNamespace::ConsumeEventQuery::getSQL(std::string &sql) +{ + sql = std::string("begin :result := ")+DatabaseConnection::getInstance().getSchemaQualifier()+"login.consume_reward_event(:station_id, :character_id, :cluster_id, :event_id); end;"; +} + +// ---------------------------------------------------------------------- + +bool TaskClaimRewardsNamespace::ConsumeEventQuery::bindParameters() +{ + if (!bindParameter(result)) return false; + if (!bindParameter(station_id)) return false; + if (!bindParameter(character_id)) return false; + if (!bindParameter(cluster_id)) return false; + if (!bindParameter(event_id)) return false; + return true; +} + +// ---------------------------------------------------------------------- + +bool TaskClaimRewardsNamespace::ConsumeEventQuery::bindColumns() +{ + return true; +} + +// ---------------------------------------------------------------------- + +TaskClaimRewardsNamespace::ConsumeEventQuery::QueryMode TaskClaimRewardsNamespace::ConsumeEventQuery::getExecutionMode() const +{ + return MODE_PROCEXEC; +} + +// ---------------------------------------------------------------------- + +bool TaskClaimRewardsNamespace::ConsumeEventQuery::getResult() const +{ + return (result.getValue() != 0); +} + +// ====================================================================== + +TaskClaimRewardsNamespace::ClaimItemQuery::ClaimItemQuery(StationId stationId, NetworkId const & characterId, uint32 clusterId, std::string const & itemId) : + DB::Query(), + station_id(static_cast(stationId)), + character_id(characterId), + cluster_id(static_cast(clusterId)), + item_id(itemId), + result(0) +{ +} + +// ---------------------------------------------------------------------- + +void TaskClaimRewardsNamespace::ClaimItemQuery::getSQL(std::string &sql) +{ + sql = std::string("begin :result := ")+DatabaseConnection::getInstance().getSchemaQualifier()+"login.claim_reward_item(:station_id, :character_id, :cluster_id, :item_id); end;"; +} + +// ---------------------------------------------------------------------- + +bool TaskClaimRewardsNamespace::ClaimItemQuery::bindParameters() +{ + if (!bindParameter(result)) return false; + if (!bindParameter(station_id)) return false; + if (!bindParameter(character_id)) return false; + if (!bindParameter(cluster_id)) return false; + if (!bindParameter(item_id)) return false; + return true; +} + +// ---------------------------------------------------------------------- + +bool TaskClaimRewardsNamespace::ClaimItemQuery::bindColumns() +{ + return true; +} + +// ---------------------------------------------------------------------- + +TaskClaimRewardsNamespace::ClaimItemQuery::QueryMode TaskClaimRewardsNamespace::ClaimItemQuery::getExecutionMode() const +{ + return MODE_PROCEXEC; +} + +// ---------------------------------------------------------------------- + +bool TaskClaimRewardsNamespace::ClaimItemQuery::getResult() const +{ + return (result.getValue() != 0); +} + +// ====================================================================== + +TaskClaimRewardsNamespace::UpdateFeatureIdTransactionQuery::UpdateFeatureIdTransactionQuery(StationId stationId, NetworkId const & characterId, uint32 clusterId, std::string const & itemId, int countAdjustment) : +DB::Query(), +station_id(static_cast(stationId)), +character_id(characterId), +cluster_id(static_cast(clusterId)), +item_id(itemId), +count_adjustment(static_cast(countAdjustment)), +result(0) +{ +} + +// ---------------------------------------------------------------------- + +void TaskClaimRewardsNamespace::UpdateFeatureIdTransactionQuery::getSQL(std::string &sql) +{ + sql = std::string("begin :result := ")+DatabaseConnection::getInstance().getSchemaQualifier()+"login.update_feature_id_transaction(:station_id, :cluster_id, :character_id, :item_id, :count_adjustment); end;"; +} + +// ---------------------------------------------------------------------- + +bool TaskClaimRewardsNamespace::UpdateFeatureIdTransactionQuery::bindParameters() +{ + if (!bindParameter(result)) return false; + if (!bindParameter(station_id)) return false; + if (!bindParameter(cluster_id)) return false; + if (!bindParameter(character_id)) return false; + if (!bindParameter(item_id)) return false; + if (!bindParameter(count_adjustment)) return false; + return true; +} + +// ---------------------------------------------------------------------- + +bool TaskClaimRewardsNamespace::UpdateFeatureIdTransactionQuery::bindColumns() +{ + return true; +} + +// ---------------------------------------------------------------------- + +TaskClaimRewardsNamespace::UpdateFeatureIdTransactionQuery::QueryMode TaskClaimRewardsNamespace::UpdateFeatureIdTransactionQuery::getExecutionMode() const +{ + return MODE_PROCEXEC; +} + +// ---------------------------------------------------------------------- + +bool TaskClaimRewardsNamespace::UpdateFeatureIdTransactionQuery::getResult() const +{ + return (result.getValue() != 0); +} + +// ====================================================================== + +TaskClaimRewardsNamespace::GetFeatureIdTransactionsQuery::GetFeatureIdTransactionsQuery(StationId stationId, NetworkId const & characterId, uint32 clusterId) : +DB::Query(), +item_id(), +count(0), +station_id(static_cast(stationId)), +character_id(characterId), +cluster_id(static_cast(clusterId)) +{ +} + +// ---------------------------------------------------------------------- + +void TaskClaimRewardsNamespace::GetFeatureIdTransactionsQuery::getSQL(std::string &sql) +{ + sql = std::string("begin :result := ")+DatabaseConnection::getInstance().getSchemaQualifier()+"login.get_feature_id_transactions(:station_id, :cluster_id, :character_id); end;"; +} + +// ---------------------------------------------------------------------- + +bool TaskClaimRewardsNamespace::GetFeatureIdTransactionsQuery::bindParameters() +{ + if (!bindParameter(station_id)) return false; + if (!bindParameter(cluster_id)) return false; + if (!bindParameter(character_id)) return false; + return true; +} + +// ---------------------------------------------------------------------- + +bool TaskClaimRewardsNamespace::GetFeatureIdTransactionsQuery::bindColumns() +{ + if (!bindCol(item_id)) return false; + if (!bindCol(count)) return false; + + return true; +} + +// ---------------------------------------------------------------------- + +TaskClaimRewardsNamespace::GetFeatureIdTransactionsQuery::QueryMode TaskClaimRewardsNamespace::GetFeatureIdTransactionsQuery::getExecutionMode() const +{ + return MODE_PLSQL_REFCURSOR; +} + +// ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/TaskClaimRewards.h b/engine/server/application/LoginServer/src/shared/TaskClaimRewards.h new file mode 100644 index 00000000..ba86e7dc --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskClaimRewards.h @@ -0,0 +1,92 @@ +// ====================================================================== +// +// TaskClaimRewards.h +// copyright (c) 2004 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_TaskClaimRewards_H +#define INCLUDED_TaskClaimRewards_H + +// ====================================================================== + +#include "sharedDatabaseInterface/DbTaskRequest.h" +#include "sharedFoundation/StationId.h" + +// ====================================================================== + +class TaskClaimRewards : public DB::TaskRequest +{ + public: + TaskClaimRewards(uint32 clusterId, uint32 gameServerId, StationId stationId, NetworkId const & playerId, std::string const & rewardEvent, bool consumeEvent, std::string const & rewardItem, bool consumeItem, uint32 accountFeatureId, bool consumeAccountFeatureId, int previousAccountFeatureIdCount, int currentAccountFeatureIdCount); + + public: + virtual bool process (DB::Session *session); + virtual void onComplete (); + + private: + uint32 const m_clusterId; + uint32 const m_gameServerId; + StationId const m_stationId; + NetworkId const m_playerId; + std::string const m_rewardEvent; + bool const m_consumeEvent; + std::string const m_rewardItem; + bool const m_consumeItem; + uint32 const m_accountFeatureId; + bool const m_consumeAccountFeatureId; + int m_previousAccountFeatureIdCount; + int m_currentAccountFeatureIdCount; + bool m_result; + + private: + TaskClaimRewards(); // disabled default constructor +}; + +// ====================================================================== + +class TaskFeatureIdTransactionRequest : public DB::TaskRequest +{ +public: + TaskFeatureIdTransactionRequest(uint32 clusterId, StationId stationId, NetworkId const & playerId, uint32 gameServerId); + +public: + virtual bool process (DB::Session *session); + virtual void onComplete (); + +private: + uint32 const m_clusterId; + StationId const m_stationId; + NetworkId const m_playerId; + uint32 const m_gameServerId; + std::map m_transactions; + +private: + TaskFeatureIdTransactionRequest(); // disabled default constructor +}; + +// ====================================================================== + +class TaskFeatureIdTransactionSyncUpdate : public DB::TaskRequest +{ +public: + TaskFeatureIdTransactionSyncUpdate(uint32 clusterId, StationId stationId, NetworkId const & playerId, std::string const & itemId, int adjustment); + +public: + virtual bool process (DB::Session *session); + virtual void onComplete (); + +private: + uint32 const m_clusterId; + StationId const m_stationId; + NetworkId const m_playerId; + std::string const m_itemId; + int const m_adjustment; + +private: + TaskFeatureIdTransactionSyncUpdate(); // disabled default constructor +}; + +// ====================================================================== + +#endif diff --git a/engine/server/application/LoginServer/src/shared/TaskCreateCharacter.cpp b/engine/server/application/LoginServer/src/shared/TaskCreateCharacter.cpp new file mode 100644 index 00000000..6e8ed6d4 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskCreateCharacter.cpp @@ -0,0 +1,112 @@ +// ====================================================================== +// +// TaskCreateCharacter.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLoginServer.h" +#include "TaskCreateCharacter.h" + +#include "LoginServer.h" +#include "DatabaseConnection.h" +#include "sharedNetworkMessages/GenericValueTypeMessage.h" +#include "serverNetworkMessages/LoginCreateCharacterAckMessage.h" +#include "sharedDatabaseInterface/DbSession.h" +#include "sharedFoundation/NetworkIdArchive.h" + +// ====================================================================== + +TaskCreateCharacter::TaskCreateCharacter(uint32 clusterId, StationId stationId, const Unicode::String &characterName, const NetworkId &characterId, int templateId, bool jedi) : + TaskRequest(), + m_clusterId(clusterId), + m_stationId(stationId), + m_characterName(characterName), + m_characterId(characterId), + m_templateId(templateId), + m_jedi(jedi) +{ +} + +// ---------------------------------------------------------------------- + +bool TaskCreateCharacter::process(DB::Session *session) +{ + CreateCharacterQuery qry; + qry.cluster_id = static_cast(m_clusterId); + qry.station_id = static_cast(m_stationId); + qry.character_name = m_characterName; + qry.character_id = m_characterId; + qry.template_id = m_templateId; + if (m_jedi) + qry.character_type = 2; //TODO: Make an enum somewhere + else + qry.character_type = 1; + + bool rval = session->exec(&qry); + + qry.done(); + return rval; +} + +// ---------------------------------------------------------------------- + +void TaskCreateCharacter::onComplete() +{ + LoginCreateCharacterAckMessage ackMessage(m_stationId,m_characterId); + LoginServer::getInstance().sendToCluster(m_clusterId,ackMessage); + + // let all other galaxies know that a new character has been created for the station account + GenericValueTypeMessage const ncc("NewCharacterCreated", m_stationId); + LoginServer::getInstance().sendToAllClusters(ncc, NULL, m_clusterId); +} + +// ====================================================================== + +TaskCreateCharacter::CreateCharacterQuery::CreateCharacterQuery() : + Query(), + cluster_id(), + station_id(), + character_name(), + character_id(), + template_id(), + character_type() +{ +} + +// ---------------------------------------------------------------------- + +void TaskCreateCharacter::CreateCharacterQuery::getSQL(std::string &sql) +{ + sql = std::string("begin ")+DatabaseConnection::getInstance().getSchemaQualifier()+"login.create_character(:cluster_id, :station_id, :character_name, :character_id, :template_name, :character_type); end;"; + // DEBUG_REPORT_LOG(true, ("TaskCreateCharacter SQL: %s\n", sql.c_str())); +} + +// ---------------------------------------------------------------------- + +bool TaskCreateCharacter::CreateCharacterQuery::bindParameters() +{ + if (!bindParameter(cluster_id)) return false; + if (!bindParameter(station_id)) return false; + if (!bindParameter(character_name)) return false; + if (!bindParameter(character_id)) return false; + if (!bindParameter(template_id)) return false; + if (!bindParameter(character_type)) return false; + return true; +} + +// ---------------------------------------------------------------------- + +bool TaskCreateCharacter::CreateCharacterQuery::bindColumns() +{ + return true; +} + +// ---------------------------------------------------------------------- + +DB::Query::QueryMode TaskCreateCharacter::CreateCharacterQuery::getExecutionMode() const +{ + return MODE_PROCEXEC; +} + +// ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/TaskCreateCharacter.h b/engine/server/application/LoginServer/src/shared/TaskCreateCharacter.h new file mode 100644 index 00000000..3c53e296 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskCreateCharacter.h @@ -0,0 +1,64 @@ +// ====================================================================== +// +// TaskCreateCharacter.h +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_TaskCreateCharacter_H +#define INCLUDED_TaskCreateCharacter_H + +// ====================================================================== + +#include "sharedDatabaseInterface/Bindable.h" +#include "sharedDatabaseInterface/BindableNetworkId.h" +#include "sharedDatabaseInterface/DbQuery.h" +#include "sharedDatabaseInterface/DbTaskRequest.h" + +// ====================================================================== + +class TaskCreateCharacter : public DB::TaskRequest +{ + public: + TaskCreateCharacter(uint32 clusterId, StationId stationId, const Unicode::String &characterName, const NetworkId &characterId, int templateId, bool jedi); + + public: + virtual bool process (DB::Session *session); + virtual void onComplete (); + + private: + TaskCreateCharacter(); // disabled default constructor + class CreateCharacterQuery : public DB::Query + { + public: + CreateCharacterQuery(); + + DB::BindableLong cluster_id; //lint !e1925 // public data member + DB::BindableLong station_id; //lint !e1925 // public data member + DB::BindableString<127> character_name; //lint !e1925 // public data member + DB::BindableNetworkId character_id; //lint !e1925 // public data member + DB::BindableLong template_id; //lint !e1925 // public data member + DB::BindableLong character_type; //lint !e1925 // public data member + + virtual void getSQL (std::string &sql); + virtual bool bindParameters (); + virtual bool bindColumns (); + virtual QueryMode getExecutionMode () const; + + private: //disable + CreateCharacterQuery (const CreateCharacterQuery&); + CreateCharacterQuery &operator= (const CreateCharacterQuery&); + }; + + private: + uint32 m_clusterId; + StationId m_stationId; + Unicode::String m_characterName; + NetworkId m_characterId; + int m_templateId; + bool m_jedi; +}; + +// ====================================================================== + +#endif diff --git a/engine/server/application/LoginServer/src/shared/TaskDeleteCharacter.cpp b/engine/server/application/LoginServer/src/shared/TaskDeleteCharacter.cpp new file mode 100644 index 00000000..5f0eb20b --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskDeleteCharacter.cpp @@ -0,0 +1,93 @@ +// ====================================================================== +// +// TaskDeleteCharacter.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLoginServer.h" +#include "TaskDeleteCharacter.h" + +#include "ClientConnection.h" +#include "LoginServer.h" +#include "DatabaseConnection.h" +#include "sharedDatabaseInterface/DbSession.h" + +// ====================================================================== + +TaskDeleteCharacter::TaskDeleteCharacter(uint32 clusterId, const NetworkId &characterId, StationId stationId) : + TaskRequest(), + m_clusterId(clusterId), + m_characterId(characterId), + m_stationId(stationId) +{ +} + +// ---------------------------------------------------------------------- + +bool TaskDeleteCharacter::process(DB::Session *session) +{ + DeleteCharacterQuery qry; + qry.cluster_id=m_clusterId; //lint !e713 // loss ofp recision unsigned long to long + qry.character_id=m_characterId; + qry.station_id=m_stationId; //lint !e713 // loss ofp recision unsigned long to long + + bool rval = session->exec(&qry); + + qry.done(); + return rval; +} + +// ---------------------------------------------------------------------- + +void TaskDeleteCharacter::onComplete() +{ + ClientConnection* target = LoginServer::getInstance().getValidatedClient(m_stationId); + if (target) + target->onCharacterDeletedFromLoginDatabase(m_characterId); +} + +// ====================================================================== + +TaskDeleteCharacter::DeleteCharacterQuery::DeleteCharacterQuery() : + Query(), + cluster_id(), + character_id(), + station_id() +{ +} + +// ---------------------------------------------------------------------- + +void TaskDeleteCharacter::DeleteCharacterQuery::getSQL(std::string &sql) +{ + sql = std::string("begin ")+DatabaseConnection::getInstance().getSchemaQualifier()+"login.delete_character(:cluster_id, :character_id, :station_id); end;"; + // DEBUG_REPORT_LOG(true, ("TaskDeleteCharacter SQL: %s\n", sql.c_str())); + +} + +// ---------------------------------------------------------------------- + +bool TaskDeleteCharacter::DeleteCharacterQuery::bindParameters() +{ + if (!bindParameter(cluster_id)) return false; + if (!bindParameter(character_id)) return false; + if (!bindParameter(station_id)) return false; + return true; +} + +// ---------------------------------------------------------------------- + +bool TaskDeleteCharacter::DeleteCharacterQuery::bindColumns() +{ + return true; +} + +// ---------------------------------------------------------------------- + +DB::Query::QueryMode TaskDeleteCharacter::DeleteCharacterQuery::getExecutionMode() const +{ + return MODE_PROCEXEC; +} + +// ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/TaskDeleteCharacter.h b/engine/server/application/LoginServer/src/shared/TaskDeleteCharacter.h new file mode 100644 index 00000000..5b3130a4 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskDeleteCharacter.h @@ -0,0 +1,60 @@ +// ====================================================================== +// +// TaskDeleteCharacter.h +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_TaskDeleteCharacter_H +#define INCLUDED_TaskDeleteCharacter_H + +// ====================================================================== + +#include "serverNetworkMessages/AvatarList.h" +#include "sharedDatabaseInterface/Bindable.h" +#include "sharedDatabaseInterface/BindableNetworkId.h" +#include "sharedDatabaseInterface/DbQuery.h" +#include "sharedDatabaseInterface/DbTaskRequest.h" + +// ====================================================================== + +class TaskDeleteCharacter : public DB::TaskRequest +{ + public: + TaskDeleteCharacter(uint32 clusterId, const NetworkId &characterId, StationId stationId); + + public: + virtual bool process (DB::Session *session); + virtual void onComplete (); + + private: + TaskDeleteCharacter(); // disabled default constructor + + class DeleteCharacterQuery : public DB::Query + { + public: + DeleteCharacterQuery(); + + DB::BindableLong cluster_id; //lint !e1925 // public data member + DB::BindableNetworkId character_id; //lint !e1925 // public data member + DB::BindableLong station_id; //lint !e1925 // public data member + + virtual void getSQL(std::string &sql); + virtual bool bindParameters(); + virtual bool bindColumns(); + virtual QueryMode getExecutionMode() const; + + private: //disable + DeleteCharacterQuery(const DeleteCharacterQuery&); + DeleteCharacterQuery &operator=(const DeleteCharacterQuery&); + }; + + private: + uint32 m_clusterId; + NetworkId m_characterId; + StationId m_stationId; +}; + +// ====================================================================== + +#endif diff --git a/engine/server/application/LoginServer/src/shared/TaskEnableCharacter.cpp b/engine/server/application/LoginServer/src/shared/TaskEnableCharacter.cpp new file mode 100644 index 00000000..b72adbe3 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskEnableCharacter.cpp @@ -0,0 +1,119 @@ +// ====================================================================== +// +// TaskEnableCharacter.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLoginServer.h" +#include "TaskEnableCharacter.h" +#include "CentralServerConnection.h" + +#include "ClientConnection.h" +#include "LoginServer.h" +#include "DatabaseConnection.h" +#include "sharedDatabaseInterface/DbSession.h" +#include "sharedNetworkMessages/GenericValueTypeMessage.h" + +// ====================================================================== + +TaskEnableCharacter::TaskEnableCharacter(StationId &stationId, const NetworkId &characterId, const std::string &whoRequested, bool enabled, uint32 clusterId) : + TaskRequest(), + m_stationId(stationId), + m_characterId(characterId), + m_whoRequested(whoRequested), + m_enabled(enabled), + m_clusterId(clusterId) +{ +} + +// ---------------------------------------------------------------------- + +bool TaskEnableCharacter::process(DB::Session *session) +{ + EnableCharacterQuery qry; + qry.station_id=static_cast(m_stationId); + qry.character_id=m_characterId; + qry.enabled.setValue(m_enabled); + + bool rval = session->exec(&qry); + + qry.done(); + m_result = qry.result.getValue(); + return rval; + +} + +// ---------------------------------------------------------------------- + +void TaskEnableCharacter::onComplete() +{ + std::string message; + switch (m_result) + { + case 1: + if (m_enabled) + message = "Character enabled."; + else + message = "Character disabled."; + break; + + case 2: + message = "Could not find Character"; + break; + + default: + message = "The database returned an unknown error code"; + break; + } + + GenericValueTypeMessage > reply("EnableCharacterReplyMessage", + std::make_pair(m_whoRequested, message)); + LoginServer::getInstance().sendToCluster(m_clusterId, reply); +} + +// ---------------------------------------------------------------------- + +TaskEnableCharacter::EnableCharacterQuery::EnableCharacterQuery() : + Query(), + station_id(), + character_id(), + enabled() +{ +} + +// ---------------------------------------------------------------------- + +void TaskEnableCharacter::EnableCharacterQuery::getSQL(std::string &sql) +{ + sql = std::string("begin :result := ") + DatabaseConnection::getInstance().getSchemaQualifier() + "login.enable_disable_character(:station_id, :character_id, :enabled); end;"; + +} + +// ---------------------------------------------------------------------- + +bool TaskEnableCharacter::EnableCharacterQuery::bindParameters() +{ + if (!bindParameter(result)) return false; + if (!bindParameter(station_id)) return false; + if (!bindParameter(character_id)) return false; + if (!bindParameter(enabled)) return false; + + return true; +} + +// ---------------------------------------------------------------------- + +bool TaskEnableCharacter::EnableCharacterQuery::bindColumns() +{ + return true; +} + +// ---------------------------------------------------------------------- + +DB::Query::QueryMode TaskEnableCharacter::EnableCharacterQuery::getExecutionMode() const +{ + return MODE_PROCEXEC; +} + +// ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/TaskEnableCharacter.h b/engine/server/application/LoginServer/src/shared/TaskEnableCharacter.h new file mode 100644 index 00000000..32125532 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskEnableCharacter.h @@ -0,0 +1,65 @@ +// ====================================================================== +// +// TaskEnableCharacter.h +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_TaskEnableCharacter_H +#define INCLUDED_TaskEnableCharacter_H + +// ====================================================================== + +#include "serverNetworkMessages/AvatarList.h" +#include "sharedDatabaseInterface/Bindable.h" +#include "sharedDatabaseInterface/BindableNetworkId.h" +#include "sharedDatabaseInterface/DbQuery.h" +#include "sharedDatabaseInterface/DbTaskRequest.h" + +// ====================================================================== + +class TaskEnableCharacter : public DB::TaskRequest +{ + public: + TaskEnableCharacter(StationId &stationId, const NetworkId &characterId, const std::string &whoRequested, bool enabled, uint32 clusterId); + + public: + virtual bool process (DB::Session *session); + virtual void onComplete (); + + private: + TaskEnableCharacter(); // disabled default constructor + + class EnableCharacterQuery : public DB::Query + { + public: + EnableCharacterQuery(); + + DB::BindableLong station_id; //lint !e1925 // public data member : suppressed because this is a private inner class + DB::BindableNetworkId character_id; //lint !e1925 // public data member : suppressed because this is a private inner class + DB::BindableBool enabled; //lint !e1925 // public data member : suppressed because this is a private inner class + DB::BindableLong result; //lint !e1925 // public data member : suppressed because this is a private inner class + + + virtual void getSQL(std::string &sql); + virtual bool bindParameters(); + virtual bool bindColumns(); + virtual QueryMode getExecutionMode() const; + + private: //disable + EnableCharacterQuery(const EnableCharacterQuery&); + EnableCharacterQuery &operator=(const EnableCharacterQuery&); + }; + + private: + StationId m_stationId; + NetworkId m_characterId; + std::string m_whoRequested; + bool m_enabled; + uint32 m_clusterId; + int m_result; +}; + +// ====================================================================== + +#endif diff --git a/engine/server/application/LoginServer/src/shared/TaskGetAccountForPurge.cpp b/engine/server/application/LoginServer/src/shared/TaskGetAccountForPurge.cpp new file mode 100644 index 00000000..bc755e82 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskGetAccountForPurge.cpp @@ -0,0 +1,124 @@ +// ====================================================================== +// +// TaskGetAccountForPurge.cpp +// copyright (c) 2005 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLoginServer.h" +#include "TaskGetAccountForPurge.h" + +#include "ConfigLoginServer.h" +#include "DatabaseConnection.h" +#include "PurgeManager.h" +#include "sharedDatabaseInterface/Bindable.h" +#include "sharedDatabaseInterface/DbQuery.h" +#include "sharedDatabaseInterface/DbSession.h" + +// ====================================================================== + +namespace TaskGetAccountForPurgeNamespace +{ + class GetAccountForPurgeQuery : public DB::Query + { + public: + GetAccountForPurgeQuery(int purgePhase, int minAge); + + virtual void getSQL(std::string &sql); + virtual bool bindParameters(); + virtual bool bindColumns(); + virtual QueryMode getExecutionMode() const; + + StationId getAccount() const; + + private: + DB::BindableLong m_account; + DB::BindableLong m_min_age; + DB::BindableLong m_purge_phase; + + private: //disable + GetAccountForPurgeQuery(const GetAccountForPurgeQuery&); + GetAccountForPurgeQuery& operator=(const GetAccountForPurgeQuery&); + }; +} +using namespace TaskGetAccountForPurgeNamespace; + +// ====================================================================== + +TaskGetAccountForPurge::TaskGetAccountForPurge(int purgePhase) : + DB::TaskRequest(), + m_purgePhase(purgePhase) +{ +} + +// ---------------------------------------------------------------------- + +bool TaskGetAccountForPurge::process(DB::Session *session) +{ + GetAccountForPurgeQuery qry(m_purgePhase, ConfigLoginServer::getPurgePhaseAdvanceDays(m_purgePhase)); + if (!session->exec(&qry)) + return false; + m_account = qry.getAccount(); + return true; +} + +// ---------------------------------------------------------------------- + +void TaskGetAccountForPurge::onComplete() +{ + PurgeManager::onGetAccountForPurge(m_account, m_purgePhase); +} + +// ====================================================================== + + +GetAccountForPurgeQuery::GetAccountForPurgeQuery(int purgePhase, int minAge) : + Query(), + m_account(), + m_min_age(minAge), + m_purge_phase(purgePhase) +{ +} + +// ---------------------------------------------------------------------- + +void GetAccountForPurgeQuery::getSQL(std::string &sql) +{ + sql=std::string("begin :account := ")+DatabaseConnection::getInstance().getSchemaQualifier()+"purge_process.get_account_for_purge(:purge_phase, :min_age); end;"; +} + +// ---------------------------------------------------------------------- + +bool GetAccountForPurgeQuery::bindParameters() +{ + if (!bindParameter(m_account)) return false; + if (!bindParameter(m_purge_phase)) return false; + if (!bindParameter(m_min_age)) return false; + return true; +} + +// ---------------------------------------------------------------------- + +bool GetAccountForPurgeQuery::bindColumns() +{ + return true; +} + +// ---------------------------------------------------------------------- + +GetAccountForPurgeQuery::QueryMode GetAccountForPurgeQuery::getExecutionMode() const +{ + return MODE_PROCEXEC; +} + +// ---------------------------------------------------------------------- + +StationId GetAccountForPurgeQuery::getAccount() const +{ + if (!m_account.isNull()) + return m_account.getValue(); + else + return 0; +} + +// ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/TaskGetAccountForPurge.h b/engine/server/application/LoginServer/src/shared/TaskGetAccountForPurge.h new file mode 100644 index 00000000..00e67c1f --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskGetAccountForPurge.h @@ -0,0 +1,29 @@ +// ====================================================================== +// +// TaskGetAccountForPurge.h +// copyright (c) 2005 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_TaskGetAccountForPurge_H +#define INCLUDED_TaskGetAccountForPurge_H + +// ====================================================================== + +#include "sharedDatabaseInterface/DbTaskRequest.h" + +class TaskGetAccountForPurge : public DB::TaskRequest +{ + public: + explicit TaskGetAccountForPurge(int purgePhase); + virtual bool process (DB::Session *session); + virtual void onComplete (); + + private: + int m_purgePhase; + StationId m_account; +}; + +// ====================================================================== + +#endif diff --git a/engine/server/application/LoginServer/src/shared/TaskGetAvatarList.cpp b/engine/server/application/LoginServer/src/shared/TaskGetAvatarList.cpp new file mode 100644 index 00000000..df33d81c --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskGetAvatarList.cpp @@ -0,0 +1,221 @@ +// ====================================================================== +// +// TaskGetAvatarList.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLoginServer.h" +#include "TaskGetAvatarList.h" + +#include "serverNetworkMessages/AvatarList.h" +#include "CentralServerConnection.h" +#include "DatabaseConnection.h" +#include "sharedLog/Log.h" +#include "serverNetworkMessages/TransferAccountData.h" +#include "serverNetworkMessages/TransferAccountDataArchive.h" +#include "serverNetworkMessages/TransferCharacterData.h" +#include "sharedDatabaseInterface/DbSession.h" +#include "sharedNetworkMessages/GenericValueTypeMessage.h" +#include "TaskUpgradeAccount.h" +#include + +// ====================================================================== + +TaskGetAvatarList::TaskGetAvatarList (StationId stationId, int clusterGroupId, const TransferCharacterData * transferCharacterData) : + TaskRequest(), + m_stationId(stationId), + m_stationIdNumberJediSlot(0), + m_clusterGroupId(clusterGroupId), + m_avatars(), + m_transferCharacterData(0), + m_transferAccountData(0) +{ + if(transferCharacterData) + { + m_transferCharacterData = new TransferCharacterData(*transferCharacterData); + } +} + +// ---------------------------------------------------------------------- + +TaskGetAvatarList::TaskGetAvatarList (int clusterGroupId, const TransferAccountData * transferAccountData) : + TaskRequest(), + m_stationId(), + m_stationIdNumberJediSlot(0), + m_clusterGroupId(clusterGroupId), + m_avatars(), + m_transferCharacterData(0), + m_transferAccountData(0) +{ + if(transferAccountData) + { + m_transferAccountData = new TransferAccountData(*transferAccountData); + m_stationId = m_transferAccountData->getSourceStationId(); + } +} + +// ---------------------------------------------------------------------- + +TaskGetAvatarList::~TaskGetAvatarList() +{ + delete m_transferCharacterData; + m_transferCharacterData = 0; + delete m_transferAccountData; + m_transferAccountData = 0; +} + +// ---------------------------------------------------------------------- + +bool TaskGetAvatarList::process(DB::Session *session) +{ + if (m_transferAccountData) + { + // if we are doing an account transfer, we need to also check the number of avatars in the destination station id + GetCharactersQuery qry; + int rowsFetched; + + qry.station_id = m_transferAccountData->getDestinationStationId(); + qry.cluster_group_id = m_clusterGroupId; + + if (! (session->exec(&qry))) + return false; + + bool hasAvatars = false; + while ((rowsFetched = qry.fetch()) > 0) + { + hasAvatars = true; + } + + m_transferAccountData->setDestinationHasAvatars(hasAvatars); + } + + m_stationIdNumberJediSlot = 0; + if (!m_transferAccountData) + { + TaskUpgradeAccount::QueryJediQuery qryHasJediSlot; + qryHasJediSlot.station_id = m_stationId; //lint !e713 // loss of precision unsigned long to long + qryHasJediSlot.character_type = 2; + + if (session->exec(&qryHasJediSlot)) + { + m_stationIdNumberJediSlot = qryHasJediSlot.result.getValue(); + } + + qryHasJediSlot.done(); + } + + GetCharactersQuery qry; + int rowsFetched; + + qry.station_id = m_stationId; //lint !e713 // loss of precision unsigned long to long + qry.cluster_group_id = m_clusterGroupId; + + if (! (session->exec(&qry))) + return false; + + AvatarRecord temp; + + while ((rowsFetched = qry.fetch()) > 0) + { + qry.character_name.getValue(temp.m_name); + qry.object_template_id.getValue(temp.m_objectTemplateId); + qry.object_id.getValue(temp.m_networkId); + qry.cluster_id.getValue(temp.m_clusterId); + qry.character_type.getValue(temp.m_characterType); + + m_avatars.push_back(temp); + } + return (rowsFetched >= 0); +} + +// ---------------------------------------------------------------------- + +void TaskGetAvatarList::onComplete() +{ + if (m_transferAccountData) + { + if (m_transferAccountData->getDestinationHasAvatars()) + { + // send a message back to the transfer server + LOG("CustomerService", ("CharacterTransfer: Cannot complete account transfer from %lu to %lu: destination stationId contains avatars\n", m_transferAccountData->getSourceStationId(), m_transferAccountData->getDestinationStationId())); + const GenericValueTypeMessage response("TransferAccountFailedDestinationNotEmpty", *m_transferAccountData); + CentralServerConnection::sendToCentralServer(m_transferAccountData->getStartGalaxy(), response); + } + else + DatabaseConnection::getInstance().onAvatarListRetrievedAccountTransfer(m_avatars, m_transferAccountData); + + } + else + { + DatabaseConnection::getInstance().onAvatarListRetrieved(m_stationId, m_stationIdNumberJediSlot, m_avatars, m_transferCharacterData); + } +} + +// ---------------------------------------------------------------------- + +AvatarList const & TaskGetAvatarList::getAvatars() const +{ + return m_avatars; +} + +// ---------------------------------------------------------------------- + +StationId TaskGetAvatarList::getStationId() const +{ + return m_stationId; +} + +// ====================================================================== + +void TaskGetAvatarList::GetCharactersQuery::getSQL(std::string &sql) +{ + sql=std::string("begin :result := ")+DatabaseConnection::getInstance().getSchemaQualifier()+"login.get_avatar_list(:station_id, :cluster_group_id); end;"; + // DEBUG_REPORT_LOG(true, ("TaskGetAvatarList SQL: %s\n", sql.c_str())); +} + +// ---------------------------------------------------------------------- + +bool TaskGetAvatarList::GetCharactersQuery::bindParameters() +{ + if (!bindParameter(station_id)) return false; + if (!bindParameter(cluster_group_id)) return false; + + return true; +} + +// ---------------------------------------------------------------------- + +bool TaskGetAvatarList::GetCharactersQuery::bindColumns() +{ + if (!bindCol(character_name)) return false; + if (!bindCol(object_template_id)) return false; + if (!bindCol(object_id)) return false; + if (!bindCol(cluster_id)) return false; + if (!bindCol(character_type)) return false; + + return true; +} + +// ---------------------------------------------------------------------- + +DB::Query::QueryMode TaskGetAvatarList::GetCharactersQuery::getExecutionMode() const +{ + return MODE_PLSQL_REFCURSOR; +} + +// ---------------------------------------------------------------------- + +TaskGetAvatarList::GetCharactersQuery::GetCharactersQuery() : + Query(), + station_id(), + cluster_group_id(), + character_name(), + object_template_id(), + object_id(), + cluster_id(), + character_type() +{ +} + +// ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/TaskGetAvatarList.h b/engine/server/application/LoginServer/src/shared/TaskGetAvatarList.h new file mode 100644 index 00000000..1c7c6cb1 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskGetAvatarList.h @@ -0,0 +1,74 @@ +// ====================================================================== +// +// TaskGetAvatarList.h +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_TaskGetAvatarList_H +#define INCLUDED_TaskGetAvatarList_H + +// ====================================================================== + +#include "serverNetworkMessages/AvatarList.h" +#include "sharedDatabaseInterface/Bindable.h" +#include "sharedDatabaseInterface/BindableNetworkId.h" +#include "sharedDatabaseInterface/DbQuery.h" +#include "sharedDatabaseInterface/DbTaskRequest.h" + +// ====================================================================== + +class TransferAccountData; +class TransferCharacterData; + +class TaskGetAvatarList : public DB::TaskRequest +{ + public: + explicit TaskGetAvatarList (StationId stationId, int clusterGroupId, const TransferCharacterData * transferCharacterData); + explicit TaskGetAvatarList (int clusterGroupId, const TransferAccountData * transferAccountData); + virtual ~TaskGetAvatarList (); + + public: + virtual bool process (DB::Session *session); + virtual void onComplete (); + AvatarList const & getAvatars() const; + StationId getStationId() const; + + class GetCharactersQuery : public DB::Query + { + public: + DB::BindableLong station_id; //lint !e1925 // public data member + DB::BindableLong cluster_group_id; //lint !e1925 // public data member + DB::BindableString<128> character_name; //lint !e1925 // public data member + DB::BindableLong object_template_id; //lint !e1925 // public data member + DB::BindableNetworkId object_id; //lint !e1925 // public data member + DB::BindableLong cluster_id; //lint !e1925 // public data member + DB::BindableLong character_type; //lint !e1925 // public data member + + GetCharactersQuery(); + + virtual void getSQL(std::string &sql); + virtual bool bindParameters(); + virtual bool bindColumns(); + virtual QueryMode getExecutionMode() const; + + private: //disable + GetCharactersQuery(const GetCharactersQuery&); + GetCharactersQuery& operator=(const GetCharactersQuery&); + }; + + private: + TaskGetAvatarList(); // disabled default constructor + TaskGetAvatarList(const TaskGetAvatarList &); + TaskGetAvatarList & operator= (const TaskGetAvatarList &); + StationId m_stationId; + int m_stationIdNumberJediSlot; + int m_clusterGroupId; + AvatarList m_avatars; + TransferCharacterData * m_transferCharacterData; + TransferAccountData * m_transferAccountData; +}; + +// ====================================================================== + +#endif diff --git a/engine/server/application/LoginServer/src/shared/TaskGetCharactersForDelete.cpp b/engine/server/application/LoginServer/src/shared/TaskGetCharactersForDelete.cpp new file mode 100644 index 00000000..5259daf4 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskGetCharactersForDelete.cpp @@ -0,0 +1,42 @@ +// ====================================================================== +// +// TaskGetCharactersForDelete.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLoginServer.h" +#include "TaskGetCharactersForDelete.h" + +#include "PurgeManager.h" +#include "serverNetworkMessages/AvatarList.h" + +// ====================================================================== + +TaskGetCharactersForDelete::TaskGetCharactersForDelete (StationId stationId, int clusterGroupId) : + TaskGetAvatarList(stationId, clusterGroupId, NULL) +{ +} + +// ---------------------------------------------------------------------- + +TaskGetCharactersForDelete::~TaskGetCharactersForDelete() +{ +} + +// ---------------------------------------------------------------------- + +void TaskGetCharactersForDelete::onComplete() +{ + bool success=true; + AvatarList const & theList = getAvatars(); + for (AvatarList::const_iterator i=theList.begin(); i!=theList.end(); ++i) + { + if (!LoginServer::getInstance().deleteCharacter(i->m_clusterId, i->m_networkId, getStationId())) + success=false; + } + + PurgeManager::onAllCharactersDeleted(getStationId(), success); +} + +// ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/TaskGetCharactersForDelete.h b/engine/server/application/LoginServer/src/shared/TaskGetCharactersForDelete.h new file mode 100644 index 00000000..c081c091 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskGetCharactersForDelete.h @@ -0,0 +1,29 @@ +// ====================================================================== +// +// TaskGetCharactersForDelete.h +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_TaskGetCharactersForDelete_H +#define INCLUDED_TaskGetCharactersForDelete_H + +// ====================================================================== + +#include "TaskGetAvatarList.h" + +// ====================================================================== + +class TaskGetCharactersForDelete : public TaskGetAvatarList +{ + public: + explicit TaskGetCharactersForDelete (StationId stationId, int clusterGroupId); + virtual ~TaskGetCharactersForDelete (); + + public: + virtual void onComplete (); +}; + +// ====================================================================== + +#endif diff --git a/engine/server/application/LoginServer/src/shared/TaskGetClusterList.cpp b/engine/server/application/LoginServer/src/shared/TaskGetClusterList.cpp new file mode 100644 index 00000000..23919142 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskGetClusterList.cpp @@ -0,0 +1,137 @@ +// ====================================================================== +// +// TaskGetClusterList.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLoginServer.h" +#include "TaskGetClusterList.h" + +#include "serverNetworkMessages/AvatarList.h" +#include "ConfigLoginServer.h" +#include "DatabaseConnection.h" +#include "sharedDatabaseInterface/DbSession.h" + +// ====================================================================== + +TaskGetClusterList::TaskGetClusterList (int const groupId) : + TaskRequest(), + m_clusterData(), + m_groupId(groupId) +{ +} + +// ---------------------------------------------------------------------- + +bool TaskGetClusterList::process(DB::Session *session) +{ + GetClustersQuery qry; + int rowsFetched; + + qry.group_id = m_groupId; + + if (! (session->exec(&qry))) + return false; + + ClusterData temp; + + while ((rowsFetched = qry.fetch()) > 0) + { + qry.cluster_id.getValue(temp.m_clusterId); + qry.cluster_name.getValue(temp.m_clusterName); + qry.address.getValue(temp.m_address); + if (qry.port.isNull()) + temp.m_port = ConfigLoginServer::getCentralServicePort(); + else + temp.m_port = static_cast(qry.port.getValue()); + qry.secret.getValue(temp.m_secret); + qry.locked.getValue(temp.m_locked); + qry.not_recommended.getValue(temp.m_notRecommended); + qry.maxCharacterPerAccount.getValue(temp.m_maxCharactersPerAccount); + qry.online_player_limit.getValue(temp.m_onlinePlayerLimit); + qry.online_free_trial_limit.getValue(temp.m_onlineFreeTrialLimit); + qry.free_trial_can_create_char.getValue(temp.m_freeTrialCanCreateChar); + qry.online_tutorial_limit.getValue(temp.m_onlineTutorialLimit); + + m_clusterData.push_back(temp); + } + return (rowsFetched >= 0); +} + +// ---------------------------------------------------------------------- + +void TaskGetClusterList::onComplete() +{ + for (std::vector::const_iterator i=m_clusterData.begin(); i!= m_clusterData.end(); ++i) + { + FATAL(i->m_clusterId<1,("Cluster id %i was specified in the database for cluster \"%s\". 1 is the minimum legal cluster id",i->m_clusterId, i->m_clusterName.c_str())); + LoginServer::getInstance().updateClusterData((*i).m_clusterId, (*i).m_clusterName, (*i).m_address, (*i).m_port, (*i).m_secret, (*i).m_locked, (*i).m_notRecommended, (*i).m_maxCharactersPerAccount, (*i).m_onlinePlayerLimit, (*i).m_onlineFreeTrialLimit, (*i).m_freeTrialCanCreateChar, (*i).m_onlineTutorialLimit); + } +} + +// ====================================================================== + +void TaskGetClusterList::GetClustersQuery::getSQL(std::string &sql) +{ + sql=std::string("begin :result := ")+DatabaseConnection::getInstance().getSchemaQualifier()+"login.get_cluster_list(:group_id); end;"; + // DEBUG_REPORT_LOG(true, ("TaskGetClusterList SQL: %s\n", sql.c_str())); + +} + +// ---------------------------------------------------------------------- + +bool TaskGetClusterList::GetClustersQuery::bindParameters() +{ + if (!bindParameter(group_id)) return false; + return true; +} + +// ---------------------------------------------------------------------- + +bool TaskGetClusterList::GetClustersQuery::bindColumns() +{ + if (!bindCol(cluster_id)) return false; + if (!bindCol(cluster_name)) return false; + if (!bindCol(address)) return false; + if (!bindCol(port)) return false; + if (!bindCol(secret)) return false; + if (!bindCol(locked)) return false; + if (!bindCol(not_recommended)) return false; + if (!bindCol(maxCharacterPerAccount)) return false; + if (!bindCol(online_player_limit)) return false; + if (!bindCol(online_free_trial_limit)) return false; + if (!bindCol(free_trial_can_create_char)) return false; + if (!bindCol(online_tutorial_limit)) return false; + + return true; +} + +// ---------------------------------------------------------------------- + +DB::Query::QueryMode TaskGetClusterList::GetClustersQuery::getExecutionMode() const +{ + return MODE_PLSQL_REFCURSOR; +} + +// ---------------------------------------------------------------------- + +TaskGetClusterList::GetClustersQuery::GetClustersQuery() : + Query(), + group_id(), + cluster_id(), + cluster_name(), + address(), + port(), + secret(), + locked(), + not_recommended(), + maxCharacterPerAccount(), + online_player_limit(), + online_free_trial_limit(), + free_trial_can_create_char(), + online_tutorial_limit() +{ +} + +// ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/TaskGetClusterList.h b/engine/server/application/LoginServer/src/shared/TaskGetClusterList.h new file mode 100644 index 00000000..534c95f1 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskGetClusterList.h @@ -0,0 +1,86 @@ +// ====================================================================== +// +// TaskGetClusterList.h +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_TaskGetClusterList_H +#define INCLUDED_TaskGetClusterList_H + +// ====================================================================== + +#include "serverNetworkMessages/AvatarList.h" +#include "sharedDatabaseInterface/Bindable.h" +#include "sharedDatabaseInterface/BindableNetworkId.h" +#include "sharedDatabaseInterface/DbQuery.h" +#include "sharedDatabaseInterface/DbTaskRequest.h" + +// ====================================================================== + +class TaskGetClusterList : public DB::TaskRequest +{ + public: + explicit TaskGetClusterList (int groupId); + + public: + virtual bool process (DB::Session *session); + virtual void onComplete (); + + private: + class GetClustersQuery : public DB::Query + { + public: + DB::BindableLong group_id; //lint !e1925 // public data member + + DB::BindableLong cluster_id; //lint !e1925 // public data member + DB::BindableString<255> cluster_name; //lint !e1925 // public data member + DB::BindableString<255> address; //lint !e1925 // public data member + DB::BindableLong port; //lint !e1925 // public data member + DB::BindableBool secret; //lint !e1925 // public data member + DB::BindableBool locked; //lint !e1925 // public data member + DB::BindableBool not_recommended; //lint !e1925 // public data member + DB::BindableLong maxCharacterPerAccount; //lint !e1925 // public data member + DB::BindableLong online_player_limit; //lint !e1925 // public data member + DB::BindableLong online_free_trial_limit; //lint !e1925 // public data member + DB::BindableBool free_trial_can_create_char; //lint !e1925 // public data member + DB::BindableLong online_tutorial_limit; //lint !e1925 // public data member + + GetClustersQuery(); + + virtual void getSQL(std::string &sql); + virtual bool bindParameters(); + virtual bool bindColumns(); + virtual QueryMode getExecutionMode() const; + + private: //disable + GetClustersQuery(const GetClustersQuery&); + GetClustersQuery& operator=(const GetClustersQuery&); + }; + + struct ClusterData + { + uint32 m_clusterId; + std::string m_clusterName; + std::string m_address; + uint16 m_port; + bool m_secret; + bool m_locked; + bool m_notRecommended; + int m_maxCharactersPerAccount; + int m_onlinePlayerLimit; + int m_onlineFreeTrialLimit; + bool m_freeTrialCanCreateChar; + int m_onlineTutorialLimit; + }; + + std::vector m_clusterData; + int m_groupId; + + private: + TaskGetClusterList (); // disable +}; + +// ====================================================================== + +#endif diff --git a/engine/server/application/LoginServer/src/shared/TaskGetValidationData.cpp b/engine/server/application/LoginServer/src/shared/TaskGetValidationData.cpp new file mode 100644 index 00000000..d646b57c --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskGetValidationData.cpp @@ -0,0 +1,591 @@ +// ====================================================================== +// +// TaskGetValidationData.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLoginServer.h" +#include "TaskGetValidationData.h" + +#include "ConfigLoginServer.h" +#include "DatabaseConnection.h" +#include "TaskGetAvatarList.h" +#include "TaskUpgradeAccount.h" +#include "serverNetworkMessages/AvatarList.h" +#include "serverNetworkMessages/TransferRequestMoveValidation.h" +#include "sharedDatabaseInterface/BindableNetworkId.h" +#include "sharedDatabaseInterface/DbSession.h" + +// ====================================================================== + +namespace TaskGetValidationDataNamespace +{ + class GetValidationDataQuery : public DB::Query + { + public: + GetValidationDataQuery(); + + DB::BindableLong station_id; //lint !e1925 // public data member + DB::BindableLong cluster_id; //lint !e1925 // public data member + DB::BindableLong character_type_id; //lint !e1925 // public data member + DB::BindableLong num_open_slots; //lint !e1925 // public data member + + virtual void getSQL(std::string &sql); + virtual bool bindParameters(); + virtual bool bindColumns(); + virtual QueryMode getExecutionMode() const; + + private: //disable + GetValidationDataQuery(const GetValidationDataQuery&); + GetValidationDataQuery &operator=(const GetValidationDataQuery&); + }; + + class GetCompletedTutorialQuery : public DB::Query + { + public: + GetCompletedTutorialQuery(StationId stationId); + + DB::BindableLong station_id; + DB::BindableBool completed_tutorial; + + virtual void getSQL(std::string &sql); + virtual bool bindParameters(); + virtual bool bindColumns(); + virtual QueryMode getExecutionMode() const; + + private: //disable + GetCompletedTutorialQuery(const GetCompletedTutorialQuery&); + GetCompletedTutorialQuery &operator=(const GetCompletedTutorialQuery&); + }; + + class GetConsumedRewardEventsQuery : public DB::Query + { + public: + explicit GetConsumedRewardEventsQuery(StationId stationId); + + virtual void getSQL(std::string &sql); + virtual bool bindParameters(); + virtual bool bindColumns(); + virtual QueryMode getExecutionMode() const; + + std::string getEventId() const; + uint32 getClusterId() const; + NetworkId const getCharacterId() const; + + private: + DB::BindableLong station_id; + DB::BindableString<100> event_id; + DB::BindableLong cluster_id; + DB::BindableNetworkId character_id; + + private: //disable + GetConsumedRewardEventsQuery(); + GetConsumedRewardEventsQuery(const GetConsumedRewardEventsQuery&); + GetConsumedRewardEventsQuery &operator=(const GetConsumedRewardEventsQuery&); + }; + + class GetClaimedRewardItemsQuery : public DB::Query + { + public: + explicit GetClaimedRewardItemsQuery(StationId stationId); + + virtual void getSQL(std::string &sql); + virtual bool bindParameters(); + virtual bool bindColumns(); + virtual QueryMode getExecutionMode() const; + + std::string getItemId() const; + uint32 getClusterId() const; + NetworkId const getCharacterId() const; + + private: + DB::BindableLong station_id; + DB::BindableString<100> item_id; + DB::BindableLong cluster_id; + DB::BindableNetworkId character_id; + + private: //disable + GetClaimedRewardItemsQuery(); + GetClaimedRewardItemsQuery(const GetClaimedRewardItemsQuery&); + GetClaimedRewardItemsQuery &operator=(const GetClaimedRewardItemsQuery&); + }; + + class IsClusterAtLimitQuery : public DB::Query + { + public: + IsClusterAtLimitQuery(); + + DB::BindableLong cluster_id; //lint !e1925 // public data member + DB::BindableLong result; //lint !e1925 // public data member + + virtual void getSQL (std::string &sql); + virtual bool bindParameters (); + virtual bool bindColumns (); + virtual QueryMode getExecutionMode () const; + + private: //disable + IsClusterAtLimitQuery (const IsClusterAtLimitQuery&); + IsClusterAtLimitQuery &operator= (const IsClusterAtLimitQuery&); + }; +} + +using namespace TaskGetValidationDataNamespace; + +// ====================================================================== + +TaskGetValidationData::TaskGetValidationData (StationId stationId, int clusterGroupId, uint32 clusterId, unsigned int track, uint32 subscriptionBits) : + TaskRequest(), + m_stationId(stationId), + m_clusterGroupId(clusterGroupId), + m_clusterId(clusterId), + m_openCharacterSlots(4,0), + m_canSkipTutorial(false), + m_track(track), + m_subscriptionBits(subscriptionBits), + m_transferRequest(0), + m_transferRequestSourceCharacterTemplateId(0), + m_consumedRewardEvents(), + m_claimedRewardItems() +{ +} + +// ---------------------------------------------------------------------- + +TaskGetValidationData::TaskGetValidationData(const TransferRequestMoveValidation & request, int clusterGroupId, uint32 clusterId) : + TaskRequest(), + m_stationId(request.getDestinationStationId()), + m_clusterGroupId(clusterGroupId), + m_clusterId(clusterId), + m_openCharacterSlots(4,0), + m_canSkipTutorial(true), + m_track(request.getTrack()), + m_transferRequest(0), + m_transferRequestSourceCharacterTemplateId(request.getSourceCharacterTemplateId()), + m_consumedRewardEvents(), + m_claimedRewardItems() +{ + Archive::ByteStream bs; + request.pack(bs); + Archive::ReadIterator ri(bs); + m_transferRequest = new TransferRequestMoveValidation(ri); +} + +// ---------------------------------------------------------------------- + +TaskGetValidationData::~TaskGetValidationData() +{ + delete m_transferRequest; +} + +// ---------------------------------------------------------------------- + +bool TaskGetValidationData::process(DB::Session *session) +{ + // if this is a same account transfer request, use a different check + // for available character slots; specifically, don't enforce the max + // characters per account rule because this is a same account transfer + // and after everything is said and done, the number of characters on + // the account will not change + if (m_transferRequest && (m_transferRequest->getSourceStationId() == m_transferRequest->getDestinationStationId())) + { + IsClusterAtLimitQuery clusterLimitQry; + clusterLimitQry.cluster_id = static_cast(m_clusterId); + + if (!(session->exec(&clusterLimitQry))) + return false; + + clusterLimitQry.done(); + + if (clusterLimitQry.result.getValue() == 0) + { + // cluster is not at limit, check per account per cluster limit + TaskVacateUnlockedSlot::GetOnlyOpenCharacterSlotsQuery qry; + qry.station_id = static_cast(m_stationId); + qry.cluster_id = static_cast(m_clusterId); + + int rowsFetched; + if (! (session->exec(&qry))) + return false; + while ((rowsFetched = qry.fetch()) > 0) + m_openCharacterSlots[static_cast(qry.character_type_id.getValue())]=qry.num_open_slots.getValue(); + qry.done(); + if (rowsFetched < 0) + return false; + } + } + else + { + GetValidationDataQuery qry; + qry.station_id = static_cast(m_stationId); + qry.cluster_id = static_cast(m_clusterId); + + int rowsFetched; + if (! (session->exec(&qry))) + return false; + while ((rowsFetched = qry.fetch()) > 0) + m_openCharacterSlots[static_cast(qry.character_type_id.getValue())]=qry.num_open_slots.getValue(); + qry.done(); + if (rowsFetched < 0) + return false; + } + + // if transfer request and the source character + // template id hasn't been specified, retrieve it + if (m_transferRequest && (m_openCharacterSlots[1] > 0) && (m_transferRequestSourceCharacterTemplateId == 0)) + { + uint32 const sourceClusterId = LoginServer::getInstance().getClusterIDByName(m_transferRequest->getSourceGalaxy()); + + TaskGetAvatarList::GetCharactersQuery qryGetCharacters; + qryGetCharacters.station_id = m_transferRequest->getSourceStationId(); //lint !e713 // loss of precision unsigned long to long + qryGetCharacters.cluster_group_id = m_clusterGroupId; + + if (!session->exec(&qryGetCharacters)) + return false; + + uint32 characterClusterId; + std::string characterName; + int rowsFetched; + while ((rowsFetched = qryGetCharacters.fetch()) > 0) + { + qryGetCharacters.cluster_id.getValue(characterClusterId); + if (characterClusterId == sourceClusterId) + { + qryGetCharacters.character_name.getValue(characterName); + if (characterName == m_transferRequest->getSourceCharacter()) + { + qryGetCharacters.object_template_id.getValue(m_transferRequestSourceCharacterTemplateId); + break; + } + } + } + + qryGetCharacters.done(); + } + + if (!m_transferRequest) + { + GetConsumedRewardEventsQuery eventQuery(m_stationId); + int rowsFetched; + if (! (session->exec(&eventQuery))) + return false; + while ((rowsFetched = eventQuery.fetch()) > 0) + { + // If the event was claimed on this cluster, tell the cluster the network ID of the character that claimed it. + // If claimed on another cluster, hide the network ID because it's not meaningful + NetworkId const characterId = eventQuery.getClusterId()==m_clusterId ? eventQuery.getCharacterId() : NetworkId::cms_invalid; + m_consumedRewardEvents.push_back(std::make_pair(characterId, eventQuery.getEventId())); + } + eventQuery.done(); + if (rowsFetched < 0) + return false; + + GetClaimedRewardItemsQuery itemQuery(m_stationId); + if (! (session->exec(&itemQuery))) + return false; + while ((rowsFetched = itemQuery.fetch()) > 0) + { + NetworkId const characterId = itemQuery.getClusterId()==m_clusterId ? itemQuery.getCharacterId() : NetworkId::cms_invalid; + m_claimedRewardItems.push_back(std::make_pair(characterId, itemQuery.getItemId())); + } + itemQuery.done(); + if (rowsFetched < 0) + return false; + + // check to see if the account can skip the tutorial or not + GetCompletedTutorialQuery tutorialQuery(m_stationId); + if (! (session->exec(&tutorialQuery))) + return false; + while ((rowsFetched = tutorialQuery.fetch()) > 0) + { + tutorialQuery.completed_tutorial.getValue(m_canSkipTutorial); + } + tutorialQuery.done(); + if (rowsFetched < 0) + return false; + } + return true; +} + +// ---------------------------------------------------------------------- + +void TaskGetValidationData::onComplete() +{ + bool canCreateNormal=false; + bool canCreateJedi=false; + if (m_openCharacterSlots[1] > 0) + canCreateNormal=true; + if (m_openCharacterSlots[2] > 0 && m_openCharacterSlots[3] > 0) + canCreateJedi=true; + + // check to see if character creation has been disabled for the cluster + if (ConfigLoginServer::isCharacterCreationDisabled(LoginServer::getInstance().getClusterNameById(m_clusterId))) + { + canCreateNormal=false; + canCreateJedi=false; + } + + if(m_transferRequest) + { + LoginServer::getInstance().validateAccountForTransfer(*m_transferRequest, m_clusterId, m_transferRequestSourceCharacterTemplateId, canCreateNormal, false); + } + else + { + LoginServer::getInstance().validateAccount(m_stationId, m_clusterId, m_subscriptionBits, canCreateNormal, canCreateJedi, m_canSkipTutorial, m_track, m_consumedRewardEvents, m_claimedRewardItems); + } +} + +// ====================================================================== + +void GetValidationDataQuery::getSQL(std::string &sql) +{ + sql = std::string("begin :rc := ")+DatabaseConnection::getInstance().getSchemaQualifier()+"login.get_open_character_slots(:station_id,:cluster_id); end;"; +} + +// ---------------------------------------------------------------------- + +bool GetValidationDataQuery::bindParameters() +{ + if (!bindParameter(station_id)) return false; + if (!bindParameter(cluster_id)) return false; + + return true; +} + +// ---------------------------------------------------------------------- + +bool GetValidationDataQuery::bindColumns() +{ + if (!bindCol(character_type_id)) return false; + if (!bindCol(num_open_slots)) return false; + + return true; +} + +// ---------------------------------------------------------------------- + +DB::Query::QueryMode GetValidationDataQuery::getExecutionMode() const +{ + return MODE_PLSQL_REFCURSOR; +} + +// ---------------------------------------------------------------------- + +GetValidationDataQuery::GetValidationDataQuery() : + Query(), + station_id(), + cluster_id(), + character_type_id(), + num_open_slots() +{ +} + +// ====================================================================== + +void GetCompletedTutorialQuery::getSQL(std::string &sql) +{ + sql = std::string("begin :rc := ")+DatabaseConnection::getInstance().getSchemaQualifier()+"login.get_completed_tutorial(:station_id); end;"; +} + +// ---------------------------------------------------------------------- + +bool GetCompletedTutorialQuery::bindParameters() +{ + if (!bindParameter(station_id)) return false; + + return true; +} + +// ---------------------------------------------------------------------- + +bool GetCompletedTutorialQuery::bindColumns() +{ + if (!bindCol(completed_tutorial)) return false; + + return true; +} + +// ---------------------------------------------------------------------- + +DB::Query::QueryMode GetCompletedTutorialQuery::getExecutionMode() const +{ + return MODE_PLSQL_REFCURSOR; +} + +// ---------------------------------------------------------------------- + +GetCompletedTutorialQuery::GetCompletedTutorialQuery(StationId stationId) : + DB::Query(), + station_id(stationId), + completed_tutorial(false) +{ +} + +// ====================================================================== + +GetConsumedRewardEventsQuery::GetConsumedRewardEventsQuery(StationId stationId) : + DB::Query(), + station_id(static_cast(stationId)), + event_id(), + cluster_id(), + character_id() +{ +} + +// ---------------------------------------------------------------------- + +void GetConsumedRewardEventsQuery::getSQL(std::string &sql) +{ + sql = std::string("begin :result := ")+DatabaseConnection::getInstance().getSchemaQualifier()+"login.get_consumed_reward_events(:station_id); end;"; +} + +// ---------------------------------------------------------------------- + +bool GetConsumedRewardEventsQuery::bindParameters() +{ + if (!bindParameter(station_id)) return false; + return true; +} + +// ---------------------------------------------------------------------- + +bool GetConsumedRewardEventsQuery::bindColumns() +{ + if (!bindCol(event_id)) return false; + if (!bindCol(cluster_id)) return false; + if (!bindCol(character_id)) return false; + return true; +} + +// ---------------------------------------------------------------------- + +DB::Query::QueryMode GetConsumedRewardEventsQuery::getExecutionMode() const +{ + return MODE_PLSQL_REFCURSOR; +} + +// ---------------------------------------------------------------------- + +std::string GetConsumedRewardEventsQuery::getEventId() const +{ + return (event_id.getValueASCII()); +} + +// ---------------------------------------------------------------------- + +uint32 GetConsumedRewardEventsQuery::getClusterId() const +{ + return static_cast(cluster_id.getValue()); +} + +// ---------------------------------------------------------------------- + +NetworkId const GetConsumedRewardEventsQuery::getCharacterId() const +{ + return character_id.getValue(); +} + +// ====================================================================== + +GetClaimedRewardItemsQuery::GetClaimedRewardItemsQuery(StationId stationId) : + DB::Query(), + station_id(static_cast(stationId)), + item_id(), + cluster_id(), + character_id() +{ +} + +// ---------------------------------------------------------------------- + +void GetClaimedRewardItemsQuery::getSQL(std::string &sql) +{ + sql = std::string("begin :result := ")+DatabaseConnection::getInstance().getSchemaQualifier()+"login.get_claimed_reward_items(:station_id); end;"; +} + +// ---------------------------------------------------------------------- + +bool GetClaimedRewardItemsQuery::bindParameters() +{ + if (!bindParameter(station_id)) return false; + return true; +} + +// ---------------------------------------------------------------------- + +bool GetClaimedRewardItemsQuery::bindColumns() +{ + if (!bindCol(item_id)) return false; + if (!bindCol(cluster_id)) return false; + if (!bindCol(character_id)) return false; + return true; +} + +// ---------------------------------------------------------------------- + +DB::Query::QueryMode GetClaimedRewardItemsQuery::getExecutionMode() const +{ + return MODE_PLSQL_REFCURSOR; +} + +// ---------------------------------------------------------------------- + +std::string GetClaimedRewardItemsQuery::getItemId() const +{ + return (item_id.getValueASCII()); +} + +// ---------------------------------------------------------------------- + +uint32 GetClaimedRewardItemsQuery::getClusterId() const +{ + return static_cast(cluster_id.getValue()); +} + +// ---------------------------------------------------------------------- + +NetworkId const GetClaimedRewardItemsQuery::getCharacterId() const +{ + return character_id.getValue(); +} + +// ====================================================================== + +IsClusterAtLimitQuery::IsClusterAtLimitQuery() : +Query(), +cluster_id(), +result() +{ +} + +// ---------------------------------------------------------------------- + +void IsClusterAtLimitQuery::getSQL(std::string &sql) +{ + sql = std::string("begin :result := ")+DatabaseConnection::getInstance().getSchemaQualifier()+"login.is_cluster_at_limit(:cluster_id); end;"; +} + +// ---------------------------------------------------------------------- + +bool IsClusterAtLimitQuery::bindParameters() +{ + if (!bindParameter(result)) return false; + if (!bindParameter(cluster_id)) return false; + return true; +} + +// ---------------------------------------------------------------------- + +bool IsClusterAtLimitQuery::bindColumns() +{ + return true; +} + +// ---------------------------------------------------------------------- + +DB::Query::QueryMode IsClusterAtLimitQuery::getExecutionMode() const +{ + return MODE_PROCEXEC; +} + +// ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/TaskGetValidationData.h b/engine/server/application/LoginServer/src/shared/TaskGetValidationData.h new file mode 100644 index 00000000..39f29fae --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskGetValidationData.h @@ -0,0 +1,55 @@ +// ====================================================================== +// +// TaskGetValidationData.h +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_TaskGetValidationData_H +#define INCLUDED_TaskGetValidationData_H + +// ====================================================================== + +#include "serverNetworkMessages/AvatarList.h" +#include "sharedDatabaseInterface/Bindable.h" +#include "sharedDatabaseInterface/DbQuery.h" +#include "sharedDatabaseInterface/DbTaskRequest.h" + +class TransferRequestMoveValidation; + +// ====================================================================== + +class TaskGetValidationData : public DB::TaskRequest +{ + public: + TaskGetValidationData (StationId stationId, int clusterGroupId, uint32 clusterId, unsigned int track, uint32 subscriptionBits); + TaskGetValidationData (const TransferRequestMoveValidation & request, int clusterGroupId, uint32 clusterId); + ~TaskGetValidationData(); + public: + virtual bool process (DB::Session *session); + virtual void onComplete (); + + private: + TaskGetValidationData(); // disabled default constructor + + private: + StationId m_stationId; + int m_clusterGroupId; + uint32 m_clusterId; + std::vector m_openCharacterSlots; + bool m_canSkipTutorial; + unsigned int m_track; + uint32 m_subscriptionBits; + TransferRequestMoveValidation * m_transferRequest; + uint32 m_transferRequestSourceCharacterTemplateId; + std::vector > m_consumedRewardEvents; + std::vector > m_claimedRewardItems; + + private: + TaskGetValidationData(const TaskGetValidationData&); //disable + TaskGetValidationData &operator=(const TaskGetValidationData&); //disable +}; + +// ====================================================================== + +#endif diff --git a/engine/server/application/LoginServer/src/shared/TaskRegisterNewCluster.cpp b/engine/server/application/LoginServer/src/shared/TaskRegisterNewCluster.cpp new file mode 100644 index 00000000..b5e8bc54 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskRegisterNewCluster.cpp @@ -0,0 +1,90 @@ +// ====================================================================== +// +// TaskRegisterNewCluster.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLoginServer.h" +#include "TaskRegisterNewCluster.h" + +#include "serverNetworkMessages/AvatarList.h" +#include "DatabaseConnection.h" +#include "sharedDatabaseInterface/DbSession.h" + +// ====================================================================== + +TaskRegisterNewCluster::TaskRegisterNewCluster (const std::string &newClusterName, const std::string &address) : + TaskRequest(), + m_clusterId(0), + m_clusterName(newClusterName), + m_address(address) +{ +} + +// ---------------------------------------------------------------------- + +bool TaskRegisterNewCluster::process(DB::Session *session) +{ + RegisterClusterQuery qry; + qry.cluster_name=m_clusterName; + qry.address=m_address; + + bool rval = session->exec(&qry); + + qry.cluster_id.getValue(m_clusterId); + return rval; +} + +// ---------------------------------------------------------------------- + +void TaskRegisterNewCluster::onComplete() +{ + DEBUG_FATAL(m_clusterId == 0 || m_clusterId > 10000,("TaskRegisterNewCluster got invalid number %u for cluster id when trying to register cluster %s\n",m_clusterId,m_clusterName.c_str())); + LoginServer::getInstance().onClusterRegistered(m_clusterId, m_clusterName); +} + +// ====================================================================== + +void TaskRegisterNewCluster::RegisterClusterQuery::getSQL(std::string &sql) +{ + sql = std::string("begin ")+DatabaseConnection::getInstance().getSchemaQualifier()+"login.register_new_cluster(:cluster_name, :address, :cluster_id); end;"; + // DEBUG_REPORT_LOG(true, ("TaskRegisterNewCluster SQL: %s\n", sql.c_str())); +} + +// ---------------------------------------------------------------------- + +bool TaskRegisterNewCluster::RegisterClusterQuery::bindParameters() +{ + if (!bindParameter(cluster_name)) return false; + if (!bindParameter(address)) return false; + if (!bindParameter(cluster_id)) return false; + + return true; +} + +// ---------------------------------------------------------------------- + +bool TaskRegisterNewCluster::RegisterClusterQuery::bindColumns() +{ + return true; +} + +// ---------------------------------------------------------------------- + +DB::Query::QueryMode TaskRegisterNewCluster::RegisterClusterQuery::getExecutionMode() const +{ + return MODE_PROCEXEC; +} + +// ---------------------------------------------------------------------- + +TaskRegisterNewCluster::RegisterClusterQuery::RegisterClusterQuery() : + Query(), + cluster_id(), + cluster_name(), + address() +{ +} + +// ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/TaskRegisterNewCluster.h b/engine/server/application/LoginServer/src/shared/TaskRegisterNewCluster.h new file mode 100644 index 00000000..e756e2d9 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskRegisterNewCluster.h @@ -0,0 +1,59 @@ +// ====================================================================== +// +// TaskRegisterNewCluster.h +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_TaskRegisterNewCluster_H +#define INCLUDED_TaskRegisterNewCluster_H + +// ====================================================================== + +#include "serverNetworkMessages/AvatarList.h" +#include "sharedDatabaseInterface/Bindable.h" +#include "sharedDatabaseInterface/BindableNetworkId.h" +#include "sharedDatabaseInterface/DbQuery.h" +#include "sharedDatabaseInterface/DbTaskRequest.h" + +// ====================================================================== + +class TaskRegisterNewCluster : public DB::TaskRequest +{ + public: + explicit TaskRegisterNewCluster (const std::string &newClusterName, const std::string &address); + + public: + virtual bool process (DB::Session *session); + virtual void onComplete (); + + private: + TaskRegisterNewCluster(); // disabled default constructor + class RegisterClusterQuery : public DB::Query + { + public: + RegisterClusterQuery(); + + DB::BindableLong cluster_id; //lint !e1925 // public data member + DB::BindableString<255> cluster_name; //lint !e1925 // public data member + DB::BindableString<255> address; //lint !e1925 // public data member + + virtual void getSQL(std::string &sql); + virtual bool bindParameters(); + virtual bool bindColumns(); + virtual QueryMode getExecutionMode() const; + + private: //disable + RegisterClusterQuery(const RegisterClusterQuery&); + RegisterClusterQuery &operator=(const RegisterClusterQuery&); + }; + + private: + uint32 m_clusterId; + std::string m_clusterName; + std::string m_address; +}; + +// ====================================================================== + +#endif diff --git a/engine/server/application/LoginServer/src/shared/TaskRenameCharacter.cpp b/engine/server/application/LoginServer/src/shared/TaskRenameCharacter.cpp new file mode 100644 index 00000000..ebcf473e --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskRenameCharacter.cpp @@ -0,0 +1,110 @@ +// ====================================================================== +// +// TaskRenameCharacter.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLoginServer.h" +#include "TaskRenameCharacter.h" + +#include "LoginServer.h" +#include "DatabaseConnection.h" +#include "serverNetworkMessages/TransferCharacterData.h" +#include "serverNetworkMessages/TransferCharacterDataArchive.h" +#include "sharedDatabaseInterface/DbSession.h" +#include "sharedNetworkMessages/GenericValueTypeMessage.h" + +// ====================================================================== + +TaskRenameCharacter::TaskRenameCharacter(uint32 clusterId, const NetworkId &characterId, const Unicode::String &newName, const TransferCharacterData * requestData) : + TaskRequest(), + m_clusterId(clusterId), + m_characterId(characterId), + m_newName(newName), + m_success(false), + m_requestData(0) +{ + if(requestData) + { + m_requestData = new TransferCharacterData(*requestData); + } +} + +// ---------------------------------------------------------------------- + +TaskRenameCharacter::~TaskRenameCharacter() +{ + delete m_requestData; +} + +// ---------------------------------------------------------------------- + +bool TaskRenameCharacter::process(DB::Session *session) +{ + RenameCharacterQuery qry; + qry.cluster_id=m_clusterId; //lint !e713 loss of precision + qry.character_id=m_characterId; + qry.new_name=m_newName; + + m_success = session->exec(&qry); + + qry.done(); + return m_success; +} + +// ---------------------------------------------------------------------- + +void TaskRenameCharacter::onComplete() +{ + if(m_requestData) + { + m_requestData->setIsValidName(m_success); + GenericValueTypeMessage reply("TransferRenameCharacterReplyFromLoginServer", *m_requestData); + LoginServer::getInstance().sendToCluster(m_clusterId, reply); + } +} + +// ====================================================================== + +TaskRenameCharacter::RenameCharacterQuery::RenameCharacterQuery() : + Query(), + cluster_id(), + character_id(), + new_name() +{ +} + +// ---------------------------------------------------------------------- + +void TaskRenameCharacter::RenameCharacterQuery::getSQL(std::string &sql) +{ + sql = std::string("begin ")+DatabaseConnection::getInstance().getSchemaQualifier()+"login.rename_character(:cluster_id, :character_id, :new_name); end;"; + // DEBUG_REPORT_LOG(true, ("TaskRenameCharacter SQL: %s\n", sql.c_str())); +} + +// ---------------------------------------------------------------------- + +bool TaskRenameCharacter::RenameCharacterQuery::bindParameters() +{ + if (!bindParameter(cluster_id)) return false; + if (!bindParameter(character_id)) return false; + if (!bindParameter(new_name)) return false; + return true; +} + +// ---------------------------------------------------------------------- + +bool TaskRenameCharacter::RenameCharacterQuery::bindColumns() +{ + return true; +} + +// ---------------------------------------------------------------------- + +DB::Query::QueryMode TaskRenameCharacter::RenameCharacterQuery::getExecutionMode() const +{ + return MODE_PROCEXEC; +} + +// ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/TaskRenameCharacter.h b/engine/server/application/LoginServer/src/shared/TaskRenameCharacter.h new file mode 100644 index 00000000..525cc3ac --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskRenameCharacter.h @@ -0,0 +1,62 @@ +// ====================================================================== +// +// TaskRenameCharacter.h +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_TaskRenameCharacter_H +#define INCLUDED_TaskRenameCharacter_H + +// ====================================================================== + +#include "sharedDatabaseInterface/Bindable.h" +#include "sharedDatabaseInterface/BindableNetworkId.h" +#include "sharedDatabaseInterface/DbQuery.h" +#include "sharedDatabaseInterface/DbTaskRequest.h" + +class TransferCharacterData; + +// ====================================================================== + +class TaskRenameCharacter : public DB::TaskRequest +{ + public: + TaskRenameCharacter(uint32 clusterId, const NetworkId &characterId, const Unicode::String &newName, const TransferCharacterData * requestData); + ~TaskRenameCharacter(); + public: + virtual bool process (DB::Session *session); + virtual void onComplete (); + + private: + TaskRenameCharacter(); // disabled default constructor + class RenameCharacterQuery : public DB::Query + { + public: + RenameCharacterQuery(); + + DB::BindableLong cluster_id; //lint !e1925 // public data member + DB::BindableNetworkId character_id; //lint !e1925 // public data member + DB::BindableString<127> new_name; //lint !e1925 // public data member + + virtual void getSQL (std::string &sql); + virtual bool bindParameters (); + virtual bool bindColumns (); + virtual QueryMode getExecutionMode () const; + + private: //disable + RenameCharacterQuery (const RenameCharacterQuery&); + RenameCharacterQuery &operator= (const RenameCharacterQuery&); + }; + + private: + uint32 m_clusterId; + NetworkId m_characterId; + Unicode::String m_newName; + bool m_success; + TransferCharacterData * m_requestData; +}; + +// ====================================================================== + +#endif diff --git a/engine/server/application/LoginServer/src/shared/TaskRestoreCharacter.cpp b/engine/server/application/LoginServer/src/shared/TaskRestoreCharacter.cpp new file mode 100644 index 00000000..3820e61d --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskRestoreCharacter.cpp @@ -0,0 +1,133 @@ +// ====================================================================== +// +// TaskRestoreCharacter.cpp +// copyright (c) 2003 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLoginServer.h" +#include "TaskRestoreCharacter.h" + +#include "DatabaseConnection.h" +#include "LoginServer.h" +#include "serverNetworkMessages/LoginCreateCharacterAckMessage.h" +#include "sharedDatabaseInterface/DbSession.h" +#include "sharedFoundation/NetworkIdArchive.h" +#include "sharedNetworkMessages/GenericValueTypeMessage.h" + +// ====================================================================== + +TaskRestoreCharacter::TaskRestoreCharacter(uint32 clusterId, const std::string &whoRequested, StationId stationId, const Unicode::String &characterName, const NetworkId &characterId, int templateId, bool jedi) : + TaskRequest(), + m_clusterId(clusterId), + m_whoRequested(whoRequested), + m_stationId(stationId), + m_characterName(characterName), + m_characterId(characterId), + m_templateId(templateId), + m_jedi(jedi), + m_result(0) +{ +} + +// ---------------------------------------------------------------------- + +bool TaskRestoreCharacter::process(DB::Session *session) +{ + RestoreCharacterQuery qry; + qry.cluster_id = static_cast(m_clusterId); + qry.station_id = static_cast(m_stationId); + qry.character_name = m_characterName; + qry.character_id = m_characterId; + qry.template_id = m_templateId; + if (m_jedi) + qry.character_type = 2; + else + qry.character_type = 1; + + bool rval = session->exec(&qry); + qry.done(); + + qry.result.getValue(m_result); + return rval; +} + +// ---------------------------------------------------------------------- + +void TaskRestoreCharacter::onComplete() +{ + std::string message; + switch (m_result) + { + case 1: + message = "Character restored."; + break; + + case 2: + message = "Character restored. The player now has more characters on this cluster than the normal limit."; + break; + + case 3: + message = "There was an error in the database while attempting to restore the character."; + break; + + default: + message = "The database returned an unknown code in response to the request to restore the character."; + break; + } + + GenericValueTypeMessage > reply("DatabaseConsoleReplyMessage", + std::make_pair(m_whoRequested, message)); + LoginServer::getInstance().sendToCluster(m_clusterId, reply); +} + +// ====================================================================== + +TaskRestoreCharacter::RestoreCharacterQuery::RestoreCharacterQuery() : + Query(), + cluster_id(), + station_id(), + character_name(), + character_id(), + template_id(), + character_type(), + result() +{ +} + +// ---------------------------------------------------------------------- + +void TaskRestoreCharacter::RestoreCharacterQuery::getSQL(std::string &sql) +{ + sql = std::string("begin :result := ")+DatabaseConnection::getInstance().getSchemaQualifier()+"login.restore_character(:cluster_id, :station_id, :character_name, :character_id, :template_name, :character_type); end;"; +} + +// ---------------------------------------------------------------------- + +bool TaskRestoreCharacter::RestoreCharacterQuery::bindParameters() +{ + if (!bindParameter(result)) return false; + if (!bindParameter(cluster_id)) return false; + if (!bindParameter(station_id)) return false; + if (!bindParameter(character_name)) return false; + if (!bindParameter(character_id)) return false; + if (!bindParameter(template_id)) return false; + if (!bindParameter(character_type)) return false; + return true; +} + +// ---------------------------------------------------------------------- + +bool TaskRestoreCharacter::RestoreCharacterQuery::bindColumns() +{ + return true; +} + +// ---------------------------------------------------------------------- + +DB::Query::QueryMode TaskRestoreCharacter::RestoreCharacterQuery::getExecutionMode() const +{ + return MODE_PROCEXEC; +} + +// ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/TaskRestoreCharacter.h b/engine/server/application/LoginServer/src/shared/TaskRestoreCharacter.h new file mode 100644 index 00000000..d30d6abd --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskRestoreCharacter.h @@ -0,0 +1,67 @@ +// ====================================================================== +// +// TaskRestoreCharacter.h +// copyright (c) 2003 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_TaskRestoreCharacter_H +#define INCLUDED_TaskRestoreCharacter_H + +// ====================================================================== + +#include "sharedDatabaseInterface/Bindable.h" +#include "sharedDatabaseInterface/BindableNetworkId.h" +#include "sharedDatabaseInterface/DbQuery.h" +#include "sharedDatabaseInterface/DbTaskRequest.h" + +// ====================================================================== + +class TaskRestoreCharacter : public DB::TaskRequest +{ + public: + TaskRestoreCharacter(uint32 clusterId, const std::string &whoRequested, StationId stationId, const Unicode::String &characterName, const NetworkId &characterId, int templateId, bool jedi); + + public: + virtual bool process (DB::Session *session); + virtual void onComplete (); + + private: + TaskRestoreCharacter(); // disabled default constructor + class RestoreCharacterQuery : public DB::Query + { + public: + RestoreCharacterQuery(); + + DB::BindableLong cluster_id; //lint !e1925 // public data member + DB::BindableLong station_id; //lint !e1925 // public data member + DB::BindableString<127> character_name; //lint !e1925 // public data member + DB::BindableNetworkId character_id; //lint !e1925 // public data member + DB::BindableLong template_id; //lint !e1925 // public data member + DB::BindableLong character_type; //lint !e1925 // public data member + DB::BindableLong result; //lint !e1925 // public data member + + virtual void getSQL (std::string &sql); + virtual bool bindParameters (); + virtual bool bindColumns (); + virtual QueryMode getExecutionMode () const; + + private: //disable + RestoreCharacterQuery (const RestoreCharacterQuery&); + RestoreCharacterQuery &operator= (const RestoreCharacterQuery&); + }; + + private: + uint32 m_clusterId; + std::string m_whoRequested; + StationId m_stationId; + Unicode::String m_characterName; + NetworkId m_characterId; + int m_templateId; + bool m_jedi; + int m_result; +}; + +// ====================================================================== + +#endif diff --git a/engine/server/application/LoginServer/src/shared/TaskSetPurgeStatus.cpp b/engine/server/application/LoginServer/src/shared/TaskSetPurgeStatus.cpp new file mode 100644 index 00000000..3f20de28 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskSetPurgeStatus.cpp @@ -0,0 +1,107 @@ +// ====================================================================== +// +// TaskSetPurgeStatus.cpp +// copyright (c) 2005 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLoginServer.h" +#include "TaskSetPurgeStatus.h" + +#include "DatabaseConnection.h" +#include "PurgeManager.h" +#include "sharedDatabaseInterface/Bindable.h" +#include "sharedDatabaseInterface/DbQuery.h" +#include "sharedDatabaseInterface/DbSession.h" + +// ====================================================================== + +namespace TaskSetPurgeStatusNamespace +{ + class SetPurgeStatusQuery : public DB::Query + { + public: + SetPurgeStatusQuery(StationId account, int purgePhase); + + virtual void getSQL(std::string &sql); + virtual bool bindParameters(); + virtual bool bindColumns(); + virtual QueryMode getExecutionMode() const; + + private: + DB::BindableLong m_account; + DB::BindableLong m_purge_phase; + + private: //disable + SetPurgeStatusQuery(const SetPurgeStatusQuery&); + SetPurgeStatusQuery& operator=(const SetPurgeStatusQuery&); + }; +} +using namespace TaskSetPurgeStatusNamespace; + +// ====================================================================== + +TaskSetPurgeStatus::TaskSetPurgeStatus(StationId account, int purgePhase) : + DB::TaskRequest(), + m_account(account), + m_purgePhase(purgePhase) +{ +} + +// ---------------------------------------------------------------------- + +bool TaskSetPurgeStatus::process(DB::Session *session) +{ + SetPurgeStatusQuery qry(m_account, m_purgePhase); + if (!session->exec(&qry)) + return false; + return true; +} + +// ---------------------------------------------------------------------- + +void TaskSetPurgeStatus::onComplete() +{ +} + +// ====================================================================== + + +SetPurgeStatusQuery::SetPurgeStatusQuery(StationId account, int purgePhase) : + Query(), + m_account(account), + m_purge_phase(purgePhase) +{ +} + +// ---------------------------------------------------------------------- + +void SetPurgeStatusQuery::getSQL(std::string &sql) +{ + sql=std::string("begin ")+DatabaseConnection::getInstance().getSchemaQualifier()+"purge_process.set_purge_status(:account, :purge_phase); end;"; +} + +// ---------------------------------------------------------------------- + +bool SetPurgeStatusQuery::bindParameters() +{ + if (!bindParameter(m_account)) return false; + if (!bindParameter(m_purge_phase)) return false; + return true; +} + +// ---------------------------------------------------------------------- + +bool SetPurgeStatusQuery::bindColumns() +{ + return true; +} + +// ---------------------------------------------------------------------- + +SetPurgeStatusQuery::QueryMode SetPurgeStatusQuery::getExecutionMode() const +{ + return MODE_PROCEXEC; +} + +// ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/TaskSetPurgeStatus.h b/engine/server/application/LoginServer/src/shared/TaskSetPurgeStatus.h new file mode 100644 index 00000000..065752f6 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskSetPurgeStatus.h @@ -0,0 +1,29 @@ +// ====================================================================== +// +// TaskSetPurgeStatus.h +// copyright (c) 2005 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_TaskSetPurgeStatus_H +#define INCLUDED_TaskSetPurgeStatus_H + +// ====================================================================== + +#include "sharedDatabaseInterface/DbTaskRequest.h" + +class TaskSetPurgeStatus : public DB::TaskRequest +{ + public: + explicit TaskSetPurgeStatus(StationId account, int purgePhase); + virtual bool process (DB::Session *session); + virtual void onComplete (); + + private: + StationId m_account; + int m_purgePhase; +}; + +// ====================================================================== + +#endif diff --git a/engine/server/application/LoginServer/src/shared/TaskToggleCharacterDisable.cpp b/engine/server/application/LoginServer/src/shared/TaskToggleCharacterDisable.cpp new file mode 100644 index 00000000..79fe61e8 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskToggleCharacterDisable.cpp @@ -0,0 +1,95 @@ +// ====================================================================== +// +// TaskToggleCharacterDisable.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLoginServer.h" +#include "TaskToggleCharacterDisable.h" + +#include "ClientConnection.h" +#include "LoginServer.h" +#include "DatabaseConnection.h" +#include "sharedDatabaseInterface/DbSession.h" + +// ====================================================================== + +TaskToggleCharacterDisable::TaskToggleCharacterDisable(uint32 clusterId, const NetworkId &characterId, StationId stationId, bool enabled) : + TaskRequest(), + m_clusterId(clusterId), + m_characterId(characterId), + m_stationId(stationId), + m_enabled(enabled) +{ +} + +// ---------------------------------------------------------------------- + +bool TaskToggleCharacterDisable::process(DB::Session *session) +{ + ToggleCharacterDisableQuery qry; + qry.cluster_id=static_cast(m_clusterId); + qry.character_id=m_characterId; + qry.station_id=static_cast(m_stationId); + qry.enabled_flag=m_enabled; + + bool rval = session->exec(&qry); + + qry.done(); + return rval; +} + +// ---------------------------------------------------------------------- + +void TaskToggleCharacterDisable::onComplete() +{ +} + +// ---------------------------------------------------------------------- + +TaskToggleCharacterDisable::ToggleCharacterDisableQuery::ToggleCharacterDisableQuery() : + Query(), + cluster_id(), + character_id(), + station_id(), + enabled_flag() +{ +} + +// ---------------------------------------------------------------------- + +void TaskToggleCharacterDisable::ToggleCharacterDisableQuery::getSQL(std::string &sql) +{ + sql = std::string("begin ")+DatabaseConnection::getInstance().getSchemaQualifier()+"login.toggle_disable_character(:cluster_id, :character_id, :station_id, :enabled); end;"; + // DEBUG_REPORT_LOG(true, ("TaskToggleCharacterDisable SQL: %s\n", sql.c_str())); + +} + +// ---------------------------------------------------------------------- + +bool TaskToggleCharacterDisable::ToggleCharacterDisableQuery::bindParameters() +{ + if (!bindParameter(cluster_id)) return false; + if (!bindParameter(character_id)) return false; + if (!bindParameter(station_id)) return false; + if (!bindParameter(enabled_flag)) return false; + + return true; +} + +// ---------------------------------------------------------------------- + +bool TaskToggleCharacterDisable::ToggleCharacterDisableQuery::bindColumns() +{ + return true; +} + +// ---------------------------------------------------------------------- + +DB::Query::QueryMode TaskToggleCharacterDisable::ToggleCharacterDisableQuery::getExecutionMode() const +{ + return MODE_PROCEXEC; +} + +// ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/TaskToggleCharacterDisable.h b/engine/server/application/LoginServer/src/shared/TaskToggleCharacterDisable.h new file mode 100644 index 00000000..32d21cb1 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskToggleCharacterDisable.h @@ -0,0 +1,63 @@ +// ====================================================================== +// +// TaskToggleCharacterDisable.h +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_TaskToggleCharacterDisable_H +#define INCLUDED_TaskToggleCharacterDisable_H + +// ====================================================================== + +#include "serverNetworkMessages/AvatarList.h" +#include "sharedDatabaseInterface/Bindable.h" +#include "sharedDatabaseInterface/BindableNetworkId.h" +#include "sharedDatabaseInterface/DbQuery.h" +#include "sharedDatabaseInterface/DbTaskRequest.h" + +// ====================================================================== + +class TaskToggleCharacterDisable : public DB::TaskRequest +{ + public: + TaskToggleCharacterDisable(uint32 clusterId, const NetworkId &characterId, StationId stationId, bool enabled); + + public: + virtual bool process (DB::Session *session); + virtual void onComplete (); + + private: + TaskToggleCharacterDisable(); // disabled default constructor + + class ToggleCharacterDisableQuery : public DB::Query + { + public: + ToggleCharacterDisableQuery(); + + DB::BindableLong cluster_id; //lint !e1925 // public data member : suppressed because this is a private inner class + DB::BindableNetworkId character_id; //lint !e1925 // public data member : suppressed because this is a private inner class + DB::BindableLong station_id; //lint !e1925 // public data member : suppressed because this is a private inner class + DB::BindableBool enabled_flag; //lint !e1925 // public data member : suppressed because this is a private inner class + + + virtual void getSQL(std::string &sql); + virtual bool bindParameters(); + virtual bool bindColumns(); + virtual QueryMode getExecutionMode() const; + + private: //disable + ToggleCharacterDisableQuery(const ToggleCharacterDisableQuery&); + ToggleCharacterDisableQuery &operator=(const ToggleCharacterDisableQuery&); + }; + + private: + uint32 m_clusterId; + NetworkId m_characterId; + StationId m_stationId; + bool m_enabled; +}; + +// ====================================================================== + +#endif diff --git a/engine/server/application/LoginServer/src/shared/TaskToggleCompletedTutorial.cpp b/engine/server/application/LoginServer/src/shared/TaskToggleCompletedTutorial.cpp new file mode 100644 index 00000000..3e063bf9 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskToggleCompletedTutorial.cpp @@ -0,0 +1,85 @@ +// ====================================================================== +// +// TaskToggleCompletedTutorial.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLoginServer.h" +#include "TaskToggleCompletedTutorial.h" + +#include "LoginServer.h" +#include "DatabaseConnection.h" +#include "sharedDatabaseInterface/DbSession.h" + +// ====================================================================== + +TaskToggleCompletedTutorial::TaskToggleCompletedTutorial(StationId stationId, bool completed) : + TaskRequest(), + m_stationId(stationId), + m_completed(completed) +{ +} + +// ---------------------------------------------------------------------- + +bool TaskToggleCompletedTutorial::process(DB::Session *session) +{ + ToggleCompletedTutorialQuery qry; + qry.station_id=static_cast(m_stationId); + qry.completed_flag=m_completed; + + bool rval = session->exec(&qry); + + qry.done(); + return rval; +} + +// ---------------------------------------------------------------------- + +void TaskToggleCompletedTutorial::onComplete() +{ +} + +// ---------------------------------------------------------------------- + +TaskToggleCompletedTutorial::ToggleCompletedTutorialQuery::ToggleCompletedTutorialQuery() : + Query(), + station_id(), + completed_flag() +{ +} + +// ---------------------------------------------------------------------- + +void TaskToggleCompletedTutorial::ToggleCompletedTutorialQuery::getSQL(std::string &sql) +{ + sql = std::string("begin ")+DatabaseConnection::getInstance().getSchemaQualifier()+"login.toggle_completed_tutorial(:station_id, :completed_flag); end;"; + //DEBUG_REPORT_LOG(true, ("TaskToggleCompletedTutorial SQL: %s\n", sql.c_str())); +} + +// ---------------------------------------------------------------------- + +bool TaskToggleCompletedTutorial::ToggleCompletedTutorialQuery::bindParameters() +{ + if (!bindParameter(station_id)) return false; + if (!bindParameter(completed_flag)) return false; + + return true; +} + +// ---------------------------------------------------------------------- + +bool TaskToggleCompletedTutorial::ToggleCompletedTutorialQuery::bindColumns() +{ + return true; +} + +// ---------------------------------------------------------------------- + +DB::Query::QueryMode TaskToggleCompletedTutorial::ToggleCompletedTutorialQuery::getExecutionMode() const +{ + return MODE_PROCEXEC; +} + +// ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/TaskToggleCompletedTutorial.h b/engine/server/application/LoginServer/src/shared/TaskToggleCompletedTutorial.h new file mode 100644 index 00000000..1e1def17 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskToggleCompletedTutorial.h @@ -0,0 +1,57 @@ +// ====================================================================== +// +// TaskToggleCompletedTutorial.h +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_TaskToggleCompletedTutorial_H +#define INCLUDED_TaskToggleCompletedTutorial_H + +// ====================================================================== + +#include "sharedDatabaseInterface/Bindable.h" +#include "sharedDatabaseInterface/BindableNetworkId.h" +#include "sharedDatabaseInterface/DbQuery.h" +#include "sharedDatabaseInterface/DbTaskRequest.h" + +// ====================================================================== + +class TaskToggleCompletedTutorial : public DB::TaskRequest +{ + public: + TaskToggleCompletedTutorial(StationId stationId, bool completed); + + public: + virtual bool process (DB::Session *session); + virtual void onComplete (); + + private: + TaskToggleCompletedTutorial(); // disabled default constructor + + class ToggleCompletedTutorialQuery : public DB::Query + { + public: + ToggleCompletedTutorialQuery(); + + DB::BindableLong station_id; //lint !e1925 // public data member : suppressed because this is a private inner class + DB::BindableBool completed_flag; //lint !e1925 // public data member : suppressed because this is a private inner class + + virtual void getSQL(std::string &sql); + virtual bool bindParameters(); + virtual bool bindColumns(); + virtual QueryMode getExecutionMode() const; + + private: //disable + ToggleCompletedTutorialQuery(const ToggleCompletedTutorialQuery&); + ToggleCompletedTutorialQuery &operator=(const ToggleCompletedTutorialQuery&); + }; + + private: + StationId m_stationId; + bool m_completed; +}; + +// ====================================================================== + +#endif diff --git a/engine/server/application/LoginServer/src/shared/TaskUpdatePurgeAccountList.cpp b/engine/server/application/LoginServer/src/shared/TaskUpdatePurgeAccountList.cpp new file mode 100644 index 00000000..114573c5 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskUpdatePurgeAccountList.cpp @@ -0,0 +1,102 @@ +// ====================================================================== +// +// TaskUpdatePurgeAccountList.cpp +// copyright (c) 2005 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLoginServer.h" +#include "TaskUpdatePurgeAccountList.h" + +#include "ConfigLoginServer.h" +#include "DatabaseConnection.h" +#include "PurgeManager.h" +#include "sharedDatabaseInterface/Bindable.h" +#include "sharedDatabaseInterface/DbQuery.h" +#include "sharedDatabaseInterface/DbSession.h" + +// ====================================================================== + +namespace TaskUpdatePurgeAccountListNamespace +{ + class UpdateAccoutListQuery : public DB::Query + { + public: + UpdateAccoutListQuery(); + + virtual void getSQL(std::string &sql); + virtual bool bindParameters(); + virtual bool bindColumns(); + virtual QueryMode getExecutionMode() const; + + DB::BindableString<100> m_source_table; + + private: //disable + UpdateAccoutListQuery(const UpdateAccoutListQuery&); + UpdateAccoutListQuery& operator=(const UpdateAccoutListQuery&); + }; +} +using namespace TaskUpdatePurgeAccountListNamespace; + +// ====================================================================== + +TaskUpdatePurgeAccountList::TaskUpdatePurgeAccountList() : + DB::TaskRequest() +{ +} + +// ---------------------------------------------------------------------- + +bool TaskUpdatePurgeAccountList::process(DB::Session *session) +{ + UpdateAccoutListQuery qry; + if (!session->exec(&qry)) + return false; + return true; +} + +// ---------------------------------------------------------------------- + +void TaskUpdatePurgeAccountList::onComplete() +{ +} + +// ====================================================================== + + +UpdateAccoutListQuery::UpdateAccoutListQuery() : + Query(), + m_source_table(ConfigLoginServer::getPurgeAccountSourceTable()) +{ +} + +// ---------------------------------------------------------------------- + +void UpdateAccoutListQuery::getSQL(std::string &sql) +{ + sql=std::string("begin ")+DatabaseConnection::getInstance().getSchemaQualifier()+"purge_process.update_account_list(:source_table); end;"; +} + +// ---------------------------------------------------------------------- + +bool UpdateAccoutListQuery::bindParameters() +{ + if (!bindParameter(m_source_table)) return false; + return true; +} + +// ---------------------------------------------------------------------- + +bool UpdateAccoutListQuery::bindColumns() +{ + return true; +} + +// ---------------------------------------------------------------------- + +UpdateAccoutListQuery::QueryMode UpdateAccoutListQuery::getExecutionMode() const +{ + return MODE_PROCEXEC; +} + +// ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/TaskUpdatePurgeAccountList.h b/engine/server/application/LoginServer/src/shared/TaskUpdatePurgeAccountList.h new file mode 100644 index 00000000..3888e9a5 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskUpdatePurgeAccountList.h @@ -0,0 +1,29 @@ +// ====================================================================== +// +// TaskUpdatePurgeAccountList.h +// copyright (c) 2005 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_TaskUpdatePurgeAccountList_H +#define INCLUDED_TaskUpdatePurgeAccountList_H + +// ====================================================================== + +#include "sharedDatabaseInterface/DbTaskRequest.h" + +class TaskUpdatePurgeAccountList : public DB::TaskRequest +{ + public: + TaskUpdatePurgeAccountList(); + virtual bool process (DB::Session *session); + virtual void onComplete (); + + private: + StationId m_account; + int m_purgePhase; +}; + +// ====================================================================== + +#endif diff --git a/engine/server/application/LoginServer/src/shared/TaskUpgradeAccount.cpp b/engine/server/application/LoginServer/src/shared/TaskUpgradeAccount.cpp new file mode 100644 index 00000000..86643069 --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskUpgradeAccount.cpp @@ -0,0 +1,687 @@ +// ====================================================================== +// +// TaskUpgradeAccount.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLoginServer.h" +#include "TaskUpgradeAccount.h" + +#include "LoginServer.h" +#include "DatabaseConnection.h" +#include "serverNetworkMessages/LoginUpgradeAccountMessage.h" +#include "sharedDatabaseInterface/DbSession.h" +#include "sharedFoundation/NetworkIdArchive.h" +#include "sharedNetworkMessages/GenericValueTypeMessage.h" +#include "TaskGetAvatarList.h" + +// ====================================================================== + +TaskUpgradeAccount::TaskUpgradeAccount(LoginUpgradeAccountMessage *message, uint32 clusterId) : + TaskRequest(), + m_message(message), + m_clusterId(clusterId) +{ + NOT_NULL(message); +} + +// ---------------------------------------------------------------------- + +TaskUpgradeAccount::~TaskUpgradeAccount() +{ + delete m_message; + m_message=0; +} + +// ---------------------------------------------------------------------- + +bool TaskUpgradeAccount::process(DB::Session *session) +{ + bool rval = true; + switch (m_message->getUpgradeType()) + { + case LoginUpgradeAccountMessage::UT_addJedi: + { + QueryJediQuery qryHasJediSlot; + qryHasJediSlot.station_id = static_cast(m_message->getStationId()); + qryHasJediSlot.character_type = 2; + + rval = session->exec(&qryHasJediSlot); + + qryHasJediSlot.done(); + + // account doesn't have jedi slot yet, add it + if (!rval || (qryHasJediSlot.result.getValue() == 0)) + { + AddJediQuery qry; + qry.cluster_id = static_cast(m_clusterId); + qry.station_id = static_cast(m_message->getStationId()); + + rval = session->exec(&qry); + + qry.done(); + } + } + break; + + case LoginUpgradeAccountMessage::UT_setSpectral: + { + SetCharacterTypeQuery qry; + qry.cluster_id = static_cast(m_clusterId); + qry.station_id = static_cast(m_message->getStationId()); + qry.character = m_message->getCharacter(); + qry.character_type = 3; + + rval = session->exec(&qry); + + qry.done(); + } + break; + + default: + WARNING_STRICT_FATAL(true,("LoginUpgradeAccountMessage contained unrecognized upgrade type.\n")); + } + return rval; + +} + +// ---------------------------------------------------------------------- + +void TaskUpgradeAccount::onComplete() +{ + m_message->setAck(); + LoginServer::getInstance().sendToCluster(m_clusterId,*m_message); +} + +// ====================================================================== + +TaskUpgradeAccount::SetCharacterTypeQuery::SetCharacterTypeQuery() : + Query(), + cluster_id(), + station_id(), + character(), + character_type() +{ +} + +// ---------------------------------------------------------------------- + +void TaskUpgradeAccount::SetCharacterTypeQuery::getSQL(std::string &sql) +{ + sql = std::string("begin ")+DatabaseConnection::getInstance().getSchemaQualifier()+"login.set_character_type(:cluster_id, :station_id, :character, :character_type); end;"; + // DEBUG_REPORT_LOG(true, ("TaskUpgradeAccount SQL: %s\n", sql.c_str())); +} + +// ---------------------------------------------------------------------- + +bool TaskUpgradeAccount::SetCharacterTypeQuery::bindParameters() +{ + if (!bindParameter(cluster_id)) return false; + if (!bindParameter(station_id)) return false; + if (!bindParameter(character)) return false; + if (!bindParameter(character_type)) return false; + return true; +} + +// ---------------------------------------------------------------------- + +bool TaskUpgradeAccount::SetCharacterTypeQuery::bindColumns() +{ + return true; +} + +// ---------------------------------------------------------------------- + +DB::Query::QueryMode TaskUpgradeAccount::SetCharacterTypeQuery::getExecutionMode() const +{ + return MODE_PROCEXEC; +} + +// ====================================================================== + +TaskUpgradeAccount::AddJediQuery::AddJediQuery() : + Query(), + cluster_id(), + station_id() +{ +} + +// ---------------------------------------------------------------------- + +void TaskUpgradeAccount::AddJediQuery::getSQL(std::string &sql) +{ + sql = std::string("begin ")+DatabaseConnection::getInstance().getSchemaQualifier()+"login.set_character_slots(:cluster_id, :station_id, 2, 1); end;"; +} + +// ---------------------------------------------------------------------- + +bool TaskUpgradeAccount::AddJediQuery::bindParameters() +{ + if (!bindParameter(cluster_id)) return false; + if (!bindParameter(station_id)) return false; + return true; +} + +// ---------------------------------------------------------------------- + +bool TaskUpgradeAccount::AddJediQuery::bindColumns() +{ + return true; +} + +// ---------------------------------------------------------------------- + +DB::Query::QueryMode TaskUpgradeAccount::AddJediQuery::getExecutionMode() const +{ + return MODE_PROCEXEC; +} + +// ====================================================================== + +TaskUpgradeAccount::QueryJediQuery::QueryJediQuery() : +Query(), +station_id(), +character_type(), +result() +{ +} + +// ---------------------------------------------------------------------- + +void TaskUpgradeAccount::QueryJediQuery::getSQL(std::string &sql) +{ + sql = std::string("begin :result := ")+DatabaseConnection::getInstance().getSchemaQualifier()+"login.has_extra_character_slot(:station_id, :character_type); end;"; +} + +// ---------------------------------------------------------------------- + +bool TaskUpgradeAccount::QueryJediQuery::bindParameters() +{ + if (!bindParameter(result)) return false; + if (!bindParameter(station_id)) return false; + if (!bindParameter(character_type)) return false; + return true; +} + +// ---------------------------------------------------------------------- + +bool TaskUpgradeAccount::QueryJediQuery::bindColumns() +{ + return true; +} + +// ---------------------------------------------------------------------- + +DB::Query::QueryMode TaskUpgradeAccount::QueryJediQuery::getExecutionMode() const +{ + return MODE_PROCEXEC; +} + +// ====================================================================== + +TaskOccupyUnlockedSlot::TaskOccupyUnlockedSlot(int clusterGroupId, uint32 clusterId, StationId stationId, NetworkId const & characterId, uint32 replyGameServerId) : +TaskRequest(), +m_clusterGroupId(clusterGroupId), +m_clusterId(clusterId), +m_stationId(stationId), +m_characterId(characterId), +m_replyGameServerId(replyGameServerId), +m_result(static_cast(LoginUpgradeAccountMessage::OUSR_db_error)) +{ +} + +// ---------------------------------------------------------------------- + +TaskOccupyUnlockedSlot::~TaskOccupyUnlockedSlot() +{ +} + +// ---------------------------------------------------------------------- + +bool TaskOccupyUnlockedSlot::process(DB::Session *session) +{ + bool rval = true; + m_result = static_cast(LoginUpgradeAccountMessage::OUSR_success); + + // see if account has an unlocked slot + TaskUpgradeAccount::QueryJediQuery qryHasJediSlot; + qryHasJediSlot.station_id = static_cast(m_stationId); + qryHasJediSlot.character_type = 2; + + rval = session->exec(&qryHasJediSlot); + + qryHasJediSlot.done(); + + if (!rval) + { + m_result = static_cast(LoginUpgradeAccountMessage::OUSR_db_error); + return false; + } + + // account doesn't have unlocked slot + int const numberUnlockedSlot = static_cast(qryHasJediSlot.result.getValue()); + if (numberUnlockedSlot == 0) + { + m_result = static_cast(LoginUpgradeAccountMessage::OUSR_account_has_no_unlocked_slot); + return true; + } + + // get the list of characters for the account to see if the account already has an unlocked slot character + TaskGetAvatarList::GetCharactersQuery qryGetCharacters; + + qryGetCharacters.station_id = m_stationId; //lint !e713 // loss of precision unsigned long to long + qryGetCharacters.cluster_group_id = m_clusterGroupId; + + rval = session->exec(&qryGetCharacters); + if (!rval) + { + m_result = static_cast(LoginUpgradeAccountMessage::OUSR_db_error); + return false; + } + + int numberUnlockedSlotCharacter = 0; + bool hasUnlockedSlotCharacterOnCluster = false; + int rowsFetched; + while ((rowsFetched = qryGetCharacters.fetch()) > 0) + { + if (qryGetCharacters.character_type.getValue() == 2) + { + ++numberUnlockedSlotCharacter; + + if (qryGetCharacters.cluster_id.getValue() == static_cast(m_clusterId)) + hasUnlockedSlotCharacterOnCluster = true; + } + } + + qryGetCharacters.done(); + + if (numberUnlockedSlotCharacter >= numberUnlockedSlot) + { + m_result = static_cast(LoginUpgradeAccountMessage::OUSR_account_has_no_unoccupied_unlocked_slot); + return true; + } + + if (hasUnlockedSlotCharacterOnCluster) + { + m_result = static_cast(LoginUpgradeAccountMessage::OUSR_cluster_already_has_unlocked_slot_character); + return true; + } + + // make the character an unlocked slot character + TaskUpgradeAccount::SetCharacterTypeQuery qrySetUnlocked; + qrySetUnlocked.cluster_id = static_cast(m_clusterId); + qrySetUnlocked.station_id = static_cast(m_stationId); + qrySetUnlocked.character = m_characterId; + qrySetUnlocked.character_type = 2; + + rval = session->exec(&qrySetUnlocked); + + qrySetUnlocked.done(); + + if (!rval) + { + m_result = static_cast(LoginUpgradeAccountMessage::OUSR_db_error); + return false; + } + + return true; +} + +// ---------------------------------------------------------------------- + +void TaskOccupyUnlockedSlot::onComplete() +{ + GenericValueTypeMessage, uint32> > const occupyUnlockedSlotRsp("OccupyUnlockedSlotRsp", std::make_pair(std::make_pair(m_result, m_characterId), m_replyGameServerId)); + LoginServer::getInstance().sendToCluster(m_clusterId, occupyUnlockedSlotRsp); +} + +// ====================================================================== + +TaskVacateUnlockedSlot::TaskVacateUnlockedSlot(int clusterGroupId, uint32 clusterId, StationId stationId, NetworkId const & characterId, uint32 replyGameServerId) : +TaskRequest(), +m_clusterGroupId(clusterGroupId), +m_clusterId(clusterId), +m_stationId(stationId), +m_characterId(characterId), +m_replyGameServerId(replyGameServerId), +m_result(static_cast(LoginUpgradeAccountMessage::VUSR_db_error)) +{ +} + +// ---------------------------------------------------------------------- + +TaskVacateUnlockedSlot::~TaskVacateUnlockedSlot() +{ +} + +// ---------------------------------------------------------------------- + +bool TaskVacateUnlockedSlot::process(DB::Session *session) +{ + bool rval = true; + m_result = static_cast(LoginUpgradeAccountMessage::VUSR_success); + + // see if account has an unlocked slot + TaskUpgradeAccount::QueryJediQuery qryHasJediSlot; + qryHasJediSlot.station_id = static_cast(m_stationId); + qryHasJediSlot.character_type = 2; + + rval = session->exec(&qryHasJediSlot); + + qryHasJediSlot.done(); + + if (!rval) + { + m_result = static_cast(LoginUpgradeAccountMessage::VUSR_db_error); + return false; + } + + // account doesn't have unlocked slot + if (qryHasJediSlot.result.getValue() == 0) + { + m_result = static_cast(LoginUpgradeAccountMessage::VUSR_account_has_no_unlocked_slot); + return true; + } + + // get the list of characters for the account to see if this character is an unlocked slot character + TaskGetAvatarList::GetCharactersQuery qryGetCharacters; + + qryGetCharacters.station_id = m_stationId; //lint !e713 // loss of precision unsigned long to long + qryGetCharacters.cluster_group_id = m_clusterGroupId; + + rval = session->exec(&qryGetCharacters); + if (!rval) + { + m_result = static_cast(LoginUpgradeAccountMessage::VUSR_db_error); + return false; + } + + bool isUnlockedSlotCharacter = false; + int rowsFetched; + while ((rowsFetched = qryGetCharacters.fetch()) > 0) + { + if ((qryGetCharacters.cluster_id.getValue() == static_cast(m_clusterId)) && (qryGetCharacters.object_id.getValue() == m_characterId)) + { + if (qryGetCharacters.character_type.getValue() == 2) + { + isUnlockedSlotCharacter = true; + } + + break; + } + } + + qryGetCharacters.done(); + + if (!isUnlockedSlotCharacter) + { + m_result = static_cast(LoginUpgradeAccountMessage::VUSR_not_unlocked_slot_character); + return true; + } + + // check to see if the account can create a normal character, because + // we are going to be making the character into a normal character, and + // we must be sure that doing will not violate the normal character limit + GetOnlyOpenCharacterSlotsQuery qryGetOnlyOpenCharacterSlots; + qryGetOnlyOpenCharacterSlots.station_id = static_cast(m_stationId); + qryGetOnlyOpenCharacterSlots.cluster_id = static_cast(m_clusterId); + + rval = session->exec(&qryGetOnlyOpenCharacterSlots); + if (!rval) + { + m_result = static_cast(LoginUpgradeAccountMessage::VUSR_db_error); + return false; + } + + std::vector openCharacterSlots(4,0); + while ((rowsFetched = qryGetOnlyOpenCharacterSlots.fetch()) > 0) + { + openCharacterSlots[static_cast(qryGetOnlyOpenCharacterSlots.character_type_id.getValue())]=qryGetOnlyOpenCharacterSlots.num_open_slots.getValue(); + } + + qryGetOnlyOpenCharacterSlots.done(); + + if (openCharacterSlots[1] <= 0) + { + m_result = static_cast(LoginUpgradeAccountMessage::VUSR_no_available_normal_character_slot); + return true; + } + + // make the character a normal slot character + TaskUpgradeAccount::SetCharacterTypeQuery qrySetNormal; + qrySetNormal.cluster_id = static_cast(m_clusterId); + qrySetNormal.station_id = static_cast(m_stationId); + qrySetNormal.character = m_characterId; + qrySetNormal.character_type = 1; + + rval = session->exec(&qrySetNormal); + + qrySetNormal.done(); + + if (!rval) + { + m_result = static_cast(LoginUpgradeAccountMessage::VUSR_db_error); + return false; + } + + return true; +} + +// ---------------------------------------------------------------------- + +void TaskVacateUnlockedSlot::onComplete() +{ + GenericValueTypeMessage, std::pair > > const vacateUnlockedSlotRsp("VacateUnlockedSlotRsp", std::make_pair(std::make_pair(m_result, m_characterId), std::make_pair(static_cast(m_stationId), m_replyGameServerId))); + LoginServer::getInstance().sendToCluster(m_clusterId, vacateUnlockedSlotRsp); +} + +// ====================================================================== + +TaskVacateUnlockedSlot::GetOnlyOpenCharacterSlotsQuery::GetOnlyOpenCharacterSlotsQuery() : +Query(), +station_id(), +cluster_id(), +character_type_id(), +num_open_slots() +{ +} + +// ---------------------------------------------------------------------- + +void TaskVacateUnlockedSlot::GetOnlyOpenCharacterSlotsQuery::getSQL(std::string &sql) +{ + sql = std::string("begin :rc := ")+DatabaseConnection::getInstance().getSchemaQualifier()+"login.get_only_open_character_slots(:station_id,:cluster_id); end;"; +} + +// ---------------------------------------------------------------------- + +bool TaskVacateUnlockedSlot::GetOnlyOpenCharacterSlotsQuery::bindParameters() +{ + if (!bindParameter(station_id)) return false; + if (!bindParameter(cluster_id)) return false; + + return true; +} + +// ---------------------------------------------------------------------- + +bool TaskVacateUnlockedSlot::GetOnlyOpenCharacterSlotsQuery::bindColumns() +{ + if (!bindCol(character_type_id)) return false; + if (!bindCol(num_open_slots)) return false; + + return true; +} + +// ---------------------------------------------------------------------- + +DB::Query::QueryMode TaskVacateUnlockedSlot::GetOnlyOpenCharacterSlotsQuery::getExecutionMode() const +{ + return MODE_PLSQL_REFCURSOR; +} + +// ====================================================================== + +TaskSwapUnlockedSlot::TaskSwapUnlockedSlot(int clusterGroupId, uint32 clusterId, StationId stationId, NetworkId const & sourceCharacterId, NetworkId const & targetCharacterId, uint32 replyGameServerId) : +TaskRequest(), +m_clusterGroupId(clusterGroupId), +m_clusterId(clusterId), +m_stationId(stationId), +m_sourceCharacterId(sourceCharacterId), +m_targetCharacterId(targetCharacterId), +m_targetCharacterName(), +m_replyGameServerId(replyGameServerId), +m_result(static_cast(LoginUpgradeAccountMessage::SUSR_db_error)) +{ +} + +// ---------------------------------------------------------------------- + +TaskSwapUnlockedSlot::~TaskSwapUnlockedSlot() +{ +} + +// ---------------------------------------------------------------------- + +bool TaskSwapUnlockedSlot::process(DB::Session *session) +{ + bool rval = true; + m_result = static_cast(LoginUpgradeAccountMessage::SUSR_success); + + // see if account has an unlocked slot + TaskUpgradeAccount::QueryJediQuery qryHasJediSlot; + qryHasJediSlot.station_id = static_cast(m_stationId); + qryHasJediSlot.character_type = 2; + + rval = session->exec(&qryHasJediSlot); + + qryHasJediSlot.done(); + + if (!rval) + { + m_result = static_cast(LoginUpgradeAccountMessage::SUSR_db_error); + return false; + } + + // account doesn't have unlocked slot + if (qryHasJediSlot.result.getValue() == 0) + { + m_result = static_cast(LoginUpgradeAccountMessage::SUSR_account_has_no_unlocked_slot); + return true; + } + + // get the list of characters for the account to see if this character is an unlocked slot character, + // and the the target character is not an unlocked slot character, and the target character is on + // the same cluster + TaskGetAvatarList::GetCharactersQuery qryGetCharacters; + + qryGetCharacters.station_id = m_stationId; //lint !e713 // loss of precision unsigned long to long + qryGetCharacters.cluster_group_id = m_clusterGroupId; + + rval = session->exec(&qryGetCharacters); + if (!rval) + { + m_result = static_cast(LoginUpgradeAccountMessage::SUSR_db_error); + return false; + } + + bool foundSourceCharacter = false; + bool isSourceUnlockedSlotCharacter = false; + bool isTargetUnlockedSlotCharacter = false; + bool isTargetOnSameCluster = false; + int rowsFetched; + while ((rowsFetched = qryGetCharacters.fetch()) > 0) + { + if ((qryGetCharacters.cluster_id.getValue() == static_cast(m_clusterId)) && (qryGetCharacters.object_id.getValue() == m_sourceCharacterId)) + { + foundSourceCharacter = true; + + if (qryGetCharacters.character_type.getValue() == 2) + { + isSourceUnlockedSlotCharacter = true; + } + } + + // this is not a "else if" because we don't trust that m_sourceCharacterId is always different from m_targetCharacterId + if ((qryGetCharacters.cluster_id.getValue() == static_cast(m_clusterId)) && (qryGetCharacters.object_id.getValue() == m_targetCharacterId)) + { + qryGetCharacters.character_name.getValue(m_targetCharacterName); + isTargetOnSameCluster = true; + + if (qryGetCharacters.character_type.getValue() == 2) + { + isTargetUnlockedSlotCharacter = true; + } + } + + if (foundSourceCharacter && isTargetOnSameCluster) + break; + } + + qryGetCharacters.done(); + + if (!isSourceUnlockedSlotCharacter) + { + m_result = static_cast(LoginUpgradeAccountMessage::SUSR_not_unlocked_slot_character); + return true; + } + + if (!isTargetOnSameCluster) + { + m_result = static_cast(LoginUpgradeAccountMessage::SUSR_invalid_target_character); + return true; + } + + if (isTargetUnlockedSlotCharacter) + { + m_result = static_cast(LoginUpgradeAccountMessage::SUSR_target_character_already_unlocked_slot_character); + return true; + } + + // make the source character a normal slot character + TaskUpgradeAccount::SetCharacterTypeQuery qrySetNormal; + qrySetNormal.cluster_id = static_cast(m_clusterId); + qrySetNormal.station_id = static_cast(m_stationId); + qrySetNormal.character = m_sourceCharacterId; + qrySetNormal.character_type = 1; + + rval = session->exec(&qrySetNormal); + + qrySetNormal.done(); + + if (!rval) + { + m_result = static_cast(LoginUpgradeAccountMessage::SUSR_db_error); + return false; + } + + // make the target character an unlocked slot character + TaskUpgradeAccount::SetCharacterTypeQuery qrySetUnlocked; + qrySetUnlocked.cluster_id = static_cast(m_clusterId); + qrySetUnlocked.station_id = static_cast(m_stationId); + qrySetUnlocked.character = m_targetCharacterId; + qrySetUnlocked.character_type = 2; + + rval = session->exec(&qrySetUnlocked); + + qrySetUnlocked.done(); + + if (!rval) + { + m_result = static_cast(LoginUpgradeAccountMessage::SUSR_db_error); + return false; + } + + return true; +} + +// ---------------------------------------------------------------------- + +void TaskSwapUnlockedSlot::onComplete() +{ + GenericValueTypeMessage, std::pair > > > const swapUnlockedSlotRsp("SwapUnlockedSlotRsp", std::make_pair(std::make_pair(m_result, m_sourceCharacterId), std::make_pair(m_replyGameServerId, std::make_pair(m_targetCharacterId, m_targetCharacterName)))); + LoginServer::getInstance().sendToCluster(m_clusterId, swapUnlockedSlotRsp); +} + +// ====================================================================== diff --git a/engine/server/application/LoginServer/src/shared/TaskUpgradeAccount.h b/engine/server/application/LoginServer/src/shared/TaskUpgradeAccount.h new file mode 100644 index 00000000..325014ff --- /dev/null +++ b/engine/server/application/LoginServer/src/shared/TaskUpgradeAccount.h @@ -0,0 +1,200 @@ +// ====================================================================== +// +// TaskSetCharacterType.h +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_TaskUpgradeAccount_H +#define INCLUDED_TaskUpgradeAccount_H + +// ====================================================================== + +#include "sharedDatabaseInterface/Bindable.h" +#include "sharedDatabaseInterface/BindableNetworkId.h" +#include "sharedDatabaseInterface/DbQuery.h" +#include "sharedDatabaseInterface/DbTaskRequest.h" + +// ====================================================================== + +class LoginUpgradeAccountMessage; + +// ====================================================================== + +class TaskUpgradeAccount : public DB::TaskRequest +{ + public: + TaskUpgradeAccount(LoginUpgradeAccountMessage *message, uint32 clusterId); + ~TaskUpgradeAccount(); + + public: + virtual bool process (DB::Session *session); + virtual void onComplete (); + + class SetCharacterTypeQuery : public DB::Query + { + public: + SetCharacterTypeQuery(); + + DB::BindableLong cluster_id; //lint !e1925 // public data member + DB::BindableLong station_id; //lint !e1925 // public data member + DB::BindableNetworkId character; //lint !e1925 // public data member + DB::BindableLong character_type; //lint !e1925 // public data member + + virtual void getSQL (std::string &sql); + virtual bool bindParameters (); + virtual bool bindColumns (); + virtual QueryMode getExecutionMode () const; + + private: //disable + SetCharacterTypeQuery (const SetCharacterTypeQuery&); + SetCharacterTypeQuery &operator= (const SetCharacterTypeQuery&); + }; + + class QueryJediQuery : public DB::Query + { + public: + QueryJediQuery(); + + DB::BindableLong station_id; //lint !e1925 // public data member + DB::BindableLong character_type; //lint !e1925 // public data member + DB::BindableLong result; //lint !e1925 // public data member + + virtual void getSQL (std::string &sql); + virtual bool bindParameters (); + virtual bool bindColumns (); + virtual QueryMode getExecutionMode () const; + + private: //disable + QueryJediQuery (const QueryJediQuery&); + QueryJediQuery &operator= (const QueryJediQuery&); + }; + + private: + class AddJediQuery : public DB::Query + { + public: + AddJediQuery(); + + DB::BindableLong cluster_id; //lint !e1925 // public data member + DB::BindableLong station_id; //lint !e1925 // public data member + + virtual void getSQL (std::string &sql); + virtual bool bindParameters (); + virtual bool bindColumns (); + virtual QueryMode getExecutionMode () const; + + private: //disable + AddJediQuery (const AddJediQuery&); + AddJediQuery &operator= (const AddJediQuery&); + }; + + private: + TaskUpgradeAccount(); // disable default constructor + TaskUpgradeAccount(const TaskUpgradeAccount &); // disable copy constructor + TaskUpgradeAccount & operator = (const TaskUpgradeAccount &); // disable assignment operator + + LoginUpgradeAccountMessage *m_message; + uint32 m_clusterId; +}; + +// ====================================================================== + +class TaskOccupyUnlockedSlot : public DB::TaskRequest +{ +public: + TaskOccupyUnlockedSlot(int clusterGroupId, uint32 clusterId, StationId stationId, NetworkId const & characterId, uint32 replyGameServerId); + ~TaskOccupyUnlockedSlot(); + +public: + virtual bool process (DB::Session *session); + virtual void onComplete (); + +private: + TaskOccupyUnlockedSlot(); // disable default constructor + TaskOccupyUnlockedSlot(const TaskOccupyUnlockedSlot &); // disable copy constructor + TaskOccupyUnlockedSlot & operator = (const TaskOccupyUnlockedSlot &); // disable assignment operator + + int m_clusterGroupId; + uint32 m_clusterId; + StationId m_stationId; + NetworkId m_characterId; + uint32 m_replyGameServerId; + int m_result; +}; + +// ====================================================================== + +class TaskVacateUnlockedSlot : public DB::TaskRequest +{ +public: + TaskVacateUnlockedSlot(int clusterGroupId, uint32 clusterId, StationId stationId, NetworkId const & characterId, uint32 replyGameServerId); + ~TaskVacateUnlockedSlot(); + +public: + virtual bool process (DB::Session *session); + virtual void onComplete (); + + class GetOnlyOpenCharacterSlotsQuery : public DB::Query + { + public: + GetOnlyOpenCharacterSlotsQuery(); + + DB::BindableLong station_id; //lint !e1925 // public data member + DB::BindableLong cluster_id; //lint !e1925 // public data member + DB::BindableLong character_type_id; //lint !e1925 // public data member + DB::BindableLong num_open_slots; //lint !e1925 // public data member + + virtual void getSQL(std::string &sql); + virtual bool bindParameters(); + virtual bool bindColumns(); + virtual QueryMode getExecutionMode() const; + + private: //disable + GetOnlyOpenCharacterSlotsQuery(const GetOnlyOpenCharacterSlotsQuery&); + GetOnlyOpenCharacterSlotsQuery &operator=(const GetOnlyOpenCharacterSlotsQuery&); + }; + +private: + TaskVacateUnlockedSlot(); // disable default constructor + TaskVacateUnlockedSlot(const TaskVacateUnlockedSlot &); // disable copy constructor + TaskVacateUnlockedSlot & operator = (const TaskVacateUnlockedSlot &); // disable assignment operator + + int m_clusterGroupId; + uint32 m_clusterId; + StationId m_stationId; + NetworkId m_characterId; + uint32 m_replyGameServerId; + int m_result; +}; + +// ====================================================================== + +class TaskSwapUnlockedSlot : public DB::TaskRequest +{ +public: + TaskSwapUnlockedSlot(int clusterGroupId, uint32 clusterId, StationId stationId, NetworkId const & sourceCharacterId, NetworkId const & targetCharacterId, uint32 replyGameServerId); + ~TaskSwapUnlockedSlot(); + +public: + virtual bool process (DB::Session *session); + virtual void onComplete (); + +private: + TaskSwapUnlockedSlot(); // disable default constructor + TaskSwapUnlockedSlot(const TaskSwapUnlockedSlot &); // disable copy constructor + TaskSwapUnlockedSlot & operator = (const TaskSwapUnlockedSlot &); // disable assignment operator + + int m_clusterGroupId; + uint32 m_clusterId; + StationId m_stationId; + NetworkId m_sourceCharacterId; + NetworkId m_targetCharacterId; + std::string m_targetCharacterName; + uint32 m_replyGameServerId; + int m_result; +}; + +// ====================================================================== + +#endif diff --git a/engine/server/application/LoginServer/src/win32/CMakeLists.txt b/engine/server/application/LoginServer/src/win32/CMakeLists.txt new file mode 100644 index 00000000..36a35ab6 --- /dev/null +++ b/engine/server/application/LoginServer/src/win32/CMakeLists.txt @@ -0,0 +1,8 @@ + +add_executable(LoginServer + WinMain.cpp +) + +target_link_libraries(LoginServer + LoginServershared +) \ No newline at end of file diff --git a/engine/server/application/LoginServer/src/win32/FirstLoginServer.cpp b/engine/server/application/LoginServer/src/win32/FirstLoginServer.cpp new file mode 100644 index 00000000..199562bb --- /dev/null +++ b/engine/server/application/LoginServer/src/win32/FirstLoginServer.cpp @@ -0,0 +1 @@ +#include "FirstLoginServer.h" diff --git a/engine/server/application/LoginServer/src/win32/WinMain.cpp b/engine/server/application/LoginServer/src/win32/WinMain.cpp new file mode 100644 index 00000000..f5c7056c --- /dev/null +++ b/engine/server/application/LoginServer/src/win32/WinMain.cpp @@ -0,0 +1,46 @@ +#include "FirstLoginServer.h" +#include "ConfigLoginServer.h" +#include "LoginServer.h" + +#include "sharedCompression/SetupSharedCompression.h" +#include "sharedDebug/SetupSharedDebug.h" +#include "sharedFile/SetupSharedFile.h" +#include "sharedFoundation/SetupSharedFoundation.h" +#include "sharedNetworkMessages/SetupSharedNetworkMessages.h" +#include "sharedRandom/SetupSharedRandom.h" +#include "sharedThread/SetupSharedThread.h" + +#include + +int main(int argc, char **argv) +{ + + SetupSharedThread::install(); + SetupSharedDebug::install(1024); + + //-- setup foundation + SetupSharedFoundation::Data setupFoundationData(SetupSharedFoundation::Data::D_game); + + setupFoundationData.argc = argc; + setupFoundationData.argv = argv; + setupFoundationData.createWindow = false; + + SetupSharedFoundation::install (setupFoundationData); + SetupSharedNetworkMessages::install(); + + SetupSharedCompression::install(); + + SetupSharedFile::install(false); + + SetupSharedRandom::install(time(NULL)); + + //-- setup game server + ConfigLoginServer::install (); + + //-- run game + SetupSharedFoundation::callbackWithExceptionHandling(LoginServer::run); + + SetupSharedFoundation::remove(); + + return 0; +}