Added TransferServer project and CTServiceGameAPI library

This commit is contained in:
Anonymous
2014-01-18 06:31:13 -07:00
parent b33724e9f7
commit a5b073e4f2
87 changed files with 13669 additions and 0 deletions
+1
View File
@@ -6,3 +6,4 @@ add_subdirectory(LoginServer)
add_subdirectory(LogServer)
add_subdirectory(PlanetServer)
add_subdirectory(TaskManager)
add_subdirectory(TransferServer)
@@ -0,0 +1,6 @@
cmake_minimum_required(VERSION 2.8)
project(TransferServer)
add_subdirectory(src)
@@ -0,0 +1,89 @@
set(SHARED_SOURCES
shared/CentralServerConnection.cpp
shared/CentralServerConnection.h
shared/ConfigTransferServer.cpp
shared/ConfigTransferServer.h
shared/ConsoleCommandParser.cpp
shared/ConsoleCommandParser.h
shared/ConsoleManager.cpp
shared/ConsoleManager.h
shared/CTSAPIClient.cpp
shared/CTSAPIClient.h
shared/FirstTransferServer.h
shared/TransferServer.cpp
shared/TransferServer.h
)
if(WIN32)
set(PLATFORM_SOURCES
win32/WinMain.cpp
)
else()
set(PLATFORM_SOURCES
linux/main.cpp
)
endif()
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/shared
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedCommandParser/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedCompression/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedDebug/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFile/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundation/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundationTypes/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedLog/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMath/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMemoryManager/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMessageDispatch/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedNetwork/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedNetworkMessages/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedThread/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedUtility/include/public
${SWG_ENGINE_SOURCE_DIR}/server/library/serverNetworkMessages/include/public
${SWG_ENGINE_SOURCE_DIR}/server/library/serverUtility/include/public
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/archive/include
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicode/include
${SWG_EXTERNALS_SOURCE_DIR}/3rd/library/soePlatform/CTServiceGameAPI
)
link_directories(${STLPORT_LIBDIR})
add_executable(TransferServer
${SHARED_SOURCES}
${PLATFORM_SOURCES}
)
target_link_libraries(TransferServer
sharedCommandParser
sharedCompression
sharedDebug
sharedFile
sharedFoundation
sharedLog
sharedMath
sharedMemoryManager
sharedMessageDispatch
sharedNetwork
sharedNetworkMessages
sharedRandom
sharedSynchronization
sharedThread
sharedUtility
serverNetworkMessages
serverUtility
archive
fileInterface
localization
localizationArchive
unicode
unicodeArchive
udplibrary
CTServiceGameAPI
${ZLIB_LIBRARY}
)
if(WIN32)
target_link_libraries(TransferServer mswsock ws2_32)
endif()
@@ -0,0 +1,60 @@
// main.cpp
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "FirstTransferServer.h"
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedCompression/SetupSharedCompression.h"
#include "sharedDebug/SetupSharedDebug.h"
#include "sharedFile/SetupSharedFile.h"
#include "sharedFoundation/Os.h"
#include "sharedFoundation/SetupSharedFoundation.h"
#include "sharedNetwork/SetupSharedNetwork.h"
#include "sharedNetwork/NetworkHandler.h"
#include "sharedNetworkMessages/SetupSharedNetworkMessages.h"
#include "sharedThread/SetupSharedThread.h"
#include "TransferServer.h"
#include "ConfigTransferServer.h"
//-----------------------------------------------------------------------
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.runInBackground = true;
SetupSharedFoundation::install (setupFoundationData);
SetupSharedCompression::install();
SetupSharedFile::install(false);
SetupSharedNetworkMessages::install();
SetupSharedNetwork::SetupData networkSetupData;
SetupSharedNetwork::getDefaultServerSetupData(networkSetupData);
SetupSharedNetwork::install(networkSetupData);
NetworkHandler::install();
Os::setProgramName("TransferServer");
ConfigTransferServer::install();
//-- run server
SetupSharedFoundation::callbackWithExceptionHandling(TransferServer::run);
NetworkHandler::remove();
SetupSharedFoundation::remove();
SetupSharedThread::remove();
return 0;
}
//-----------------------------------------------------------------------
@@ -0,0 +1,336 @@
// CTSAPIClient.h
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "FirstTransferServer.h"
#include "CentralServerConnection.h"
#include "ConfigTransferServer.h"
#include "CTSAPIClient.h"
#include "CTCommon/CTServiceServer.h"
#include <map>
#include "sharedLog/Log.h"
#include "TransferServer.h"
#include "UnicodeUtils.h"
#include <set>
#include <vector>
class CentralServerConnection;
//-----------------------------------------------------------------------
namespace CTSAPIClientNamespace
{
struct TransactionTrackData
{
const CentralServerConnection * m_sourceCentralServerConnection;
const CentralServerConnection * m_destinationCentralServerConnection;
unsigned int m_track;
};
std::map<unsigned int, TransactionTrackData> s_activeTransfers;
std::map<unsigned int, int> s_completedTransfers;
}
using namespace CTSAPIClientNamespace;
//-----------------------------------------------------------------------
CTSAPIClient::CTSAPIClient(const std::string & hostName, const std::string & game) :
CTServiceAPI(hostName.c_str(), game.c_str())
{
}
//-----------------------------------------------------------------------
CTSAPIClient::~CTSAPIClient()
{
}
//-----------------------------------------------------------------------
void CTSAPIClient::onTest(const unsigned track, const int resultCode, const unsigned value, void *user)
{
LOG("CTSAPI", ("CTSAPIClient::onTest(%d, %d, %d, %p)", track, resultCode, value, user));
}
//-----------------------------------------------------------------------
void CTSAPIClient::onReplyTest(const unsigned track, const int resultCode, void *user)
{
LOG("CTSAPI", ("CTSAPIClient::onReplyTest(%d, %d, %p)", track, resultCode, user));
}
//-----------------------------------------------------------------------
void CTSAPIClient::onReplyMoveStatus(const unsigned track, const int resultCode, void *user)
{
LOG("CTSAPI", ("CTSAPIClient::onReplyMoveStatus(%d, %d, %p)", track, resultCode, user));
}
//-----------------------------------------------------------------------
void CTSAPIClient::onReplyValidateMove(const unsigned track, const int resultCode, void *user)
{
LOG("CTSAPI", ("CTSAPIClient::onReplyValidateMove(%d, %d, %p)", track, resultCode, user));
}
//-----------------------------------------------------------------------
void CTSAPIClient::onReplyMove(const unsigned track, const int resultCode, void *user)
{
LOG("CTSAPI", ("CTSAPIClient::onReplyMove(%d, %d, %p)", track, resultCode, user));
}
//-----------------------------------------------------------------------
void CTSAPIClient::onReplyTransferAccount(const unsigned track, const int resultCode, void *user)
{
LOG("CTSAPI", ("CTSAPIClient::onReplyTransferAccount(%d, %d, %p)", track, resultCode, user));
}
//-----------------------------------------------------------------------
void CTSAPIClient::onReplyCharacterList(const unsigned track, const int resultCode, void *user)
{
LOG("CTSAPI", ("CTSAPIClient::onReplyCharacterList(%d, %d, %p)", track, resultCode, user));
}
//-----------------------------------------------------------------------
void CTSAPIClient::onReplyServerList(const unsigned track, const int resultCode, void *user)
{
LOG("CTSAPI", ("CTSAPIClient::onReplyServerList(%d, %d, %p)",track, resultCode, user));
}
//-----------------------------------------------------------------------
void CTSAPIClient::onReplyDestinationServerList(const unsigned track, const int resultCode, void *user)
{
LOG("CTSAPI", ("CTSAPIClient::onReplyDestinationServerList(%d, %d, %p)", track, resultCode, user));
}
//-----------------------------------------------------------------------
void CTSAPIClient::onServerTest(const unsigned server_track, const char *game, const char *param)
{
LOG("CTSAPI", ("CTSAPIClient::onServerTest(%d, %s, %s)", server_track, game, param));
}
//-----------------------------------------------------------------------
void CTSAPIClient::onRequestMoveStatus(const unsigned server_track, const char *language, const unsigned transactionID)
{
LOG("CTSAPI", ("CTSAPIClient::onRequestMoveStatus(%d, %s, %d)", server_track, language, transactionID));
}
//-----------------------------------------------------------------------
void CTSAPIClient::onRequestValidateMove(const unsigned server_track, const char *language, const CTService::CTUnicodeChar *sourceServer, const CTService::CTUnicodeChar *destServer, const CTService::CTUnicodeChar *sourceCharacter, const CTService::CTUnicodeChar *destCharacter, const unsigned uid, const unsigned destuid, bool /*withItems*/, bool /*allowOverride*/)
{
LOG("CTSAPI", ("CTSAPIClient::onRequestValidateMove(%d, %s, %s, %s, %s, %s, %d, %d", server_track, language, Unicode::wideToNarrow(sourceServer).c_str(), Unicode::wideToNarrow(destServer).c_str(), Unicode::wideToNarrow(sourceCharacter).c_str(), Unicode::wideToNarrow(destCharacter).c_str(), uid, destuid));
TransferServer::requestMoveValidation(server_track, uid, destuid, Unicode::wideToNarrow(Unicode::String(sourceServer)), Unicode::wideToNarrow(Unicode::String(destServer)), Unicode::wideToNarrow(Unicode::String(sourceCharacter)), Unicode::wideToNarrow(Unicode::String(destCharacter)), std::string(language));
}
//-----------------------------------------------------------------------
void CTSAPIClient::onRequestMove(const unsigned server_track, const char *language, const CTService::CTUnicodeChar *sourceServer, const CTService::CTUnicodeChar *destServer, const CTService::CTUnicodeChar *sourceCharacter, const CTService::CTUnicodeChar *destCharacter, const unsigned uid, const unsigned destuid, const unsigned transactionID, bool withItems, bool allowOverride)
{
std::map<unsigned int, TransactionTrackData>::const_iterator f = s_activeTransfers.find(uid);
if(f == s_activeTransfers.end())
{
std::string isWithItems = "false";
if(withItems)
isWithItems = "true";
LOG("CTSAPI", ("CTSAPIClient::onRequestMove(%d, %s, %s, %s, %s, %s, %d, %d, %d, %s)", server_track, language, Unicode::wideToNarrow(sourceServer).c_str(), Unicode::wideToNarrow(destServer).c_str(), Unicode::wideToNarrow(sourceCharacter).c_str(), Unicode::wideToNarrow(destCharacter).c_str(), uid, destuid, transactionID, isWithItems.c_str()));
TransferServer::requestMove(server_track, std::string(language), Unicode::wideToNarrow(Unicode::String(sourceServer)), Unicode::wideToNarrow(Unicode::String(destServer)), Unicode::wideToNarrow(Unicode::String(sourceCharacter)), Unicode::wideToNarrow(Unicode::String(destCharacter)), uid, destuid, transactionID, withItems, allowOverride);
}
else
{
LOG("CTSAPI", ("Received a transfer request for station ID %d, but a transfer for that id is already in progress", uid));
const unsigned int result = static_cast<unsigned int>(CTService::CT_GAMERESULT_SOFTERROR);
IGNORE_RETURN(replyMove(server_track, result, NULL, NULL));
}
}
//-----------------------------------------------------------------------
void CTSAPIClient::onRequestTransferAccount(const unsigned server_track, const unsigned uid, const unsigned destuid, const unsigned transactionID)
{
std::map<unsigned int, TransactionTrackData>::const_iterator f = s_activeTransfers.find(uid);
if(f == s_activeTransfers.end())
{
LOG("CTSAPI", ("CTSAPIClient::onRequestTransferAccount(%d, d, %d, %d)", server_track, uid, destuid, transactionID));
TransferServer::requestTransferAccount(server_track, uid, destuid, transactionID);
}
else
{
LOG("CTSAPI", ("Received a transfer request for station ID %d, but a transfer for that id is already in progress", uid));
const unsigned int result = static_cast<unsigned int>(CTService::CT_GAMERESULT_SOFTERROR);
IGNORE_RETURN(replyTransferAccount(server_track, result, NULL, NULL));
}
}
//-----------------------------------------------------------------------
void CTSAPIClient::onRequestCharacterList(const unsigned server_track, const char *language, const CTService::CTUnicodeChar *server, const unsigned uid)
{
LOG("CTSAPI", ("CTSAPIClient::onRequestCharacterList(%d, %s, %s, %d)", server_track, language, Unicode::wideToNarrow(server).c_str(), uid));
TransferServer::requestCharacterList(server_track, uid, Unicode::wideToNarrow(Unicode::String(server)), std::string(language));
}
//-----------------------------------------------------------------------
void CTSAPIClient::onRequestServerList(const unsigned server_track, const char *language)
{
LOG("CTSAPI", ("CTSAPIClient::onRequestServerList(%d, %s)", server_track, language));
std::map<std::string, CentralServerConnection *> galaxies = CentralServerConnection::getGalaxies();
std::vector<CTService::CTServiceServer> servers;
std::vector<std::string>::const_iterator i;
for (i = ConfigTransferServer::getServersAllowedToUploadCharacterData().begin(); i != ConfigTransferServer::getServersAllowedToUploadCharacterData().end(); ++i)
{
std::map<std::string, CentralServerConnection *>::iterator f = galaxies.find(*i);
if(f != galaxies.end())
{
servers.push_back(CTService::CTServiceServer(Unicode::narrowToWide(i->c_str()).c_str()));
}
}
if(! servers.empty())
{
const unsigned int result = static_cast<unsigned int>(CTService::CT_RESULT_SUCCESS);
IGNORE_RETURN(replyServerList(server_track, result, servers.size(), &servers[0], NULL));
}
else
{
const unsigned int result = static_cast<unsigned int>(CTService::CT_RESULT_FAILURE);
IGNORE_RETURN(replyServerList(server_track, result, servers.size(), NULL, NULL));
}
}
//-----------------------------------------------------------------------
void CTSAPIClient::onRequestDestinationServerList(const unsigned server_track, const char *language, const CTService::CTUnicodeChar *character, const CTService::CTUnicodeChar *server)
{
LOG("CTSAPI", ("CTSAPIClient::onRequestDestinationServerList(%d, %s, %s, %s)", server_track, language, Unicode::wideToNarrow(character).c_str(), Unicode::wideToNarrow(server).c_str()));
std::map<std::string, CentralServerConnection *> galaxies = CentralServerConnection::getGalaxies();
std::vector<CTService::CTServiceServer> servers;
std::vector<std::string>::const_iterator i;
for (i = ConfigTransferServer::getServersAllowedToDownloadCharacterData().begin(); i != ConfigTransferServer::getServersAllowedToDownloadCharacterData().end(); ++i)
{
std::map<std::string, CentralServerConnection *>::iterator f = galaxies.find(*i);
if(f != galaxies.end())
{
servers.push_back(CTService::CTServiceServer(Unicode::narrowToWide(i->c_str()).c_str()));
}
}
if(! servers.empty())
{
const unsigned int result = static_cast<unsigned int>(CTService::CT_RESULT_SUCCESS);
IGNORE_RETURN(replyDestinationServerList(server_track, result, servers.size(), &servers[0], NULL));
}
else
{
const unsigned int result = static_cast<unsigned int>(CTService::CT_RESULT_FAILURE);
IGNORE_RETURN(replyDestinationServerList(server_track, result, servers.size(), NULL, NULL));
}
}
//-----------------------------------------------------------------------
void CTSAPIClient::onConnect(const char *host, const short port, const short current, const short max)
{
LOG("CTSAPI", ("CTSAPIClient::onConnect(%s, %d, %d, %d)", host, port, current, max));
REPORT_LOG(true, ("CTSAPIClient::onConnect(%s, %d, %d, %d)\n", host, port, current, max));
}
//-----------------------------------------------------------------------
void CTSAPIClient::onDisconnect(const char *host, const short port, const short current, const short max)
{
LOG("CTSAPI", ("CTSAPIClient::onDisconnect(%s, %d, %d, %d)", host, port, current, max));
REPORT_LOG(true, ("CTSAPIClient::onDisconnect(%s, %d, %d, %d)\n", host, port, current, max));
}
//-----------------------------------------------------------------------
void CTSAPIClient::moveStart(unsigned int stationId, unsigned int track, const CentralServerConnection * sourceCentralServerConnection, const CentralServerConnection * destinationCentralServerConnection)
{
// first check to see if this track has been completed
std::map<unsigned int, int>::iterator f = s_completedTransfers.find(track);
if(f != s_completedTransfers.end())
{
IGNORE_RETURN(replyMove(track, f->second, NULL, NULL));
}
else
{
TransactionTrackData trackData;
trackData.m_destinationCentralServerConnection = destinationCentralServerConnection;
trackData.m_sourceCentralServerConnection = sourceCentralServerConnection;
trackData.m_track = track;
IGNORE_RETURN(s_activeTransfers.insert(std::make_pair(stationId, trackData)));
}
}
//-----------------------------------------------------------------------
void CTSAPIClient::lostCentralServerConnection(const CentralServerConnection * centralServerConnection)
{
// send a failure response to the CTS backend for all id's with
// a transaction in progress on the dead server
std::map<unsigned int, TransactionTrackData>::iterator i;
const unsigned int result = static_cast<unsigned int>(CTService::CT_GAMERESULT_SERVER_IS_DOWN);
for(i = s_activeTransfers.begin(); i != s_activeTransfers.end();)
{
if(i->second.m_sourceCentralServerConnection == centralServerConnection || i->second.m_destinationCentralServerConnection == centralServerConnection)
{
IGNORE_RETURN(replyMove(i->second.m_track, result, NULL, NULL));
s_activeTransfers.erase(i++);
}
else
{
++i;
}
}
}
//-----------------------------------------------------------------------
// NOT IMPLEMENTED IN SWG TRANSFER SERVICE
void CTSAPIClient::moveComplete(unsigned int id, unsigned int track, int result) const
{
std::map<unsigned int, TransactionTrackData>::iterator f = s_activeTransfers.find(id);
if(f != s_activeTransfers.end())
{
s_activeTransfers.erase(f);
}
if(track != 0)
{
s_completedTransfers.insert(std::make_pair(track, result));
}
}
//-----------------------------------------------------------------------
// NOT IMPLEMENTED IN SWG TRANSFER SERVICE
void CTSAPIClient::onReplyDelete(const unsigned int, const int, void *)
{
}
//-----------------------------------------------------------------------
// NOT IMPLEMENTED IN SWG TRANSFER SERVICE
void CTSAPIClient::onReplyRestore(const unsigned int, const int, void *)
{
}
//-----------------------------------------------------------------------
// NOT IMPLEMENTED IN SWG TRANSFER SERVICE
void CTSAPIClient::onRequestDelete(const unsigned int, const char *, const CTService::CTUnicodeChar *, const CTService::CTUnicodeChar *, const CTService::CTUnicodeChar *, const CTService::CTUnicodeChar *, const unsigned int, const unsigned int, const unsigned int, bool, bool)
{
}
//-----------------------------------------------------------------------
// NOT IMPLEMENTED IN SWG TRANSFER SERVICE
void CTSAPIClient::onRequestRestore(const unsigned int, const char *, const CTService::CTUnicodeChar *, const CTService::CTUnicodeChar *, const CTService::CTUnicodeChar *, const CTService::CTUnicodeChar *, const unsigned int, const unsigned int, const unsigned int, bool, bool)
{
}
//-----------------------------------------------------------------------
@@ -0,0 +1,65 @@
// CTSAPIClient.h
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _INCLUDED_CTSAPIClient_H
#define _INCLUDED_CTSAPIClient_H
//-----------------------------------------------------------------------
#include "CTServiceAPI.h"
#include <string>
//-----------------------------------------------------------------------
class CTSAPIClient : public CTService::CTServiceAPI
{
public:
CTSAPIClient(const std::string & hostName, const std::string & game);
virtual ~CTSAPIClient();
virtual void onConnect(const char *host, const short port, const short current, const short max);
virtual void onDisconnect(const char *host, const short port, const short current, const short max);
// ----- Normal Callbacks as a response to requests sent -----
virtual void onTest(const unsigned track, const int resultCode, const unsigned value, void *user);
virtual void onReplyTest(const unsigned track, const int resultCode, void *user);
virtual void onReplyMoveStatus(const unsigned track, const int resultCode, void *user);
virtual void onReplyValidateMove(const unsigned track, const int resultCode, void *user);
virtual void onReplyMove(const unsigned track, const int resultCode, void *user);
virtual void onReplyTransferAccount(const unsigned track, const int resultCode, void *user);
virtual void onReplyCharacterList(const unsigned track, const int resultCode, void *user);
virtual void onReplyServerList(const unsigned track, const int resultCode, void *user);
virtual void onReplyDestinationServerList(const unsigned track, const int resultCode, void *user);
// ----- Callbacks generated by the server directly -----
virtual void onServerTest(const unsigned server_track, const char *game, const char *param);
virtual void onRequestMoveStatus(const unsigned server_track, const char *language, const unsigned transactionID);
virtual void onRequestValidateMove(const unsigned server_track, const char *language, const CTService::CTUnicodeChar *sourceServer, const CTService::CTUnicodeChar *destServer, const CTService::CTUnicodeChar *sourceCharacter,const CTService::CTUnicodeChar *destCharacter, const unsigned uid, const unsigned destuid, bool withItems, bool);
virtual void onRequestMove(const unsigned server_track, const char *language, const CTService::CTUnicodeChar *sourceServer, const CTService::CTUnicodeChar *destServer, const CTService::CTUnicodeChar *sourceCharacter, const CTService::CTUnicodeChar *destCharacter, const unsigned uid, const unsigned destuid, const unsigned transactionID, bool withItems, bool allowOverride);
virtual void onRequestTransferAccount(const unsigned server_track, const unsigned uid, const unsigned destuid, const unsigned transactionID);
virtual void onRequestCharacterList(const unsigned server_track, const char *language, const CTService::CTUnicodeChar *server, const unsigned uid);
virtual void onRequestServerList(const unsigned server_track, const char *language);
virtual void onRequestDestinationServerList(const unsigned server_track, const char *language, const CTService::CTUnicodeChar *character, const CTService::CTUnicodeChar *server);
void moveComplete(unsigned int id, unsigned int track, int result) const;
void moveStart(unsigned int id, unsigned int track, const CentralServerConnection * sourceCentralServerConnection, const CentralServerConnection * destinationCentralServerConnection);
void lostCentralServerConnection(const CentralServerConnection * centralServerConnection);
private:
/* NOT IMPLEMENTED IN SWG TRANSFER SERVICE */
void onReplyDelete(const unsigned int, const int, void *);
void onReplyRestore(const unsigned int, const int, void *);
void onRequestDelete(const unsigned int, const char *, const CTService::CTUnicodeChar *, const CTService::CTUnicodeChar *, const CTService::CTUnicodeChar *, const CTService::CTUnicodeChar *, const unsigned int, const unsigned int, const unsigned int, bool, bool);
void onRequestRestore(const unsigned int, const char *, const CTService::CTUnicodeChar *, const CTService::CTUnicodeChar *, const CTService::CTUnicodeChar *, const CTService::CTUnicodeChar *, const unsigned int, const unsigned int, const unsigned int, bool, bool);
private:
CTSAPIClient();
CTSAPIClient(const CTSAPIClient &);
CTSAPIClient & operator= (const CTSAPIClient &);
};
//-----------------------------------------------------------------------
#endif//_INCLUDED_CTSAPIClient_H
@@ -0,0 +1,410 @@
// CentralServerConnection.cpp
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "FirstTransferServer.h"
#include "CentralServerConnection.h"
#include "ConsoleManager.h"
#include "TransferServer.h"
#include "serverNetworkMessages/CharacterTransferStatusMessage.h"
#include "serverNetworkMessages/DownloadCharacterMessage.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 "serverNetworkMessages/TransferReplyMoveValidation.h"
#include "serverNetworkMessages/UploadCharacterMessage.h"
#include "sharedLog/Log.h"
#include "sharedCommandParser/CommandParser.h"
#include "sharedNetworkMessages/ConsoleChannelMessages.h"
#include "sharedNetworkMessages/GameNetworkMessage.h"
#include "sharedNetworkMessages/GenericValueTypeMessage.h"
#include "UnicodeUtils.h"
//-----------------------------------------------------------------------
namespace CentralServerConnectionNamespace
{
std::map<std::string, CentralServerConnection *> s_centralServerConnections;
}
using namespace CentralServerConnectionNamespace;
//-----------------------------------------------------------------------
CentralServerConnection::CentralServerConnection(UdpConnectionMT * u, TcpClient * t) :
ServerConnection(u, t),
m_galaxyName("")
{
}
//-----------------------------------------------------------------------
CentralServerConnection::~CentralServerConnection()
{
std::map<std::string, CentralServerConnection *>::iterator f = s_centralServerConnections.find(m_galaxyName);
if(f != s_centralServerConnections.end())
{
s_centralServerConnections.erase(f);
}
}
//-----------------------------------------------------------------------
CentralServerConnection * CentralServerConnection::getCentralServerConnectionForGalaxy(const std::string & galaxyName)
{
CentralServerConnection * result = 0;
std::map<std::string, CentralServerConnection *>::iterator f = s_centralServerConnections.find(galaxyName);
if(f != s_centralServerConnections.end())
{
result = f->second;
}
return result;
}
//-----------------------------------------------------------------------
const std::map<std::string, CentralServerConnection *> & CentralServerConnection::getGalaxies()
{
return s_centralServerConnections;
}
//-----------------------------------------------------------------------
void CentralServerConnection::onConnectionClosed()
{
LOG("CustomerService", ("CharacterTransfer: Connection with CentralServer running Galaxy %s has closed\n", m_galaxyName.c_str()));
}
//-----------------------------------------------------------------------
void CentralServerConnection::onConnectionOpened()
{
LOG("CustomerService", ("CharacterTransfer: A connection with a CentralServer has opened\n"));
}
//-----------------------------------------------------------------------
void CentralServerConnection::onReceive(const Archive::ByteStream & message)
{
Archive::ReadIterator ri = message.begin();
const GameNetworkMessage msg(ri);
ri = message.begin();
if(msg.isType("CentralGalaxyName"))
{
const GenericValueTypeMessage<std::string> cgn(ri);
setGalaxyName(cgn.getValue());
LOG("CustomerService", ("CharacterTransfer: Received CentralGalaxyName for %s", cgn.getValue().c_str()));
}
else if(msg.isType("UploadCharacterMessage"))
{
// receiving character data
const UploadCharacterMessage ucm(ri);
CharacterTransferData data;
data.stationId = ucm.getStationId();
data.fromGalaxy = m_galaxyName;
data.packedData = ucm.getPackedCharacterData();
bool result = TransferServer::uploadCharacterTransferData(data, ucm.getIsAdmin());
if(result)
{
CharacterTransferStatusMessage uploadResult(ucm.getFromGameServerId(), ucm.getFromCharacterId(), "@base_player:upload_success");
send(uploadResult, true);
}
else
{
CharacterTransferStatusMessage uploadResult(ucm.getFromGameServerId(), ucm.getFromCharacterId(), "@base_player:upload_fail");
send(uploadResult, true);
}
}
else if(msg.isType("DownloadCharacterMessage"))
{
// retreive packed data from transfer server and
// send it to the requesting central server
const DownloadCharacterMessage dcm(ri);
const CharacterTransferData * data = TransferServer::getCharacterTransferData(dcm.getStationId(), m_galaxyName, dcm.getIsAdmin());
if(data)
{
const UploadCharacterMessage ucm(data->stationId, data->packedData, dcm.getGameServerId(), dcm.getToCharacterId(), true);
send(ucm, true);
LOG("CustomerService", ("CharacterTransfer: Character data for SUID %d downloaded\n", data->stationId));
}
else
{
CharacterTransferStatusMessage downloadResult(dcm.getGameServerId(), dcm.getToCharacterId(), "@base_player:download_fail");
send(downloadResult, true);
}
}
else if(msg.isType("AuthorizeDownload"))
{
const GenericValueTypeMessage<unsigned int> auth(ri);
TransferServer::authorizeDownload(auth.getValue());
}
else if(msg.isType("UnauthorizeDownload"))
{
const GenericValueTypeMessage<unsigned int> auth(ri);
TransferServer::unauthorizeDownload(auth.getValue());
}
else if(msg.isType("TransferReplyCharacterList"))
{
const TransferReplyCharacterList reply(ri);
// TESTING!
LOG("CustomerService", ("CharacterTransfer: Received character list for station id %d\n", reply.getStationId()));
const std::vector<AvatarRecord> & avatarList = reply.getAvatarList();
std::vector<AvatarRecord>::const_iterator i;
LOG("CustomerService", ("CharacterTransfer: Enumerating %d characters", avatarList.size()));
for(i = avatarList.begin() ; i != avatarList.end(); ++i)
{
LOG("CustomerService", ("CharacterTransfer: m_name = \"%s\" m_networkId = %s\n", Unicode::wideToNarrow(i->m_name).c_str(), i->m_networkId.getValueString().c_str()));
}
// TESTING END
TransferServer::replyCharacterList(reply);
}
else if(msg.isType("TransferReplyMoveValidation"))
{
const TransferReplyMoveValidation reply(ri);
if(reply.getResult() == TransferReplyMoveValidation::TRMVR_can_create_regular_character)
{
// save off the source character's template crc so it can be used in
// subsequent TransferRequestMoveValidation queries, so the LoginServer
// doesn't have to continually query the DB to fetch the same information
// over and over again, because the character's template crc
// (i.e. the character's species) should never, ever change
TransferServer::cacheSourceCharacterTemplateCrc(reply.getSourceStationId(), reply.getSourceGalaxy(), reply.getSourceCharacter(), reply.getSourceCharacterTemplateId());
TransferCharacterData requestData(reply.getTransferRequestSource());
requestData.setTrack(reply.getTrack());
requestData.setCustomerLocalizedLanguage(reply.getCustomerLocalizedLanguage());
requestData.setSourceGalaxy(reply.getSourceGalaxy());
requestData.setDestinationGalaxy(reply.getDestinationGalaxy());
requestData.setSourceCharacterName(reply.getSourceCharacter());
requestData.setObjectTemplateCrc(reply.getSourceCharacterTemplateId());
requestData.setDestinationCharacterName(reply.getDestinationCharacter());
requestData.setSourceStationId(reply.getSourceStationId());
requestData.setDestinationStationId(reply.getDestinationStationId());
const GenericValueTypeMessage<TransferCharacterData> requestNameValidation("TransferRequestNameValidation", requestData);
CentralServerConnection * destinationConnection = CentralServerConnection::getCentralServerConnectionForGalaxy(reply.getDestinationGalaxy());
LOG("CustomerService", ("CharacterTransfer: Received TransferReplyMoveValidation for %s on %s to %s on %s from CentralServer. Sending TransferRequestNameValidation to destination CentralServer.", reply.getSourceCharacter().c_str(), reply.getSourceGalaxy().c_str(), reply.getDestinationCharacter().c_str(), reply.getDestinationGalaxy().c_str()));
const GenericValueTypeMessage<std::pair<unsigned int, unsigned int> > kick("TransferRequestKickConnectedClients", std::make_pair(requestData.getSourceStationId(), requestData.getDestinationStationId()));
if(destinationConnection)
{
destinationConnection->send(requestNameValidation, true);
destinationConnection->send(kick, true);
}
CentralServerConnection * sourceConnection = CentralServerConnection::getCentralServerConnectionForGalaxy(reply.getSourceGalaxy());
if(sourceConnection)
{
sourceConnection->send(kick, true);
}
}
else
{
LOG("CustomerService", ("CharacterTransfer: TransferReplyMoveValidation failed for %s on %s to %s on %s from CentralServer because the account cannot create a new character on the destination server", reply.getSourceCharacter().c_str(), reply.getSourceGalaxy().c_str(), reply.getDestinationCharacter().c_str(), reply.getDestinationGalaxy().c_str()));
TransferServer::failedToValidateTransfer(reply);
}
}
else if(msg.isType("TransferReplyNameValidation"))
{
const GenericValueTypeMessage<std::pair<std::string, TransferCharacterData> > replyNameValidation(ri);
if(!replyNameValidation.getValue().second.getIsMoveRequest())
{
LOG("CustomerService", ("CharacterTransfer: Received replyNameValidation for move validation request. (%s) %s", replyNameValidation.getValue().first.c_str(), replyNameValidation.getValue().second.toString().c_str()));
TransferServer::replyValidateMove(replyNameValidation.getValue().second);
}
else
{
if(TransferServer::isRename(replyNameValidation.getValue().second))
{
LOG("CustomerService", ("CharacterTransfer: Received replyNameValidation for rename request, starting character rename protocol. (%s) %s", replyNameValidation.getValue().first.c_str(), replyNameValidation.getValue().second.toString().c_str()));
const GenericValueTypeMessage<TransferCharacterData> renameCharacter("TransferRenameCharacter", replyNameValidation.getValue().second);
CentralServerConnection * centralServerConnection = CentralServerConnection::getCentralServerConnectionForGalaxy(replyNameValidation.getValue().second.getSourceGalaxy());
if(centralServerConnection)
{
centralServerConnection->send(renameCharacter, true);
}
else
{
TransferServer::transferCreateCharacterFailed(replyNameValidation.getValue().second);
}
}
else
{
DEBUG_FATAL(true, ("Received TransferReplyNameValidation for a move request that is not a rename!"));
}
}
}
else if(msg.isType("TransferReplyCharacterDataFromLoginServer"))
{
const GenericValueTypeMessage<TransferCharacterData> reply(ri);
LOG("CustomerService", ("CharacterTransfer: Got TransferReplyCharacterDataFromLoginServer, characterId=%s\n", reply.getValue().getCharacterId().getValueString().c_str()));
// is this a transfer or a rename?
if(TransferServer::isRename(reply.getValue()))
{
LOG("CustomerService", ("CharacterTransfer: Sending TransferRequestNameValidation for character rename request: %s", reply.getValue().toString().c_str()));
// send a name validation request
const GenericValueTypeMessage<TransferCharacterData> requestNameValidation("TransferRequestNameValidation", reply.getValue());
CentralServerConnection * centralServerConnection = CentralServerConnection::getCentralServerConnectionForGalaxy(reply.getValue().getSourceGalaxy());
if(centralServerConnection)
{
centralServerConnection->send(requestNameValidation, true);
}
}
else
{
// this is a transfer
TransferServer::getLoginLocationData(reply.getValue());
}
}
else if(msg.isType("TransferReplyLoginLocationData"))
{
const GenericValueTypeMessage<TransferCharacterData> reply(ri);
LOG("CustomerService", ("CharacterTransfer: Got TransferReplyLoginLocationData from CentralServer. TransferCharacterData=%s\n", reply.getValue().toString().c_str()));
// send character to ConnectionServer for login to a game server
const GenericValueTypeMessage<TransferCharacterData> login("TransferLoginCharacterToSourceServer", reply.getValue());
LOG("CustomerService", ("CharacterTransfer: Sending TransferLoginCharacterToSourceServer to CentralServer : %s", login.getValue().toString().c_str()));
send(login, true);
}
else if(msg.isType("TransferReceiveDataFromGameServer"))
{
const GenericValueTypeMessage<TransferCharacterData> transferReply(ri);
LOG("CustomerService", ("CharacterTransfer: Got TransferReceiveDataFromGameServer: %s", transferReply.getValue().toString().c_str()));
REPORT_LOG(true, ("Got TransferReceiveDataFromGameServer: %s\n", transferReply.getValue().toString().c_str()));
// find a central server connection for the target cluster
CentralServerConnection * destinationCentralConnection = CentralServerConnection::getCentralServerConnectionForGalaxy(transferReply.getValue().getDestinationGalaxy());
if(destinationCentralConnection)
{
// send character to ConnectionServer for creation on the destination server
GenericValueTypeMessage<TransferCharacterData> login("TransferLoginCharacterToDestinationServer", transferReply.getValue());
destinationCentralConnection->send(login, true);
LOG("CustomerService", ("CharacterTransfer: Sending TransferLoginCharacterToDestinationServer to CentralServer (%s) for (%s)", transferReply.getValue().getDestinationGalaxy().c_str(), login.getValue().toString().c_str()));
}
else
{
//@todo: report error to CTS API
LOG("CustomerService", ("CharacterTransfer: Failed to get a CentralServer connection for %s", transferReply.getValue().getDestinationGalaxy().c_str()));
TransferServer::transferCreateCharacterFailed(transferReply.getValue());
}
}
else if(msg.isType("ApplyTransferDataSuccess"))
{
const GenericValueTypeMessage<TransferCharacterData> success(ri);
LOG("CustomerService", ("CharacterTransfer: Received ApplyTransferDataSuccess from target galaxy. %s", success.getValue().toString().c_str()));
CentralServerConnection * centralServerConnection = CentralServerConnection::getCentralServerConnectionForGalaxy(success.getValue().getSourceGalaxy());
if(centralServerConnection)
{
LOG("CustomerService", ("CharacterTransfer: Sending ToggleAvatarLoginStatus request to source central server"));
const ToggleAvatarLoginStatus toggleLoginStatus(success.getValue().getSourceGalaxy(), success.getValue().getSourceStationId(), success.getValue().getCharacterId(), false);
centralServerConnection->send(toggleLoginStatus, true);
TransferServer::replyMoveSuccess(success.getValue());
LOG("CustomerService", ("CharacterTransfer: TRANSFER SUCCESSFUL for transactionId=%u", success.getValue().getTransactionId()));
}
else
{
LOG("CustomerService", ("CharacterTransfer: Transfer failed on target galaxy : %s", success.getValue().toString().c_str()));
TransferServer::transferCreateCharacterFailed(success.getValue());
}
}
else if(msg.isType("ApplyTransferDataFail"))
{
const GenericValueTypeMessage<TransferCharacterData> fail(ri);
LOG("CustomerService", ("CharacterTransfer: Received ApplyTransferDataFail from target galaxy. %s", fail.getValue().toString().c_str()));
CentralServerConnection * centralServerConnection = CentralServerConnection::getCentralServerConnectionForGalaxy(fail.getValue().getDestinationGalaxy());
if(centralServerConnection)
{
LOG("CustomerService", ("CharacterTransfer: failed to apply transfer data. Deleting character on destination server. %s", fail.getValue().toString().c_str()));
const GenericValueTypeMessage<TransferCharacterData> deleteCharacter("DeleteFailedTransfer", fail.getValue());
centralServerConnection->send(deleteCharacter, true);
TransferServer::failedToApplyTransferData(fail.getValue());
}
}
else if(msg.isType("TransferCreateCharacterFailed"))
{
const GenericValueTypeMessage<TransferCharacterData> fail(ri);
LOG("CustomerService", ("CharacterTransfer: Received TransferCreateCharacterFailed, sending response to CTS API. %s", fail.getValue().toString().c_str()));
TransferServer::transferCreateCharacterFailed(fail.getValue());
}
else if(msg.isType("TransferRenameCharacterReply"))
{
const GenericValueTypeMessage<TransferCharacterData> reply(ri);
LOG("CustomerService", ("CharacterTransfer: Received TransferRenameCharacterReply from Central Server : %s", reply.getValue().toString().c_str()));
if(reply.getValue().getIsValidName())
{
TransferServer::replyMoveSuccess(reply.getValue());
}
else
{
TransferServer::transferCreateCharacterFailed(reply.getValue());
}
}
else if(msg.isType("TransferAccountReplySuccessTransferServer"))
{
const GenericValueTypeMessage<TransferAccountData> reply(ri);
LOG("CustomerService", ("CharacterTransfer: Received TransferAccountReplySuccessTransferServer from station Id %d to station Id %d", reply.getValue().getSourceStationId(), reply.getValue().getDestinationStationId()));
TransferServer::replyTransferAccountSuccess(reply.getValue());
}
else if(msg.isType("TransferAccountFailedToUpdateGameDatabase"))
{
const GenericValueTypeMessage<TransferAccountData> reply(ri);
LOG("CustomerService", ("CharacterTransfer: Received TransferAccountFailedToUpdateGameDatabase for transfer from station Id %d to station Id %d", reply.getValue().getSourceStationId(), reply.getValue().getDestinationStationId()));
TransferServer::failedToTransferAccountNoCentralConnection(reply.getValue());
}
else if(msg.isType("TransferAccountFailedDestinationNotEmpty"))
{
const GenericValueTypeMessage<TransferAccountData> reply(ri);
LOG("CustomerService", ("CharacterTransfer: Received TransferAccountFailedDestinationNotEmpty for transfer from station Id %d to station Id %d", reply.getValue().getSourceStationId(), reply.getValue().getDestinationStationId()));
TransferServer::failedToTransferAccountDestinationNotEmpty(reply.getValue());
}
else if(msg.isType("ReplyTransferDataFail"))
{
const GenericValueTypeMessage<TransferCharacterData> reply(ri);
TransferServer::failedToRetrieveTransferData(reply.getValue());
}
else if(msg.isType("TransferFailGameServerClosedConnectionWithConnectionServer"))
{
const GenericValueTypeMessage<TransferCharacterData> fail(ri);
TransferServer::failedToTransferCharacterGameConnectionClosed(fail.getValue());
}
else if(msg.isType("TransferFailConnectionServerClosedConnectionWithCentralServer"))
{
const GenericValueTypeMessage<unsigned int> fail(ri);
TransferServer::failedToTransferCharacterConnectionServerConnectionClosed(fail.getValue());
}
else if(msg.isType("ConGenericMessage"))
{
const ConGenericMessage cm(ri);
std::string result;
ConsoleManager::processString(cm.getMsg(), static_cast<const NetworkId::NetworkIdType>(cm.getMsgId()), result);
const ConGenericMessage response(result, cm.getMsgId());
send(response, true);
}
}
//-----------------------------------------------------------------------
void CentralServerConnection::setGalaxyName(const std::string & galaxyName)
{
s_centralServerConnections[galaxyName] = this;
m_galaxyName = galaxyName;
REPORT_LOG("CentralServerConnection", ("Galaxy %s is handled by CentralServerConnection with %s:%d\n", m_galaxyName.c_str(), getRemoteAddress().c_str(), getRemotePort()));
}
//-----------------------------------------------------------------------
@@ -0,0 +1,42 @@
// CentralServerConnection.h
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _INCLUDED_CentralServerConnection_H
#define _INCLUDED_CentralServerConnection_H
//-----------------------------------------------------------------------
#include "serverUtility/ServerConnection.h"
#include <map>
#include <string>
class CentralServerConnection;
//-----------------------------------------------------------------------
class CentralServerConnection : public ServerConnection
{
public:
CentralServerConnection(UdpConnectionMT *, TcpClient * t);
~CentralServerConnection();
virtual void onConnectionClosed ();
virtual void onConnectionOpened ();
virtual void onReceive (const Archive::ByteStream & message);
static CentralServerConnection * getCentralServerConnectionForGalaxy(const std::string & galaxyName);
void setGalaxyName (const std::string & galaxyName);
static const std::map<std::string, CentralServerConnection *> & getGalaxies();
private:
CentralServerConnection & operator = (const CentralServerConnection & rhs);
CentralServerConnection(const CentralServerConnection & source);
std::string m_galaxyName;
}; //lint !e1712 default constructor not defined for class 'CentralServerConnection'
//-----------------------------------------------------------------------
#endif // _INCLUDED_CentralServerConnection_H
@@ -0,0 +1,137 @@
// ConfigTransferServer.cpp
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "FirstTransferServer.h"
#include "sharedFoundation/ConfigFile.h"
#include "sharedNetwork/SetupSharedNetwork.h"
#include "ConfigTransferServer.h"
#include <vector>
//-----------------------------------------------------------------------
ConfigTransferServer::Data * ConfigTransferServer::data = 0;
#define KEY_INT(a,b) (data->a = ConfigFile::getKeyInt("TransferServer", #a, b))
#define KEY_BOOL(a,b) (data->a = ConfigFile::getKeyBool("TransferServer", #a, b))
#define KEY_STRING(a,b) (data->a = ConfigFile::getKeyString("TransferServer", #a, b))
//-----------------------------------------------------------------------
namespace ConfigTransferServerNamespace
{
std::vector<std::string> s_serversAllowedToUploadCharacterData;
std::vector<std::string> s_serversAllowedToDownloadCharacterData;
}
using namespace ConfigTransferServerNamespace;
// ----------------------------------------------------------------------
const std::vector<std::string> & ConfigTransferServer::getServersAllowedToUploadCharacterData()
{
return s_serversAllowedToUploadCharacterData;
}
// ----------------------------------------------------------------------
const std::vector<std::string> & ConfigTransferServer::getServersAllowedToDownloadCharacterData()
{
return s_serversAllowedToDownloadCharacterData;
}
// ----------------------------------------------------------------------
void ConfigTransferServer::install(void)
{
SetupSharedNetwork::SetupData networkSetupData;
SetupSharedNetwork::getDefaultServerSetupData(networkSetupData);
data = new ConfigTransferServer::Data;
KEY_INT (centralServerServiceBindPort, 50005);
KEY_STRING (centralServerServiceBindInterface, "");
KEY_BOOL (allowSameServerTransfers, false);
KEY_BOOL (allowAccountTransfers, true);
KEY_STRING (apiServerHostAddress, "");
KEY_BOOL (transferChatAvatar, false);
int index = 0;
char const * result = 0;
do
{
result = ConfigFile::getKeyString("TransferServer", "serverAllowedToUploadCharacterData", index++, 0);
if (result != 0)
{
s_serversAllowedToUploadCharacterData.push_back(result);
}
}
while (result);
index = 0;
result = 0;
do
{
result = ConfigFile::getKeyString("TransferServer", "serverAllowedToDownloadCharacterData", index++, 0);
if (result != 0)
{
s_serversAllowedToDownloadCharacterData.push_back(result);
}
}
while (result);
}
//-----------------------------------------------------------------------
void ConfigTransferServer::remove(void)
{
delete data;
data = 0;
}
//-----------------------------------------------------------------------
unsigned short ConfigTransferServer::getCentralServerServiceBindPort()
{
return static_cast<unsigned short>(data->centralServerServiceBindPort);
}
//-----------------------------------------------------------------------
const char * ConfigTransferServer::getCentralServerServiceBindInterface()
{
return data->centralServerServiceBindInterface;
}
//-----------------------------------------------------------------------
bool ConfigTransferServer::getAllowSameServerTransfers()
{
return data->allowSameServerTransfers;
}
//-----------------------------------------------------------------------
bool ConfigTransferServer::getAllowAccountTransfers()
{
return data->allowAccountTransfers;
}
//-----------------------------------------------------------------------
const char * ConfigTransferServer::getApiServerHostAddress()
{
return data->apiServerHostAddress;
}
//-----------------------------------------------------------------------
const bool ConfigTransferServer::getTransferChatAvatar()
{
return data->transferChatAvatar;
}
//-----------------------------------------------------------------------
@@ -0,0 +1,48 @@
// ConfigTransferServer.h
// Copyright 2000-04, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _ConfigTransferServer_H
#define _ConfigTransferServer_H
//-----------------------------------------------------------------------
#include <string>
#include <vector>
//-----------------------------------------------------------------------
class ConfigTransferServer
{
public:
struct Data
{
int centralServerServiceBindPort;
const char * consoleServiceBindInterface;
const char * gameServiceBindInterface;
const char * centralServerServiceBindInterface;
bool allowSameServerTransfers;
bool allowAccountTransfers;
const char * apiServerHostAddress;
bool transferChatAvatar;
};
static uint16 getCentralServerServiceBindPort ();
static const char * getCentralServerServiceBindInterface ();
static bool getAllowSameServerTransfers ();
static bool getAllowAccountTransfers ();
static void install ();
static void remove ();
static const std::vector<std::string> & getServersAllowedToUploadCharacterData();
static const std::vector<std::string> & getServersAllowedToDownloadCharacterData();
static const char * getApiServerHostAddress();
static const bool getTransferChatAvatar();
private:
static Data * data;
};
// ----------------------------------------------------------------------
#endif // _ConfigTransferServer_H
@@ -0,0 +1,139 @@
// ConsoleCommandParser.cpp
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/NetworkId.h"
#include "sharedLog/Log.h"
#include "ConsoleCommandParser.h"
#include "TransferServer.h"
#include "UnicodeUtils.h"
#include <vector>
#include "Unicode.h"
//-----------------------------------------------------------------------
namespace CommandNames
{
#define MAKE_COMMAND(a) const char * const a = #a
#undef MAKE_COMMAND
}
const CommandParser::CmdInfo cmds[] =
{
{"transfer", 4, "<requestMove> <station id> <character name> <source server> <destination server>", "Request a character transfer for <character name> from <source server> to <destination server>"},
{"transfer", 2, "<requestAccountMove> <source station id> <destination station id>", "Request an account transfer from <source station id> to <destination station id>"},
{"", 0, "", ""} // this must be last
};
//-----------------------------------------------------------------------
ConsoleCommandParser::ConsoleCommandParser() :
CommandParser ("", 0, "...", "console commands", this)
{
createDelegateCommands(cmds);
}
//-----------------------------------------------------------------------
ConsoleCommandParser::~ConsoleCommandParser()
{
}
//-----------------------------------------------------------------------
bool ConsoleCommandParser::performParsing(const NetworkId & track, const StringVector_t & argv, const String_t &, String_t & result, const CommandParser *)
{
bool successResult = false;
if(isCommand(argv[0], "transfer"))
{
if(isCommand(argv[1], "requestMove"))
{
if(argv.size() > 5)
{
std::string stationIdString = Unicode::wideToNarrow(argv[2]);
std::string characterName = Unicode::wideToNarrow(argv[3]);
std::string sourceServer = Unicode::wideToNarrow(argv[4]);
std::string destinationServer = Unicode::wideToNarrow(argv[5]);
LOG("CustomerService", ("CharacterTransfer: received console request to transfer %s, belonging to %s from %s to %s", characterName.c_str(), stationIdString.c_str(), sourceServer.c_str(), destinationServer.c_str()));
result += Unicode::narrowToWide("Received request to move ");
result += Unicode::narrowToWide(characterName);
result += Unicode::narrowToWide(" owned by station ID ");
result += Unicode::narrowToWide(stationIdString);
result += Unicode::narrowToWide(" on cluster ");
result += Unicode::narrowToWide(sourceServer);
result += Unicode::narrowToWide(" to cluster ");
result += Unicode::narrowToWide(destinationServer);
const unsigned int stationId = static_cast<const unsigned int>(atoi (stationIdString.c_str()));
const unsigned int trackId = static_cast<const unsigned int>(track.getValue());
//todo : drive these through the command handler, just testing
// basic functionality for now.
const bool withItems = true;
const bool allowOverride = true;
TransferServer::requestMove(trackId, "en", sourceServer, destinationServer, characterName, characterName, stationId, stationId, trackId, withItems, allowOverride);
successResult = true;
}
else
{
std::string messageString = "not enough arguments to 'requestMove <station id> <character name> <source server> <destination server>'";
StringVector_t::const_iterator i;
for(i = argv.begin(); i != argv.end(); ++i)
{
messageString = messageString + Unicode::wideToNarrow(*i) + " | ";
}
LOG("CustomerService", ("CharacterTransfer: %s", messageString.c_str()));
result += Unicode::narrowToWide(messageString);
}
}
else if (isCommand(argv[1], "requestAccountMove"))
{
if (argv.size() > 3)
{
std::string sourceStationIdString = Unicode::wideToNarrow(argv[2]);
std::string destinationStationIdString = Unicode::wideToNarrow(argv[3]);
LOG("CustomerService", ("CharacterTransfer: received console request to transfer account from station ID %s to station ID %s", sourceStationIdString.c_str(), destinationStationIdString.c_str()));
result += Unicode::narrowToWide("Received request to move from station ID ");
result += Unicode::narrowToWide(sourceStationIdString);
result += Unicode::narrowToWide(" to station ID ");
result += Unicode::narrowToWide(destinationStationIdString);
result += Unicode::narrowToWide("\n");
const unsigned int sourceStationId = static_cast<const unsigned int>(atoi (sourceStationIdString.c_str()));
const unsigned int destinationStationId = static_cast<const unsigned int>(atoi (destinationStationIdString.c_str()));
const unsigned int trackId = static_cast<const unsigned int>(track.getValue());
TransferServer::requestTransferAccount(trackId, sourceStationId, destinationStationId, trackId);
successResult = true;
}
else
{
std::string messageString = "not enough arguments to 'requestAccountMove <source station id> <destination station id>'";
StringVector_t::const_iterator i;
for(i = argv.begin(); i != argv.end(); ++i)
{
messageString = messageString + Unicode::wideToNarrow(*i) + " | ";
}
LOG("CustomerService", ("CharacterTransfer: %s\n", messageString.c_str()));
result += Unicode::narrowToWide(messageString);
result += Unicode::narrowToWide("\n");
}
}
}
return successResult;
}
//-----------------------------------------------------------------------
@@ -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
@@ -0,0 +1,58 @@
// ConsoleManager.cpp
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundation/NetworkId.h"
#include "ConsoleManager.h"
#include "ConsoleCommandParser.h"
#include "UnicodeUtils.h"
//-----------------------------------------------------------------------
namespace ConsoleManagerNamespace
{
ConsoleCommandParser * s_consoleCommandParserRoot = NULL;
}
using namespace ConsoleManagerNamespace;
//-----------------------------------------------------------------------
ConsoleManager::ConsoleManager()
{
}
//-----------------------------------------------------------------------
ConsoleManager::~ConsoleManager()
{
}
//-----------------------------------------------------------------------
void ConsoleManager::install()
{
s_consoleCommandParserRoot = new ConsoleCommandParser;
}
//-----------------------------------------------------------------------
void ConsoleManager::remove()
{
delete s_consoleCommandParserRoot;
}
//-----------------------------------------------------------------------
void ConsoleManager::processString(const std::string & msg, const int track, std::string & result)
{
Unicode::String wideResult;
IGNORE_RETURN(s_consoleCommandParserRoot->parse(NetworkId(static_cast<NetworkId::NetworkIdType>(track)), Unicode::narrowToWide(msg), wideResult));
result = Unicode::wideToNarrow(wideResult);
}
//-----------------------------------------------------------------------
@@ -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 <string>
//-----------------------------------------------------------------------
class ConsoleManager
{
public:
static void install();
static void remove();
static void 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
@@ -0,0 +1,14 @@
// FirstServerConsole.h
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _INCLUDED_FirstServerConsole_H
#define _INCLUDED_FirstServerConsole_H
//-----------------------------------------------------------------------
#include "sharedFoundation/FirstSharedFoundation.h"
//-----------------------------------------------------------------------
#endif // _INCLUDED_FirstServerConsole_H
@@ -0,0 +1,872 @@
// TransferServer.cpp
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "FirstTransferServer.h"
#include "CentralServerConnection.h"
#include "ConfigTransferServer.h"
#include "ConsoleManager.h"
#include "CTSAPIClient.h"
#include "CTCommon/CTServiceCharacter.h"
#include "serverNetworkMessages/TransferAccountData.h"
#include "serverNetworkMessages/TransferAccountDataArchive.h"
#include "serverNetworkMessages/TransferCharacterData.h"
#include "serverNetworkMessages/TransferCharacterDataArchive.h"
#include "serverNetworkMessages/TransferReplyCharacterList.h"
#include "serverNetworkMessages/TransferReplyMoveValidation.h"
#include "serverNetworkMessages/TransferRequestMoveValidation.h"
#include "sharedFoundation/Os.h"
#include "sharedLog/Log.h"
#include "sharedLog/SetupSharedLog.h"
#include "sharedMath/Vector.h"
#include "sharedNetwork/Connection.h"
#include "sharedNetwork/Service.h"
#include "sharedNetwork/NetworkSetupData.h"
#include "sharedNetworkMessages/GenericValueTypeMessage.h"
#include "sharedUtility/DataTableManager.h"
#include "TransferServer.h"
#include "CentralServerConnection.h"
#include <cstdio>
#include <string>
#include <sstream>
#include <ostream>
#include "Unicode.h"
#include "UnicodeUtils.h"
//-----------------------------------------------------------------------
namespace TransferServerNamespace
{
Service * s_transferServerService;
std::map<unsigned int, CharacterTransferData> s_transferData;
std::set<std::string> s_serversAllowedToUpload;
std::set<std::string> s_serversAllowedToDownload;
std::set<unsigned int> s_authorizedDownloads;
bool s_done = false;
CTSAPIClient * s_apiClient = 0;
// as we receive the source character's template crc that comes back from the LoginServer
// in the TransferReplyMoveValidation message, save it here, and send it back in subseqnent
// TransferRequestMoveValidation messages as an optimization so the LoginServer doesn't have
// to continually query the DB to fetch the same information over and over again, because
// the character's template crc (i.e. the character's species) should never, ever change
std::map<std::pair<unsigned int, std::pair<std::string, std::string> >, uint32> s_cacheSourceCharacterTemplateCrc;
void closePseudoClientConnection(const std::string & galaxyName, const unsigned int stationId)
{
CentralServerConnection * centralServerConnection = CentralServerConnection::getCentralServerConnectionForGalaxy(galaxyName);
if(centralServerConnection)
{
GenericValueTypeMessage<unsigned int> closeRequest("TransferClosePseudoClientConnection", stationId);
centralServerConnection->send(closeRequest, true);
}
}
void closePseudoClientConnections(const std::string & sourceGalaxyName, const unsigned int sourceStationId, const std::string & destinationGalaxyName, const unsigned int destinationStationId)
{
// close pseudoclientconnections
closePseudoClientConnection(sourceGalaxyName, sourceStationId);
unsigned int destId = destinationStationId;
if(destId == 0)
destId = sourceStationId;
closePseudoClientConnection(destinationGalaxyName, destId);
}
std::string resultToString(CTService::CTMoveResult resultCode)
{
std::string resultString;
switch (resultCode)
{
case CTService::CT_GAMERESULT_SUCCESS:
resultString = "CTService::CT_GAMERESULT_SUCCESS";
break;
case CTService::CT_GAMERESULT_SOFTERROR:
resultString = "CTService::CT_GAMERESULT_SOFTERROR";
break;
case CTService::CT_GAMERESULT_HARDERROR:
resultString = "CTService::CT_GAMERESULT_HARDERROR";
break;
case CTService::CT_GAMERESULT_INVALID_NAME:
resultString = "CTService::CT_GAMERESULT_INVALID_NAME";
break;
case CTService::CT_GAMERESULT_NAME_ALREADY_TAKE:
resultString = "CTService::CT_GAMERESULT_NAME_ALREADY_TAKE";
break;
case CTService::CT_GAMERESULT_HAS_CORPSE:
resultString = "CTService::CT_GAMERESULT_NAME_HAS_CORPSE";
break;
case CTService::CT_GAMERESULT_SERVER_IS_DOWN:
resultString = "CTService::CT_GAMERESULT_SERVER_IS_DOWN";
break;
case CTService::CT_GAMERESULT_MAX_CHAR_ON_DEST_SERVER:
resultString = "CTService::CT_GAMERESULT_MAX_CHAR_ON_DEST_SERVER";
break;
case CTService::CT_GAMERESULT_CHAR_HAS_ITEM_NOT_ALLOWED_TO_LEAVE_SRC_SERVER:
resultString = "CTService::CT_GAMERESULT_CHAR_HAS_ITEM_NOT_ALLOWED_TO_LEAVE_SRC_SERVER";
break;
case CTService::CT_GAMERESULT_CHAR_HAS_ITEM_NOT_ALLOWED_ON_DEST_SERVER:
resultString = "CTService::CT_GAMERESULT_CHAR_HAS_ITEM_NOT_ALLOWED_ON_DEST_SERVER";
break;
case CTService::CT_GAMERESULT_CHAR_NOT_ALLOWED_TO_MOVE_FROM_SRC_SERVER:
resultString = "CTService::CT_GAMERESULT_CHAR_NOT_ALLOWED_TO_MOVE_FROM_SRC_SERVER";
break;
case CTService::CT_GAMERESULT_CHAR_NOT_ALLOWED_TO_MOVE_TO_DEST_SERVER:
resultString = "CTService::CT_GAMERESULT_CHAR_NOT_ALLOWED_TO_MOVE_TO_DEST_SERVER";
break;
case CTService::CT_GAMERESULT_CHAR_NOT_ALLOWED_TO_MOVE_FROM_THIS_SRC_SERVER_TO_THIS_DEST_SERVER:
resultString = "CTService::CT_GAMERESULT_CHAR_NOT_ALLOWED_TO_MOVE_FROM_THIS_SRC_SERVER_TO_THIS_DEST_SERVER";
break;
case CTService::CT_GAMERESULT_CHAR_TYPE_NOT_ALLOWED_TO_LEAVE_SRC_SERVER:
resultString = "CTService::CT_GAMERESULT_CHAR_TYPE_NOT_ALLOWED_TO_LEAVE_SRC_SERVER";
break;
case CTService::CT_GAMERESULT_CHAR_TYPE_NOT_ALLOWED_ON_DEST_SERVER:
resultString = "CTService::CT_GAMERESULT_CHAR_TYPE_NOT_ALLOWED_ON_DEST_SERVER";
break;
case CTService::CT_GAMERESULT_SOFTERROR_FOR_LOCALIZED_TEXT:
resultString = "CTService::CT_GAMERESULT_SOFTERROR_FOR_LOCALIZED_TEXT";
break;
case CTService::CT_GAMERESULT_HARDERROR_FOR_LOCALIZED_TEXT:
resultString = "CTService::CT_GAMERESULT_HARDERROR_FOR_LOCALIZED_TEXT";
break;
default:
{
std::ostringstream buffer;
buffer << "unknown code (" << resultCode << ")" << std::ends;
resultString = buffer.str();
}
break;
}
return resultString;
}
void replyMove(const TransferCharacterData & reply, CTService::CTMoveResult resultCode)
{
if(s_apiClient)
{
const std::string resultString = resultToString(resultCode);
LOG("CustomerService", ("CharacterTransfer: transactionId=%u replyMove(%u, %s, NULL, NULL)", reply.getTransactionId(), reply.getTrack(), resultString.c_str()));
const unsigned int result = static_cast<unsigned int>(resultCode);
s_apiClient->moveComplete(reply.getSourceStationId(), reply.getTrack(), result);
IGNORE_RETURN(s_apiClient->replyMove(reply.getTrack(), result, Unicode::narrowToWide(resultString).c_str(), NULL));
}
}
}
using namespace TransferServerNamespace;
//-----------------------------------------------------------------------
TransferServer::TransferServer()
{
}
//-----------------------------------------------------------------------
TransferServer::~TransferServer()
{
}
//-----------------------------------------------------------------------
void TransferServer::authorizeDownload(unsigned int stationId)
{
IGNORE_RETURN(s_authorizedDownloads.insert(stationId));
REPORT_LOG(true, ("Received download authorization for station id %d\n", stationId));
}
//-----------------------------------------------------------------------
void TransferServer::unauthorizeDownload(unsigned int stationId)
{
std::set<unsigned int>::iterator f = s_authorizedDownloads.find(stationId);
if(f != s_authorizedDownloads.end())
{
s_authorizedDownloads.erase(f);
REPORT_LOG(true, ("Received request to remove download authorization for station id %d\n", stationId));
}
}
//-----------------------------------------------------------------------
const CharacterTransferData * TransferServer::getCharacterTransferData(unsigned int stationId, const std::string & fromGalaxy, bool administrativeRequest)
{
const CharacterTransferData * result = 0;
std::map<unsigned int, CharacterTransferData>::const_iterator f = s_transferData.find(stationId);
if(f != s_transferData.end())
result = &(*f).second;
if(result)
{
bool authorized = false;
// was the request administratively initiated?
if(administrativeRequest)
{
// admins always get what they want
authorized = true;
}
else
{
// users, however, must live up to a higher standard
// is the request coming from a server that is allowed
// to download character data?
std::set<std::string>::const_iterator g = s_serversAllowedToDownload.find(fromGalaxy);
if(g != s_serversAllowedToDownload.end())
{
// the request is coming from a server that a user is allowed to download to
if(ConfigTransferServer::getAllowSameServerTransfers())
{
authorized = true;
}
else
{
if(fromGalaxy != result->fromGalaxy)
{
authorized = true;
}
}
}
else
{
// was this transfer pre-authorized administratively?
std::set<unsigned int>::const_iterator a = s_authorizedDownloads.find(stationId);
if(a != s_authorizedDownloads.end())
{
authorized = true;
}
}
}
// were all requirements met?
if(! authorized)
result = 0;
}
else
{
REPORT_LOG(true, ("Download failed: Transfer data for SUID %d was not found.\n", stationId));
}
return result;
}
//-----------------------------------------------------------------------
void TransferServer::requestCharacterList(unsigned int track, unsigned int stationId, const std::string & serverName, const std::string & customerLocalizedLanguage)
{
CentralServerConnection * centralConnection = CentralServerConnection::getCentralServerConnectionForGalaxy(serverName);
if(centralConnection)
{
// this request is routed to the central server for the target
// galaxy, which in turn queries a LoginServer for the character
// list. The LoginServer returns the list, with the tracking
// ID, to the CentralServer, and ultimately responds to this
// transfer server with the listing.
static const std::string emptyString("");
TransferCharacterData characterData(TransferRequestMoveValidation::TRS_transfer_server);
characterData.setCustomerLocalizedLanguage(customerLocalizedLanguage);
characterData.setSourceGalaxy(serverName);
characterData.setSourceStationId(stationId);
characterData.setTrack(track);
const GenericValueTypeMessage<TransferCharacterData> request("TransferRequestCharacterList", characterData);
centralConnection->send(request, true);
}
else
{
// send failure to CTS API backend
if(s_apiClient)
{
const unsigned int result = static_cast<int>(CTService::CT_RESULT_FAILURE);
IGNORE_RETURN(s_apiClient->replyCharacterList(track, result, 0, NULL, NULL));
s_apiClient->moveComplete(stationId, track, result);
}
}
}
//-----------------------------------------------------------------------
void TransferServer::getLoginLocationData(const TransferCharacterData & characterData)
{
CentralServerConnection * sourceCentralConnection = CentralServerConnection::getCentralServerConnectionForGalaxy(characterData.getSourceGalaxy());
if(sourceCentralConnection)
{
LOG("CustomerService", ("CharacterTransfer: Sending getLoginLocationData for %s", characterData.getSourceCharacterName().c_str()));
const GenericValueTypeMessage<TransferCharacterData> getLoginLocation("TransferGetLoginLocationData", characterData);
sourceCentralConnection->send(getLoginLocation, true);
}
}
//-----------------------------------------------------------------------
void TransferServer::requestMove(unsigned int track, const std::string & customerLocalizedLanguage, const std::string & sourceGalaxy, const std::string & destinationGalaxy, const std::string & sourceCharacter, const std::string & destinationCharacter, unsigned int sourceStationId, unsigned int destinationStationId, unsigned int transactionId, const bool withItems, const bool allowOverride)
{
std::string withItemsString = "UNINITIALIZED";
if(withItems)
withItemsString = "true";
else
withItemsString = "false";
std::string allowOverrideString = "UNINITIALIZED";
if(allowOverride)
allowOverrideString = "true";
else
allowOverrideString = "false";
LOG("CustomerService", ("CharacterTransfer: TransferServer::requestMove(%d, %s, %s, %s, %s, %s, %d, %d, %d, %s, %s)", track, customerLocalizedLanguage.c_str(), sourceGalaxy.c_str(), destinationGalaxy.c_str(), sourceCharacter.c_str(), destinationCharacter.c_str(), sourceStationId, destinationStationId, transactionId, withItemsString.c_str(), allowOverrideString.c_str()));
// this request is routed to the central server for the target
// galaxy, which in turn queries a LoginServer for the character
// list. The LoginServer populates the TransferCharacterData
// with the source characterID. After the response is received
// in CentralServerConnection.cpp, TransferServer::getLoginLocationData
// is called.
// prequalification: if both Galaxies are available, send request, otherwise send failure
CentralServerConnection * sourceCentralConnection = CentralServerConnection::getCentralServerConnectionForGalaxy(sourceGalaxy);
CentralServerConnection * destinationCentralConnection = CentralServerConnection::getCentralServerConnectionForGalaxy(destinationGalaxy);
if(destinationStationId == 0)
destinationStationId = sourceStationId;
std::string destinationCharacterName = destinationCharacter;
if(destinationCharacter.empty())
destinationCharacterName = sourceCharacter;
TransferCharacterData characterData(TransferRequestMoveValidation::TRS_transfer_server);
characterData.setCustomerLocalizedLanguage(customerLocalizedLanguage);
characterData.setSourceGalaxy(sourceGalaxy);
characterData.setDestinationGalaxy(destinationGalaxy);
characterData.setSourceCharacterName(sourceCharacter);
characterData.setDestinationCharacterName(destinationCharacterName);
characterData.setSourceStationId(sourceStationId);
characterData.setDestinationStationId(destinationStationId);
characterData.setTransactionId(transactionId);
characterData.setIsMoveRequest(true);
characterData.setWithItems(withItems);
characterData.setAllowOverride(allowOverride);
characterData.setTrack(track);
/*
TransferCharacterData characterData(track, // track
customerLocalizedLanguage, // customerLocalizedLanguage
sourceGalaxy, // sourceGalaxy
destinationGalaxy, // destinationGalaxy
sourceCharacter, // sourceCharacterName
destinationCharacterName, // destinationCharacterName
sourceStationId, // sourceStationId
destinationStationId, // destinationStationId
transactionId, // transactionId
NetworkId::cms_invalid, // characterId
NetworkId::cms_invalid, // containerId
std::string(""), // scene
0, // clusterId
Vector(), // starting coordinates
std::string(""), // customization data
std::vector<unsigned char>(), // script dictionary buffer
std::string(""), // object template name
1.0f, // scale factor
std::string(""), // hair template name
std::string(""), // hair appearance data
std::string(""), // profession
false, // is a jedi
Unicode::String(), // Biography
NetworkId::cms_invalid, // destination character id
false, // is name validated?
true, // is this a move request?
withItems); // does the move include items?
*/
if(sourceCentralConnection && destinationCentralConnection)
{
// transfer the character
const GenericValueTypeMessage<TransferCharacterData> getCharacterData("TransferGetCharacterDataFromLoginServer", characterData);
sourceCentralConnection->send(getCharacterData, true);
s_apiClient->moveStart(sourceStationId, track, sourceCentralConnection, destinationCentralConnection);
LOG("CustomerService", ("CharacterTransfer: sent TransferGetCharacterDataFromLoginServer message : %s\n", characterData.toString().c_str()));
const GenericValueTypeMessage<std::pair<unsigned int, unsigned int> > kick("TransferRequestKickConnectedClients", std::make_pair(sourceStationId, destinationStationId));
sourceCentralConnection->send(kick, true);
destinationCentralConnection->send(kick, true);
}
else
{
replyMove(characterData, CTService::CT_GAMERESULT_SERVER_IS_DOWN);
}
}
//-----------------------------------------------------------------------
void TransferServer::requestTransferAccount(unsigned int track, unsigned int sourceStationId, unsigned int destinationStationId, unsigned int transactionId)
{
LOG("CustomerService", ("CharacterTransfer: TransferServer::requestAccount(%d, %d, %d, %d)", track, sourceStationId, destinationStationId, transactionId));
if(!ConfigTransferServer::getAllowAccountTransfers())
{
LOG("CustomerService", ("Cannot transfer account, account transfers are not enabled\n"));
if(s_apiClient)
{
const unsigned int result = static_cast<unsigned int>(CTService::CT_GAMERESULT_HARDERROR);
IGNORE_RETURN(s_apiClient->replyValidateMove(track, result, NULL, NULL, NULL));
s_apiClient->moveComplete(sourceStationId, track, result);
}
return;
}
// this request is routed to a login server
// which in turn updates the DatabaseProcess in the CentralServer, and finally updates the ChatServer
// prequalification: if a galaxy is available, send request, otherwise send failure
std::map<std::string, CentralServerConnection *> galaxies = CentralServerConnection::getGalaxies();
std::map<std::string, CentralServerConnection *>::iterator firstGalaxy = galaxies.begin();
if (firstGalaxy == galaxies.end())
{
LOG("CustomerService", ("CharacterTransfer: Account to account move request made, but no central server connections are available in transfer server source station id: %lu destination station id: %lu\n", sourceStationId, destinationStationId));
if(s_apiClient)
{
const unsigned int result = static_cast<unsigned int>(CTService::CT_GAMERESULT_SERVER_IS_DOWN);
IGNORE_RETURN(s_apiClient->replyTransferAccount(track, result, NULL, NULL));
s_apiClient->moveComplete(sourceStationId, track, result);
}
return;
}
const std::string galaxyName = firstGalaxy->first;
CentralServerConnection * sourceCentralConnection = firstGalaxy->second;
if(destinationStationId == 0 || sourceStationId == 0)
{
LOG("CustomerService", ("CharacterTransfer: Account move request made with a null destination station id: or source station id: %lu\n", sourceStationId));
if(s_apiClient)
{
const unsigned int result = static_cast<unsigned int>(CTService::CT_GAMERESULT_HARDERROR);
IGNORE_RETURN(s_apiClient->replyTransferAccount(track, result, NULL, NULL));
s_apiClient->moveComplete(sourceStationId, track, result);
}
return;
}
TransferAccountData transferData;
transferData.setSourceStationId(sourceStationId);
transferData.setDestinationStationId(destinationStationId);
transferData.setTransactionId(transactionId);
transferData.setStartGalaxy(galaxyName);
transferData.setTrack(track);
// verify neither of the station ids are connected
const GenericValueTypeMessage<std::pair<unsigned int, unsigned int> > kick("TransferRequestKickConnectedClients", std::make_pair(sourceStationId, destinationStationId));
sourceCentralConnection->send(kick, true);
// start the transfer process
const GenericValueTypeMessage<TransferAccountData> getAccountData("TransferAccountRequestLoginServer", transferData);
sourceCentralConnection->send(getAccountData, true);
if (s_apiClient)
s_apiClient->moveStart(sourceStationId, track, sourceCentralConnection, 0);
LOG("CustomerService", ("CharacterTransfer: sent TransferAccountRequestLoginServer message : %s\n", transferData.toString().c_str()));
}
//-----------------------------------------------------------------------
void TransferServer::requestMoveValidation(unsigned int track, unsigned int sourceStationId, unsigned int destinationStationId, const std::string & sourceGalaxy, const std::string & destinationGalaxy, const std::string & sourceCharacter, const std::string & destinationCharacter, const std::string & customerLocalizedLanguage)
{
// prequalification: if both Galaxies are available, send request, otherwise send failure
const CentralServerConnection * sourceCentralConnection = CentralServerConnection::getCentralServerConnectionForGalaxy(sourceGalaxy);
CentralServerConnection * destinationCentralConnection = CentralServerConnection::getCentralServerConnectionForGalaxy(destinationGalaxy);
if(sourceStationId != destinationStationId && (!ConfigTransferServer::getAllowAccountTransfers()))
{
if(s_apiClient)
{
const unsigned int result = static_cast<unsigned int>(CTService::CT_GAMERESULT_HARDERROR);
IGNORE_RETURN(s_apiClient->replyValidateMove(track, result, NULL, NULL, NULL));
s_apiClient->moveComplete(sourceStationId, track, result);
}
}
else
{
if(sourceCentralConnection && destinationCentralConnection)
{
// This is sent to the CentralServer on the destination galaxy
// which then forwards it to an arbitrary LoginServer
// the validation response is routed back to the TransferServer
// and is handled in CentralServerConnection as a TransferReplyMoveValidation
// see if we already have the source character's template crc from a previous query
// and if so, pass that along as an optimization so the LoginServer doesn't have
// to continually query the DB to fetch the same information over and over again, because
// the character's template crc (i.e. the character's species) should never, ever change
std::map<std::pair<unsigned int, std::pair<std::string, std::string> >, uint32>::const_iterator const iterFind = s_cacheSourceCharacterTemplateCrc.find(std::make_pair(sourceStationId, std::make_pair(sourceGalaxy, sourceCharacter)));
const TransferRequestMoveValidation request(TransferRequestMoveValidation::TRS_transfer_server, track, sourceStationId, destinationStationId, sourceGalaxy, destinationGalaxy, sourceCharacter, NetworkId::cms_invalid, ((iterFind == s_cacheSourceCharacterTemplateCrc.end()) ? 0 : iterFind->second), destinationCharacter, customerLocalizedLanguage);
destinationCentralConnection->send(request, true);
}
else
{
if(s_apiClient)
{
const unsigned int result = static_cast<unsigned int>(CTService::CT_GAMERESULT_SERVER_IS_DOWN);
IGNORE_RETURN(s_apiClient->replyValidateMove(track, result, NULL, NULL, NULL));
s_apiClient->moveComplete(sourceStationId, track, result);
}
}
}
}
//-----------------------------------------------------------------------
void TransferServer::cacheSourceCharacterTemplateCrc(unsigned int stationId, const std::string & galaxy, const std::string & characterName, uint32 characterTemplateCrc)
{
s_cacheSourceCharacterTemplateCrc[std::make_pair(stationId, std::make_pair(galaxy, characterName))] = characterTemplateCrc;
}
//-----------------------------------------------------------------------
void TransferServer::run()
{
SetupSharedLog::install("TransferServer");
ConsoleManager::install();
DataTableManager::install();
std::vector<std::string>::const_iterator i;
for (i = ConfigTransferServer::getServersAllowedToUploadCharacterData().begin(); i != ConfigTransferServer::getServersAllowedToUploadCharacterData().end(); ++i)
{
IGNORE_RETURN(s_serversAllowedToUpload.insert(*i));
REPORT_LOG(true, ("%s allows players to upload character data\n", i->c_str()));
}
for (i = ConfigTransferServer::getServersAllowedToDownloadCharacterData().begin(); i != ConfigTransferServer::getServersAllowedToDownloadCharacterData().end(); ++i)
{
IGNORE_RETURN(s_serversAllowedToDownload.insert(*i));
REPORT_LOG(true, ("%s allows players to download character data without administrative intervention\n", i->c_str()));
}
NetworkSetupData setup;
setup.port = ConfigTransferServer::getCentralServerServiceBindPort();
setup.bindInterface = ConfigTransferServer::getCentralServerServiceBindInterface();
setup.maxConnections=500;
if(strlen(ConfigTransferServer::getApiServerHostAddress()))
{
s_apiClient = new CTSAPIClient(ConfigTransferServer::getApiServerHostAddress(), "SWG");
REPORT_LOG(true, ("Attempting to connect to CTS Backend %s\n", ConfigTransferServer::getApiServerHostAddress()));
LOG("CTSAPI", ("Attempting to connect to CTS Backend %s", ConfigTransferServer::getApiServerHostAddress()));
}
else
{
REPORT_LOG(true, ("Running without CTS backend connection because none is configured.\n"));
LOG("CTSAPI", ("Running without CTS backend connection because none is configured."));
}
s_transferServerService = new Service(ConnectionAllocator<CentralServerConnection>(), setup);
while(! s_done)
{
if(s_apiClient)
{
s_apiClient->process();
}
NetworkHandler::update();
NetworkHandler::dispatch();
NetworkHandler::clearBytesThisFrame();
Os::sleep(1);
}
delete s_apiClient;
}
//-----------------------------------------------------------------------
void TransferServer::setDone(bool isDone)
{
s_done = isDone;
}
//-----------------------------------------------------------------------
bool TransferServer::uploadCharacterTransferData(const CharacterTransferData & data, bool administrative)
{
bool result = false;
std::set<std::string>::const_iterator f = s_serversAllowedToUpload.find(data.fromGalaxy);
bool authorized = administrative;
if(! authorized)
{
std::set<unsigned int>::const_iterator a = s_authorizedDownloads.find(data.stationId);
if(a != s_authorizedDownloads.end())
{
authorized = true;
}
}
if(f != s_serversAllowedToUpload.end() || authorized)
{
s_transferData[data.stationId] = data;
REPORT_LOG(true, ("%d bytes of data for SUID %d uploaded\n", data.packedData.length(), data.stationId));
result = true;
}
else
{
REPORT_LOG(true, ("An attempt to upload character data from %s was denied by the TransferServer configuration\n", data.fromGalaxy.c_str()));
}
return result;
}
//-----------------------------------------------------------------------
void TransferServer::replyCharacterList(const TransferReplyCharacterList & reply)
{
if(s_apiClient)
{
std::vector<AvatarRecord>::const_iterator i;
std::vector<CTService::CTServiceCharacter> chars;
for(i = reply.getAvatarList().begin(); i != reply.getAvatarList().end(); ++i)
{
CTService::CTServiceCharacter character;
character.SetCharacter(i->m_name.c_str());
chars.push_back(character);
LOG("CTSAPI", ("adding CTService::CTServiceCharacter(%s) to replyCharacterList", Unicode::wideToNarrow(i->m_name).c_str()));
}
CTService::CTServiceCharacter * characters = 0;
unsigned int result = static_cast<unsigned int>(CTService::CT_RESULT_SUCCESS);
if(! reply.getAvatarList().empty())
{
characters = &chars[0];
}
else
{
result = static_cast<unsigned int>(CTService::CT_RESULT_FAILURE);
s_apiClient->moveComplete(reply.getStationId(), reply.getTrack(), result);
}
LOG("CTSAPI", ("invoking CTServiceAPI::replyCharacterList(%d, %d, %d, characters, NULL)", reply.getTrack(), result, chars.size()));
IGNORE_RETURN(s_apiClient->replyCharacterList(reply.getTrack(), result, reply.getAvatarList().size(), characters, NULL));
}
// else use another interface if available
}
//-----------------------------------------------------------------------
void TransferServer::replyValidateMove(const TransferCharacterData & reply)
{
LOG("CustomerService", ("CharacterTransfer: Received replyValidateMove for %s", reply.toString().c_str()));
if(s_apiClient)
{
unsigned int result = static_cast<unsigned int>(CTService::CT_GAMERESULT_SUCCESS);
if(! reply.getIsValidName())
{
LOG("CustomerService", ("CharacterTransfer: replyValidateMove failed name validation for %s", reply.toString().c_str()));
result = static_cast<unsigned int>(CTService::CT_GAMERESULT_NAME_ALREADY_TAKE);
}
else
{
LOG("CustomerService", ("CharacterTransfer: replyValidateMove passed name validation for %s", reply.toString().c_str()));
}
IGNORE_RETURN(s_apiClient->replyValidateMove(reply.getTrack(), result, NULL, NULL, NULL));
s_apiClient->moveComplete(reply.getSourceStationId(), reply.getTrack(), result);
}
}
//-----------------------------------------------------------------------
void TransferServer::replyMoveSuccess(const TransferCharacterData & reply)
{
// send RequestTransferAvatar to ChatServer via CentralServer
CentralServerConnection * centralServerConnection = CentralServerConnection::getCentralServerConnectionForGalaxy(reply.getSourceGalaxy());
if(centralServerConnection)
{
if(ConfigTransferServer::getTransferChatAvatar())
{
const GenericValueTypeMessage<TransferCharacterData> chatTransfer("RequestChatTransferAvatar", reply);
LOG("CustomerService", ("CharacterTransfer: Sending RequestChatTransferAvatar to Central Server %s. %s", chatTransfer.getValue().getSourceGalaxy().c_str(), chatTransfer.getValue().toString().c_str()));
centralServerConnection->send(chatTransfer, true);
}
else
{
LOG("CustomerService", ("Not transfering chat avatar. Chat transfers are currently disabled"));
}
}
replyMove(reply, CTService::CT_GAMERESULT_SUCCESS);
}
//-----------------------------------------------------------------------
void TransferServer::replyTransferAccountSuccess(const TransferAccountData & reply)
{
// send RequestTransferAvatar to ChatServer via CentralServer for each of the cluster ids
if(ConfigTransferServer::getTransferChatAvatar())
{
const std::vector<AvatarData> avatarData(reply.getSourceAvatarData());
for (std::vector<AvatarData>::const_iterator i = avatarData.begin(); i != avatarData.end(); ++i)
{
LOG("CustomerService", ("CharacterTransfer: Sending request to update chat server (cluster: %s) for account transfer from %lu to %lu\n", (i->first).c_str(), reply.getSourceStationId(), reply.getDestinationStationId()));
// need to make a small transferCharacterData object to send with the message
TransferCharacterData chatRequest(TransferRequestMoveValidation::TRS_transfer_server);
chatRequest.setSourceStationId(reply.getSourceStationId());
chatRequest.setSourceGalaxy(i->first);
chatRequest.setSourceCharacterName(i->second);
chatRequest.setDestinationStationId(reply.getDestinationStationId());
chatRequest.setDestinationGalaxy(i->first);
chatRequest.setDestinationCharacterName(i->second);
CentralServerConnection * centralServerConnection = CentralServerConnection::getCentralServerConnectionForGalaxy(i->first);
if (centralServerConnection)
{
const GenericValueTypeMessage<TransferCharacterData> message("RequestChatTransferAvatar", chatRequest);
centralServerConnection->send(message, true);
}
else
{
LOG("CustomerService", ("CharacterTransfer: Could not transfer chat avatars for character %s on cluster %s from %lu to %lu: central connection does not exist in transferserver", i->second.c_str(), i->first.c_str(), reply.getSourceStationId(), reply.getDestinationStationId()));
const unsigned int result = static_cast<unsigned int>(CTService::CT_GAMERESULT_HARDERROR);
s_apiClient->moveComplete(reply.getSourceStationId(), reply.getTrack(), result);
IGNORE_RETURN(s_apiClient->replyTransferAccount(reply.getTrack(), result, NULL, NULL));
}
}
}
else
{
LOG("CustomerService", ("CharacterTransfer: Not transfering any chat avatars. Chat transfers are currently disabled"));
}
if(s_apiClient)
{
const unsigned int result = static_cast<unsigned int>(CTService::CT_GAMERESULT_SUCCESS);
IGNORE_RETURN(s_apiClient->replyTransferAccount(reply.getTrack(), result, NULL, NULL));
s_apiClient->moveComplete(reply.getSourceStationId(), reply.getTrack(), result);
}
}
//-----------------------------------------------------------------------
void TransferServer::transferCreateCharacterFailed(const TransferCharacterData & failed)
{
replyMove(failed, CTService::CT_GAMERESULT_INVALID_NAME);
// close pseudoclientconnections
closePseudoClientConnections(failed.getSourceGalaxy(), failed.getSourceStationId(), failed.getDestinationGalaxy(), failed.getDestinationStationId());
}
//-----------------------------------------------------------------------
bool TransferServer::isRename(const TransferCharacterData & request)
{
// IF:
// the source and destination station ID are identcal (not a transfer to another account)
// the source and destination galaxy are identicay (not a transfer to another server)
// the destination name is not empty
// the source and destination name are different
// This is a character rename request
return (request.getSourceStationId() == request.getDestinationStationId() && request.getSourceGalaxy() == request.getDestinationGalaxy() && !request.getDestinationCharacterName().empty() && request.getSourceCharacterName() != request.getDestinationCharacterName());
}
//-----------------------------------------------------------------------
void TransferServer::failedToRetrieveTransferData(const TransferCharacterData & failed)
{
LOG("CustomerService", ("CharacterTransfer: Transfer failed: Failed to retrieve character data. Sending HARD ERROR to CTS API. %s", failed.toString().c_str()));
replyMove(failed, CTService::CT_GAMERESULT_HARDERROR);
// close pseudoclientconnections
closePseudoClientConnections(failed.getSourceGalaxy(), failed.getSourceStationId(), failed.getDestinationGalaxy(), failed.getDestinationStationId());
}
//-----------------------------------------------------------------------
void TransferServer::failedToApplyTransferData(const TransferCharacterData & failed)
{
LOG("CustomerService", ("CharacterTransfer: Transfer failed: Failed to apply character data. Sending HARD ERROR to CTS API. %s", failed.toString().c_str()));
replyMove(failed, CTService::CT_GAMERESULT_HARDERROR);
// close pseudoclientconnections
closePseudoClientConnections(failed.getSourceGalaxy(), failed.getSourceStationId(), failed.getDestinationGalaxy(), failed.getDestinationStationId());
}
//-----------------------------------------------------------------------
void TransferServer::failedToTransferAccountNoCentralConnection(const TransferAccountData & failed)
{
if(s_apiClient)
{
LOG("CustomerService", ("CharacterTransfer: Transfer failed: Could not connect to central server to update game database. Sending HARD ERROR to CTS API. %s", failed.toString().c_str()));
const unsigned int result = static_cast<unsigned int>(CTService::CT_GAMERESULT_HARDERROR);
s_apiClient->moveComplete(failed.getSourceStationId(), failed.getTrack(), result);
IGNORE_RETURN(s_apiClient->replyTransferAccount(failed.getTrack(), result, NULL, NULL));
}
}
//-----------------------------------------------------------------------
void TransferServer::failedToTransferAccountDestinationNotEmpty (const TransferAccountData & failed)
{
if(s_apiClient)
{
LOG("CustomerService", ("CharacterTransfer: Transfer failed: Destination stationId has avatars. Sending HARD ERROR to CTS API. %s", failed.toString().c_str()));
const unsigned int result = static_cast<unsigned int>(CTService::CT_GAMERESULT_HARDERROR);
s_apiClient->moveComplete(failed.getSourceStationId(), failed.getTrack(), result);
IGNORE_RETURN(s_apiClient->replyTransferAccount(failed.getTrack(), result, NULL, NULL));
}
}
//-----------------------------------------------------------------------
void TransferServer::failedToTransferCharacterGameConnectionClosed(const TransferCharacterData & failed)
{
LOG("CustomerService", ("CharacterTransfer: Transfer failed: GameServer connection closed while transfer was in progress. Sending SOFT ERROR to CTS API. %s", failed.toString().c_str()));
replyMove(failed, CTService::CT_GAMERESULT_SOFTERROR);
// close pseudoclientconnections
closePseudoClientConnections(failed.getSourceGalaxy(), failed.getSourceStationId(), failed.getDestinationGalaxy(), failed.getDestinationStationId());
}
//-----------------------------------------------------------------------
void TransferServer::failedToTransferCharacterConnectionServerConnectionClosed(unsigned int stationId)
{
if(s_apiClient)
{
LOG("CustomerService", ("CharacterTransfer: Transfer failed: ConnectionServer connection closed with CentralServer while transfer was in progress for station id %d", stationId));
const unsigned int result = static_cast<unsigned int>(CTService::CT_GAMERESULT_SOFTERROR);
s_apiClient->moveComplete(stationId, 0, result);
// tracking information is not availalable in this case, so an
// API call can not be made. This is a SOFT error, however, and
// the API will retry the transfer if there is a timeout.
}
}
//-----------------------------------------------------------------------
void TransferServer::failedToValidateTransfer(const TransferReplyMoveValidation & reply)
{
if(s_apiClient)
{
const unsigned int result = ((reply.getResult() == TransferReplyMoveValidation::TRMVR_cannot_create_regular_character) ? static_cast<unsigned int>(CTService::CT_GAMERESULT_MAX_CHAR_ON_DEST_SERVER) : static_cast<unsigned int>(CTService::CT_GAMERESULT_SERVER_IS_DOWN));
IGNORE_RETURN(s_apiClient->replyValidateMove(reply.getTrack(), result, NULL, NULL, NULL));
s_apiClient->moveComplete(reply.getSourceStationId(), reply.getTrack(), result);
// close pseudoclientconnections
closePseudoClientConnections(reply.getSourceGalaxy(), reply.getSourceStationId(), reply.getDestinationGalaxy(), reply.getDestinationStationId());
}
}
//-----------------------------------------------------------------------
@@ -0,0 +1,71 @@
// TransferServer.h
// Copyright 2000-03, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _INCLUDED_TransferServer_H
#define _INCLUDED_TransferServer_H
//-----------------------------------------------------------------------
#include "Archive/ByteStream.h"
#include <string>
//-----------------------------------------------------------------------
struct CharacterTransferData
{
unsigned int stationId;
std::string packedData;
std::string fromGalaxy;
};
class TransferAccountData;
class TransferCharacterData;
class TransferReplyCharacterList;
class TransferReplyMoveValidation;
class TransferReplyNameValidation;
//-----------------------------------------------------------------------
class TransferServer
{
public:
TransferServer();
~TransferServer();
static void unauthorizeDownload (unsigned int stationId);
static void authorizeDownload (unsigned int stationId);
static const CharacterTransferData * getCharacterTransferData (unsigned int stationId, const std::string & fromGalaxy, bool administrativeRequest);
static void run ();
static void setDone (bool isDone);
static bool uploadCharacterTransferData (const CharacterTransferData &, bool administrative);
static void requestCharacterList (unsigned int track, unsigned int stationId, const std::string & serverName, const std::string & customerLocalizedLanguage);
static void requestMoveValidation (unsigned int track, unsigned int sourceStationId, unsigned int destinationStationId, const std::string & sourceGalaxy, const std::string & destinationGalaxy, const std::string & sourceCharacter, const std::string & destinationCharacter, const std::string & customerLocalizedLanguage);
static void cacheSourceCharacterTemplateCrc(unsigned int stationId, const std::string & galaxy, const std::string & characterName, uint32 characterTemplateCrc);
static void requestMove (unsigned int track, const std::string & customerLocalizedLanguage, const std::string & sourceGalaxy, const std::string & destinationGalaxy, const std::string & sourceCharacter, const std::string & destinationCharacter, unsigned int sourceStationId, unsigned int destinationStationId, unsigned int transactionId, const bool withItems, const bool allowOverride);
static void requestTransferAccount (unsigned int track, unsigned int sourceStationId, unsigned int destinationStationId, unsigned int transactionId);
static void getLoginLocationData (const TransferCharacterData & characterData);
static void replyCharacterList (const TransferReplyCharacterList & characterList);
static void replyValidateMove (const TransferCharacterData &);
static void replyMoveSuccess (const TransferCharacterData & reply);
static void replyTransferAccountSuccess (const TransferAccountData & reply);
static void transferCreateCharacterFailed(const TransferCharacterData & failed);
static bool isRename (const TransferCharacterData & request);
static void failedToRetrieveTransferData (const TransferCharacterData & failed);
static void failedToApplyTransferData (const TransferCharacterData & failed);
static void failedToTransferAccountNoCentralConnection (const TransferAccountData & failed);
static void failedToTransferAccountDestinationNotEmpty (const TransferAccountData & failed);
static void failedToTransferCharacterGameConnectionClosed (const TransferCharacterData & failed);
static void failedToTransferCharacterConnectionServerConnectionClosed (const unsigned int stationId);
static void failedToValidateTransfer (const TransferReplyMoveValidation & reply);
private:
TransferServer & operator = (const TransferServer & rhs);
TransferServer(const TransferServer & source);
};
//-----------------------------------------------------------------------
#endif // _INCLUDED_TransferServer_H
@@ -0,0 +1,60 @@
// main.cpp
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "FirstTransferServer.h"
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedCompression/SetupSharedCompression.h"
#include "sharedDebug/SetupSharedDebug.h"
#include "sharedFile/SetupSharedFile.h"
#include "sharedFoundation/Os.h"
#include "sharedFoundation/SetupSharedFoundation.h"
#include "sharedNetwork/SetupSharedNetwork.h"
#include "sharedNetwork/NetworkHandler.h"
#include "sharedNetworkMessages/SetupSharedNetworkMessages.h"
#include "sharedThread/SetupSharedThread.h"
#include "TransferServer.h"
#include "ConfigTransferServer.h"
//-----------------------------------------------------------------------
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 = true;
SetupSharedFoundation::install (setupFoundationData);
SetupSharedCompression::install();
SetupSharedFile::install(false);
SetupSharedNetworkMessages::install();
SetupSharedNetwork::SetupData networkSetupData;
SetupSharedNetwork::getDefaultServerSetupData(networkSetupData);
SetupSharedNetwork::install(networkSetupData);
NetworkHandler::install();
//Os::setProgramName("TransferServer");
ConfigTransferServer::install();
//-- run server
SetupSharedFoundation::callbackWithExceptionHandling(TransferServer::run);
NetworkHandler::remove();
SetupSharedFoundation::remove();
SetupSharedThread::remove();
return 0;
}
//-----------------------------------------------------------------------
+1
View File
@@ -1,3 +1,4 @@
add_subdirectory(ChatAPI)
add_subdirectory(CTServiceGameAPI)
add_subdirectory(VChatAPI)
@@ -0,0 +1,283 @@
////////////////////////////////////////////////////////////////////////////////
// The author of this code is Justin Randall
//
// I have made modifications to the ByteStream
// and AutoByteStream classes in order to make them suitable
// for use in messaging systems which require objects that
// are copyable and assignable. It is also desirable for
// the ByteStream object to use a flexible allocator system
// that may support multi-threaded programming models.
#include "Archive.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
////////////////////////////////////////////////////////////////////////////////
#if defined(USE_ARCHIVE_MUTEX)
CMutex ByteStreamMutex;
#endif
#if defined (PASCAL_STRING)
#pragma message ("--- Packing pascal style strings ---")
void get(Base::ByteStream::ReadIterator& source, std::string& target)
{
unsigned int size = 0;
Base::get (source, size);
const unsigned char *buf = source.getBuffer();
target.assign((const char *)buf, (const char *)(buf + size));
const unsigned int readSize = size * sizeof(char);
source.advance(readSize);
}
void put(ByteStream& target, const std::string& source)
{
const unsigned int size = source.size();
put(target, size);
target.put(source.data(), size * sizeof (char));
}
#else
#pragma message ("--- Packing c style strings ---")
void get(ByteStream::ReadIterator & source, std::string & target)
{
target = reinterpret_cast<const char *>(source.getBuffer());
source.advance(target.length() + 1);
}
void put(ByteStream & target, const std::string & source)
{
target.put(source.c_str(), source.size()+1);
}
#endif
ByteStream::ReadIterator::ReadIterator() :
readPtr(0),
stream(0)
{
}
ByteStream::ReadIterator::ReadIterator(const ReadIterator & source) :
readPtr(source.readPtr),
stream(source.stream)
{
}
ByteStream::ReadIterator::ReadIterator(const ByteStream & source) :
readPtr(0),
stream(&source)
{
}
ByteStream::ReadIterator::~ReadIterator()
{
stream = 0;
}
ByteStream::ByteStream() :
allocatedSize(0),
beginReadIterator(),
data(NULL),
size(0),
lastPutSize(0)
{
data = Data::getNewData();
beginReadIterator = ReadIterator(*this);
}
ByteStream::ByteStream(const unsigned char * const newBuffer, const unsigned int bufferSize) :
allocatedSize(bufferSize),
data(0),
size(bufferSize),
lastPutSize(0)
{
data = Data::getNewData();
if(data->size < size)
{
delete[] data->buffer;
data->buffer = new unsigned char[size];
data->size = size;
}
memcpy(data->buffer, newBuffer, size);
beginReadIterator = ReadIterator(*this);
}
ByteStream::ByteStream(const ByteStream & source):
allocatedSize(source.getSize()), // only allocate what is really there, be opportinistic when grow()'ing
data(source.data),
size(source.getSize()),
lastPutSize(source.lastPutSize)
{
source.data->ref();
beginReadIterator = ReadIterator(*this);
}
ByteStream::ByteStream(ReadIterator & source) :
allocatedSize(0),
size(0),
lastPutSize(0)
{
data = Data::getNewData();
put(source.getBuffer(), source.getSize());
source.advance(source.getSize());
beginReadIterator = ReadIterator(*this);
}
ByteStream::~ByteStream()
{
data->deref();
allocatedSize = 0;
data = 0; //lint !e672 (data deref insures the data is deleted if no one references it)
size = 0;
}
ByteStream & ByteStream::operator=(const ByteStream & rhs)
{
if(this != &rhs)
{
data->deref(); // deref local data
rhs.data->ref();
allocatedSize = rhs.allocatedSize;
size = rhs.size;
data = rhs.data; //lint !e672 (data is ref counted)
}
return *this;
}
void ByteStream::get(void * target, ReadIterator & readIterator, const unsigned long int targetSize) const
{
assert(readIterator.getReadPosition() + targetSize <= allocatedSize);
memcpy(target, &data->buffer[readIterator.getReadPosition()], targetSize);
}
void ByteStream::put(const void * const source, const unsigned int sourceSize)
{
if(data->getRef() > 1)
{
const unsigned char * const tmp = data->buffer;
data->deref();
data = Data::getNewData();
if(data->size < sourceSize)
{
delete[] data->buffer;
data->buffer = new unsigned char[size];
data->size = size;
}
memcpy(data->buffer, tmp, size);
allocatedSize = size;
}
growToAtLeast(size + sourceSize);
memcpy(&data->buffer[size], source, sourceSize);
size += sourceSize;
if (sourceSize > 0)
lastPutSize = sourceSize;
}
bool ByteStream::overwriteEnd(const void * const source, const unsigned int sourceSize)
{
if(data->getRef() <= 1 &&
lastPutSize == sourceSize &&
sourceSize <= data->size)
{
memcpy(&data->buffer[size-sourceSize], source, sourceSize);
return true;
}
else
{
return false;
}
}
void ByteStream::reAllocate(const unsigned int newSize)
{
allocatedSize = newSize;
if(data->size < allocatedSize)
{
unsigned char * tmp = new unsigned char[newSize];
if(data->buffer != NULL)
memcpy(tmp, data->buffer, size);
delete[] data->buffer;
data->buffer = tmp;
data->size = newSize;
}
}
////////////////////////////////////////////////////////////////////////////////
AutoByteStream::AutoByteStream() :
members()
{
}
AutoByteStream::~AutoByteStream()
{
}
void AutoByteStream::addVariable(AutoVariableBase & newVariable)
{
members.push_back(&newVariable);
}
const unsigned int AutoByteStream::getItemCount() const
{
return members.size();
}
void AutoByteStream::pack(ByteStream & target) const
{
std::vector<AutoVariableBase *>::const_iterator i;
unsigned short packedSize=static_cast<unsigned short>(members.size());
put(target,packedSize);
for(i = members.begin(); i != members.end(); ++i)
{
(*i)->pack(target);
}
}
void AutoByteStream::unpack(ByteStream::ReadIterator & source)
{
std::vector<AutoVariableBase *>::iterator i;
unsigned short packedSize;
get(source,packedSize);
for(i = members.begin(); i != members.end(); ++i)
{
(*i)->unpack(source);
}
}
////////////////////////////////////////////////////////////////////////////////
AutoVariableBase::AutoVariableBase()
{
}
AutoVariableBase::~AutoVariableBase()
{
}
////////////////////////////////////////////////////////////////////////////////
};
#ifdef EXTERNAL_DISTRO
};
#endif
@@ -0,0 +1,746 @@
////////////////////////////////////////////////////////////////////////////////
// The author of this code is Justin Randall
//
// I have made modifications to the ByteStream
// and AutoByteStream classes in order to make them suitable
// for use in messaging systems which require objects that
// are copyable and assignable. It is also desirable for
// the ByteStream object to use a flexible allocator system
// that may support multi-threaded programming models.
#ifndef BASE_ARCHIVE_H
#define BASE_ARCHIVE_H
#include <assert.h>
#include <string>
#include <vector>
#include "Platform.h"
//#if defined _MT || defined _REENTRANT
//# define USE_ARCHIVE_MUTEX
//# include "Mutex.h"
//#endif
#ifdef WIN32
# include "win32/Archive.h"
#elif linux
# include "linux/Archive.h"
#elif sparc
# include "solaris/Archive.h"
#else
#error /Base/Archive.h: Undefine platform type
#endif
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
const unsigned MAX_ARRAY_SIZE = 1024;
////////////////////////////////////////////////////////////////////////////////
#if defined(USE_ARCHIVE_MUTEX)
extern CMutex ByteStreamMutex;
#endif
class ByteStream
{
public:
class ReadIterator
{
public:
ReadIterator();
ReadIterator(const ReadIterator & source);
explicit ReadIterator(const ByteStream & source);
~ReadIterator();
ReadIterator & operator = (const ReadIterator & source);
void advance (const unsigned int distance);
void get (void * target, const unsigned long int readSize);
const unsigned int getSize () const;
const unsigned char * const getBuffer () const;
const unsigned int getReadPosition () const;
private:
unsigned int readPtr;
const ByteStream * stream;
};
private:
class Data
{
friend class ByteStream;
friend class ReadIterator;
public:
~Data();
static Data * getNewData();
const int getRef () const;
void deref ();
void ref ();
protected:
unsigned char * buffer;
unsigned long size;
private:
struct DataFreeList
{
~DataFreeList()
{
std::vector<ByteStream::Data *>::iterator i;
for(i = freeList.begin(); i != freeList.end(); ++i)
{
delete (*i);
}
};
std::vector<Data *> freeList;
};
Data();
//explicit Data(unsigned char * buffer);
static std::vector<Data *> & getDataFreeList();
static void releaseOldData(Data * oldData);
private:
int refCount;
};
friend class ReadIterator;
public:
ByteStream();
ByteStream(const unsigned char * const buffer, const unsigned int bufferSize);
ByteStream(const ByteStream & source);
virtual ~ByteStream();
public:
ByteStream(ReadIterator & source);
ByteStream & operator = (const ByteStream & source);
ByteStream & operator = (ReadIterator & source);
const ReadIterator & begin() const;
void clear();
const unsigned char * const getBuffer() const;
const unsigned int getSize() const;
void put(const void * const source, const unsigned int sourceSize);
bool overwriteEnd(const void * const source, const unsigned int sourceSize);
private:
void get(void * target, ReadIterator & readIterator, const unsigned long int readSize) const;
void growToAtLeast(const unsigned int targetSize);
void reAllocate(const unsigned int newSize);
private:
unsigned int allocatedSize;
ReadIterator beginReadIterator;
Data * data;
unsigned int size;
unsigned int lastPutSize;
};
inline ByteStream::Data::Data() :
buffer(0),
size(0),
refCount(1)
{
}
inline ByteStream::Data::~Data()
{
#if defined(USE_ARCHIVE_MUTEX)
ByteStreamMutex.Lock();
#endif
refCount = 0;
delete[] buffer;
#if defined(USE_ARCHIVE_MUTEX)
ByteStreamMutex.Unlock();
#endif
}
inline void ByteStream::Data::deref()
{
#if defined(USE_ARCHIVE_MUTEX)
ByteStreamMutex.Lock();
#endif
refCount--;
#if defined(USE_ARCHIVE_MUTEX)
ByteStreamMutex.Unlock();
#endif
if(refCount < 1)
releaseOldData(this);
}
inline std::vector<ByteStream::Data *> & ByteStream::Data::getDataFreeList()
{
static DataFreeList freeList;
return freeList.freeList;
}
inline ByteStream::Data * ByteStream::Data::getNewData()
{
#if defined(USE_ARCHIVE_MUTEX)
ByteStreamMutex.Lock();
#endif
Data * result = 0;
if(getDataFreeList().empty())
{
result = new Data;
}
else
{
result = getDataFreeList().back();
getDataFreeList().pop_back();
}
result->refCount = 1;
#if defined(USE_ARCHIVE_MUTEX)
ByteStreamMutex.Unlock();
#endif
return result;
}
inline const int ByteStream::Data::getRef() const
{
return refCount;
}
inline void ByteStream::Data::ref()
{
#if defined(USE_ARCHIVE_MUTEX)
ByteStreamMutex.Lock();
#endif
refCount++;
#if defined(USE_ARCHIVE_MUTEX)
ByteStreamMutex.Unlock();
#endif
}
inline void ByteStream::Data::releaseOldData(ByteStream::Data * oldData)
{
#if defined(USE_ARCHIVE_MUTEX)
ByteStreamMutex.Lock();
#endif
getDataFreeList().push_back(oldData);
oldData->refCount = 0;
#if defined(USE_ARCHIVE_MUTEX)
ByteStreamMutex.Unlock();
#endif
}
inline ByteStream::ReadIterator & ByteStream::ReadIterator::operator = (const ByteStream::ReadIterator & rhs)
{
if(&rhs != this)
{
readPtr = rhs.readPtr;
stream = rhs.stream;
}
return *this;
}
inline void ByteStream::ReadIterator::get(void * target, const unsigned long int readSize)
{
assert(stream);
stream->get(target, *this, readSize);
readPtr += readSize;
}
inline const unsigned int ByteStream::ReadIterator::getSize() const
{
assert(stream);
return stream->getSize() - readPtr;
}
inline const ByteStream::ReadIterator & ByteStream::begin() const
{
return beginReadIterator;
}
inline void ByteStream::ReadIterator::advance(const unsigned int distance)
{
readPtr += distance;
}
inline const unsigned int ByteStream::ReadIterator::getReadPosition() const
{
return readPtr;
}
inline const unsigned char * const ByteStream::ReadIterator::getBuffer() const
{
if(stream)
return &stream->data->buffer[readPtr];
return 0;
}
inline void ByteStream::clear()
{
#if defined(USE_ARCHIVE_MUTEX)
ByteStreamMutex.Lock();
#endif
size = 0;
#if defined(USE_ARCHIVE_MUTEX)
ByteStreamMutex.Unlock();
#endif
}
inline const unsigned char * const ByteStream::getBuffer() const
{
return data->buffer;
}
inline const unsigned int ByteStream::getSize() const
{
return size;
}
inline void ByteStream::growToAtLeast(const unsigned int targetSize)
{
if(allocatedSize < targetSize)
{
reAllocate(allocatedSize + allocatedSize + targetSize);
}
}
////////////////////////////////////////////////////////////////////////////////
class AutoVariableBase
{
public:
AutoVariableBase();
virtual ~AutoVariableBase();
virtual void pack(ByteStream & target) const = 0;
virtual void unpack(ByteStream::ReadIterator & source) = 0;
};
////////////////////////////////////////////////////////////////////////////////
class AutoByteStream
{
public:
AutoByteStream();
virtual ~AutoByteStream();
void addVariable(AutoVariableBase & newVariable);
virtual const unsigned int getItemCount() const;
virtual void pack(ByteStream & target) const;
virtual void unpack(ByteStream::ReadIterator & source);
protected:
std::vector<AutoVariableBase *> members;
private:
AutoByteStream(const AutoByteStream & source);
};
////////////////////////////////////////////////////////////////////////////////
template<class ValueType>
class AutoVariable : public AutoVariableBase
{
public:
AutoVariable();
explicit AutoVariable(const ValueType & source);
virtual ~AutoVariable();
const ValueType & get() const;
virtual void pack(ByteStream & target) const;
void set(const ValueType & rhs);
virtual void unpack(ByteStream::ReadIterator & source);
private:
ValueType value;
};
template<class ValueType>
AutoVariable<ValueType>::AutoVariable() :
AutoVariableBase(),
value()
{
}
template<class ValueType>
AutoVariable<ValueType>::AutoVariable(const ValueType & source) :
AutoVariableBase(),
value(source)
{
}
template<class ValueType>
AutoVariable<ValueType>::~AutoVariable()
{
}
template<class ValueType>
const ValueType & AutoVariable<ValueType>::get() const
{
return value;
}
template<class ValueType>
void AutoVariable<ValueType>::pack(ByteStream & target) const
{
Base::put(target, value);
}
template<class ValueType>
void AutoVariable<ValueType>::set(const ValueType & rhs)
{
value = rhs;
}
template<class ValueType>
void AutoVariable<ValueType>::unpack(ByteStream::ReadIterator & source)
{
Base::get(source, value);
}
////////////////////////////////////////////////////////////////////////////////
template<class ValueType>
class AutoArray : public AutoVariableBase
{
public:
AutoArray();
AutoArray(const AutoArray & source);
~AutoArray();
const std::vector<ValueType> & get() const;
void set(const std::vector<ValueType> & source);
virtual void pack(ByteStream & target) const;
virtual void unpack(ByteStream::ReadIterator & source);
private:
std::vector<ValueType> array;
};
template<class ValueType>
inline AutoArray<ValueType>::AutoArray()
{
}
template<class ValueType>
inline AutoArray<ValueType>::AutoArray(const AutoArray & source) :
array(source.array)
{
}
template<class ValueType>
inline AutoArray<ValueType>::~AutoArray()
{
}
template<class ValueType>
inline const std::vector<ValueType> & AutoArray<ValueType>::get() const
{
return array;
}
template<class ValueType>
inline void AutoArray<ValueType>::set(const std::vector<ValueType> & source)
{
array = source;
}
template<class ValueType>
inline void AutoArray<ValueType>::pack(ByteStream & target) const
{
unsigned int arraySize = array.size();
Base::put(target, arraySize);
typename std::vector<ValueType>::const_iterator i;
for(i = array.begin(); i != array.end(); ++i)
{
ValueType v = (*i);
Base::put(target, v);
}
}
template<class ValueType>
inline void AutoArray<ValueType>::unpack(ByteStream::ReadIterator & source)
{
unsigned int arraySize;
Base::get(source, arraySize);
ValueType v;
if (arraySize > MAX_ARRAY_SIZE)
arraySize = 0;
for(unsigned int i = 0; i < arraySize; ++i)
{
Base::get(source, v);
array.push_back(v);
}
}
////////////////////////////////////////////////////////////////////////////////
inline void get(ByteStream::ReadIterator & source, ByteStream & target)
{
target.put(source.getBuffer(), source.getSize());
source.advance(source.getSize());
}
inline void get(ByteStream::ReadIterator & source, double & target)
{
source.get(&target, 8);
target = byteSwap(target);
}
inline void get(ByteStream::ReadIterator & source, float & target)
{
source.get(&target, 4);
target = byteSwap(target);
}
inline void get(ByteStream::ReadIterator & source, uint64 & target)
{
source.get(&target, 8);
target = byteSwap(target);
}
inline void get(ByteStream::ReadIterator & source, int64 & target)
{
source.get(&target, 8);
target = byteSwap(target);
}
inline void get(ByteStream::ReadIterator & source, uint32 & target)
{
source.get(&target, 4);
target = byteSwap(target);
}
inline void get(ByteStream::ReadIterator & source, int32 & target)
{
source.get(&target, 4);
target = byteSwap(target);
}
inline void get(ByteStream::ReadIterator & source, uint16 & target)
{
source.get(&target, 2);
target = byteSwap(target);
}
inline void get(ByteStream::ReadIterator & source, int16 & target)
{
source.get(&target, 2);
target = byteSwap(target);
}
inline void get(ByteStream::ReadIterator & source, uint8 & target)
{
source.get(&target, 1);
}
inline void get(ByteStream::ReadIterator & source, int8 & target)
{
source.get(&target, 1);
}
inline void get(ByteStream::ReadIterator & source, unsigned char * const target, const unsigned int targetSize)
{
source.get(target, targetSize);
}
inline void get(ByteStream::ReadIterator & source, bool & target)
{
source.get(&target, 1);
}
////////////////////////////////////////////////////////////////////////////////
inline void put(ByteStream & target, ByteStream::ReadIterator & source)
{
target.put(source.getBuffer(), source.getSize());
source.advance(source.getSize());
}
inline void put(ByteStream & target, const double value)
{
double temp = byteSwap(value);
target.put(&temp, 8);
}
inline void put(ByteStream & target, const float value)
{
float temp = byteSwap(value);
target.put(&temp, 4);
}
inline void put(ByteStream & target, const uint64 value)
{
uint64 temp = byteSwap(value);
target.put(&temp, 8);
}
inline void put(ByteStream & target, const int64 value)
{
int64 temp = byteSwap(value);
target.put(&temp, 8);
}
inline void put(ByteStream & target, const uint32 value)
{
uint32 temp = byteSwap(value);
target.put(&temp, 4);
}
inline void put(ByteStream & target, const int32 value)
{
int32 temp = byteSwap(value);
target.put(&temp, 4);
}
inline void put(ByteStream & target, const uint16 value)
{
uint16 temp = byteSwap(value);
target.put(&temp, 2);
}
inline void put(ByteStream & target, const int16 value)
{
int16 temp = byteSwap(value);
target.put(&temp, 2);
}
inline void put(ByteStream & target, const uint8 value)
{
target.put(&value, 1);
}
inline void put(ByteStream & target, const int8 value)
{
target.put(&value, 1);
}
inline void put(ByteStream & target, const bool & source)
{
target.put(&source, 1);
}
inline void put(ByteStream & target, const unsigned char * const source, const unsigned int sourceSize)
{
target.put(source, sourceSize);
}
inline void put(ByteStream & target, const ByteStream & source)
{
target.put(source.begin().getBuffer(), source.begin().getSize());
}
void get(ByteStream::ReadIterator & source, std::string & target);
void put(ByteStream & target, const std::string & source);
////////////////////////////////////////////////////////////////////////////////
inline bool overwriteEnd(ByteStream & target, const double value)
{
double temp = byteSwap(value);
return target.overwriteEnd(&temp, 8);
}
inline bool overwriteEnd(ByteStream & target, const float value)
{
float temp = byteSwap(value);
return target.overwriteEnd(&temp, 4);
}
inline bool overwriteEnd(ByteStream & target, const uint64 value)
{
uint64 temp = byteSwap(value);
return target.overwriteEnd(&temp, 8);
}
inline bool overwriteEnd(ByteStream & target, const int64 value)
{
int64 temp = byteSwap(value);
return target.overwriteEnd(&temp, 8);
}
inline bool overwriteEnd(ByteStream & target, const uint32 value)
{
uint32 temp = byteSwap(value);
return target.overwriteEnd(&temp, 4);
}
inline bool overwriteEnd(ByteStream & target, const int32 value)
{
int32 temp = byteSwap(value);
return target.overwriteEnd(&temp, 4);
}
inline bool overwriteEnd(ByteStream & target, const uint16 value)
{
uint16 temp = byteSwap(value);
return target.overwriteEnd(&temp, 2);
}
inline bool overwriteEnd(ByteStream & target, const int16 value)
{
int16 temp = byteSwap(value);
return target.overwriteEnd(&temp, 2);
}
inline bool overwriteEnd(ByteStream & target, const uint8 value)
{
return target.overwriteEnd(&value, 1);
}
inline bool overwriteEnd(ByteStream & target, const int8 value)
{
return target.overwriteEnd(&value, 1);
}
inline bool overwriteEnd(ByteStream & target, const bool & source)
{
return target.overwriteEnd(&source, 1);
}
inline bool overwriteEnd(ByteStream & target, const unsigned char * const source, const unsigned int sourceSize)
{
return target.overwriteEnd(source, sourceSize);
}
////////////////////////////////////////////////////////////////////////////////
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif
@@ -0,0 +1,105 @@
#ifndef BASE_PLATFORM_H
#define BASE_PLATFORM_H
#include <assert.h>
#ifdef WIN32
#include "win32/Platform.h"
#elif linux
#include "linux/Platform.h"
#elif sparc
#include "solaris/Platform.h"
#else
#error /Base/Platform.h: Undefine platform type
#endif
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
template <class T> inline T rotlFixed(T x, unsigned int y)
{
assert(y < sizeof(T)*8);
return (T)((x<<y) | (x>>(sizeof(T)*8-y)));
}
template <class T> inline T rotrFixed(T x, unsigned int y)
{
assert(y < sizeof(T)*8);
return (x>>y) | (x<<(sizeof(T)*8-y));
}
template <class T> inline T rotlMod(T x, unsigned int y)
{
y %= sizeof(T)*8;
return (x<<y) | (x>>(sizeof(T)*8-y));
}
template <class T> inline T rotrMod(T x, unsigned int y)
{
y %= sizeof(T)*8;
return (x>>y) | (x<<(sizeof(T)*8-y));
}
inline uint16 byteReverse16(void * data)
{
uint16 value = *static_cast<uint16 *>(data);
return *static_cast<uint16 *>(data) = rotlFixed(value, 8U);
// return rotlFixed(value, 8U);
}
inline uint32 byteReverse32(void * data)
{
uint32 value = *static_cast<uint32 *>(data);
return *static_cast<uint32 *>(data) = (rotrFixed(value, 8U) & 0xff00ff00) | (rotlFixed(value, 8U) & 0x00ff00ff);
// return (rotrFixed(value, 8U) & 0xff00ff00) | (rotlFixed(value, 8U) & 0x00ff00ff);
}
inline uint64 byteReverse64(void * data)
{
uint64 value = *static_cast<uint64 *>(data);
return *static_cast<uint64 *>(data) = (
uint64((rotrFixed(uint32(value), 8U) & 0xff00ff00) | (rotlFixed(uint32(value), 8U) & 0x00ff00ff)) << 32) |
(rotrFixed(uint32(value>>32), 8U) & 0xff00ff00) | (rotlFixed(uint32(value>>32), 8U) & 0x00ff00ff);
// return (uint64(byteReverse(uint32(value))) << 32) | byteReverse(uint32(value>>32));
}
inline uint32 strlen(const unsigned short * string)
{
if (string == 0)
return 0;
uint32 length=0;
while (*(string+length++) != 0);
return length-1;
}
inline double getTimerLatency(Base::uint64 startTime, Base::uint64 finishTime=0)
{
Base::int64 requestAge;
Base::int64 freq = Base::getTimerFrequency();
Base::uint64 finish = (finishTime ? finishTime : Base::getTimer());
if (finish < startTime)
requestAge = (0 - 1) - startTime - finish;
else
requestAge = finish - startTime;
return (double)requestAge/freq;
}
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // BASE_PLATFORM_H
@@ -0,0 +1,23 @@
#ifndef BASE_TYPES_H
#define BASE_TYPES_H
#ifdef WIN32
#include "win32/Types.h"
#elif linux
#include "linux/Types.h"
#elif sparc
#include "solaris/Types.h"
#else
#error /Base/Types.h: Undefine platform type
#endif
#endif
@@ -0,0 +1,44 @@
#ifndef BASE_LINUX_ARCHIVE_H
#define BASE_LINUX_ARCHIVE_H
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
#ifdef PACK_BIG_ENDIAN
inline double byteSwap(double value) { byteReverse(&value); return value; }
inline float byteSwap(float value) { byteReverse(&value); return value; }
inline uint64 byteSwap(uint64 value) { byteReverse(&value); return value; }
inline int64 byteSwap(int64 value) { byteReverse(&value); return value; }
inline uint32 byteSwap(uint32 value) { byteReverse(&value); return value; }
inline int32 byteSwap(int32 value) { byteReverse(&value); return value; }
inline uint16 byteSwap(uint16 value) { byteReverse(&value); return value; }
inline int16 byteSwap(int16 value) { byteReverse(&value); return value; }
#else
inline double byteSwap(double value) { return value; }
inline float byteSwap(float value) { return value; }
inline uint64 byteSwap(uint64 value) { return value; }
inline int64 byteSwap(int64 value) { return value; }
inline uint32 byteSwap(uint32 value) { return value; }
inline int32 byteSwap(int32 value) { return value; }
inline uint16 byteSwap(uint16 value) { return value; }
inline int16 byteSwap(int16 value) { return value; }
#endif
}
#ifdef EXTERNAL_DISTRO
};
#endif
#endif
@@ -0,0 +1,55 @@
////////////////////////////////////////
// Platform.cpp
//
// Purpose:
// 1. Implementation of the global functionality declaired in Platform.h.
//
// Revisions:
// 07/10/2001 Created
//
#include <ctype.h>
#include "Platform.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
// Implementation of microsoft strlwr extension
// This non-ANSI function is not supported under UNIX
void _strlwr(char * s)
{
while (*s)
{
*s = tolower(*s);
s++;
}
}
// Implementation of microsoft strlwr extension
// This non-ANSI function is not supported under UNIX
void _strupr(char * s)
{
while (*s)
{
*s = toupper(*s);
s++;
}
}
CTimer::CTimer() :
mTimer(0)
{
}
}
#ifdef EXTERNAL_DISTRO
};
#endif
@@ -0,0 +1,112 @@
////////////////////////////////////////
// Platform.h
//
// Purpose:
// 1. Include relevent system headers that are platform specific.
// 2. Declair global platform specific functionality.
// 3. Include primative type definitions
//
// Global Functions:
// getTimer() : Return the current high resolution clock count.
// getTimerFrequency() : Return the frequency of the high resolution clock.
// sleep() : Voluntarily relinquish timeslice of the calling thread for a
// specified number of milliseconds.
// strlwr() : Alters the contents of a string, making it all lower-case.
//
// Revisions:
// 07/10/2001 Created
//
#ifndef BASE_LINUX_PLATFORM_H
#define BASE_LINUX_PLATFORM_H
#include <errno.h>
#include <assert.h>
#include <sys/errno.h>
#include <pthread.h>
#include <resolv.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include "Types.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
uint64 getTimer(void);
uint64 getTimerFrequency(void);
void sleep(uint32 ms);
inline uint64 getTimer(void)
{
uint64 t;
struct timeval tv;
gettimeofday(&tv, 0);
t = tv.tv_sec;
t = t * 1000000;
t += tv.tv_usec;
return t;
}
inline uint64 getTimerFrequency(void)
{
uint64 f = 1000000;
return f;
}
inline void sleep(uint32 ms)
{
usleep(static_cast<unsigned long>(ms * 1000));
}
void _strlwr(char * s);
void _strupr(char * s);
class CTimer
{
public:
CTimer();
void Set(uint32 seconds);
void Signal();
bool Expired();
private:
uint32 mTimer;
};
inline void CTimer::Set(uint32 interval)
{
mTimer = (uint32)time(0) + interval;
}
inline void CTimer::Signal()
{
mTimer = 0;
}
inline bool CTimer::Expired()
{
return (mTimer <= (uint32)time(0));
}
}
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // BASE_LINUX_PLATFORM_H
@@ -0,0 +1,42 @@
////////////////////////////////////////
// Types.h
//
// Purpose:
// 1. Define integer types that are unambiguous with respect to size
//
// Revisions:
// 07/10/2001 Created
//
#ifndef BASE_LINUX_TYPES_H
#define BASE_LINUX_TYPES_H
#include <sys/bitypes.h>
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
#define INT32_MAX 0x7FFFFFFF
#define INT32_MIN 0x80000000
#define UINT32_MAX 0xFFFFFFFF
typedef signed char int8;
typedef unsigned char uint8;
typedef signed short int16;
typedef unsigned short uint16;
typedef int32_t int32;
typedef u_int32_t uint32;
typedef int64_t int64;
typedef u_int64_t uint64;
}
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // BASE_LINUX_TYPES_H
@@ -0,0 +1,42 @@
#ifndef BASE_WIN32_ARCHIVE_H
#define BASE_WIN32_ARCHIVE_H
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
#ifdef PACK_BIG_ENDIAN
inline double byteSwap(double value) { byteReverse64(&value); return value; }
inline float byteSwap(float value) { byteReverse32(&value); return value; }
inline uint64 byteSwap(uint64 value) { byteReverse64(&value); return value; }
inline int64 byteSwap(int64 value) { byteReverse64(&value); return value; }
inline uint32 byteSwap(uint32 value) { byteReverse32(&value); return value; }
inline int32 byteSwap(int32 value) { byteReverse32(&value); return value; }
inline uint16 byteSwap(uint16 value) { byteReverse16(&value); return value; }
inline int16 byteSwap(int16 value) { byteReverse16(&value); return value; }
#else
inline double byteSwap(double value) { return value; }
inline float byteSwap(float value) { return value; }
inline uint64 byteSwap(uint64 value) { return value; }
inline int64 byteSwap(int64 value) { return value; }
inline uint32 byteSwap(uint32 value) { return value; }
inline int32 byteSwap(int32 value) { return value; }
inline uint16 byteSwap(uint16 value) { return value; }
inline int16 byteSwap(int16 value) { return value; }
#endif
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif
@@ -0,0 +1,31 @@
////////////////////////////////////////
// Platform.cpp
//
// Purpose:
// 1. Implementation of the global functionality declaired in Platform.h.
//
// Revisions:
// 07/10/2001 Created
//
#include "Platform.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
CTimer::CTimer() :
mTimer(0)
{
}
};
#ifdef EXTERNAL_DISTRO
};
#endif
@@ -0,0 +1,98 @@
////////////////////////////////////////
// Platform.h
//
// Purpose:
// 1. Include relevent system headers that are platform specific.
// 2. Declair global platform specific functionality.
// 3. Include primative type definitions
//
// Global Functions:
// getTimer() : Return the current high resolution clock count.
// getTimerFrequency() : Return the frequency of the high resolution clock.
// sleep() : Voluntarily relinquish timeslice of the calling thread for a
// specified number of milliseconds.
//
// Revisions:
// 07/10/2001 Created
//
#ifndef BASE_WIN32_PLATFORM_H
#define BASE_WIN32_PLATFORM_H
#include <memory.h>
#include <winsock2.h>
#include <time.h>
#include <io.h>
#include <fcntl.h>
#include <direct.h>
#include <stdio.h>
#include <errno.h>
#include "Types.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
uint64 getTimer(void);
uint64 getTimerFrequency(void);
inline uint64 getTimer(void)
{
uint64 result;
if (!QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER *>(&result)))
result = 0;
return result;
}
inline uint64 getTimerFrequency(void)
{
uint64 result;
if (!QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER *>(&result)))
result = 0;
return result;
}
inline void sleep(uint32 ms)
{
Sleep(ms);
}
class CTimer
{
public:
CTimer();
void Set(uint32 seconds);
void Signal();
bool Expired();
private:
uint32 mTimer;
};
inline void CTimer::Set(uint32 interval)
{
mTimer = (uint32)time(0) + interval;
}
inline void CTimer::Signal()
{
mTimer = 0;
}
inline bool CTimer::Expired()
{
return (mTimer <= (uint32)time(0));
}
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif BASE_WIN32_PLATFORM_H
@@ -0,0 +1,42 @@
////////////////////////////////////////
// Types.h
//
// Purpose:
// 1. Define integer types that are unambiguous with respect to size
//
// Revisions:
// 07/10/2001 Created
//
#ifndef BASE_WIN32_TYPES_H
#define BASE_WIN32_TYPES_H
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
#define INT32_MAX 0x7FFFFFFF
#define INT32_MIN 0x80000000
#define UINT32_MAX 0xFFFFFFFF
typedef signed char int8;
typedef unsigned char uint8;
typedef short int16;
typedef unsigned short uint16;
typedef int int32;
typedef unsigned uint32;
typedef __int64 int64;
typedef unsigned __int64 uint64;
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif // BASE_WIN32_TYPES_H
@@ -0,0 +1,77 @@
set(SHARED_SOURCES
CTServiceAPI.cpp
CTServiceAPI.h
CTServiceAPICore.cpp
CTServiceAPICore.h
Request.cpp
Request.h
Response.cpp
Response.h
Base/Archive.cpp
CTCommon/CTEnum.h
CTCommon/CTServiceCharacter.cpp
CTCommon/CTServiceCharacter.h
CTCommon/CTServiceCustomer.h
CTCommon/CTServiceDBOrder.h
CTCommon/CTServiceDBTransaction.h
CTCommon/CTServiceObjects.h
CTCommon/CTServiceServer.cpp
CTCommon/CTServiceServer.h
CTCommon/CTServiceWebAPITransaction.h
CTCommon/RequestStrings.h
CTGenericAPI/GenericApiCore.cpp
CTGenericAPI/GenericApiCore.h
CTGenericAPI/GenericConnection.cpp
CTGenericAPI/GenericConnection.h
CTGenericAPI/GenericMessage.cpp
CTGenericAPI/GenericMessage.h
TcpLibrary/Clock.cpp
TcpLibrary/Clock.h
TcpLibrary/IPAddress.cpp
TcpLibrary/IPAddress.h
TcpLibrary/TcpBlockAllocator.cpp
TcpLibrary/TcpBlockAllocator.h
TcpLibrary/TcpConnection.cpp
TcpLibrary/TcpConnection.h
TcpLibrary/TcpHandlers.h
TcpLibrary/TcpManager.cpp
TcpLibrary/TcpManager.h
Unicode/FirstUnicode.cpp
Unicode/FirstUnicode.h
Unicode/Unicode.cpp
Unicode/Unicode.h
Unicode/UnicodeBlocks.cpp
Unicode/UnicodeBlocks.h
Unicode/UnicodeCharacterData.cpp
Unicode/UnicodeCharacterData.h
Unicode/UnicodeCharacterDataMap.cpp
Unicode/UnicodeCharacterDataMap.h
Unicode/UnicodeUtils.cpp
Unicode/UnicodeUtils.h
)
if(WIN32)
set(PLATFORM_SOURCES
Base/win32/Platform.cpp
)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/Base/win32)
else()
set(PLATFORM_SOURCES
Base/linux/Platform.cpp
)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/Base/linux)
endif()
add_definitions(-DNAMESPACE=CTService -DUSE_TCP_LIBRARY)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
add_library(CTServiceGameAPI
${SHARED_SOURCES}
${PLATFORM_SOURCES}
)
@@ -0,0 +1,434 @@
#ifndef CTENUM_H
#define CTENUM_H
namespace CTService
{
enum InternalErrorCodes
{
CONFIG_PARAMS_MISSING=-1,
FAIL_LOAD_CONFIG_FILE=-2
};
enum ServerStatus
{
SERVER_READY = 0,
SERVER_SHUTTING_DOWN,
SERVER_DOWN
};
enum LOG_TYPES
{
LOG_ERROR=1,
LOG_REQUEST,
LOG_CONNECTION,
LOG_GENERAL,
LOG_STATS
};
//-----------------------------------------
// Add New API requests Here
//-----------------------------------------
enum RequestTypes
{
// ----- Store/Web API begins at 1 -----
//CTWEB_REQUEST_TEST = 1,
CTWEB_REQUEST_GET_GAMES = 2,
CTWEB_REQUEST_GET_SUBSCRIPTIONS = 3,
CTWEB_REQUEST_GET_CHARACTERS = 4,
CTWEB_REQUEST_GET_SOURCE_SERVERS = 5,
CTWEB_REQUEST_GET_DEST_SERVERS = 6,
CTWEB_REQUEST_VALIDATE_TRANSACTION = 7,
CTWEB_REQUEST_VALIDATE_ORDER = 8,
CTWEB_REQUEST_SUBMIT_ORDER = 9,
CTWEB_REQUEST_GET_ORDER_STATUS = 10,
CTWEB_REQUEST_GET_ORDERS_BY_STATION_ID = 11,
CTWEB_REQUEST_GET_TRANSACTIONS_BY_ORDER_ID = 12,
CTWEB_REQUEST_CSR_MOVE = 13,
CTWEB_REQUEST_CSR_DELETE = 14,
CTWEB_REQUEST_CSR_RESTORE = 15,
CTWEB_REQUEST_CSR_TRANSFER_ACCOUNT = 16,
// ----- Game API begins at 1000 -----
// first requests sent from API to server
//CTGAME_REQUEST_TEST = 1000,
CTGAME_REQUEST_CONNECT = 1001,
CTGAME_REPLY_TEST,
CTGAME_REPLY_MOVESTATUS,
CTGAME_REPLY_VALIDATEMOVE,
CTGAME_REPLY_MOVE,
CTGAME_REPLY_CHARACTERLIST,
CTGAME_REPLY_SERVERLIST,
CTGAME_REPLY_DESTSERVERLIST,
CTGAME_REPLY_DELETE,
CTGAME_REPLY_RESTORE,
CTGAME_REPLY_TRANSFER_ACCOUNT,
// then requests send from server to API
CTGAME_SERVER_TEST = 1100,
CTGAME_SERVER_MOVESTATUS,
CTGAME_SERVER_VALIDATEMOVE,
CTGAME_SERVER_MOVE,
CTGAME_SERVER_CHARACTERLIST,
CTGAME_SERVER_SERVERLIST,
CTGAME_SERVER_DESTSERVERLIST,
CTGAME_SERVER_DELETE,
CTGAME_SERVER_RESTORE,
CTGAME_SERVER_TRANSFER_ACCOUNT,
// ----- Login API begins at 2000 -----
CTLOGIN_REQUEST_GET_ACCOUNT_STATUS = 2000,
CTLOGIN_REQUEST_GET_ACCOUNT_SUBSCRIPTIONS,
CTLOGIN_REQUEST_GET_MEMBER_INFO,
// ----- Ecomm API begins at 3000 -----
CTECOMM_REQUEST_VALIDATE_CARD = 3000,
CTECOMM_REQUEST_GET_PRODUCT,
CTECOMM_REQUEST_GET_PRODUCT_LIST,
CTECOMM_REQUEST_CALUCULATE_ORDER_AMOUNT,
CTECOMM_REQUEST_GET_PRODUCTS_BY_GAME_AND_TYPE,
CTECOMM_REQUEST_PREAUTH_ORDER,
CTECOMM_REQUEST_DEPOSIT_CREDIT_CARD
};
//-----------------------------------------
// Add result codes for both API's Here
//-----------------------------------------
enum CTResultCodes
{
CT_RESULT_SUCCESS = 0, // general hardware/system type messages
CT_RESULT_TIMEOUT,
CT_RESULT_FAILURE,
CT_RESULT_1OR_MORE_TRANSACTIONS_FAILED,
CT_RESULT_NO_TRANS_IN_ORDER,
CT_RESULT_ORDER_FOR_DIFFERENT_GAMES,//5
CT_RESULT_ORDER_FOR_DIFFERENT_USERS,
CT_RESULT_MULTI_TRANS_FOR_CHARACTER,
CT_RESULT_DEST_STATIONNAME_PASSWORD_INVALID,
CT_RESULT_SOURCE_STATION_ACCOUNT_NOT_ACTIVE,
CT_RESULT_DEST_STATION_ACCOUNT_NOT_ACTIVE,//10
CT_RESULT_INVALID_UID,
CT_RESULT_SOURCE_UID_INVALID,
CT_RESULT_ALL_REQUIRED_TRANSACTION_INFO_NOT_PROVIDED,
CT_RESULT_NOT_SAME_FIRST_NAME_ON_STATION_ACCOUNTS,
CT_RESULT_NOT_SAME_LAST_NAME_ON_STATION_ACCOUNTS,//15
CT_RESULT_NOT_SAME_EMAIL_ON_STATION_ACCOUNTS,
CT_RESULT_TRANSFER_TO_SAME_ACCOUNT,
CT_RESULT_WEB_INFO_DOES_NOT_MATCH_STATION_INFO,
CT_RESULT_SOURCE_SUBSCRIPTION_STATUS_NOT_ALLOWED,
CT_RESULT_DEST_SUBSCRIPTION_STATUS_NOT_ALLOWED,//20
CT_RESULT_BAD_CC_INFO,
CT_RESULT_ZIP_FAILED_AVS,
CT_RESULT_HARD_DECLINE_ECOMM,
CT_RESULT_SOFT_DECLINE_ECOMM,
CT_RESULT_OTHER_ECOMM_ERROR,//25
CT_RESULT_INVALID_STOREFRONT,
CT_RESULT_ILLEGAL_TRANSACTION_REQUESTED_FOR_GAME,
CT_RESULT_ILLEGAL_GAME_CODE,
CT_RESULT_UPDATE_ORDER_PRICE_FAILED,
CT_RESULT_UPDATE_ORDER_PRICE_FAILED_TWICE,//30
CT_RESULT_HARD_DECLINE_GAME,
CT_RESULT_SOFT_DECLINE_GAME,
CT_RESULT_TRANSACTION_DOES_NOT_DO_ANYTHING,
// ADDITIONS HERE SHOULD BE ADDED TO REQUESTSTRINGS.H AS WELL
};
//-----------------------------------------
// Add localized messages here
//-----------------------------------------
enum CTLocalizedMessages
{
CT_MESSAGE_SOURCE_SUBSCRIPTION_STATUS_NOT_ALLOWED = 1,
CT_MESSAGE_DEST_SUBSCRIPTION_STATUS_NOT_ALLOWED,
CT_MESSAGE_TIMEOUT,
CT_MESSAGE_FAILURE,
CT_MESSAGE_SOURCE_STATION_ACCOUNT_NOT_ACTIVE,//5
CT_MESSAGE_SOURCE_UID_INVALID,
CT_MESSAGE_TRANSFER_TO_SAME_ACCOUNT,
CT_MESSAGE_NOT_SAME_FIRST_NAME_ON_STATION_ACCOUNTS,
CT_MESSAGE_NOT_SAME_LAST_NAME_ON_STATION_ACCOUNTS,
CT_MESSAGE_NOT_SAME_EMAIL_ON_STATION_ACCOUNTS,//10
CT_MESSAGE_INVALID_UID,
CT_MESSAGE_DEST_STATION_ACCOUNT_NOT_ACTIVE,
CT_MESSAGE_DEST_STATIONNAME_PASSWORD_INVALID,
CT_MESSAGE_ALL_REQUIRED_TRANSACTION_INFO_NOT_PROVIDED,
CT_MESSAGE_ILLEGAL_TRANSACTION_REQUESTED_FOR_GAME,//15
CT_MESSAGE_ILLEGAL_GAME_CODE,
// ADDITIONS HERE SHOULD BE ADDED TO REQUESTSTRINGS.H AS WELL
};
//-----------------------------------------
// Add resource manager codes Here
//-----------------------------------------
enum ServiceTypes
{
SERVICE_DATABASE=0,
SERVICE_GAMEAPI,
SERVICE_LOGIN_SERVER,
SERVICE_ECOMM_SERVER,
SERVICE_TRANSACTION
};
//-----------------------------------------
// Add resource request ID's Here
//-----------------------------------------
enum ResourceRequestTypes
{
CTGAMEAPI_RESOURCE_TEST=1,
CTGAMEAPI_RESOURCE_MOVESTATUS,
CTGAMEAPI_RESOURCE_VALIDATEMOVE,
CTGAMEAPI_RESOURCE_MOVE,
CTGAMEAPI_RESOURCE_CHARACTERLIST,//5
CTGAMEAPI_RESOURCE_SERVERLIST,
CTGAMEAPI_RESOURCE_DESTSERVERLIST,
CTGAMEAPI_RESOURCE_DELETE,
CTGAMEAPI_RESOURCE_RESTORE,
CTGAMEAPI_RESOURCE_TRANSFER_ACCOUNT,
LOGIN_SERVER_REQUEST_VALIDATE_STATION_ACCOUNT=101,
LOGIN_SERVER_REQUEST_VALIDATE_STATION_ACCOUNT_WITH_ID,
LOGIN_SERVER_REQUEST_GET_ACCOUNT_SUBSCRIPTIONS,
LOGIN_SERVER_REQUEST_VALIDATE_TRANSFER_OWNERSHIP,
ECOMM_VALIDATE_CARD=201,
ECOMM_GET_PRODUCT,
ECOMM_GET_PRODUCT_LIST,
ECOMM_CALCULATE_ORDER_AMOUNTS,
ECOMM_GET_PRODUCTS_BY_GAME_AND_TYPE,//205
ECOMM_PREAUTH_ORDER,
ECOMM_DEPOSIT_CREDIT_CARD,
// DB Requests
DB_REQUEST_GET_GAMES=301,
DB_REQUEST_GET_GAME,
DB_REQUEST_SUBMIT_ORDER,
DB_REQUEST_CREATE_TRANSACTION,
DB_REQUEST_FINISH_TRANSACTION,//305
DB_REQUEST_GET_OLDEST_TRANSACTION,
DB_REQUEST_GET_ORDER_BY_ORDER_ID,
DB_REQUEST_GET_ORDER_STATUS,
DB_REQUEST_GET_TRANSACTION,
DB_REQUEST_GET_TRANSACTIONS_BY_SERVER,//310
DB_REQUEST_GET_TRANSACTIONS_FOR_ORDER,
DB_REQUEST_GET_ORDERS_BY_STATION_ID,
DB_REQUEST_SET_TRANSACTION_WAITING,
DB_REQUEST_UPDATE_ORDER_PRICE,
DB_REQUEST_UPDATE_ORDER_STATUS,//315
DB_REQUEST_UPDATE_TRANSACTION_STATUS,
DB_REQUEST_GET_ALL_LOCALIZED_MESSAGES,
DB_REQUEST_GET_LOCALIZED_MESSAGE_LANGUAGES,
DB_REQUEST_CREATE_LOCALIZED_MESSAGE,
DB_REQUEST_MODIFY_LOCALIZED_MESSAGE_TEXT,//320
DB_REQUEST_MODIFY_GAME,
DB_REQUEST_ADD_GAME,
};
//-----------------------------------------
// Status codes used by onGetOrderStatus for webAPI
//-----------------------------------------
enum CTOrderStatus
{
CT_ORDER_STATUS_UNKNOWN = 0, // A problem occured retrieving the status of an order
CT_ORDER_STATUS_NEW, // Just created in DB
CT_ORDER_STATUS_PENDING, // Pre-Auth of Credit Card OK. Waiting for TransactionManager to process.
CT_ORDER_STATUS_PREAUTH_FAILED, // Pre-Auth of Credit Card Failed
CT_ORDER_STATUS_ABOUT_TO_DEPOSIT, // All game transactions are complete, fixing to deposit credit card
CT_ORDER_STATUS_FINISHED,//5 // Deposit successful. Order is complete. (some transaction may not have been processed by game, deposit amount was adjusted in this case
CT_ORDER_STATUS_BILLING_FAILED, // Deposit failed, CS Alerted
CT_ORDER_STATUS_ORDER_ID_NOT_FOUND_IN_DB, // DB Call was successful, but the order does not exist
CSR_NEW,
CSR_HARD_FAIL,
CSR_SOFT_FAIL,//10
CSR_SPECIFIC_HARD_FAIL,
CSR_FINISHED,
CSR_SOFT_GAME_FAIL,
CSR_FAILED_GAME
};
//-----------------------------------------
// Status codes used by replyMoveStatus in game API
//-----------------------------------------
enum CTMoveStatus
{
CT_STATUS_COMPLETE = 0, // operation completed by game server
CT_STATUS_INPROGRESS, // operation still in progress
CT_STATUS_UNKNOWN, // transaction ID unrecognised by game server
};
//-----------------------------------------
// Result codes used by replyMove, replyDelete, replyRestore, and replyTransferAccount in game API
//-----------------------------------------
enum CTMoveResult
{
CT_GAMERESULT_SUCCESS = 0, // operation completed ok
CT_GAMERESULT_SOFTERROR, // operation cannot be completed at this time, a "temporary" fail
CT_GAMERESULT_HARDERROR, // operation failed and cannot succeed even if retried
// any values below this are game-specific HARDERRORS. Use these to help provide feedback to the customers and CSR's
CT_GAMERESULT_INVALID_NAME = 1000,
CT_GAMERESULT_NAME_ALREADY_TAKE,
CT_GAMERESULT_HAS_CORPSE,
CT_GAMERESULT_SERVER_IS_DOWN,
CT_GAMERESULT_MAX_CHAR_ON_DEST_SERVER,
CT_GAMERESULT_CHAR_HAS_ITEM_NOT_ALLOWED_TO_LEAVE_SRC_SERVER,//1005
CT_GAMERESULT_CHAR_HAS_ITEM_NOT_ALLOWED_ON_DEST_SERVER,
CT_GAMERESULT_CHAR_NOT_ALLOWED_TO_MOVE_FROM_SRC_SERVER,
CT_GAMERESULT_CHAR_NOT_ALLOWED_TO_MOVE_TO_DEST_SERVER,
CT_GAMERESULT_CHAR_NOT_ALLOWED_TO_MOVE_FROM_THIS_SRC_SERVER_TO_THIS_DEST_SERVER,
CT_GAMERESULT_CHAR_TYPE_NOT_ALLOWED_TO_LEAVE_SRC_SERVER,//1010 this type of character is not allowed to leave source server(faction, race, class, etc)
CT_GAMERESULT_CHAR_TYPE_NOT_ALLOWED_ON_DEST_SERVER, // this type of character is not allowed on dest server(faction, race, class, etc)
CT_GAMERESULT_SOFTERROR_FOR_LOCALIZED_TEXT, // ctserver will convert CT_GAMERESULT_SOFTERROR to this for getting localized text
CT_GAMERESULT_HARDERROR_FOR_LOCALIZED_TEXT, // ctserver will convert CT_GAMERESULT_HARDERROR to this for getting localized text
};
enum CTLocalizedEmailMessages
{
// 2000 - 2999 CUSTOMER EMAIL SUBJECT
CT_EMAIL_ORDER_COMP_SUCCESS = 2001, // NO PROBLEMS AT ALL IN THE ORDER, ALL TRANSACTIONS SUCCESSFUL
CT_EMAIL_ORDER_COMP = 2002, // ORDER WAS BILLED FOR A CORRECTED AMOUNT (NOT ALL TRANSACTIONS WERE SUCCESFUL)
CT_EMAIL_ORDER_PROCESSING = 2003, // ORDER PASSED VALIDATION AND GOT WRITTEN TO DB, PREAUTH DONE, TRANSACTION MANAGER HAS NOT BEGUN TO PROCESS IT YET
CT_EMAIL_ORDER_NOT_PROCESSED = 2004, // A FAIL OCCURED THAT WILL NOT ALLOW THE ORDER TO BE PROCESSED. ALTHOUGH A PREAUTH WAS DONE, NO TRANSACTIONS WERE COMPLETED, AND DEPOSIT WAS NOT CALLED
CT_EMAIL_ORDER_PROBLEM = 2005, // AT LEAST ONE TRANSACTION WAS COMPLETED, ORDER WAS NOT BILLED. CSR INTERVENTION A MUST AT THIS POINT
// 3000 - 3999 CUSTOMER EMAIL CONTENT (ENGLISH)
CT_EMAIL_PRE_NAME_GREETING = 3001, //ALL EMAILS (ex. Dear)
// AUTO EMAIL ONCE ORDER HAS BEEN WRITTEN TO DB AND BEFORE TRANSACTION MANAGER STARTS
CT_EMAIL_ORDER_BEING_PROCESSED_LINE_1 = 3002,
CT_EMAIL_ORDER_BEING_PROCESSED_LINE_2 = 3003,
CT_EMAIL_ORDER_BEING_PROCESSED_LINE_3 = 3004,
CT_EMAIL_ORDER_BEING_PROCESSED_LINE_4 = 3005,
CT_EMAIL_ORDER_BEING_PROCESSED_LINE_5 = 3006,
CT_EMAIL_ORDER_BEING_PROCESSED_LINE_6 = 3007,
CT_EMAIL_ORDER_BEING_PROCESSED_LINE_7 = 3008,
CT_EMAIL_ORDER_BEING_PROCESSED_LINE_8 = 3009,
CT_EMAIL_ORDER_BEING_PROCESSED_LINE_9 = 3010,
CT_EMAIL_ORDER_BEING_PROCESSED_CLOSING_LINE_1 = 3011,
CT_EMAIL_ORDER_BEING_PROCESSED_CLOSING_LINE_2 = 3012,
CT_EMAIL_ORDER_BEING_PROCESSED_CLOSING_LINE_3 = 3013,
CT_EMAIL_ORDER_BEING_PROCESSED_CLOSING_LINE_4 = 3014,
CT_EMAIL_ORDER_BEING_PROCESSED_CLOSING_LINE_5 = 3015,
CT_EMAIL_ORDER_BEING_PROCESSED_CLOSING_LINE_6 = 3016,
// EMAIL SENT TO CUSTOMER AFTER ALL TRANSACTIONS ARE SUCCESSFUL AND BILLING IS SUCCESFUL
CT_EMAIL_ORDER_COMPLETE_SUCCESS_LINE_1 = 3102,
CT_EMAIL_ORDER_COMPLETE_SUCCESS_LINE_2 = 3103,
CT_EMAIL_ORDER_COMPLETE_SUCCESS_LINE_3 = 3104,
CT_EMAIL_ORDER_COMPLETE_SUCCESS_LINE_4 = 3105,
CT_EMAIL_ORDER_COMPLETE_SUCCESS_LINE_5 = 3106,
CT_EMAIL_ORDER_COMPLETE_SUCCESS_LINE_6 = 3107,
CT_EMAIL_ORDER_COMPLETE_SUCCESS_LINE_7 = 3108,
CT_EMAIL_ORDER_COMPLETE_SUCCESS_LINE_8 = 3109,
CT_EMAIL_ORDER_COMPLETE_SUCCESS_LINE_9 = 3110,
CT_EMAIL_ORDER_COMPLETE_SUCCESS_CLOSING_LINE_1 = 3111,
CT_EMAIL_ORDER_COMPLETE_SUCCESS_CLOSING_LINE_2 = 3112,
CT_EMAIL_ORDER_COMPLETE_SUCCESS_CLOSING_LINE_3 = 3113,
CT_EMAIL_ORDER_COMPLETE_SUCCESS_CLOSING_LINE_4 = 3114,
CT_EMAIL_ORDER_COMPLETE_SUCCESS_CLOSING_LINE_5 = 3115,
CT_EMAIL_ORDER_COMPLETE_SUCCESS_CLOSING_LINE_6 = 3116,
// EMAIL SENT TO CUSTOMER AFTER ALL TRANSACTIONS ARE COMPLETE
// (SOME TRANSACTION MAY NOT HAVE BEEN SUCCESFUL, BUT THE CUSTOMER WAS BILLED ONLY FOR THE SUCCESSFUL ONES) AND BILLING IS SUCCESFUL
CT_EMAIL_ORDER_PARTIAL_SUCCESS_LINE_1 = 3202,
CT_EMAIL_ORDER_PARTIAL_SUCCESS_LINE_2 = 3203,
CT_EMAIL_ORDER_PARTIAL_SUCCESS_LINE_3 = 3204,
CT_EMAIL_ORDER_PARTIAL_SUCCESS_LINE_4 = 3205,
CT_EMAIL_ORDER_PARTIAL_SUCCESS_LINE_5 = 3206,
CT_EMAIL_ORDER_PARTIAL_SUCCESS_LINE_6 = 3207,
CT_EMAIL_ORDER_PARTIAL_SUCCESS_LINE_7 = 3208,
CT_EMAIL_ORDER_PARTIAL_SUCCESS_LINE_8 = 3209,
CT_EMAIL_ORDER_PARTIAL_SUCCESS_LINE_9 = 3210,
CT_EMAIL_ORDER_PARTIAL_SUCCESS_CLOSING_LINE_1 = 3211,
CT_EMAIL_ORDER_PARTIAL_SUCCESS_CLOSING_LINE_2 = 3212,
CT_EMAIL_ORDER_PARTIAL_SUCCESS_CLOSING_LINE_3 = 3213,
CT_EMAIL_ORDER_PARTIAL_SUCCESS_CLOSING_LINE_4 = 3214,
CT_EMAIL_ORDER_PARTIAL_SUCCESS_CLOSING_LINE_5 = 3215,
CT_EMAIL_ORDER_PARTIAL_SUCCESS_CLOSING_LINE_6 = 3216,
// EMAIL SENT TO CUSTOMER IF AN ERROR OCCURED THAT PREVENTS ANY TRANSACTION BEING PROCESS. NO BILLING IS DONE.
CT_EMAIL_ORDER_NOT_PROCESSED_LINE_1 = 3302,
CT_EMAIL_ORDER_NOT_PROCESSED_LINE_2 = 3303,
CT_EMAIL_ORDER_NOT_PROCESSED_LINE_3 = 3304,
CT_EMAIL_ORDER_NOT_PROCESSED_LINE_4 = 3305,
CT_EMAIL_ORDER_NOT_PROCESSED_LINE_5 = 3306,
CT_EMAIL_ORDER_NOT_PROCESSED_LINE_6 = 3307,
CT_EMAIL_ORDER_NOT_PROCESSED_LINE_7 = 3308,
CT_EMAIL_ORDER_NOT_PROCESSED_LINE_8 = 3309,
CT_EMAIL_ORDER_NOT_PROCESSED_LINE_9 = 3310,
CT_EMAIL_ORDER_NOT_PROCESSED_CLOSING_LINE_1 = 3311,
CT_EMAIL_ORDER_NOT_PROCESSED_CLOSING_LINE_2 = 3312,
CT_EMAIL_ORDER_NOT_PROCESSED_CLOSING_LINE_3 = 3313,
CT_EMAIL_ORDER_NOT_PROCESSED_CLOSING_LINE_4 = 3314,
CT_EMAIL_ORDER_NOT_PROCESSED_CLOSING_LINE_5 = 3315,
CT_EMAIL_ORDER_NOT_PROCESSED_CLOSING_LINE_6 = 3316,
// EMAIL SENT TO CUSTOMER AFTER 1 TO ALL TRANSACTIONS ARE COMPLETE
// BUT BILLING WAS NOT SUCCESSFUL
CT_EMAIL_ORDER_FAILED_TO_BILL_LINE_1 = 3402,
CT_EMAIL_ORDER_FAILED_TO_BILL_LINE_2 = 3403,
CT_EMAIL_ORDER_FAILED_TO_BILL_LINE_3 = 3404,
CT_EMAIL_ORDER_FAILED_TO_BILL_LINE_4 = 3405,
CT_EMAIL_ORDER_FAILED_TO_BILL_LINE_5 = 3406,
CT_EMAIL_ORDER_FAILED_TO_BILL_LINE_6 = 3407,
CT_EMAIL_ORDER_FAILED_TO_BILL_LINE_7 = 3408,
CT_EMAIL_ORDER_FAILED_TO_BILL_LINE_8 = 3409,
CT_EMAIL_ORDER_FAILED_TO_BILL_LINE_9 = 3410,
CT_EMAIL_ORDER_FAILED_TO_BILL_CLOSING_LINE_1 = 3411,
CT_EMAIL_ORDER_FAILED_TO_BILL_CLOSING_LINE_2 = 3412,
CT_EMAIL_ORDER_FAILED_TO_BILL_CLOSING_LINE_3 = 3413,
CT_EMAIL_ORDER_FAILED_TO_BILL_CLOSING_LINE_4 = 3414,
CT_EMAIL_ORDER_FAILED_TO_BILL_CLOSING_LINE_5 = 3415,
CT_EMAIL_ORDER_FAILED_TO_BILL_CLOSING_LINE_6 = 3416,
// INDIVIDUAL LINES IN THE CUSTOMER EMAIL THAT WILL BE APPENDED WITH INFORMATION
// example: "YOUR ORDER TRACKING NUMBER IS:"
CT_EMAIL_ORDER_DETAIL_FOR_ORDER_TEXT = 3500,
CT_EMAIL_SWG_GAME_NAME_TEXT = 3501,
CT_EMAIL_EQ_GAME_NAME_TEXT = 3502,
CT_EMAIL_PS_GAME_NAME_TEXT = 3503,
CT_EMAIL_EQ2_GAME_NAME_TEXT = 3504,
CT_EMAIL_CHARACTER_TEXT = 3505,
CT_EMAIL_SERVER_NAME_TEXT = 3506,
CT_EMAIL_NAME_CHANGED_TO_TEXT = 3507,
CT_EMAIL_MOVED_TO_SERVER_NAME_TEXT = 3508,
CT_EMAIL_TRANSFERED_TO_STATION_ACCOUNT_TEXT = 3509,
CT_EMAIL_WITH_ITEMS_TEXT = 3510,
CT_EMAIL_WITHOUT_ITEMS_TEXT = 3511,
CT_EMAIL_TRANSACTIONS_REQUESTED_TEXT = 3512,
CT_EMAIL_TOTAL_RENAMES_TEXT = 3513,
CT_EMAIL_TOTAL_SERVER_TO_SERVER_MOVES_WITH_ITMES_TEXT = 3514,
CT_EMAIL_TOTAL_SERVER_TO_SERVER_MOVES_WITHOUT_ITMES_TEXT = 3515,
CT_EMAIL_TOTAL_ACCOUNT_TO_ACCOUNT_TRANSFERS_WITH_ITEMS_TEXT = 3516,
CT_EMAIL_TOTAL_ACCOUNT_TO_ACCOUNT_TRANSFERS_WITHOUT_ITEMS_TEXT = 3517,
CT_EMAIL_SUBTOTAL_FOR_ALL_TRANSACTIONS_BILLED_TEXT = 3518,
CT_EMAIL_TAX_FOR_ALL_TRANSACTIONS_BILLED_TEXT = 3519,
CT_EMAIL_VAT_TAX_FOR_ALL_TRANSACTIONS_BILLED_TEXT = 3520,
CT_EMAIL_DISCOUNTS_FOR_ALL_TRANSACTIONS_BILLED_TEXT = 3521,
CT_EMAIL_TOTAL_AMOUNT_BILLED_TEXT = 3522,
CT_EMAIL_FAILED_TO_MOVE_TO_SERVER_TEXT = 3523,
CT_EMAIL_FAILED_TO_RENAME_CHARACTER_TEXT = 3524,
CT_EMAIL_FAILED_TO_TRANSFER_CHARACTER_TO_STATION_ACCOUNT_TEXT = 3525,
CT_EMAIL_REASON_TEXT = 3526,
CT_EMAIL_TRANSACTIONS_BILLED_TEXT = 3527,
CT_EMAIL_YOUR_ORDER_TRACKING_NUMBER_TEXT = 3528,
CT_EMAIL_OVERRIDE_TRUE_TEXT = 3529,
CT_EMAIL_OVERRIDE_FALSE_TEXT = 3530,
};
/*
enum StationAccountStatus
{
ACCOUNT_STATUS_NULL, // Invalid account status
ACCOUNT_STATUS_ACTIVE,
ACCOUNT_STATUS_CLOSED,
// Add new account status codes here
ACCOUNT_STATUS_END
};
*/
}; // namespace
#endif
@@ -0,0 +1,72 @@
#include "CTServiceCharacter.h"
#include <Base/Archive.h>
#include <Unicode/UnicodeUtils.h>
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
using namespace Plat_Unicode;
void get(ByteStream::ReadIterator & source, CTService::CTServiceCharacter & target)
{
bool value;
Plat_Unicode::String temp;
get(source, temp);
target.SetCharacter(temp.c_str());
get(source, value);
target.SetCanRename(value);
get(source, value);
target.SetCanMove(value);
get(source, value);
target.SetCanTransfer(value);
get(source, temp);
target.SetRenameReason(temp.c_str());
get(source, temp);
target.SetMoveReason(temp.c_str());
get(source, temp);
target.SetTransferReason(temp.c_str());
// printf("\nCTServiceCharacter::get() -> [%s] [%d,%d,%d] [%s] [%s] [%s]",
// wideToNarrow(target.GetCharacter()).c_str(), target.GetCanRename(), target.GetCanMove(),
// target.GetCanTransfer(), wideToNarrow(target.GetRenameReason()).c_str(),
// wideToNarrow(target.GetMoveReason()).c_str(), wideToNarrow(target.GetTransferReason()).c_str()); //debug
}
void put(ByteStream & target, CTService::CTServiceCharacter & source)
{
Plat_Unicode::String temp;
temp = source.GetCharacter();
put(target, temp);
put(target, source.GetCanRename());
put(target, source.GetCanMove());
put(target, source.GetCanTransfer());
temp = source.GetRenameReason();
put(target, temp);
temp = source.GetMoveReason();
put(target, temp);
temp = source.GetTransferReason();
put(target, temp);
// printf("\nCTServiceCharacter::put() -> [%s] [%d,%d,%d] [%s] [%s] [%s]",
// wideToNarrow(source.GetCharacter()).c_str(), source.GetCanRename(), source.GetCanMove(),
// source.GetCanTransfer(), wideToNarrow(source.GetRenameReason()).c_str(),
// wideToNarrow(source.GetMoveReason()).c_str(), wideToNarrow(source.GetTransferReason()).c_str()); //debug
}
}
#ifdef EXTERNAL_DISTRO
}; // namespace
#endif
@@ -0,0 +1,70 @@
#ifndef CTSERVICECHARACTER_H
#define CTSERVICECHARACTER_H
namespace CTService
{
//--------------------------------------------------------
class CTServiceCharacter
//--------------------------------------------------------
{
typedef unsigned short uchar_t;
inline void copy_wide_string(uchar_t * target, const uchar_t * source, int length)
{
if (!target)
return;
if (!source)
{
target[0] = 0;
return;
}
int offset = 0;
while (offset < length && (target[offset++] = source[offset]));
target[length-1] = 0;
}
public:
enum { CHARACTER_SIZE=64, CHARACTER_BUFFER, REASON_SIZE=4096, REASON_BUFFER };
CTServiceCharacter() : mCharacter(), mCanRename(true), mCanMove(true), mCanTransfer(true), mRenameReason(), mMoveReason(), mTransferReason()
{ mCharacter[0] = 0;
mRenameReason[0] = 0;
mMoveReason[0] = 0;
mTransferReason[0]= 0; }
CTServiceCharacter(const unsigned short *ch) : mCharacter(), mCanRename(true), mCanMove(true), mCanTransfer(true), mRenameReason(), mMoveReason(), mTransferReason()
{ copy_wide_string(mCharacter, ch, CHARACTER_BUFFER);
mRenameReason[0] = 0;
mMoveReason[0] = 0;
mTransferReason[0]= 0; }
void SetCharacter(const uchar_t * value) { copy_wide_string(mCharacter, value, CHARACTER_BUFFER); }
const uchar_t * GetCharacter() const { return mCharacter; }
void SetCanRename(const bool value) { mCanRename = value; }
const bool GetCanRename() const { return mCanRename; }
void SetCanMove(const bool value) { mCanMove = value; }
const bool GetCanMove() const { return mCanMove; }
void SetCanTransfer(const bool value) { mCanTransfer = value; }
const bool GetCanTransfer() const { return mCanTransfer; }
void SetRenameReason(const uchar_t * value) { copy_wide_string(mRenameReason, value, REASON_BUFFER); }
const uchar_t * GetRenameReason() const { return mRenameReason; }
void SetMoveReason(const uchar_t * value) { copy_wide_string(mMoveReason, value, REASON_BUFFER); }
const uchar_t * GetMoveReason() const { return mMoveReason; }
void SetTransferReason(const uchar_t * value) { copy_wide_string(mTransferReason, value, REASON_BUFFER); }
const uchar_t * GetTransferReason() const { return mTransferReason; }
private:
uchar_t mCharacter[CHARACTER_BUFFER];
bool mCanRename;
bool mCanMove;
bool mCanTransfer;
uchar_t mRenameReason[REASON_BUFFER];
uchar_t mMoveReason[REASON_BUFFER];
uchar_t mTransferReason[REASON_BUFFER];
};
}; // namespace
#endif //CTSERVICECHARACTER_H
@@ -0,0 +1,124 @@
#ifndef CTSERVICECUSTOMER_H
#define CTSERVICECUSTOMER_H
#include <string.h>
namespace CTService
{
//--------------------------------------------------------
class CTServiceCustomer
//--------------------------------------------------------
{
inline void copy_wide_string(unsigned short * target, const unsigned short * source, int length)
{
if (!target)
return;
if (!source)
{
target[0] = 0;
return;
}
int offset = 0;
while (offset < length && (target[offset++] = source[offset]));
target[length-1] = 0;
}
public:
enum { SHORT_NAME_SIZE=64, SHORT_NAME_BUFFER,
PHONE_SIZE=32, PHONE_BUFFER,
EMAIL_SIZE=128, EMAIL_BUFFER,
CARD_NAME_SIZE=255, CARD_NAME_BUFFER,
CARD_ADDRESS1_SIZE=255, CARD_ADDRESS1_BUFFER,
CARD_ADDRESS2_SIZE=255, CARD_ADDRESS2_BUFFER,
CARD_CITY_SIZE=255, CARD_CITY_BUFFER,
CARD_STATE_SIZE=255, CARD_STATE_BUFFER,
CARD_ZIP_SIZE=255, CARD_ZIP_BUFFER,
CARD_COUNTRY_SIZE=2, CARD_COUNTRY_BUFFER,
CARD_NUMBER_SIZE=255, CARD_NUMBER_BUFFER,
CARD_EXPIRATION_MONTH_SIZE=2,CARD_EXPIRATION_MONTH_BUFFER,
CARD_EXPIRATION_YEAR_SIZE=4,CARD_EXPIRATION_YEAR_BUFFER };
CTServiceCustomer() : mFirstName(), mLastName(), mPhone(), mEmail(), mStationID(0), mCardName(), mCardAddress1(), mCardAddress2(), mCardCity(), mCardState(), mCardZip(), mCountry(), mCardNumber(), mCardExpirationMonth(), mCardExpirationYear()
{ mFirstName[0] = 0;
mLastName[0] = 0;
mPhone[0] = 0;
mEmail[0] = 0;
mCardName[0] = 0;
mCardAddress1[0] = 0;
mCardAddress2[0] = 0;
mCardCity[0] = 0;
mCardState[0] = 0;
mCardZip[0] = 0;
mCountry[0] = 0;
mCardNumber[0] = 0;
mCardExpirationMonth[0]= 0;
mCardExpirationYear[0]= 0; }
void SetFirstName(const unsigned short * value) { copy_wide_string(mFirstName, value, SHORT_NAME_BUFFER); }
unsigned short *GetFirstName() { return mFirstName; }
void SetLastName(const unsigned short * value) { copy_wide_string(mLastName, value, SHORT_NAME_BUFFER); }
unsigned short *GetLastName() { return mLastName; }
void SetPhone(const unsigned short * value) { copy_wide_string(mPhone, value, PHONE_BUFFER); }
unsigned short *GetPhone() { return mPhone; }
void SetEmail(const unsigned short * value) { copy_wide_string(mEmail, value, EMAIL_BUFFER); }
unsigned short *GetEmail() { return mEmail; }
void SetStationID(const unsigned value) { mStationID = value; }
unsigned GetStationID() { return mStationID; }
void SetCardName(const unsigned short * value) { copy_wide_string(mCardName, value, CARD_NAME_BUFFER); }
unsigned short *GetCardName() { return mCardName; }
void SetCardAddress1(const unsigned short * value) { copy_wide_string(mCardAddress1, value, CARD_ADDRESS1_BUFFER); }
unsigned short *GetCardAddress1() { return mCardAddress1; }
void SetCardAddress2(const unsigned short * value) { copy_wide_string(mCardAddress2, value, CARD_ADDRESS2_BUFFER); }
unsigned short *GetCardAddress2() { return mCardAddress2; }
void SetCardCity(const unsigned short * value) { copy_wide_string(mCardCity, value, CARD_CITY_BUFFER); }
unsigned short *GetCardCity() { return mCardCity; }
void SetCardState(const unsigned short * value) { copy_wide_string(mCardState, value, CARD_STATE_BUFFER); }
unsigned short *GetCardState() { return mCardState; }
void SetCardZip(const unsigned short * value) { copy_wide_string(mCardZip, value, CARD_ZIP_BUFFER); }
unsigned short *GetCardZip() { return mCardZip; }
void SetCountry(const unsigned short * value) { copy_wide_string(mCountry, value, CARD_COUNTRY_BUFFER); }
unsigned short *GetCountry() { return mCountry; }
void SetCardNumber(const unsigned short * value) { copy_wide_string(mCardNumber, value, CARD_NUMBER_BUFFER); }
unsigned short *GetCardNumber() { return mCardNumber; }
void SetCardExpirationMonth(const unsigned short * value){ copy_wide_string(mCardExpirationMonth, value, CARD_EXPIRATION_MONTH_BUFFER); }
unsigned short *GetCardExpirationMonth() { return mCardExpirationMonth; }
void SetCardExpirationYear(const unsigned short * value) { copy_wide_string(mCardExpirationYear, value, CARD_EXPIRATION_YEAR_BUFFER); }
unsigned short *GetCardExpirationYear() { return mCardExpirationYear; }
private:
unsigned short mFirstName[SHORT_NAME_BUFFER];
unsigned short mLastName[SHORT_NAME_BUFFER];
unsigned short mPhone[PHONE_BUFFER];
unsigned short mEmail[EMAIL_BUFFER];
unsigned mStationID;
unsigned short mCardName[CARD_NAME_BUFFER];
unsigned short mCardAddress1[CARD_ADDRESS1_BUFFER];
unsigned short mCardAddress2[CARD_ADDRESS2_BUFFER];
unsigned short mCardCity[CARD_CITY_BUFFER];
unsigned short mCardState[CARD_STATE_BUFFER];
unsigned short mCardZip[CARD_ZIP_BUFFER];
unsigned short mCountry[CARD_COUNTRY_BUFFER];
unsigned short mCardNumber[CARD_NUMBER_BUFFER];
unsigned short mCardExpirationMonth[CARD_EXPIRATION_MONTH_BUFFER];
unsigned short mCardExpirationYear[CARD_EXPIRATION_YEAR_BUFFER];
};
}; // namespace
#endif
@@ -0,0 +1,167 @@
#ifndef CTSERVICEDBORDER_H
#define CTSERVICEDBORDER_H
#include <string.h>
namespace CTService
{
//--------------------------------------------------------
// This object is used to pass back an order to the webAPI.
//this objects intended use is for CSR functionality, see also DBOrder.h(server only, not in webapi)
//--------------------------------------------------------
class CTServiceDBOrder
//--------------------------------------------------------
{
inline void copy_wide_string(unsigned short * target, const unsigned short * source, int length)
{
if (!target)
return;
if (!source)
{
target[0] = 0;
return;
}
int offset = 0;
while (offset < length && (target[offset++] = source[offset]));
target[length-1] = 0;
}
public:
enum { LANGUAGE_SIZE=2, LANGUAGE_BUFFER,
DATE_SIZE=20, DATE_BUFFER,
ECOMM_ORDER_ID_SIZE=16, ECOMM_ORDER_ID_BUFFER,
ORDER_STATUS_SIZE=16, ORDER_STATUS_BUFFER,
CUSTOMER_NAME_SIZE=64, CUSTOMER_NAME_BUFFER,
CUSTOMER_PHONE_SIZE=32, CUSTOMER_PHONE_BUFFER,
CUSTOMER_EMAIL_SIZE=128, CUSTOMER_EMAIL_BUFFER,
CARD_INFO_SIZE=255, CARD_INFO_BUFFER,
COUNTRY_SIZE=2, COUNTRY_BUFFER,
CARD_EXP_MONTH_SIZE=2, CARD_EXP_MONTH_BUFFER,
CARD_EXP_YEAR_SIZE=4, CARD_EXP_YEAR_BUFFER,
GAME_CODE_SIZE=25, GAME_CODE_BUFFER };
CTServiceDBOrder() : mOrderID(0), mEcommOrderID(), mOrderStatus(), mLanguage(), mGameCode(),
mStationID(0), mCustomerFirstName(), mCustomerLastName(), mCustomerPhone(),
mCustomerEmail(), mCardName(), mCardAddress1(), mCardAddress2(), mCardCity(),
mCardState(), mCardZip(), mCountry(), mCreationDate(), mModifyDate(), mCompletionDate(),
mTransactionCount(0), mSuccessfulTransactions(0), mFailedTransactions(0)
{
mEcommOrderID[0] = 0;
mOrderStatus[0] = 0;
mLanguage[0] = 0;
mGameCode[0] = 0;
mCustomerFirstName[0] = 0;
mCustomerLastName[0] = 0;
mCustomerPhone[0] = 0;
mCustomerEmail[0] = 0;
mCardName[0] = 0;
mCardAddress1[0] = 0;
mCardAddress2[0] = 0;
mCardCity[0] = 0;
mCardState[0] = 0;
mCardZip[0] = 0;
mCountry[0] = 0;
}
// unsigned
void SetOrderID(const unsigned value) { mOrderID = value; }
unsigned GetOrderID() { return mOrderID; }
void SetStationID(const unsigned value) { mStationID = value; }
unsigned GetStationID() { return mStationID; }
void SetTransactionCount(const unsigned value) { mTransactionCount = value; }
unsigned GetTransactionCount() { return mTransactionCount; }
void SetSuccessfulTransactions(const unsigned value) { mSuccessfulTransactions = value; }
unsigned GetSuccessfulTransactions() { return mSuccessfulTransactions; }
void SetFailedTransactions(const unsigned value) { mFailedTransactions = value; }
unsigned GetFailedTransactions() { return mFailedTransactions; }
// char
void SetCreationDate(const char * value) { if (value) strncpy(mCreationDate, value, DATE_BUFFER); else mCreationDate[0] = 0; }
const char * GetCreationDate() { return mCreationDate; }
void SetModifyDate(const char * value) { if (value) strncpy(mModifyDate, value, DATE_BUFFER); else mModifyDate[0] = 0; }
const char * GetModifyDate() { return mModifyDate; }
void SetCompletionDate(const char * value) { if (value) strncpy(mCompletionDate, value, DATE_BUFFER); else mCompletionDate[0] = 0; }
const char * GetCompletionDate() { return mCompletionDate; }
void SetEcommOrderID(const char * value) { if (value) strncpy(mEcommOrderID, value, ECOMM_ORDER_ID_BUFFER); else mEcommOrderID[0] = 0; }
const char * GetEcommOrderID() { return mEcommOrderID; }
void SetOrderStatus(const char * value) { if (value) strncpy(mOrderStatus, value, ORDER_STATUS_BUFFER); else mOrderStatus[0] = 0; }
const char * GetOrderStatus() { return mOrderStatus; }
void SetLanguage(const char * value) { if (value) strncpy(mLanguage, value, LANGUAGE_BUFFER); else mLanguage[0] = 0; }
const char * GetLanguage() { return mLanguage; }
void SetGameCode(const char * value) { if (value) strncpy(mGameCode, value, GAME_CODE_BUFFER); else mGameCode[0] = 0; }
const char * GetGameCode() { return mGameCode; }
// unsigned short
void SetCustomerFirstName(const unsigned short * value) { copy_wide_string(mCustomerFirstName, value, CUSTOMER_NAME_BUFFER); }
unsigned short *GetCustomerFirstName() { return mCustomerFirstName; }
void SetCustomerLastName(const unsigned short * value) { copy_wide_string(mCustomerLastName, value, CUSTOMER_NAME_BUFFER); }
unsigned short *GetCustomerLastName() { return mCustomerLastName; }
void SetCustomerPhone(const unsigned short * value) { copy_wide_string(mCustomerPhone, value, CUSTOMER_PHONE_BUFFER); }
unsigned short *GetCustomerPhone() { return mCustomerPhone; }
void SetCustomerEmail(const unsigned short * value) { copy_wide_string(mCustomerEmail, value, CUSTOMER_EMAIL_BUFFER); }
unsigned short *GetCustomerEmail() { return mCustomerEmail; }
void SetCardName(const unsigned short * value) { copy_wide_string(mCardName, value, CARD_INFO_BUFFER); }
unsigned short *GetCardName() { return mCardName; }
void SetCardAddress1(const unsigned short * value) { copy_wide_string(mCardAddress1, value, CARD_INFO_BUFFER); }
unsigned short *GetCardAddress1() { return mCardAddress1; }
void SetCardAddress2(const unsigned short * value) { copy_wide_string(mCardAddress2, value, CARD_INFO_BUFFER); }
unsigned short *GetCardAddress2() { return mCardAddress2; }
void SetCardCity(const unsigned short * value) { copy_wide_string(mCardCity, value, CARD_INFO_BUFFER); }
unsigned short *GetCardCity() { return mCardCity; }
void SetCardState(const unsigned short * value) { copy_wide_string(mCardState, value, CARD_INFO_BUFFER); }
unsigned short *GetCardState() { return mCardState; }
void SetCardZip(const unsigned short * value) { copy_wide_string(mCardZip, value, CARD_INFO_BUFFER); }
unsigned short *GetCardZip() { return mCardZip; }
void SetCountry(const unsigned short * value) { copy_wide_string(mCountry, value, COUNTRY_BUFFER); }
unsigned short *GetCountry() { return mCountry; }
private:
unsigned mOrderID;
char mEcommOrderID[ECOMM_ORDER_ID_BUFFER];
char mOrderStatus[ORDER_STATUS_BUFFER];
char mLanguage[LANGUAGE_BUFFER];
char mGameCode[GAME_CODE_BUFFER];
unsigned mStationID;
unsigned short mCustomerFirstName[CUSTOMER_NAME_BUFFER];
unsigned short mCustomerLastName[CUSTOMER_NAME_BUFFER];
unsigned short mCustomerPhone[CUSTOMER_PHONE_BUFFER];
unsigned short mCustomerEmail[CUSTOMER_EMAIL_BUFFER];
unsigned short mCardName[CARD_INFO_BUFFER];
unsigned short mCardAddress1[CARD_INFO_BUFFER];
unsigned short mCardAddress2[CARD_INFO_BUFFER];
unsigned short mCardCity[CARD_INFO_BUFFER];
unsigned short mCardState[CARD_INFO_BUFFER];
unsigned short mCardZip[CARD_INFO_BUFFER];
unsigned short mCountry[COUNTRY_BUFFER];
char mCreationDate[DATE_BUFFER];
char mModifyDate[DATE_BUFFER];
char mCompletionDate[DATE_BUFFER];
unsigned mTransactionCount;
unsigned mSuccessfulTransactions;
unsigned mFailedTransactions;
};
}; // namespace
#endif //CTSERVICEDBORDER_H
@@ -0,0 +1,160 @@
#ifndef CTSERVICEDBTRANSACTION_H
#define CTSERVICEDBTRANSACTION_H
#include <string.h>
namespace CTService
{
//--------------------------------------------------------
// This object is used to pass back a transaction to the webAPI.
//this objects intended use is for CSR functionality, see also DBTransaction.h(server only, not in webapi) and CTServiceWebAPITransaction.h(server and webapi, in common folder)
//--------------------------------------------------------
class CTServiceTransaction
//--------------------------------------------------------
{
inline void copy_wide_string(unsigned short * target, const unsigned short * source, int length)
{
if (!target)
return;
if (!source)
{
target[0] = 0;
return;
}
int offset = 0;
while (offset < length && (target[offset++] = source[offset]));
target[length-1] = 0;
}
public:
enum { LANGUAGE_SIZE=2, LANGUAGE_BUFFER,
DATE_SIZE=20, DATE_BUFFER,
GAME_CODE_SIZE=25, GAME_CODE_BUFFER,
NAME_SIZE=64, NAME_BUFFER,
TRANSACTIONS_STATUS_SIZE=64, TRANSACTIONS_STATUS_BUFFER };
CTServiceTransaction() : mTransactionID(0), mOrderID(0), mTransactionStatus(), mGameResultID(0),
mSuggestedName(), mGameCode(), mSourceServer(), mDestServer(),
mSourceCharacter(), mDestCharacter(), mSourceUID(0), mDestStationName(),
mDestUID(0), mWithItems(0), mOverride(0), mLanguage(), mTransferServerHost(),
mTransferServerPort(), mRetryCounter(0), mTimeoutDate(), mCreationDate(),
mModifyDate(), mCompletionDate()
{
mTransactionStatus[0] = 0;
mSuggestedName[0] = 0;
mGameCode[0] = 0;
mSourceServer[0] = 0;
mDestServer[0] = 0;
mSourceCharacter[0] = 0;
mDestCharacter[0] = 0;
mDestStationName[0] = 0;
mLanguage[0] = 0;
mTransferServerHost[0] = 0;
mTransferServerPort[0] = 0;
}
// unsigned
void SetTransactionID(const unsigned value) { mTransactionID = value; }
unsigned GetTransactionID() { return mTransactionID; }
void SetOrderID(const unsigned value) { mOrderID = value; }
unsigned GetOrderID() { return mOrderID; }
void SetGameResultID(const unsigned value) { mGameResultID = value; }
unsigned GetGameResultID() { return mGameResultID; }
void SetSourceUID(const unsigned value) { mSourceUID = value; }
unsigned GetSourceUID() { return mSourceUID; }
void SetDestUID(const unsigned value) { mDestUID = value; }
unsigned GetDestUID() { return mDestUID; }
void SetWithItems(const unsigned value) { mWithItems = value; }
unsigned GetWithItems() { return mWithItems; }
void SetOverride(const unsigned value) { mOverride = value; }
unsigned GetOverride() { return mOverride; }
void SetRetryCounter(const unsigned value) { mRetryCounter = value; }
unsigned GetRetryCounter() { return mRetryCounter; }
// char
void SetTimeoutDate(const char * value) { if (value) strncpy(mTimeoutDate, value, DATE_BUFFER); else mTimeoutDate[0] = 0; }
const char * GetTimeoutDate() { return mTimeoutDate; }
void SetCreationDate(const char * value) { if (value) strncpy(mCreationDate, value, DATE_BUFFER); else mCreationDate[0] = 0; }
const char * GetCreationDate() { return mCreationDate; }
void SetModifyDate(const char * value) { if (value) strncpy(mModifyDate, value, DATE_BUFFER); else mModifyDate[0] = 0; }
const char * GetModifyDate() { return mModifyDate; }
void SetCompletionDate(const char * value) { if (value) strncpy(mCompletionDate, value, DATE_BUFFER); else mCompletionDate[0] = 0; }
const char * GetCompletionDate() { return mCompletionDate; }
void SetTransactionStatus(const char * value) { if (value) strncpy(mTransactionStatus, value, TRANSACTIONS_STATUS_BUFFER); else mTransactionStatus[0] = 0; }
const char * GetTransactionStatus() { return mTransactionStatus; }
void SetGameCode(const char * value) { if (value) strncpy(mGameCode, value, GAME_CODE_BUFFER); else mGameCode[0] = 0; }
const char * GetGameCode() { return mGameCode; }
void SetLanguage(const char * value) { if (value) strncpy(mLanguage, value, LANGUAGE_BUFFER); else mLanguage[0] = 0; }
const char * GetLanguage() { return mLanguage; }
void SetTransferServerHost(const char * value) { if (value) strncpy(mTransferServerHost, value, NAME_BUFFER); else mTransferServerHost[0] = 0; }
const char * GetTransferServerHost() { return mTransferServerHost; }
void SetTransferServerPort(const char * value) { if (value) strncpy(mTransferServerPort, value, NAME_BUFFER); else mTransferServerPort[0] = 0; }
const char * GetTransferServerPort() { return mTransferServerPort; }
// unsigned short
void SetSuggestedName(const unsigned short * value) { copy_wide_string(mSuggestedName, value, NAME_BUFFER); }
unsigned short *GetSuggestedName() { return mSuggestedName; }
void SetSourceServer(const unsigned short * value) { copy_wide_string(mSourceServer, value, NAME_BUFFER); }
unsigned short *GetSourceServer() { return mSourceServer; }
void SetDestServer(const unsigned short * value) { copy_wide_string(mDestServer, value, NAME_BUFFER); }
unsigned short *GetDestServer() { return mDestServer; }
void SetSourceCharacter(const unsigned short * value) { copy_wide_string(mSourceCharacter, value, NAME_BUFFER); }
unsigned short *GetSourceCharacter() { return mSourceCharacter; }
void SetDestCharacter(const unsigned short * value) { copy_wide_string(mDestCharacter, value, NAME_BUFFER); }
unsigned short *GetDestCharacter() { return mDestCharacter; }
void SetDestStationName(const unsigned short * value) { copy_wide_string(mDestStationName, value, NAME_BUFFER); }
unsigned short *GetDestStationName() { return mDestStationName; }
private:
unsigned mTransactionID;
unsigned mOrderID;
char mTransactionStatus[TRANSACTIONS_STATUS_BUFFER];
unsigned mGameResultID;
unsigned short mSuggestedName[NAME_BUFFER];
char mGameCode[GAME_CODE_BUFFER];
unsigned short mSourceServer[NAME_BUFFER];
unsigned short mDestServer[NAME_BUFFER];
unsigned short mSourceCharacter[NAME_BUFFER];
unsigned short mDestCharacter[NAME_BUFFER];
unsigned mSourceUID;
unsigned short mDestStationName[NAME_BUFFER];
unsigned mDestUID;
unsigned mWithItems;
unsigned mOverride;
char mLanguage[LANGUAGE_BUFFER];
char mTransferServerHost[NAME_BUFFER];
char mTransferServerPort[NAME_BUFFER];
unsigned mRetryCounter;
char mTimeoutDate[DATE_BUFFER];
char mCreationDate[DATE_BUFFER];
char mModifyDate[DATE_BUFFER];
char mCompletionDate[DATE_BUFFER];
};
}; // namespace
#endif //CTSERVICEDBTRANSACTION_H
@@ -0,0 +1,42 @@
#if !defined (CTSERVICEOBJECTS_H_)
#define CTSERVICEOBJECTS_H_
#pragma warning (disable : 4786)
#include <Base/Archive.h>
#include "CTServiceCharacter.h"
#include "CTServiceServer.h"
#include "CTServiceWebAPITransaction.h"
#include "CTServiceCustomer.h"
#include "CTServiceDBOrder.h"
#include "CTServiceDBTransaction.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
void get(ByteStream::ReadIterator & source, CTService::CTServiceCharacter & target);
void put(ByteStream & target, CTService::CTServiceCharacter & source);
void get(ByteStream::ReadIterator & source, CTService::CTServiceServer & target);
void put(ByteStream & target, CTService::CTServiceServer & source);
void get(ByteStream::ReadIterator & source, CTService::CTServiceWebAPITransaction & target);
void put(ByteStream & target, CTService::CTServiceWebAPITransaction & source);
void get(ByteStream::ReadIterator & source, CTService::CTServiceCustomer & target);
void put(ByteStream & target, CTService::CTServiceCustomer & source);
void get(ByteStream::ReadIterator & source, CTService::CTServiceDBOrder & target);
void put(ByteStream & target, CTService::CTServiceDBOrder & source);
void get(ByteStream::ReadIterator & source, CTService::CTServiceTransaction & target);
void put(ByteStream & target, CTService::CTServiceTransaction & source);
}
#ifdef EXTERNAL_DISTRO
}; // namespace
#endif
#endif
@@ -0,0 +1,71 @@
#include "CTServiceServer.h"
#include <Base/Archive.h>
#include <Unicode/UnicodeUtils.h>
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Base
{
using namespace Plat_Unicode;
void get(ByteStream::ReadIterator & source, CTService::CTServiceServer & target)
{
bool value;
Plat_Unicode::String temp;
get(source, temp);
target.SetServer(temp.c_str());
get(source, value);
target.SetCanRename(value);
get(source, value);
target.SetCanMove(value);
get(source, value);
target.SetCanTransfer(value);
get(source, temp);
target.SetRenameReason(temp.c_str());
get(source, temp);
target.SetMoveReason(temp.c_str());
get(source, temp);
target.SetTransferReason(temp.c_str());
// printf("\nCTServiceServer::get() -> [%s] [%d,%d,%d] [%s] [%s] [%s]",
// wideToNarrow(target.GetServer()).c_str(), target.GetCanRename(), target.GetCanMove(),
// target.GetCanTransfer(), wideToNarrow(target.GetRenameReason()).c_str(),
// wideToNarrow(target.GetMoveReason()).c_str(), wideToNarrow(target.GetTransferReason()).c_str()); //debug
}
void put(ByteStream & target, CTService::CTServiceServer & source)
{
Plat_Unicode::String temp;
temp = source.GetServer();
put(target, temp);
put(target, source.GetCanRename());
put(target, source.GetCanMove());
put(target, source.GetCanTransfer());
temp = source.GetRenameReason();
put(target, temp);
temp = source.GetMoveReason();
put(target, temp);
temp = source.GetTransferReason();
put(target, temp);
// printf("\nCTServiceServer::put() -> [%s] [%d,%d,%d] [%s] [%s] [%s]",
// wideToNarrow(source.GetServer()).c_str(), source.GetCanRename(), source.GetCanMove(),
// source.GetCanTransfer(), wideToNarrow(source.GetRenameReason()).c_str(),
// wideToNarrow(source.GetMoveReason()).c_str(), wideToNarrow(source.GetTransferReason()).c_str()); //debug
}
}
#ifdef EXTERNAL_DISTRO
}; // namespace
#endif
@@ -0,0 +1,69 @@
#ifndef CTSERVICESERVER_H
#define CTSERVICESERVER_H
namespace CTService
{
//--------------------------------------------------------
class CTServiceServer
//--------------------------------------------------------
{
inline void copy_wide_string(unsigned short * target, const unsigned short * source, int length)
{
if (!target)
return;
if (!source)
{
target[0] = 0;
return;
}
int offset = 0;
while (offset < length && (target[offset++] = source[offset]));
target[length-1] = 0;
}
public:
enum { SERVER_SIZE=64, SERVER_BUFFER, REASON_SIZE=4096, REASON_BUFFER };
CTServiceServer() : mServer(), mCanRename(true), mCanMove(true), mCanTransfer(true), mRenameReason(), mMoveReason(), mTransferReason()
{ mServer[0] = 0;
mRenameReason[0] = 0;
mMoveReason[0] = 0;
mTransferReason[0]= 0; }
CTServiceServer(const unsigned short *server) : mServer(), mCanRename(true), mCanMove(true), mCanTransfer(true), mRenameReason(), mMoveReason(), mTransferReason()
{ copy_wide_string(mServer, server, SERVER_BUFFER);
mRenameReason[0] = 0;
mMoveReason[0] = 0;
mTransferReason[0]= 0; }
void SetServer(const unsigned short * value) { copy_wide_string(mServer, value, SERVER_BUFFER); }
unsigned short *GetServer() { return mServer; }
void SetCanRename(const bool value) { mCanRename = value; }
const bool GetCanRename() const { return mCanRename; }
void SetCanMove(const bool value) { mCanMove = value; }
const bool GetCanMove() const { return mCanMove; }
void SetCanTransfer(const bool value) { mCanTransfer = value; }
const bool GetCanTransfer() const { return mCanTransfer; }
void SetRenameReason(const unsigned short * value) { copy_wide_string(mRenameReason, value, REASON_BUFFER); }
const unsigned short * GetRenameReason() const { return mRenameReason; }
void SetMoveReason(const unsigned short * value) { copy_wide_string(mMoveReason, value, REASON_BUFFER); }
const unsigned short * GetMoveReason() const { return mMoveReason; }
void SetTransferReason(const unsigned short * value) { copy_wide_string(mTransferReason, value, REASON_BUFFER); }
const unsigned short * GetTransferReason() const { return mTransferReason; }
private:
unsigned short mServer[SERVER_BUFFER];
bool mCanRename;
bool mCanMove;
bool mCanTransfer;
unsigned short mRenameReason[REASON_BUFFER];
unsigned short mMoveReason[REASON_BUFFER];
unsigned short mTransferReason[REASON_BUFFER];
};
}; // namespace
#endif //CTSERVICESERVER_H
@@ -0,0 +1,95 @@
#ifndef CTSERVICEWEBAPITRANSACTION_H
#define CTSERVICEWEBAPITRANSACTION_H
#include <string.h>
namespace CTService
{
//--------------------------------------------------------
// this object is used by the webapi to send in a transaction to the CTServer.
// see also DBTransaction.h(server only, not in webapi) and CTServicDBTransaction.h(server and webapi, in common folder)
//--------------------------------------------------------
class CTServiceWebAPITransaction
//--------------------------------------------------------
{
inline void copy_wide_string(unsigned short * target, const unsigned short * source, int length)
{
if (!target)
return;
if (!source)
{
target[0] = 0;
return;
}
int offset = 0;
while (offset < length && (target[offset++] = source[offset]));
target[length-1] = 0;
}
typedef unsigned short uchar_t;
public:
enum { CHARACTER_SIZE=64, CHARACTER_BUFFER,
GAMECODE_SIZE=25, GAMECODE_BUFFER,
SERVER_SIZE=64, SERVER_BUFFER,
REASON_SIZE=4096, REASON_BUFFER,
STATION_NAME_SIZE=30, STATION_NAME_BUFFER,
STATION_PASSWORD_SIZE=30, STATION_PASSWORD_BUFFER };
CTServiceWebAPITransaction() : mGameCode(), mSourceServerName(), mDestServerName(), mSourceCharacterName(), mDestCharacterName(), mSourceUID(0), mDestStationName(), mDestStationPassword(), mWithItems(), mOverride()
{ mGameCode[0] = 0;
mSourceServerName[0] = 0;
mDestServerName[0] = 0;
mSourceCharacterName[0] = 0;
mDestCharacterName[0] = 0;
mDestStationName[0] = 0;
mDestStationPassword[0]= 0;
mWithItems = false;
mOverride = false; }
void SetGameCode(const char * value) { if (value) strncpy(mGameCode, value, GAMECODE_BUFFER); else mGameCode[0] = 0; }
// void SetGameCode(const char * value) { strncpy(mGameCode, value, GAMECODE_BUFFER); }
const char * GetGameCode() const { return mGameCode; }
void SetSourceServerName(const unsigned short * value) { copy_wide_string(mSourceServerName, value, SERVER_BUFFER); }
const uchar_t * GetSourceServerName() const { return mSourceServerName; }
void SetDestServerName(const unsigned short * value) { copy_wide_string(mDestServerName, value, SERVER_BUFFER); }
const uchar_t * GetDestServerName() const { return mDestServerName; }
void SetSourceCharacterName(const unsigned short * value){ copy_wide_string(mSourceCharacterName, value, CHARACTER_BUFFER); }
const uchar_t * GetSourceCharacterName() const { return mSourceCharacterName; }
void SetDestCharacterName(const unsigned short * value) { copy_wide_string(mDestCharacterName, value, CHARACTER_BUFFER); }
const uchar_t * GetDestCharacterName() const { return mDestCharacterName; }
void SetSourceUID(const unsigned value) { mSourceUID = value; }
unsigned GetSourceUID() { return mSourceUID; }
void SetDestStationName(const unsigned short * value) { copy_wide_string(mDestStationName, value, STATION_NAME_BUFFER); }
const uchar_t * GetDestStationName() const { return mDestStationName; }
void SetDestStationPassword(const unsigned short * value){ copy_wide_string(mDestStationPassword, value, STATION_PASSWORD_BUFFER); }
const uchar_t * GetDestStationPassword() const { return mDestStationPassword; }
void SetWithItems(const bool value) { mWithItems = value; }
bool GetWithItems() { return mWithItems; }
void SetOverride(const bool value) { mOverride = value; }
bool GetOverride() { return mOverride; }
private:
char mGameCode[GAMECODE_BUFFER];
uchar_t mSourceServerName[SERVER_BUFFER];
uchar_t mDestServerName[SERVER_BUFFER];
uchar_t mSourceCharacterName[CHARACTER_BUFFER];
uchar_t mDestCharacterName[CHARACTER_BUFFER];
unsigned mSourceUID;
uchar_t mDestStationName[STATION_NAME_BUFFER];
uchar_t mDestStationPassword[STATION_PASSWORD_BUFFER];
bool mWithItems;
bool mOverride;
};
}; // namespace
#endif
@@ -0,0 +1,155 @@
#ifndef REQUESTSTRINGS_H
#define REQUESTSTRINGS_H
#pragma warning (disable : 4786)
#include "CTEnum.h"
#include <map>
namespace CTService
{
static const char * _gamecodeName[] =
{
"",
"SP",
"EQ",
"EQ2",
"SWG",
"PS",
"EQOA-beta",
"EQOA",
"EQIM",
"EQM"
};
#define key_text std::pair<unsigned,const char *>
// ----- REQUEST NAMES -----
static const unsigned _RequestCount = 46;
static const key_text _requestString[_RequestCount] =
{
// key_text(CTWEB_REQUEST_TEST, "WEB_REQUEST_TEST"),
key_text(CTWEB_REQUEST_GET_GAMES, "WEB_REQUEST_GET_GAMES"),
key_text(CTWEB_REQUEST_GET_SUBSCRIPTIONS, "WEB_REQUEST_GET_SUBSCRIPTIONS"),
key_text(CTWEB_REQUEST_GET_CHARACTERS, "WEB_REQUEST_GET_CHARACTERS"),
key_text(CTWEB_REQUEST_GET_SOURCE_SERVERS, "WEB_REQUEST_GET_SOURCE_SERVERS"),
key_text(CTWEB_REQUEST_GET_DEST_SERVERS, "WEB_REQUEST_GET_DEST_SERVERS"),
key_text(CTWEB_REQUEST_VALIDATE_TRANSACTION,"WEB_REQUEST_VALIDATE_TRANSACTION"),
key_text(CTWEB_REQUEST_VALIDATE_ORDER, "WEB_REQUEST_VALIDATE_ORDER"),
key_text(CTWEB_REQUEST_SUBMIT_ORDER, "WEB_REQUEST_SUBMIT_ORDER"),
key_text(CTWEB_REQUEST_GET_ORDER_STATUS, "WEB_REQUEST_GET_ORDER_STATUS"),
key_text(CTWEB_REQUEST_GET_ORDERS_BY_STATION_ID, "WEB_REQUEST_GET_ORDERS_BY_STATION_ID"),
key_text(CTWEB_REQUEST_GET_TRANSACTIONS_BY_ORDER_ID, "WEB_REQUEST_GET_TRANSACTIONS_BY_ORDER_ID"),
key_text(CTWEB_REQUEST_CSR_MOVE, "WEB_REQUEST_CSR_MOVE"),
key_text(CTWEB_REQUEST_CSR_DELETE, "WEB_REQUEST_CSR_DELETE"),
key_text(CTWEB_REQUEST_CSR_RESTORE, "WEB_REQUEST_CSR_RESTORE"),
key_text(CTWEB_REQUEST_CSR_TRANSFER_ACCOUNT, "WEB_REQUEST_CSR_TRANSFER_ACCOUNT"),
// key_text(CTGAME_REQUEST_TEST, "GAME_REQUEST_TEST"),
key_text(CTGAME_REQUEST_CONNECT, "GAME_REQUEST_CONNECT"),
key_text(CTGAME_REPLY_TEST, "GAME_REPLY_TEST"),
key_text(CTGAME_SERVER_TEST, "GAME_SERVER_TEST"),
key_text(CTGAME_SERVER_MOVESTATUS, "GAME_SERVER_MOVESTATUS"),
key_text(CTGAME_REPLY_MOVESTATUS, "GAME_REPLY_MOVESTATUS"),
key_text(CTGAME_SERVER_VALIDATEMOVE, "GAME_SERVER_VALIDATEMOVE"),
key_text(CTGAME_REPLY_VALIDATEMOVE, "GAME_REPLY_VALIDATEMOVE"),
key_text(CTGAME_SERVER_MOVE, "GAME_SERVER_MOVE"),
key_text(CTGAME_REPLY_MOVE, "GAME_REPLY_MOVE"),
key_text(CTGAME_SERVER_DELETE, "GAME_SERVER_DELETE"),
key_text(CTGAME_REPLY_DELETE, "GAME_REPLY_DELETE"),
key_text(CTGAME_SERVER_RESTORE, "GAME_SERVER_RESTORE"),
key_text(CTGAME_REPLY_RESTORE, "GAME_REPLY_RESTORE"),
key_text(CTGAME_SERVER_TRANSFER_ACCOUNT, "GAME_SERVER_TRANSFER_ACCOUNT"),
key_text(CTGAME_REPLY_TRANSFER_ACCOUNT, "GAME_REPLY_TRANSFER_ACCOUNT"),
key_text(CTGAME_SERVER_CHARACTERLIST, "GAME_SERVER_CHARACTERLIST"),
key_text(CTGAME_REPLY_CHARACTERLIST, "GAME_REPLY_CHARACTERLIST"),
key_text(CTGAME_SERVER_SERVERLIST, "GAME_SERVER_SERVERLIST"),
key_text(CTGAME_REPLY_SERVERLIST, "GAME_REPLY_SERVERLIST"),
key_text(CTGAME_SERVER_DESTSERVERLIST, "GAME_SERVER_DESTSERVERLIST"),
key_text(CTGAME_REPLY_DESTSERVERLIST, "GAME_REPLY_DESTSERVERLIST"),
key_text(CTLOGIN_REQUEST_GET_ACCOUNT_STATUS, "LOGIN_REQUEST_GET_ACCOUNT_STATUS"),
key_text(CTLOGIN_REQUEST_GET_ACCOUNT_SUBSCRIPTIONS, "LOGIN_REQUEST_GET_ACCOUNT_SUBSCRIPTIONS"),
key_text(CTLOGIN_REQUEST_GET_MEMBER_INFO, "LOGIN_REQUEST_GET_MEMBER_INFO"),
key_text(CTECOMM_REQUEST_VALIDATE_CARD, "ECOMM_REQUEST_VALIDATE_CARD"),
key_text(CTECOMM_REQUEST_GET_PRODUCT, "ECOMM_REQUEST_GET_PRODUCT"),
key_text(CTECOMM_REQUEST_GET_PRODUCT_LIST, "ECOMM_REQUEST_GET_PRODUCT_LIST"),
key_text(CTECOMM_REQUEST_CALUCULATE_ORDER_AMOUNT, "ECOMM_REQUEST_CALUCULATE_ORDER_AMOUNT"),
key_text(CTECOMM_REQUEST_GET_PRODUCTS_BY_GAME_AND_TYPE, "ECOMM_REQUEST_GET_PRODUCTS_BY_GAME_AND_TYPE"),
key_text(CTECOMM_REQUEST_PREAUTH_ORDER, "ECOMM_REQUEST_PREAUTH_ORDER"),
key_text(CTECOMM_REQUEST_DEPOSIT_CREDIT_CARD, "ECOMM_REQUEST_DEPOSIT_CREDIT_CARD"),
};
static std::map<unsigned,const char *> RequestString((const std::map<unsigned,const char *>::value_type *)&_requestString[0],(const std::map<unsigned,const char *>::value_type *)&_requestString[_RequestCount]);
// ----- RESULT CODE NAMES -----
static const unsigned _ResultCount = 33;
static const key_text _resultString[_ResultCount] =
{
key_text(CT_RESULT_SUCCESS, "SUCCESS"),
key_text(CT_RESULT_TIMEOUT, "TIMEOUT"),
key_text(CT_RESULT_FAILURE, "FAILURE"),
key_text(CT_RESULT_NO_TRANS_IN_ORDER, "NO TRANSACTIONS IN ORDER"),
key_text(CT_RESULT_ORDER_FOR_DIFFERENT_GAMES, "NOT ALL TRANSACTIONS IN ORDER HAVE SAME GAMECODE"),
key_text(CT_RESULT_ORDER_FOR_DIFFERENT_USERS, "NOT ALL TRANSACTIONS IN ORDER ARE FOR SAME SOURCE UID"),
key_text(CT_RESULT_MULTI_TRANS_FOR_CHARACTER, "MULTIPLE TRANSACTIONS EXIST FOR SAME CHARACTER IN A SINGLE ORDER"),
key_text(CT_RESULT_1OR_MORE_TRANSACTIONS_FAILED, "ONE OR MORE TRANSACTIONS IN ORDER FAILED"),
key_text(CT_RESULT_DEST_STATIONNAME_PASSWORD_INVALID, "INVALID DEST STATIONNAME/PASSWORD COMBO"),
key_text(CT_RESULT_SOURCE_STATION_ACCOUNT_NOT_ACTIVE, "SOURCE STATION ACCOUNT NOT ACTIVE"),
key_text(CT_RESULT_DEST_STATION_ACCOUNT_NOT_ACTIVE, "DEST STATION ACCOUNT NOT ACTIVE"),
key_text(CT_RESULT_SOURCE_UID_INVALID, "SOURCE UID INVALID"),
key_text(CT_RESULT_INVALID_UID, "INVALID UID (Source or Dest)"),
key_text(CT_RESULT_NOT_SAME_FIRST_NAME_ON_STATION_ACCOUNTS, "SAME FIRST NAME NOT ON BOTH STATION ACCOUNTS"),
key_text(CT_RESULT_NOT_SAME_LAST_NAME_ON_STATION_ACCOUNTS, "SAME LAST NAME NOT ON BOTH STATION ACCOUNTS"),
key_text(CT_RESULT_NOT_SAME_EMAIL_ON_STATION_ACCOUNTS, "SAME EMAIL NAME NOT ON BOTH STATION ACCOUNTS"),
key_text(CT_RESULT_TRANSFER_TO_SAME_ACCOUNT, "ATTEMPT TO TRANSFER TO SAME STATION ACCOUNT"),
key_text(CT_RESULT_ALL_REQUIRED_TRANSACTION_INFO_NOT_PROVIDED,"REQUIRED TRANSACTION INFORMATION PASSED IN IS MISSING"),
key_text(CT_RESULT_WEB_INFO_DOES_NOT_MATCH_STATION_INFO, "INFORMATION PROVIDED DOES NOT MATCH STATION ACCOUNT INFO"),
key_text(CT_RESULT_SOURCE_SUBSCRIPTION_STATUS_NOT_ALLOWED, "CURRENT SOURCE SUBSCRIPTION STATUS IS INVALID FOR THIS TRANSACTION"),
key_text(CT_RESULT_DEST_SUBSCRIPTION_STATUS_NOT_ALLOWED, "CURRENT DEST SUBSCRIPTION STATUS IS INVALID FOR THIS TRANSACTION"),
key_text(CT_RESULT_BAD_CC_INFO, "ECOMM RETURNED FAIL ON CUSTOMER/CC INFO"),
key_text(CT_RESULT_ZIP_FAILED_AVS, "ECOMM RETURNED ZIP_FAILED_AVS"),
key_text(CT_RESULT_HARD_DECLINE_ECOMM, "ECOMM RETURNED HARD DECLINE"),
key_text(CT_RESULT_HARD_DECLINE_GAME, "GAME RETURNED HARD DECLINE"),
key_text(CT_RESULT_SOFT_DECLINE_ECOMM, "ECOMM RETURNED SOFT DECLINE"),
key_text(CT_RESULT_SOFT_DECLINE_GAME, "GAME RETURNED SOFT DECLINE"),
key_text(CT_RESULT_OTHER_ECOMM_ERROR, "ECOMM RETURNED OTHER ERROR"),
key_text(CT_RESULT_INVALID_STOREFRONT, "ECOMM RETURNED INVALID STOREFRONT"),
key_text(CT_RESULT_ILLEGAL_TRANSACTION_REQUESTED_FOR_GAME, "TRANSACTION REQUESTED ACTION NOT SUPPORTED BY GAME"),
key_text(CT_RESULT_ILLEGAL_GAME_CODE, "ILLEGAL GAME CODE"),
key_text(CT_RESULT_UPDATE_ORDER_PRICE_FAILED_TWICE, "FAILED TO UPDATE ORDER PRICE AND STATUS IN DB, ORDER NOT BEING PROCESS"),
key_text(CT_RESULT_TRANSACTION_DOES_NOT_DO_ANYTHING, "TRANSACTION DOES NOT DO ANYTHING"),
// REMEMBER TO INCREMENT THE _ResultCount ABOVE
};
static std::map<unsigned,const char *> ResultString((const std::map<unsigned,const char *>::value_type *)&_resultString[0],(const std::map<unsigned,const char *>::value_type *)&_resultString[_ResultCount]);
static const unsigned _ResourceCount = 10;
static const key_text _ResourceString[_ResourceCount] =
{
key_text(CTGAMEAPI_RESOURCE_TEST, "GAME_RESOURCE_TEST"),
key_text(CTGAMEAPI_RESOURCE_MOVESTATUS, "GAME_RESOURCE_MOVESTATUS"),
key_text(CTGAMEAPI_RESOURCE_VALIDATEMOVE, "GAME_RESOURCE_VALIDATEMOVE"),
key_text(CTGAMEAPI_RESOURCE_MOVE, "GAME_RESOURCE_MOVE"),
key_text(CTGAMEAPI_RESOURCE_CHARACTERLIST, "GAME_RESOURCE_CHARACTERLIST"),
key_text(CTGAMEAPI_RESOURCE_SERVERLIST, "GAME_RESOURCE_SERVERLIST"),
key_text(CTGAMEAPI_RESOURCE_DESTSERVERLIST, "GAME_RESOURCE_DESTSERVERLIST"),
key_text(CTGAMEAPI_RESOURCE_DELETE, "GAME_RESOURCE_DELETE"),
key_text(CTGAMEAPI_RESOURCE_RESTORE, "GAME_RESOURCE_RESTORE"),
key_text(CTGAMEAPI_RESOURCE_TRANSFER_ACCOUNT, "GAME_RESOURCE_TRANSFER_ACCOUNT"),
};
static std::map<unsigned,const char *> ResourceString((const std::map<unsigned,const char *>::value_type *)&_ResourceString[0],(const std::map<unsigned,const char *>::value_type *)&_ResourceString[_ResourceCount]);
//------------------------------------------------------------------------------------------------
}; // namespace
#endif
@@ -0,0 +1,272 @@
#include "GenericApiCore.h"
#include "GenericConnection.h"
#include "GenericMessage.h"
//----------------------------------------
//
// WARNING: These files are NOT standard generic API files
// They have been modified for this project.
// Do NOT replace them with generic API files
//
//----------------------------------------
using namespace std;
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
//----------------------------------------
ServerTrackObject::ServerTrackObject(unsigned mapped_track, unsigned real_track, GenericConnection *con)
: m_mappedTrack(mapped_track), m_realTrack(real_track), m_connection(con)
//----------------------------------------
{
}
//----------------------------------------
GenericAPICore::GenericAPICore(const char *host,
short port,
unsigned reqTimeout,
unsigned reconnectTimeout,
unsigned noDataTimeoutSecs,
unsigned noAckTimeoutSecs,
unsigned incomingBufSizeInKB,
unsigned outgoingBufSizeInKB,
unsigned keepAlive,
unsigned maxRecvMessageSizeInKB)
: m_currTrack(0),
m_reconnectTimeout(0),
m_outCount(0),
m_pendingCount(0),
m_requestTimeout(reqTimeout),
m_currentConnections(0), m_maxConnections(0),
m_suspended(false),
m_nextConnectionIndex(0)
//----------------------------------------
{
GenericConnection *con = new GenericConnection(host, port, this, reconnectTimeout, noDataTimeoutSecs, noAckTimeoutSecs, incomingBufSizeInKB, outgoingBufSizeInKB, keepAlive, maxRecvMessageSizeInKB);
m_serverConnections.push_back(con);
}
//----------------------------------------
GenericAPICore::GenericAPICore(const char *game, const char *hosts[],
const short port[],
unsigned arraySize,
unsigned reqTimeout,
unsigned reconnectTimeout,
unsigned noDataTimeoutSecs,
unsigned noAckTimeoutSecs,
unsigned incomingBufSizeInKB,
unsigned outgoingBufSizeInKB,
unsigned keepAlive,
unsigned maxRecvMessageSizeInKB)
: m_currTrack(0),
m_reconnectTimeout(0),
m_outCount(0),
m_pendingCount(0),
m_requestTimeout(reqTimeout),
m_currentConnections(0), m_maxConnections(0),
m_suspended(false),
m_nextConnectionIndex(0),
m_game(game)
//----------------------------------------
{
for (unsigned i=0; i<arraySize; i++)
{
GenericConnection *con = new GenericConnection(hosts[i], port[i], this, reconnectTimeout, noDataTimeoutSecs, noAckTimeoutSecs, incomingBufSizeInKB, outgoingBufSizeInKB, keepAlive, maxRecvMessageSizeInKB);
m_serverConnections.push_back(con);
}
}
//----------------------------------------
GenericAPICore::~GenericAPICore()
//----------------------------------------
{
for (std::vector<GenericConnection *>::iterator conIter = m_serverConnections.begin(); conIter != m_serverConnections.end(); conIter++)
{
GenericConnection *con = *conIter;
delete con;
}
m_serverConnections.clear();
for(map<unsigned, GenericResponse *>::iterator iter = m_pending.begin(); iter != m_pending.end(); ++iter)
{
delete (*iter).second;
}
m_pending.empty();
while(m_outCount > 0)
{
delete m_outboundQueue.front().second;
delete m_outboundQueue.front().first;
m_outboundQueue.pop();
--m_outCount;
}
}
//----------------------------------------
unsigned GenericAPICore::submitRequest(GenericRequest *req, GenericResponse *res)
//----------------------------------------
{
++m_outCount;
if(m_currTrack == 0)
{
m_currTrack++;
}
req->setTrack(m_currTrack);
res->setTrack(m_currTrack);
time_t timeout = time(NULL) + m_requestTimeout;
req->setTimeout(timeout);
res->setTimeout(timeout);
m_outboundQueue.push(pair<GenericRequest *, GenericResponse *>(req, res));
return(m_currTrack++);
}
//----------------------------------------
void GenericAPICore::process()
//----------------------------------------
{
GenericRequest *req;
GenericResponse *res;
if (!m_suspended)
{
// Process timeout on pending requests
while((m_outCount > 0) && ((req = m_outboundQueue.front().first)->getTimeout() <= time(NULL)))
{
--m_outCount;
res = m_outboundQueue.front().second;
m_outboundQueue.pop();
responseCallback(res);
delete res;
delete req;
}
// Process timeout on pending responses
while((m_pendingCount > 0) && ((res = (*m_pending.begin()).second)->getTimeout() <= time(NULL)))
{
--m_pendingCount;
m_pending.erase(m_pending.begin());
responseCallback(res);
delete res;
}
while(m_outCount > 0)
{
pair<GenericRequest *, GenericResponse *> out_pair = m_outboundQueue.front();
req = out_pair.first;
res = out_pair.second;
GenericConnection *con = NULL;
if (req->getMappedServerTrack() == 0) // request has no originating "owner" server
{
con = getNextActiveConnection(); // it does not matter which server we send this to
}
else
{
ServerTrackObject *stobj = findServer(req->getMappedServerTrack());
if (stobj)
{
con = stobj->getConnection(); // the server connection to respond to
req->setServerTrack(stobj->getRealServerTrack()); // map server track back to REAL server track
//printf("\nUnmapping %d to %d", stobj->getMappedServerTrack(), req->getMappedServerTrack()); //debug
delete stobj;
}
}
if (con != NULL)
{
Base::ByteStream msg;
req->pack(msg);
con->Send(msg);
m_pending.insert(pair<unsigned, GenericResponse *>(res->getTrack(), res));
--m_outCount;
++m_pendingCount;
m_outboundQueue.pop();
delete req;
}
else
{
//no active connections
break; //from while loop
}
}
}
for (std::vector<GenericConnection *>::iterator conIter = m_serverConnections.begin(); conIter != m_serverConnections.end(); conIter++)
{
GenericConnection *con = *conIter;
con->process();
}
}
//----------------------------------------
GenericConnection *GenericAPICore::getNextActiveConnection()
//----------------------------------------
{
unsigned startIndex = m_nextConnectionIndex;
unsigned maxIndex = m_serverConnections.size() - 1;
GenericConnection *con = NULL;
//loop until we find an active connection, or until we get back
// to where we started
do
{
if (m_serverConnections[m_nextConnectionIndex]->isConnected())
{
con = m_serverConnections[m_nextConnectionIndex];
if (m_nextConnectionIndex == maxIndex)
m_nextConnectionIndex = 0;
else
m_nextConnectionIndex++;
}
else if (++m_nextConnectionIndex > maxIndex)
{
//went past end of vector, start back at 0
m_nextConnectionIndex = 0;
}
}while (con == NULL && m_nextConnectionIndex != startIndex);
return con;
}
//----------------------------------------
void GenericAPICore::countOpenConnections()
//----------------------------------------
{
m_currentConnections = 0;
m_maxConnections = m_serverConnections.size();
for (std::vector<GenericConnection *>::iterator conIter = m_serverConnections.begin(); conIter != m_serverConnections.end(); conIter++)
{
GenericConnection *con = *conIter;
if (con->isConnected())
++m_currentConnections;
}
}
//----------------------------------------
ServerTrackObject *GenericAPICore::findServer(unsigned server_track)
//----------------------------------------
{
std::map<unsigned, ServerTrackObject *>::iterator iter = m_serverTracks.find(server_track);
if (iter == m_serverTracks.end())
return NULL;
ServerTrackObject *stobj = (*iter).second;
m_serverTracks.erase(server_track);
return stobj;
}
#ifdef EXTERNAL_DISTRO
};
#endif
@@ -0,0 +1,121 @@
#if !defined (GENERICAPICORE_H_)
#define GENERICAPICORE_H_
//----------------------------------------
//
// WARNING: These files are NOT standard generic API files
// They have been modified for this project.
// Do NOT replace them with generic API files
//
//----------------------------------------
#pragma warning (disable: 4786)
#include <map>
#include <queue>
#include <time.h>
#include <Base/Archive.h>
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
class GenericRequest;
class GenericResponse;
class GenericConnection;
//----------------------------------------------
class ServerTrackObject
//----------------------------------------------
{
public:
ServerTrackObject(unsigned mapped_track, unsigned real_track, GenericConnection *con);
~ServerTrackObject() { }
inline GenericConnection *getConnection() { return m_connection; }
inline unsigned getRealServerTrack() { return m_realTrack; }
inline unsigned getMappedServerTrack() { return m_mappedTrack; }
private:
unsigned m_mappedTrack;
unsigned m_realTrack;
GenericConnection *m_connection;
};
//----------------------------------------------
class GenericAPICore
//----------------------------------------------
{
public:
friend class GenericConnection;
GenericAPICore::GenericAPICore(const char *host,
short port,
unsigned reqTimeout,
unsigned reconnectTimeout,
unsigned noDataTimeoutSecs = 5,
unsigned noAckTimeoutSecs = 5,
unsigned incomingBufSizeInKB = 32,
unsigned outgoingBufSizeInKB = 32,
unsigned keepAlive = 1,
unsigned maxRecvMessageSizeInKB = 0);
/**
* NOTE: arraySize must be actual size of host and port arrays.
* ALSO: cannot specify a 0 array size.
*/
GenericAPICore(const char *game, const char *hosts[],
const short port[],
unsigned arraySize,
unsigned reqTimeout,
unsigned reconnectTimeout,
unsigned noDataTimeoutSecs = 5,
unsigned noAckTimeoutSecs = 5,
unsigned incomingBufSizeInKB = 32,
unsigned outgoingBufSizeInKB = 32,
unsigned keepAlive = 1,
unsigned maxRecvMessageSizeInKB = 0);
virtual ~GenericAPICore();
void process();
virtual void responseCallback(short type, Base::ByteStream::ReadIterator &iter, GenericConnection *con) = 0;
virtual void responseCallback(GenericResponse *R) = 0;
virtual void OnDisconnect(GenericConnection *con) = 0;
virtual void OnConnect(GenericConnection *con) = 0;
void countOpenConnections();
ServerTrackObject *findServer(unsigned server_track);
void suspendProcessing() { m_suspended = true; }
void resumeProcessing() { m_suspended = false; }
unsigned submitRequest(GenericRequest *req, GenericResponse *res);
GenericConnection *getNextActiveConnection();
std::string &getGameCode() { return m_game; }
protected:
std::vector<GenericConnection *> m_serverConnections;
std::map<unsigned, GenericResponse *> m_pending;
std::queue<std::pair<GenericRequest *, GenericResponse *> > m_outboundQueue;
unsigned m_currTrack;
time_t m_reconnectTimeout;
unsigned m_outCount;
unsigned m_pendingCount;
unsigned m_requestTimeout;
unsigned m_currentConnections; // number currently connected
unsigned m_maxConnections; // number that should be connected
std::map<unsigned, ServerTrackObject *> m_serverTracks;
private:
bool m_suspended;
unsigned m_nextConnectionIndex;
std::string m_game;
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif
@@ -0,0 +1,209 @@
#include "GenericApiCore.h"
#include "GenericConnection.h"
#include "GenericMessage.h"
#include "CTCommon/CTEnum.h"
//----------------------------------------
//
// WARNING: These files are NOT standard generic API files
// They have been modified for this project.
// Do NOT replace them with generic API files
//
//----------------------------------------
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
using namespace std;
using namespace Base;
GenericConnection::GenericConnection(const char *host, short port, GenericAPICore *apiCore, unsigned reconnectTimeout, unsigned noDataTimeoutSecs, unsigned noAckTimeoutSecs, unsigned incomingBufSizeInKB, unsigned outgoingBufSizeInKB, unsigned keepAlive, unsigned maxRecvMessageSizeInKB)
: m_bConnected(CON_NONE),
m_apiCore(apiCore),
m_con(NULL),
m_host(host),
m_port(port),
m_lastTrack(123455), //random choice != 1
m_conState(CON_DISCONNECT),
m_reconnectTimeout(reconnectTimeout)
{
TcpManager::TcpParams params;
params.incomingBufferSize = incomingBufSizeInKB * 1024;
params.outgoingBufferSize = outgoingBufSizeInKB * 1024;
params.maxConnections = 1;
params.port = 0;
params.maxRecvMessageSize = maxRecvMessageSizeInKB*1024;
params.keepAliveDelay = keepAlive * 1000;
params.noDataTimeout = noDataTimeoutSecs * 1000;
//params.oldestUnacknowledgedTimeout = noAckTimeoutSecs * 1000;
m_manager = new TcpManager(params);
}
GenericConnection::~GenericConnection()
{
if(m_con)
{
m_con->SetHandler(NULL);
m_con->Disconnect();//don't worry about onterminated being called, we've set it's handler to null, so it wont
m_con->Release();
}
m_manager->Release();
}
void GenericConnection::disconnect()
{
if (m_con)
{
m_con->Disconnect();
//no need to release, since callback to onTerminated releases it, and callback is allways made m_con->Release();
m_con = NULL;
}
m_conState = CON_DISCONNECT;
m_bConnected = CON_NONE;
}
void GenericConnection::OnTerminated(TcpConnection *con)
{
// m_apiCore->OnDisconnect(m_host.c_str(), m_port);
m_apiCore->OnDisconnect(this);
if(m_con)
{
m_con->Release();
m_con = NULL;
}
m_conState = CON_DISCONNECT;
m_bConnected = CON_NONE;
}
void GenericConnection::OnRoutePacket(TcpConnection *con, const unsigned char *data, int dataLen)
{
short type;
unsigned track;
ByteStream msg(data, dataLen);
ByteStream::ReadIterator iter = msg.begin();
get(iter, type);
get(iter, track);
GenericResponse *res = NULL;
// the following if block is a temporary fix that prevents
// a crash with a game team in which they occasionally find
// themselves receiving a dupe track in consecutive calls to
// OnRoutePacket (which then leads to a callback being called
// twice and data being invalid on the second call -> crash!).
if (track != 0 &&
track == m_lastTrack)
{
printf("!!! ERROR !!! Got a duplicate track ID %u\n", track);
return;
}
m_lastTrack = track;
// end temporary fix.
if(track == 0) // notification message from the server, not as a response to a request from this API
{
if (type == CTService::CTGAME_REQUEST_CONNECT)
{ // this is a special case, for when we have identified our game code to server
m_bConnected = CON_IDENTIFIED;
m_apiCore->OnConnect(this);
}
else
{
m_apiCore->responseCallback(type, iter, this);
}
}
else
{
map<unsigned, GenericResponse *>::iterator mapIter = m_apiCore->m_pending.find(track);
if(mapIter != m_apiCore->m_pending.end())
{
res = (*mapIter).second;
iter = msg.begin();
res->unpack(iter);
m_apiCore->responseCallback(res);
m_apiCore->m_pendingCount--;
m_apiCore->m_pending.erase(mapIter);
delete res;
}
}
}
void GenericConnection::process()
{
switch(m_conState)
{
case CON_DISCONNECT:
// create connection object, attempting to connect and
// checking for connection in next state, CON_NEGOTIATE
m_con = m_manager->EstablishConnection(m_host.c_str(), m_port);
if(m_con)
{
m_con->SetHandler(this);
m_conState = CON_NEGOTIATE;
m_conTimeout = time(NULL) + m_reconnectTimeout;
}
break;
case CON_NEGOTIATE:
// check for connection
if(m_con->GetStatus() == TcpConnection::StatusConnected)
{
// we're connected
m_conState = CON_CONNECT;
m_bConnected = CON_CONNECTED;
// instead of calling OnConnect() right now, we are going to submit a connection packet
// identifying us
// m_apiCore->OnConnect(this);
Base::ByteStream msg;
put(msg, (short)CTService::CTGAME_REQUEST_CONNECT);
put(msg, (unsigned)0); // track
put(msg, (unsigned)API_VERSION_CODE);
put(msg, m_apiCore->getGameCode());
Send(msg);
}
else if(time(NULL) > m_conTimeout)
{
// we did not connect
m_con->Disconnect();
//no need to release, since callback to onTerminated releases it, and callback is allways made m_con->Release();
m_con = NULL;
m_conState = CON_DISCONNECT;
m_bConnected = CON_NONE;
}
break;
case CON_CONNECT:
// do nothing
break;
default:
// this should not occur, but we revert to CON_DISCONNECT if it does
m_conState = CON_DISCONNECT;
m_bConnected = CON_NONE;
if (m_con)
{
m_con->Disconnect();
//no need to release, since callback to onTerminated releases it, and callback is allways made m_con->Release();
m_con = NULL;
}
}
m_manager->GiveTime();
}
void GenericConnection::Send(Base::ByteStream &msg)
{
if(m_con && m_con->GetStatus() == TcpConnection::StatusConnected)
{
m_con->Send((const char *)msg.getBuffer(), msg.getSize());
}
}
#ifdef EXTERNAL_DISTRO
};
#endif
@@ -0,0 +1,81 @@
#if !defined (GENERICCONNECTION_H_)
#define GENERICCONNECTION_H_
//----------------------------------------
//
// WARNING: These files are NOT standard generic API files
// They have been modified for this project.
// Do NOT replace them with generic API files
//
//----------------------------------------
#include <Base/Archive.h>
#include <TcpLibrary/TcpManager.h>
#include <TcpLibrary/TcpConnection.h>
#include <TcpLibrary/TcpHandlers.h>
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
static const unsigned API_VERSION_CODE = 1;
enum eConState
{
CON_DISCONNECT,
CON_NEGOTIATE,
CON_CONNECT
};
enum eConnectStatus
{
CON_NONE,
CON_CONNECTED,
CON_IDENTIFIED
};
class GenericConnection : public TcpConnectionHandler
{
public:
GenericConnection(const char *host,
short port,
GenericAPICore *apiCore,
unsigned reconnectTimeout,
unsigned noDataTimeoutSecs = 5,
unsigned noAckTimeoutSecs = 5,
unsigned incomingBufSizeInKB = 32,
unsigned outgoingBufSizeInKB = 32,
unsigned keepAlive = 1,
unsigned maxRecvMessageSizeInKB = 0);
virtual ~GenericConnection();
virtual void OnRoutePacket(TcpConnection *con, const unsigned char *data, int dataLen);
virtual void OnTerminated(TcpConnection *con);
void Send(Base::ByteStream &msg);
inline const char *getHost() const { return m_host.c_str(); }
inline const short getPort() const { return m_port; }
inline eConnectStatus isConnected() { return m_bConnected; }
void disconnect();
void process();
private:
eConnectStatus m_bConnected;
GenericAPICore *m_apiCore;
TcpManager *m_manager;
TcpConnection *m_con;
std::string m_host;
short m_port;
unsigned m_lastTrack;
eConState m_conState;
time_t m_conTimeout;
unsigned m_reconnectTimeout;
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif
@@ -0,0 +1,44 @@
#include "GenericMessage.h"
//----------------------------------------
//
// WARNING: These files are NOT standard generic API files
// They have been modified for this project.
// Do NOT replace them with generic API files
//
//----------------------------------------
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
using namespace Base;
//-------------------------------------------
GenericRequest::GenericRequest(short type, unsigned server_track)
: m_type(type), m_server_track(server_track)
//-------------------------------------------
{
}
//-------------------------------------------
GenericResponse::GenericResponse(short type, unsigned result, void *user)
: m_type(type), m_result(result), m_user(user)
//-------------------------------------------
{
}
//-----------------------------------------
void GenericResponse::unpack(ByteStream::ReadIterator &iter)
//-----------------------------------------
{
get(iter, m_type);
get(iter, m_track);
get(iter, m_result);
}
#ifdef EXTERNAL_DISTRO
};
#endif
@@ -0,0 +1,75 @@
#if !defined (GENERICMESSAGE_H_)
#define GENERICMESSAGE_H_
//----------------------------------------
//
// WARNING: These files are NOT standard generic API files
// They have been modified for this project.
// Do NOT replace them with generic API files
//
//----------------------------------------
#include <time.h>
#include <Base/Archive.h>
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
//-------------------------------------------
class GenericRequest
//-------------------------------------------
{
public:
GenericRequest(short type, unsigned server_track = 0);
virtual ~GenericRequest() {};
virtual void pack(Base::ByteStream &msg) = 0;
short getType() const { return m_type; }
void setTimeout(time_t t) { m_timeout = t; }
time_t getTimeout() { return m_timeout; }
void setTrack(unsigned t) { m_track = t; }
unsigned getTrack() const { return m_track; }
inline const unsigned getMappedServerTrack() const { return m_server_track; }
inline void setServerTrack(unsigned track) { m_server_track = track; }
protected:
short m_type;
unsigned m_track;
time_t m_timeout;
unsigned m_server_track;
};
// Basic response message from server. In the case that this response to a request
// submitted from this API, the response would have been generated at request submission
// time, and the timeout value filled in appropriatly
//-------------------------------------------
class GenericResponse
//-------------------------------------------
{
public:
GenericResponse(short type, unsigned result, void *user);
virtual ~GenericResponse() {};
virtual void unpack(Base::ByteStream::ReadIterator &iter);
short getType() const { return m_type; }
void setTimeout(time_t t) { m_timeout = t; }
time_t getTimeout() { return m_timeout; }
void setTrack(unsigned t) { m_track = t; }
unsigned getTrack() const { return m_track; }
unsigned getResult() const { return m_result; }
void setResult(unsigned res) { m_result = res; }
void * getUser() const { return m_user; }
protected:
short m_type;
unsigned m_track;
unsigned m_result;
void *m_user;
time_t m_timeout;
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif
@@ -0,0 +1,187 @@
#pragma warning (disable : 4786)
//test
#include <string.h>
#include "CTServiceAPI.h"
#include "CTServiceAPICore.h"
#include "Request.h"
#include "Response.h"
const unsigned short EMPTY_STRING[1] = { 0 };
const char * DEFAULT_GAMECODE = "ZZZ";
const char * DEFAULT_HOST = "ctservice.station.sony.com";
const unsigned short DEFAULT_PORT = 2000;
namespace CTService
{
using namespace Base;
//-----------------------------------------------
CTServiceAPI::CTServiceAPI(const char *hostName, const char *game)
//-----------------------------------------------
{
std::vector<const char *> hostArray;
std::vector<short> portArray;
char hostConfig[4096];
if (hostName == NULL)
hostName = DEFAULT_HOST;
if (!game)
game = DEFAULT_GAMECODE;
strncpy(hostConfig, hostName, 4096); hostConfig[4095] = 0;
if (char * ptr = strtok(hostConfig, " "))
{
do
{
char * host = ptr;
char * portStr = strchr(host, ':');
unsigned short port = DEFAULT_PORT;
if (portStr)
{
*portStr++ = 0;
port = atoi(portStr);
}
if (::strlen(host) && port)
{
hostArray.push_back(host);
portArray.push_back(port);
}
}
while ((ptr = strtok(NULL, " ")) != NULL);
}
if (hostArray.empty())
{
hostArray.push_back(DEFAULT_HOST);
portArray.push_back(DEFAULT_PORT);
}
m_apiCore = new CTServiceAPICore(&hostArray[0], &portArray[0], hostArray.size(), this, game);
}
//-----------------------------------------------
CTServiceAPI::~CTServiceAPI()
//-----------------------------------------------
{
delete m_apiCore;
}
//-----------------------------------------------
void CTServiceAPI::process()
//-----------------------------------------------
{
m_apiCore->process();
}
//-----------------------------------------------
//
// Add requests and replies here
//
//-----------------------------------------------
/*
//----------- TEST CODE ONLY ------------
//-----------------------------------------------
unsigned CTServiceAPI::requestTest(const char *astring, const unsigned anint, void *user)
//-----------------------------------------------
{
std::string s_astring = astring;
ReqTest *req = new ReqTest(s_astring, anint);
return (m_apiCore->submitRequest(req, new ResTest(user)));
}
//-----------------------------------------------
unsigned CTServiceAPI::replyTest(const unsigned server_track, const unsigned value, void *user)
//-----------------------------------------------
{
ReqReplyTest *req = new ReqReplyTest(server_track, value);
return (m_apiCore->submitRequest(req, new ResReplyTest(user)));
}
//----------- TEST CODE ONLY ------------
*/
//-----------------------------------------------
unsigned CTServiceAPI::replyMoveStatus(const unsigned server_track, const unsigned status, const unsigned result, const CTUnicodeChar *reason, void *user)
//-----------------------------------------------
{
if (!reason)
reason = EMPTY_STRING;
ReqReplyMoveStatus *req = new ReqReplyMoveStatus(server_track, status, result, reason);
return (m_apiCore->submitRequest(req, new ResReplyMoveStatus(user)));
}
//-----------------------------------------------
unsigned CTServiceAPI::replyValidateMove(const unsigned server_track, const unsigned result, const CTUnicodeChar *reason, const CTUnicodeChar *suggestedName, void *user)
//-----------------------------------------------
{
if (!reason)
reason = EMPTY_STRING;
if (!suggestedName)
suggestedName = EMPTY_STRING;
ReqReplyValidateMove *req = new ReqReplyValidateMove(server_track, result, reason, suggestedName);
return (m_apiCore->submitRequest(req, new ResReplyValidateMove(user)));
}
//-----------------------------------------------
unsigned CTServiceAPI::replyMove(const unsigned server_track, const unsigned result, const CTUnicodeChar *reason, void *user)
//-----------------------------------------------
{
if (!reason)
reason = EMPTY_STRING;
ReqReplyMove *req = new ReqReplyMove(server_track, result, reason);
return (m_apiCore->submitRequest(req, new ResReplyMove(user)));
}
//-----------------------------------------------
unsigned CTServiceAPI::replyDelete(const unsigned server_track, const unsigned result, const CTUnicodeChar *reason, void *user)
//-----------------------------------------------
{
if (!reason)
reason = EMPTY_STRING;
ReqReplyDelete *req = new ReqReplyDelete(server_track, result, reason);
return (m_apiCore->submitRequest(req, new ResReplyDelete(user)));
}
//-----------------------------------------------
unsigned CTServiceAPI::replyRestore(const unsigned server_track, const unsigned result, const CTUnicodeChar *reason, void *user)
//-----------------------------------------------
{
if (!reason)
reason = EMPTY_STRING;
ReqReplyRestore *req = new ReqReplyRestore(server_track, result, reason);
return (m_apiCore->submitRequest(req, new ResReplyRestore(user)));
}
//-----------------------------------------------
unsigned CTServiceAPI::replyTransferAccount(const unsigned server_track, const unsigned result, const CTUnicodeChar *reason, void *user)
//-----------------------------------------------
{
if (!reason)
reason = EMPTY_STRING;
ReqReplyTransferAccount *req = new ReqReplyTransferAccount(server_track, result, reason);
return (m_apiCore->submitRequest(req, new ResReplyTransferAccount(user)));
}
//-----------------------------------------------
unsigned CTServiceAPI::replyCharacterList(const unsigned server_track, const unsigned result, const unsigned count, const CTServiceCharacter *characters, void *user)
//-----------------------------------------------
{
ReqReplyCharacterList *req = new ReqReplyCharacterList(server_track, result, count, characters);
return (m_apiCore->submitRequest(req, new ResReplyCharacterList(user)));
}
//-----------------------------------------------
unsigned CTServiceAPI::replyServerList(const unsigned server_track, const unsigned result, const unsigned count, const CTServiceServer *servers, void *user)
//-----------------------------------------------
{
ReqReplyServerList *req = new ReqReplyServerList(server_track, result, count, servers);
return (m_apiCore->submitRequest(req, new ResReplyServerList(user)));
}
//-----------------------------------------------
unsigned CTServiceAPI::replyDestinationServerList(const unsigned server_track, const unsigned result, const unsigned count, const CTServiceServer *servers, void *user)
//-----------------------------------------------
{
ReqReplyDestinationServerList *req = new ReqReplyDestinationServerList(server_track, result, count, servers);
return (m_apiCore->submitRequest(req, new ResReplyDestinationServerList(user)));
}
}; // namespace
@@ -0,0 +1,112 @@
#ifndef CTSERVICEAPI_H
#define CTSERVICEAPI_H
#pragma warning (disable : 4786)
#include "CTCommon/CTServiceCharacter.h"
#include "CTCommon/CTServiceServer.h"
#include "CTCommon/CTEnum.h"
namespace CTService
{
class CTServiceAPICore;
typedef unsigned short CTUnicodeChar;
//--------------------------------------
class CTServiceAPI
//--------------------------------------
{
public:
CTServiceAPI(const char *hostName, const char *game); // hostName: "addr1:port1 addr2:port2"
virtual ~CTServiceAPI();
virtual void onConnect(const char *host, const short port, const short current, const short max) = 0;
virtual void onDisconnect(const char *host, const short port, const short current, const short max) = 0;
void process();
// ----- Requests generated by API -----
// unsigned requestTest(const char *astring, const unsigned anint, void *user);
// unsigned replyTest(const unsigned server_track, const unsigned value, void *user);
unsigned replyMoveStatus(const unsigned server_track, const unsigned status, const unsigned result, const CTUnicodeChar *reason, void *user);
unsigned replyValidateMove(const unsigned server_track, const unsigned result, const CTUnicodeChar *reason, const CTUnicodeChar *suggestedName, void *user);
unsigned replyMove(const unsigned server_track, const unsigned result, const CTUnicodeChar *reason, void *user);
unsigned replyCharacterList(const unsigned server_track, const unsigned result, const unsigned count, const CTServiceCharacter *characters, void *user);
unsigned replyServerList(const unsigned server_track, const unsigned result, const unsigned count, const CTServiceServer *servers, void *user);
unsigned replyDestinationServerList(const unsigned server_track, const unsigned result, const unsigned count, const CTServiceServer *servers, void *user);
unsigned replyDelete(const unsigned server_track, const unsigned result, const CTUnicodeChar *reason, void *user);
unsigned replyRestore(const unsigned server_track, const unsigned result, const CTUnicodeChar *reason, void *user);
unsigned replyTransferAccount(const unsigned server_track, const unsigned result, const CTUnicodeChar *reason, void *user);
// ----- Normal Callbacks as a response to requests sent -----
// virtual void onTest(const unsigned track, const int resultCode, const unsigned value, void *user) = 0;
// virtual void onReplyTest(const unsigned track, const int resultCode, void *user) = 0;
virtual void onReplyMoveStatus(const unsigned track, const int resultCode, void *user) = 0;
virtual void onReplyValidateMove(const unsigned track, const int resultCode, void *user) = 0;
virtual void onReplyMove(const unsigned track, const int resultCode, void *user) = 0;
virtual void onReplyDelete(const unsigned track, const int resultCode, void *user) = 0;
virtual void onReplyRestore(const unsigned track, const int resultCode, void *user) = 0;
virtual void onReplyTransferAccount(const unsigned track, const int resultCode, void *user) = 0;
virtual void onReplyCharacterList(const unsigned track, const int resultCode, void *user) = 0;
virtual void onReplyServerList(const unsigned track, const int resultCode, void *user) = 0;
virtual void onReplyDestinationServerList(const unsigned track, const int resultCode, void *user) = 0;
// ----- Callbacks generated by the server directly -----
virtual void onServerTest(const unsigned server_track, const char *game, const char *param) = 0;
virtual void onRequestMoveStatus(const unsigned server_track, const char *language,
const unsigned transactionID) = 0;
virtual void onRequestValidateMove(const unsigned server_track, const char *language,
const CTUnicodeChar *sourceServer,
const CTUnicodeChar *destServer,
const CTUnicodeChar *sourceCharacter,
const CTUnicodeChar *destCharacter, const unsigned uid,
const unsigned destuid, bool withItems, bool override) = 0;
virtual void onRequestMove(const unsigned server_track, const char *language,
const CTUnicodeChar *sourceServer,
const CTUnicodeChar *destServer,
const CTUnicodeChar *sourceCharacter,
const CTUnicodeChar *destCharacter, const unsigned uid,
const unsigned destuid, const unsigned transactionID,
bool withItems,
bool override) = 0;
virtual void onRequestDelete(const unsigned server_track, const char *language,
const CTUnicodeChar *sourceServer,
const CTUnicodeChar *destServer,
const CTUnicodeChar *sourceCharacter,
const CTUnicodeChar *destCharacter, const unsigned uid,
const unsigned destuid, const unsigned transactionID,
bool withItems,
bool override) = 0;
virtual void onRequestRestore(const unsigned server_track, const char *language,
const CTUnicodeChar *sourceServer,
const CTUnicodeChar *destServer,
const CTUnicodeChar *sourceCharacter,
const CTUnicodeChar *destCharacter, const unsigned uid,
const unsigned destuid, const unsigned transactionID,
bool withItems,
bool override) = 0;
virtual void onRequestTransferAccount(const unsigned server_track,
const unsigned uid,
const unsigned destuid,
const unsigned transactionID) = 0;
virtual void onRequestCharacterList(const unsigned server_track, const char *language,
const CTUnicodeChar *server, const unsigned uid) = 0;
virtual void onRequestServerList(const unsigned server_track, const char *language) = 0;
virtual void onRequestDestinationServerList(const unsigned server_track, const char *language,
const CTUnicodeChar *character, const CTUnicodeChar *server) = 0;
private:
CTServiceAPICore *m_apiCore;
};
}; // namespace
#endif //CTSERVICEAPI_H
@@ -0,0 +1,259 @@
#include "CTServiceAPICore.h"
#include "CTServiceAPI.h"
#include "Response.h"
#include <Unicode/UnicodeUtils.h>
namespace CTService
{
using namespace Base;
using namespace Plat_Unicode;
//----------------------------------------
CTServiceAPICore::CTServiceAPICore(const char *host[], const short port[], int count, CTServiceAPI *api, const char *game)
: GenericAPICore(game, host, port, count, 45, 5, 0, 90, 32, 32),
m_api(api), m_mappedServerTrack(1000)
//----------------------------------------
{
}
//----------------------------------------
CTServiceAPICore::~CTServiceAPICore()
//----------------------------------------
{
}
//----------------------------------------
void CTServiceAPICore::OnConnect(GenericConnection *con)
//----------------------------------------
{
countOpenConnections();
m_api->onConnect(con->getHost(), con->getPort(), m_currentConnections, m_maxConnections);
}
//----------------------------------------
void CTServiceAPICore::OnDisconnect(GenericConnection *con)
//----------------------------------------
{
countOpenConnections();
m_api->onDisconnect(con->getHost(), con->getPort(), m_currentConnections, m_maxConnections);
}
//----------------------------------------
void CTServiceAPICore::responseCallback(short type, Base::ByteStream::ReadIterator &iter, GenericConnection *con)
// Received a request/notification from the server
//----------------------------------------
{
unsigned real_server_track;
get(iter, real_server_track);
ServerTrackObject *stobj = new ServerTrackObject(++m_mappedServerTrack, real_server_track, con);
m_serverTracks.insert(std::pair<unsigned, ServerTrackObject *>(m_mappedServerTrack, stobj));
//printf("\nMapping %d to %d", real_server_track, m_mappedServerTrack); //debug
switch (type)
{
case CTGAME_SERVER_TEST:
{
std::string game, param;
get(iter, game);
get(iter, param);
m_api->onServerTest(m_mappedServerTrack, game.c_str(), param.c_str());
break;
}
case CTGAME_SERVER_MOVESTATUS:
{
std::string lang;
unsigned transactionID;
get(iter, lang);
get(iter, transactionID);
m_api->onRequestMoveStatus(m_mappedServerTrack, lang.c_str(), transactionID);
break;
}
case CTGAME_SERVER_VALIDATEMOVE:
{
std::string lang;
Plat_Unicode::String sourceServer, destServer, sourceCharacter, destCharacter;
unsigned UID, destUID;
bool withItems;
bool override;
get(iter, lang);
get(iter, sourceServer);
get(iter, destServer);
get(iter, sourceCharacter);
get(iter, destCharacter);
get(iter, UID);
get(iter, destUID);
get(iter, withItems);
get(iter, override);
m_api->onRequestValidateMove(m_mappedServerTrack, lang.c_str(), sourceServer.c_str(), destServer.c_str(),
sourceCharacter.c_str(), destCharacter.c_str(), UID, destUID, withItems, override);
break;
}
case CTGAME_SERVER_MOVE:
{
std::string lang;
Plat_Unicode::String sourceServer, destServer, sourceCharacter, destCharacter;
unsigned UID, destUID, transactionID;
bool withItems;
bool override;
get(iter, lang);
get(iter, sourceServer);
get(iter, destServer);
get(iter, sourceCharacter);
get(iter, destCharacter);
get(iter, UID);
get(iter, destUID);
get(iter, transactionID);
get(iter, withItems);
get(iter, override);
m_api->onRequestMove(m_mappedServerTrack, lang.c_str(), sourceServer.c_str(), destServer.c_str(),
sourceCharacter.c_str(), destCharacter.c_str(), UID, destUID, transactionID, withItems, override);
break;
}
case CTGAME_SERVER_DELETE:
{
std::string lang;
Plat_Unicode::String sourceServer, destServer, sourceCharacter, destCharacter;
unsigned UID, destUID, transactionID;
bool withItems;
bool override;
get(iter, lang);
get(iter, sourceServer);
get(iter, destServer);
get(iter, sourceCharacter);
get(iter, destCharacter);
get(iter, UID);
get(iter, destUID);
get(iter, transactionID);
get(iter, withItems);
get(iter, override);
m_api->onRequestDelete(m_mappedServerTrack, lang.c_str(), sourceServer.c_str(), destServer.c_str(),
sourceCharacter.c_str(), destCharacter.c_str(), UID, destUID, transactionID, withItems, override);
break;
}
case CTGAME_SERVER_RESTORE:
{
std::string lang;
Plat_Unicode::String sourceServer, destServer, sourceCharacter, destCharacter;
unsigned UID, destUID, transactionID;
bool withItems;
bool override;
get(iter, lang);
get(iter, sourceServer);
get(iter, destServer);
get(iter, sourceCharacter);
get(iter, destCharacter);
get(iter, UID);
get(iter, destUID);
get(iter, transactionID);
get(iter, withItems);
get(iter, override);
m_api->onRequestRestore(m_mappedServerTrack, lang.c_str(), sourceServer.c_str(), destServer.c_str(),
sourceCharacter.c_str(), destCharacter.c_str(), UID, destUID, transactionID, withItems, override);
break;
}
case CTGAME_SERVER_TRANSFER_ACCOUNT:
{
unsigned UID, destUID, transactionID;
get(iter, UID);
get(iter, destUID);
get(iter, transactionID);
m_api->onRequestTransferAccount(m_mappedServerTrack, UID, destUID, transactionID);
break;
}
case CTGAME_SERVER_CHARACTERLIST:
{
std::string lang;
Plat_Unicode::String server;
unsigned uid;
get(iter, lang);
get(iter, server);
get(iter, uid);
m_api->onRequestCharacterList(m_mappedServerTrack, lang.c_str(), server.c_str(), uid);
break;
}
case CTGAME_SERVER_SERVERLIST:
{
std::string lang;
get(iter, lang);
m_api->onRequestServerList(m_mappedServerTrack, lang.c_str());
break;
}
case CTGAME_SERVER_DESTSERVERLIST:
{
std::string lang;
Plat_Unicode::String character, server;
get(iter, lang);
get(iter, character);
get(iter, server);
m_api->onRequestDestinationServerList(m_mappedServerTrack, lang.c_str(), character.c_str(), server.c_str());
break;
}
}
}
//----------------------------------------
void CTServiceAPICore::responseCallback(GenericResponse *res)
//----------------------------------------
{
switch(res->getType())
{
/*case CTGAME_REQUEST_TEST:
m_api->onTest(((ResTest *)res)->getTrack(), ((ResTest *)res)->getResult(),
((ResTest *)res)->getValue(), ((ResTest *)res)->getUser());
break;
case CTGAME_REPLY_TEST:
m_api->onReplyTest(((ResTest *)res)->getTrack(), ((ResTest *)res)->getResult(),
((ResTest *)res)->getUser());
break;*/
case CTGAME_REPLY_MOVESTATUS:
m_api->onReplyMoveStatus(((ResReplyMoveStatus *)res)->getTrack(),
((ResReplyMoveStatus *)res)->getResult(),
((ResReplyMoveStatus *)res)->getUser());
break;
case CTGAME_REPLY_VALIDATEMOVE:
m_api->onReplyValidateMove(((ResReplyValidateMove *)res)->getTrack(),
((ResReplyValidateMove *)res)->getResult(),
((ResReplyValidateMove *)res)->getUser());
break;
case CTGAME_REPLY_MOVE:
m_api->onReplyMove(((ResReplyMove *)res)->getTrack(),
((ResReplyMove *)res)->getResult(),
((ResReplyMove *)res)->getUser());
break;
case CTGAME_REPLY_DELETE:
m_api->onReplyDelete(((ResReplyDelete *)res)->getTrack(),
((ResReplyDelete *)res)->getResult(),
((ResReplyDelete *)res)->getUser());
break;
case CTGAME_REPLY_RESTORE:
m_api->onReplyRestore(((ResReplyRestore *)res)->getTrack(),
((ResReplyRestore *)res)->getResult(),
((ResReplyRestore *)res)->getUser());
break;
case CTGAME_REPLY_TRANSFER_ACCOUNT:
m_api->onReplyTransferAccount(((ResReplyTransferAccount *)res)->getTrack(),
((ResReplyTransferAccount *)res)->getResult(),
((ResReplyTransferAccount *)res)->getUser());
break;
case CTGAME_REPLY_CHARACTERLIST:
m_api->onReplyCharacterList(((ResReplyCharacterList *)res)->getTrack(),
((ResReplyCharacterList *)res)->getResult(),
((ResReplyCharacterList *)res)->getUser());
break;
case CTGAME_REPLY_SERVERLIST:
m_api->onReplyServerList(((ResReplyServerList *)res)->getTrack(),
((ResReplyServerList *)res)->getResult(),
((ResReplyServerList *)res)->getUser());
break;
case CTGAME_REPLY_DESTSERVERLIST:
m_api->onReplyDestinationServerList(((ResReplyDestinationServerList *)res)->getTrack(),
((ResReplyDestinationServerList *)res)->getResult(),
((ResReplyDestinationServerList *)res)->getUser());
break;
default:
break;
}
}
}; // namespace
@@ -0,0 +1,39 @@
#ifndef APICORE_H
#define APICORE_H
#pragma warning (disable : 4786)
#include "CTGenericAPI/GenericApiCore.h"
#include "CTGenericAPI/GenericConnection.h"
#include <Base/Archive.h>
namespace CTService
{
class CTServiceAPI;
//---------------------------------------------------
class CTServiceAPICore : public GenericAPICore
//---------------------------------------------------
{
public:
CTServiceAPICore(const char *hostName[], const short port[], int count, CTServiceAPI *api, const char *game);
virtual ~CTServiceAPICore();
void OnConnect(GenericConnection *con);
void OnDisconnect(GenericConnection *con);
void responseCallback(GenericResponse *res);
void responseCallback(short type, Base::ByteStream::ReadIterator &iter, GenericConnection *con);
private:
CTServiceAPI *m_api;
unsigned m_mappedServerTrack;
};
}; // namespace
#endif //APICORE_H
@@ -0,0 +1,243 @@
#include "Request.h"
#include "CTCommon/CTServiceObjects.h"
namespace CTService
{
using namespace Base;
using namespace Plat_Unicode;
/*
//----------- TEST CODE ONLY ------------
//-----------------------------------------
ReqTest::ReqTest(std::string &astring, unsigned anint)
: GenericRequest(CTGAME_REQUEST_TEST),
m_astring(astring), m_anint(anint)
//-----------------------------------------
{
}
//-----------------------------------------
void ReqTest::pack(Base::ByteStream &msg)
//-----------------------------------------
{
put(msg, m_type);
put(msg, m_track);
put(msg, m_astring);
put(msg, m_anint);
}
//-----------------------------------------
ReqReplyTest::ReqReplyTest(unsigned server_track, unsigned value)
: GenericRequest(CTGAME_REPLY_TEST, server_track),
m_value(value)
//-----------------------------------------
{
}
//-----------------------------------------
void ReqReplyTest::pack(Base::ByteStream &msg)
//-----------------------------------------
{
put(msg, m_type);
put(msg, m_track);
put(msg, m_server_track);
put(msg, m_value);
}
//----------- TEST CODE ONLY ------------
*/
//-----------------------------------------
ReqReplyMoveStatus::ReqReplyMoveStatus(unsigned server_track, const unsigned status, const unsigned result, const CTUnicodeChar *reason)
: GenericRequest(CTGAME_REPLY_MOVESTATUS, server_track),
m_status(status), m_result(result), m_reason(reason)
//-----------------------------------------
{
}
//-----------------------------------------
void ReqReplyMoveStatus::pack(Base::ByteStream &msg)
//-----------------------------------------
{
put(msg, m_type);
put(msg, m_track);
put(msg, m_server_track);
put(msg, m_status);
put(msg, m_result);
put(msg, m_reason);
}
//-----------------------------------------
ReqReplyValidateMove::ReqReplyValidateMove(unsigned server_track, const unsigned result, const CTUnicodeChar *reason, const CTUnicodeChar *suggestedName)
: GenericRequest(CTGAME_REPLY_VALIDATEMOVE, server_track),
m_result(result), m_reason(reason), m_suggestedName(suggestedName)
//-----------------------------------------
{
}
//-----------------------------------------
void ReqReplyValidateMove::pack(Base::ByteStream &msg)
//-----------------------------------------
{
put(msg, m_type);
put(msg, m_track);
put(msg, m_server_track);
put(msg, m_result);
put(msg, m_reason);
put(msg, m_suggestedName);
}
//-----------------------------------------
ReqReplyMove::ReqReplyMove(unsigned server_track, const unsigned result, const CTUnicodeChar *reason)
: GenericRequest(CTGAME_REPLY_MOVE, server_track),
m_result(result), m_reason(reason)
//-----------------------------------------
{
}
//-----------------------------------------
void ReqReplyMove::pack(Base::ByteStream &msg)
//-----------------------------------------
{
put(msg, m_type);
put(msg, m_track);
put(msg, m_server_track);
put(msg, m_result);
put(msg, m_reason);
}
//-----------------------------------------
ReqReplyDelete::ReqReplyDelete(unsigned server_track, const unsigned result, const CTUnicodeChar *reason)
: GenericRequest(CTGAME_REPLY_DELETE, server_track),
m_result(result), m_reason(reason)
//-----------------------------------------
{
}
//-----------------------------------------
void ReqReplyDelete::pack(Base::ByteStream &msg)
//-----------------------------------------
{
put(msg, m_type);
put(msg, m_track);
put(msg, m_server_track);
put(msg, m_result);
put(msg, m_reason);
}
//-----------------------------------------
ReqReplyRestore::ReqReplyRestore(unsigned server_track, const unsigned result, const CTUnicodeChar *reason)
: GenericRequest(CTGAME_REPLY_RESTORE, server_track),
m_result(result), m_reason(reason)
//-----------------------------------------
{
}
//-----------------------------------------
void ReqReplyRestore::pack(Base::ByteStream &msg)
//-----------------------------------------
{
put(msg, m_type);
put(msg, m_track);
put(msg, m_server_track);
put(msg, m_result);
put(msg, m_reason);
}
//-----------------------------------------
ReqReplyTransferAccount::ReqReplyTransferAccount(unsigned server_track, const unsigned result, const CTUnicodeChar *reason)
: GenericRequest(CTGAME_REPLY_TRANSFER_ACCOUNT, server_track),
m_result(result), m_reason(reason)
//-----------------------------------------
{
}
//-----------------------------------------
void ReqReplyTransferAccount::pack(Base::ByteStream &msg)
//-----------------------------------------
{
put(msg, m_type);
put(msg, m_track);
put(msg, m_server_track);
put(msg, m_result);
put(msg, m_reason);
}
//-----------------------------------------
ReqReplyCharacterList::ReqReplyCharacterList(unsigned server_track, const unsigned result, const unsigned count, const CTServiceCharacter *characters)
: GenericRequest(CTGAME_REPLY_CHARACTERLIST, server_track),
m_result(result), m_count(count)
//-----------------------------------------
{
for (unsigned i=0; i < count; i++)
{
m_characterArray.push_back(characters[i]);
}
}
//-----------------------------------------
void ReqReplyCharacterList::pack(Base::ByteStream &msg)
//-----------------------------------------
{
put(msg, m_type);
put(msg, m_track);
put(msg, m_server_track);
put(msg, m_result);
put(msg, m_count);
for (unsigned i=0; i < m_count; i++)
put(msg, m_characterArray[i]);
printf("\nReqReplyCharacterList::pack: m_track(%d) m_server_track(%d)\n", m_track, m_server_track);
}
//-----------------------------------------
ReqReplyServerList::ReqReplyServerList(unsigned server_track, const unsigned result, const unsigned count, const CTServiceServer *servers)
: GenericRequest(CTGAME_REPLY_SERVERLIST, server_track),
m_result(result), m_count(count)
//-----------------------------------------
{
for (unsigned i=0; i < count; i++)
{
m_serverArray.push_back(servers[i]);
}
}
//-----------------------------------------
void ReqReplyServerList::pack(Base::ByteStream &msg)
//-----------------------------------------
{
put(msg, m_type);
put(msg, m_track);
put(msg, m_server_track);
put(msg, m_result);
put(msg, m_count);
for (unsigned i=0; i < m_count; i++)
put(msg, m_serverArray[i]);
}
//-----------------------------------------
ReqReplyDestinationServerList::ReqReplyDestinationServerList(unsigned server_track, const unsigned result, const unsigned count, const CTServiceServer *servers)
: GenericRequest(CTGAME_REPLY_DESTSERVERLIST, server_track),
m_result(result), m_count(count)
//-----------------------------------------
{
for (unsigned i=0; i < count; i++)
{
m_serverArray.push_back(servers[i]);
}
}
//-----------------------------------------
void ReqReplyDestinationServerList::pack(Base::ByteStream &msg)
//-----------------------------------------
{
put(msg, m_type);
put(msg, m_track);
put(msg, m_server_track);
put(msg, m_result);
put(msg, m_count);
for (unsigned i=0; i < m_count; i++)
put(msg, m_serverArray[i]);
}
}; // namespace
@@ -0,0 +1,193 @@
#if !defined (REQUEST_H_)
#define REQUEST_H_
#pragma warning (disable : 4786)
#include "CTGenericAPI/GenericMessage.h"
#include <Base/Archive.h>
#include <Unicode/UnicodeUtils.h>
#include "CTServiceAPI.h"
namespace CTService
{
/*
//----------- TEST CODE ONLY ------------
//-----------------------------------------
class ReqTest : public GenericRequest
//-----------------------------------------
{
public:
ReqTest(std::string &astring, unsigned anint);
virtual ~ReqTest() {};
void pack(Base::ByteStream &msg);
private:
std::string m_astring;
unsigned m_anint;
};
//-----------------------------------------
class ReqReplyTest : public GenericRequest
//-----------------------------------------
{
public:
ReqReplyTest(unsigned server_track, unsigned value);
virtual ~ReqReplyTest() {};
void pack(Base::ByteStream &msg);
private:
unsigned m_value;
};
//----------- TEST CODE ONLY ------------
*/
//-----------------------------------------
class ReqReplyMoveStatus : public GenericRequest
//-----------------------------------------
{
public:
ReqReplyMoveStatus(unsigned server_track, const unsigned status, const unsigned result, const CTUnicodeChar *reason);
virtual ~ReqReplyMoveStatus() {};
void pack(Base::ByteStream &msg);
private:
unsigned m_status;
unsigned m_result;
Plat_Unicode::String m_reason;
};
//-----------------------------------------
class ReqReplyValidateMove : public GenericRequest
//-----------------------------------------
{
public:
ReqReplyValidateMove(unsigned server_track, const unsigned result, const CTUnicodeChar *reason, const CTUnicodeChar *suggestedName);
virtual ~ReqReplyValidateMove() {};
void pack(Base::ByteStream &msg);
private:
unsigned m_result;
Plat_Unicode::String m_reason;
Plat_Unicode::String m_suggestedName;
};
//-----------------------------------------
class ReqReplyMove : public GenericRequest
//-----------------------------------------
{
public:
ReqReplyMove(unsigned server_track, const unsigned result, const CTUnicodeChar *reason);
virtual ~ReqReplyMove() {};
void pack(Base::ByteStream &msg);
private:
unsigned m_result;
Plat_Unicode::String m_reason;
};
//-----------------------------------------
class ReqReplyDelete : public GenericRequest
//-----------------------------------------
{
public:
ReqReplyDelete(unsigned server_track, const unsigned result, const CTUnicodeChar *reason);
virtual ~ReqReplyDelete() {};
void pack(Base::ByteStream &msg);
private:
unsigned m_result;
Plat_Unicode::String m_reason;
};
//-----------------------------------------
class ReqReplyRestore : public GenericRequest
//-----------------------------------------
{
public:
ReqReplyRestore(unsigned server_track, const unsigned result, const CTUnicodeChar *reason);
virtual ~ReqReplyRestore() {};
void pack(Base::ByteStream &msg);
private:
unsigned m_result;
Plat_Unicode::String m_reason;
};
//-----------------------------------------
class ReqReplyTransferAccount : public GenericRequest
//-----------------------------------------
{
public:
ReqReplyTransferAccount(unsigned server_track, const unsigned result, const CTUnicodeChar *reason);
virtual ~ReqReplyTransferAccount() {};
void pack(Base::ByteStream &msg);
private:
unsigned m_result;
Plat_Unicode::String m_reason;
};
//-----------------------------------------
class ReqReplyCharacterList : public GenericRequest
//-----------------------------------------
{
public:
ReqReplyCharacterList(unsigned server_track, const unsigned result, const unsigned count, const CTServiceCharacter *characters);
virtual ~ReqReplyCharacterList() {};
void pack(Base::ByteStream &msg);
private:
unsigned m_result;
unsigned m_count;
std::vector<CTServiceCharacter> m_characterArray;
};
//-----------------------------------------
class ReqReplyServerList : public GenericRequest
//-----------------------------------------
{
public:
ReqReplyServerList(unsigned server_track, const unsigned result, const unsigned count, const CTServiceServer *servers);
virtual ~ReqReplyServerList() {};
void pack(Base::ByteStream &msg);
private:
unsigned m_result;
unsigned m_count;
std::vector<CTServiceServer> m_serverArray;
};
//-----------------------------------------
class ReqReplyDestinationServerList : public GenericRequest
//-----------------------------------------
{
public:
ReqReplyDestinationServerList(unsigned server_track, const unsigned result, const unsigned count, const CTServiceServer *servers);
virtual ~ReqReplyDestinationServerList() {};
void pack(Base::ByteStream &msg);
private:
unsigned m_result;
unsigned m_count;
std::vector<CTServiceServer> m_serverArray;
};
}; // namespace
#endif
@@ -0,0 +1,100 @@
#include "Response.h"
namespace CTService
{
using namespace Base;
/*
//----------- TEST CODE ONLY ------------
//-----------------------------------------
ResTest::ResTest(void *user)
: GenericResponse(CTGAME_REQUEST_TEST, CT_RESULT_TIMEOUT, user),
m_value(0)
//-----------------------------------------
{
}
//-----------------------------------------
void ResTest::unpack(ByteStream::ReadIterator &iter)
//-----------------------------------------
{
get(iter, m_type);
get(iter, m_track);
get(iter, m_result);
get(iter, m_value);
}
//-----------------------------------------
ResReplyTest::ResReplyTest(void *user)
: GenericResponse(CTGAME_REPLY_TEST, CT_RESULT_TIMEOUT, user)
//-----------------------------------------
{
}
//----------- TEST CODE ONLY ------------
*/
//-----------------------------------------
ResReplyMoveStatus::ResReplyMoveStatus(void *user)
: GenericResponse(CTGAME_REPLY_MOVESTATUS, CT_RESULT_TIMEOUT, user)
//-----------------------------------------
{
}
//-----------------------------------------
ResReplyValidateMove::ResReplyValidateMove(void *user)
: GenericResponse(CTGAME_REPLY_VALIDATEMOVE, CT_RESULT_TIMEOUT, user)
//-----------------------------------------
{
}
//-----------------------------------------
ResReplyMove::ResReplyMove(void *user)
: GenericResponse(CTGAME_REPLY_MOVE, CT_RESULT_TIMEOUT, user)
//-----------------------------------------
{
}
//-----------------------------------------
ResReplyDelete::ResReplyDelete(void *user)
: GenericResponse(CTGAME_REPLY_DELETE, CT_RESULT_TIMEOUT, user)
//-----------------------------------------
{
}
//-----------------------------------------
ResReplyRestore::ResReplyRestore(void *user)
: GenericResponse(CTGAME_REPLY_RESTORE, CT_RESULT_TIMEOUT, user)
//-----------------------------------------
{
}
//-----------------------------------------
ResReplyTransferAccount::ResReplyTransferAccount(void *user)
: GenericResponse(CTGAME_REPLY_TRANSFER_ACCOUNT, CT_RESULT_TIMEOUT, user)
//-----------------------------------------
{
}
//-----------------------------------------
ResReplyCharacterList::ResReplyCharacterList(void *user)
: GenericResponse(CTGAME_REPLY_CHARACTERLIST, CT_RESULT_TIMEOUT, user)
//-----------------------------------------
{
}
//-----------------------------------------
ResReplyServerList::ResReplyServerList(void *user)
: GenericResponse(CTGAME_REPLY_SERVERLIST, CT_RESULT_TIMEOUT, user)
//-----------------------------------------
{
}
//-----------------------------------------
ResReplyDestinationServerList::ResReplyDestinationServerList(void *user)
: GenericResponse(CTGAME_REPLY_DESTSERVERLIST, CT_RESULT_TIMEOUT, user)
//-----------------------------------------
{
}
}; // namespace
@@ -0,0 +1,150 @@
#if !defined (RESPONSE_H_)
#define RESPONSE_H_
#pragma warning (disable : 4786)
#include "CTGenericAPI/GenericMessage.h"
#include <Base/Archive.h>
#include "CTCommon/RequestStrings.h"
namespace CTService
{
//----------- TEST CODE ONLY ------------
//-----------------------------------------
class ResTest : public GenericResponse
//-----------------------------------------
{
public:
ResTest(void *user);
virtual ~ResTest() {}
void unpack(Base::ByteStream::ReadIterator &iter);
inline unsigned getValue() { return m_value; }
private:
unsigned m_value;
};
//-----------------------------------------
class ResReplyTest : public GenericResponse
//-----------------------------------------
{
public:
ResReplyTest(void *user);
virtual ~ResReplyTest() {}
private:
};
//----------- TEST CODE ONLY ------------
//-----------------------------------------
class ResReplyMoveStatus : public GenericResponse
//-----------------------------------------
{
public:
ResReplyMoveStatus(void *user);
virtual ~ResReplyMoveStatus() {}
private:
};
//-----------------------------------------
class ResReplyValidateMove : public GenericResponse
//-----------------------------------------
{
public:
ResReplyValidateMove(void *user);
virtual ~ResReplyValidateMove() {}
private:
};
//-----------------------------------------
class ResReplyMove : public GenericResponse
//-----------------------------------------
{
public:
ResReplyMove(void *user);
virtual ~ResReplyMove() {}
private:
};
//-----------------------------------------
class ResReplyDelete : public GenericResponse
//-----------------------------------------
{
public:
ResReplyDelete(void *user);
virtual ~ResReplyDelete() {}
private:
};
//-----------------------------------------
class ResReplyRestore : public GenericResponse
//-----------------------------------------
{
public:
ResReplyRestore(void *user);
virtual ~ResReplyRestore() {}
private:
};
//-----------------------------------------
class ResReplyTransferAccount : public GenericResponse
//-----------------------------------------
{
public:
ResReplyTransferAccount(void *user);
virtual ~ResReplyTransferAccount() {}
private:
};
//-----------------------------------------
class ResReplyCharacterList : public GenericResponse
//-----------------------------------------
{
public:
ResReplyCharacterList(void *user);
virtual ~ResReplyCharacterList() {}
private:
};
//-----------------------------------------
class ResReplyServerList : public GenericResponse
//-----------------------------------------
{
public:
ResReplyServerList(void *user);
virtual ~ResReplyServerList() {}
private:
};
//-----------------------------------------
class ResReplyDestinationServerList : public GenericResponse
//-----------------------------------------
{
public:
ResReplyDestinationServerList(void *user);
virtual ~ResReplyDestinationServerList() {}
private:
};
}; // namespace
#endif //RESPONSE_H_
@@ -0,0 +1,119 @@
#include "Clock.h"
#include <time.h>
#ifdef WIN32
#include <winsock.h>
#else //WIN32
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#endif
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
Clock::Clock()
: m_lastStart(0),
m_totalRunTime(0)
{
}
ClockStamp Clock::getCurTime()
{
#if defined(WIN32)
static int sClockHigh = 0;
static ClockStamp sClockLast = 0;
int high = sClockHigh;
DWORD low = GetTickCount();
ClockStamp holdLast = sClockLast; // this should be interlocked too
ClockStamp ret = ((ClockStamp)high << 32) | low;
// crazy trick to allow threading to work, by putting in a 1000 second fudge factor, we effective say
// that it is ok to time-slice us at a bad point and we will still handle it, provided that our thread
// gets processing time again within 1000 seconds
if (ret < holdLast - 1000000)
{
sClockHigh = high + 1;
ret = ((ClockStamp)high << 32) | low;
}
sClockLast = ret; // this really should be interlocked to be totally safe since it is a 64 bit value, but I don't see a way to do that and am not sure it would mess up anything but the one call anyways
return ret;
#else
struct timeval tv;
int err;
err = gettimeofday(&tv, NULL);
return (static_cast<ClockStamp>(tv.tv_sec) * 1000 + static_cast<ClockStamp>(tv.tv_usec / 1000));
#endif
}
ClockStamp Clock::getElapsedSinceLastStart()
{
if (m_lastStart == 0)
{
//hasn't been started
return 0;
}
ClockStamp elapsed = getCurTime() - m_lastStart;
if (elapsed > 2000000000) // only time differences up to 23 days can be measured with this function
elapsed = 2000000000;
return elapsed;
}
void Clock::start()
{
if (m_lastStart != 0)
{
//already started
return;
}
//set last start to curtime
m_lastStart = getCurTime();
}
void Clock::stop()
{
if (m_lastStart == 0)
{
//need to start before stoping
return;
}
m_totalRunTime += (unsigned)getElapsedSinceLastStart(); //rlsmith - explicit cast to prevent compiler warning
m_lastStart = 0;
}
bool Clock::isDone(unsigned runTime)
{
if (m_lastStart == 0)
{
//never started, so say no
return false;
}
ClockStamp totalElapsed = getElapsedSinceLastStart() + m_totalRunTime;
return (totalElapsed >= runTime);
}
void Clock::reset()
{
m_lastStart = 0;
m_totalRunTime = 0;
}
#ifdef EXTERNAL_DISTRO
};
#endif
@@ -0,0 +1,71 @@
#ifndef CLOCK_H
#define CLOCK_H
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
#if defined(WIN32)
typedef __int64 ClockStamp;
#else
typedef long long ClockStamp;
#endif
/**
* @brief A Clock can be used as a millisecond timer.
*/
class Clock
{
public:
/**
* @brief Creates a clock, must still be started with Clock::start method.
*
* Once created, a clock can be started, and stoped as often as possible.
*/
Clock();
/**
* @brief Starts the timer running.
*/
void start();
/**
* @brief Stops the timer from running (note: can still be started again later).
*/
void stop();
/**
* @brief Tells you if the timer has been in the started state for longer than runTime.
*
* @param runTime The amount of time to test if this timer has ran longer than.
*
* @return 'true' if timer has ran for longer than or equal to runTime, false otherwise.
*/
bool isDone(unsigned runTime);
/**
* @brief Resets this clock (as if it were never started).
*/
void reset();
private:
ClockStamp m_lastStart;
unsigned m_totalRunTime;
ClockStamp getCurTime();
ClockStamp getElapsedSinceLastStart();
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif //CLOCK_H
@@ -0,0 +1,33 @@
#include "IPAddress.h"
#if defined(WIN32)
#include <winsock.h>
typedef int socklen_t;
#else // for non-windows platforms (linux)
#include <arpa/inet.h>
#include <sys/socket.h>
#include <string.h>
#endif
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
IPAddress::IPAddress(unsigned int ip)
: m_IP(ip)
{
}
char *IPAddress::GetAddress(char *buffer) const
{
struct sockaddr_in addr;
addr.sin_addr.s_addr = m_IP;
strcpy(buffer, inet_ntoa(addr.sin_addr));
return(buffer);
}
#ifdef EXTERNAL_DISTRO
};
#endif
@@ -0,0 +1,51 @@
#ifndef TCPIPADDRESS_H
#define TCPIPADDRESS_H
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
/**
* @brief Container object for IP Address.
*/
class IPAddress
{
public:
/**
* @brief Constructor, sets the ip address if specified.
*/
IPAddress(unsigned int ip = 0);
/**
* @brief Sets the ip address.
*/
void SetAddress(unsigned int ip){ m_IP = ip; }
/**
* @brief Returns the unsigned int representation of this address.
*/
unsigned int GetAddress() const { return m_IP; }
/**
* @brief Used to retreive the the dot-notation represenatatiion of this address.
*
* @param buffer A pointer to the buffer to place the ip address into.
* Must be at least 17 characters long, will be null terminated.
*
* @return A pointer to the buffer the address was placed into.
*/
char *GetAddress(char *buffer) const;
private:
unsigned int m_IP;
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif //TCPIPADDRESS_H
@@ -0,0 +1,94 @@
#include "TcpBlockAllocator.h"
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
TcpBlockAllocator::TcpBlockAllocator(const unsigned initSize, const unsigned initCount)
: m_freeHead(NULL), m_blockCount(initCount), m_blockSize(initSize), m_numAvailBlocks(0)
{
realloc();
}
TcpBlockAllocator::~TcpBlockAllocator()
{
while(m_freeHead)
{
data_block *tmp = m_freeHead;
m_freeHead = m_freeHead->m_next;
delete[] tmp->m_data;
delete tmp;m_numAvailBlocks--;
}
}
data_block *TcpBlockAllocator::getBlock()
{
data_block *tmp;
if(!m_freeHead)
{
realloc();
}
tmp = m_freeHead;
m_freeHead = m_freeHead->m_next;
tmp->m_next = NULL;
m_numAvailBlocks--;
return(tmp);
}
void TcpBlockAllocator::returnBlock(data_block *b)
{
b->m_usedSize = 0;
b->m_sentSize = 0;
if (m_numAvailBlocks >= m_blockCount)
{
delete[] b->m_data;
delete b;
return;
}
b->m_next = m_freeHead;
m_freeHead = b; m_numAvailBlocks++;
}
void TcpBlockAllocator::realloc()
{
data_block *tmp = NULL, *cursor = NULL;
tmp = new data_block; m_numAvailBlocks++;
cursor = tmp;
memset(cursor, 0, sizeof(data_block));
cursor->m_data = new char[m_blockSize];
cursor->m_totalSize = m_blockSize;
for(unsigned i = 1; i < m_blockCount; i++)
{
cursor->m_next = new data_block; m_numAvailBlocks++;
cursor = cursor->m_next;
memset(cursor, 0, sizeof(data_block));
cursor->m_data = new char[m_blockSize];
cursor->m_totalSize = m_blockSize;
}
if(m_freeHead)
{
cursor->m_next = m_freeHead;
m_freeHead = tmp;
}
else
{
m_freeHead = tmp;
}
}
#ifdef EXTERNAL_DISTRO
};
#endif
@@ -0,0 +1,44 @@
#ifndef TCPBLOCKALLOCATOR_H
#define TCPBLOCKALLOCATOR_H
#include <string.h>
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
struct data_block
{
unsigned m_usedSize;
unsigned m_sentSize;
unsigned m_totalSize;
char *m_data;
data_block *m_next;
};
class TcpBlockAllocator
{
public:
TcpBlockAllocator(const unsigned initSize, const unsigned initCount);
~TcpBlockAllocator();
data_block *getBlock();
void returnBlock(data_block *);
private:
void realloc();
data_block *m_freeHead;
unsigned m_blockCount;
unsigned m_blockSize;
unsigned m_numAvailBlocks;
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif //TCPBLOCKALLOCATOR_H
@@ -0,0 +1,784 @@
#include "TcpConnection.h"
#include "TcpManager.h"
#include "Clock.h"
#include <errno.h>
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
//used when want to open new connection with this socket
TcpConnection::TcpConnection(TcpManager *tcpManager, TcpBlockAllocator *sendAlloc, TcpManager::TcpParams &params, const IPAddress &destIP, short destPort, unsigned timeout)
: m_nextConnection(NULL),
m_prevConnection(NULL),
m_socket(INVALID_SOCKET),
m_nextKeepAliveConnection(NULL),
m_prevKeepAliveConnection(NULL),
m_aliveListId(tcpManager->m_aliveList.m_listID),
m_nextRecvDataConnection(NULL),
m_prevRecvDataConnection(NULL),
m_recvDataListId(tcpManager->m_dataList.m_listID),
m_manager(tcpManager),
m_status(StatusNegotiating),
m_handler(NULL),
m_destIP(destIP),
m_destPort(destPort),
m_refCount(0),
m_sendAllocator(sendAlloc),
m_head(NULL),
m_tail(NULL),
m_bytesRead(0),
m_bytesNeeded(0),
m_params(params),
m_recvBuff(NULL),
m_connectTimeout(timeout),
m_connectTimer(),
m_wasConRemovedFromMgr(false)
{
//start connection timer
m_connectTimer.start();
memset(&m_addr, 0, sizeof(m_addr));
if (m_params.maxRecvMessageSize != 0)
{
m_recvBuff = new char[m_params.maxRecvMessageSize];
}
m_socket = socket(AF_INET, SOCK_STREAM, 0);
setOptions();
m_addr.sin_family = AF_INET;
m_addr.sin_port = htons(m_destPort);
m_addr.sin_addr.s_addr = m_destIP.GetAddress();
int err = connect(m_socket, (sockaddr *)&m_addr, sizeof(m_addr));
if(err == SOCKET_ERROR)
{
#ifdef WIN32
int sockerr = WSAGetLastError();
if(sockerr != WSAEWOULDBLOCK)
{
//a real error
m_status = StatusDisconnected;
}
else
{
m_status = StatusNegotiating;
}
#else // UNIX
if (errno != EINPROGRESS)
{
m_status = StatusDisconnected;
}
else
{
m_status = StatusNegotiating;
}
#endif
}
else
{
//we are connected, wow
m_status = StatusConnected;
}
}
//used when server mode creates new connection object representing a connect request
TcpConnection::TcpConnection(TcpManager *tcpManager, TcpBlockAllocator *sendAlloc, TcpManager::TcpParams &params, SOCKET socket, const IPAddress &destIP, short destPort)
: m_nextConnection(NULL),
m_prevConnection(NULL),
m_socket(socket),
m_nextKeepAliveConnection(NULL),
m_prevKeepAliveConnection(NULL),
m_aliveListId(tcpManager->m_aliveList.m_listID),
m_nextRecvDataConnection(NULL),
m_prevRecvDataConnection(NULL),
m_recvDataListId(tcpManager->m_dataList.m_listID),
m_manager(tcpManager),
m_status(StatusConnected),
m_handler(NULL),
m_destIP(destIP),
m_destPort(destPort),
m_refCount(0),
m_sendAllocator(sendAlloc),
m_head(NULL),
m_tail(NULL),
m_bytesRead(0),
m_bytesNeeded(0),
m_params(params),
m_recvBuff(NULL),
m_connectTimeout(0),
m_connectTimer(),
m_wasConRemovedFromMgr(false)
{
memset(&m_addr, 0, sizeof(m_addr));
if (m_params.maxRecvMessageSize != 0)
{
m_recvBuff = new char[m_params.maxRecvMessageSize];
}
setOptions();
}
void TcpConnection::setOptions()
{
if (m_socket != INVALID_SOCKET)
{
#if defined(WIN32)
unsigned long isNonBlocking = 1;
int outBufSize = m_params.outgoingBufferSize;
int inBufSize = m_params.incomingBufferSize;
int keepAlive = 1;
int reuseAddr = 1;
struct linger ld;
ld.l_onoff = 0;
ld.l_linger = 0;
if (ioctlsocket(m_socket, FIONBIO, &isNonBlocking) != 0
|| setsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, (char *)&outBufSize, sizeof(outBufSize)) != 0
|| setsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (char *)&inBufSize, sizeof(inBufSize)) != 0
|| setsockopt(m_socket, SOL_SOCKET, SO_KEEPALIVE, (char *)&keepAlive, sizeof(keepAlive)) != 0
|| setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&reuseAddr, sizeof(reuseAddr)) != 0
|| setsockopt(m_socket, SOL_SOCKET, SO_LINGER, (char *)&ld, sizeof(ld)) != 0 )
{
//bummer, but no need to crash now.... ?
}
#else // linux is to remain the default compile mode
unsigned long isNonBlocking = 1;
unsigned long keepAlive = 1;
unsigned long outBufSize = m_params.outgoingBufferSize;
unsigned long inBufSize = m_params.incomingBufferSize;
unsigned long reuseAddr = 1;
struct linger ld;
ld.l_onoff = 0;
ld.l_linger = 0;
if (ioctl(m_socket, FIONBIO, &isNonBlocking) != 0
|| setsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, &outBufSize, sizeof(outBufSize)) != 0
|| setsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, &inBufSize, sizeof(inBufSize)) != 0
|| setsockopt(m_socket, SOL_SOCKET, SO_KEEPALIVE, &keepAlive, sizeof(keepAlive)) != 0
|| setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(reuseAddr)) != 0
|| setsockopt(m_socket, SOL_SOCKET, SO_LINGER, &ld, sizeof(ld)) != 0)
{
//bummer, but no need to crash now.... ?
}
#endif
}
}
int TcpConnection::finishConnect()
{
AddRef();
int returnVal = 0;
/**< returns < 0 if fatal error and connect will not work, =0 if need more time, >0 if connect completed */
switch (m_status)
{
case StatusDisconnected:
{
//something went wrong
Disconnect(false);
returnVal = -1;
}
break;
case StatusNegotiating:
{
#ifdef WIN32
//try to finish connection
fd_set wrSet;
FD_ZERO(&wrSet);
FD_SET(m_socket, &wrSet);
timeval t;
t.tv_sec = 0;
t.tv_usec = 0;
int err = select(m_socket + 1, NULL, &wrSet, NULL, &t);
if (err == 0)
{
//needs more time
returnVal = 0;
}
else if (err == SOCKET_ERROR)
{
//huhoh, let's hope it needs more time
int sockerr = WSAGetLastError();
if (sockerr == WSAEINPROGRESS
|| sockerr == WSAEWOULDBLOCK
|| sockerr == WSAEALREADY
|| sockerr == WSAEINVAL)
{
//yep
returnVal = 0;
}
else
{
Disconnect(false);
returnVal = -1;
}
}
else
{
//check if write bit set for socket
if (FD_ISSET(m_socket, &wrSet))
{
//connection complete
m_status = StatusConnected;
returnVal = 1;
}
else
{
//give it more time??
returnVal = 0;
}
}
#else // not WIN32
int err = connect(m_socket, (sockaddr *)&m_addr, sizeof(m_addr));
if(err == SOCKET_ERROR)
{
if (errno != EINPROGRESS && errno != EALREADY)
{
Disconnect(false);
returnVal = -1;//failure
}
else
{
returnVal = 0;//need to wait
}
}
else
{
m_status = StatusConnected;
returnVal = 1;//connect success
}
#endif
}
break;
case StatusConnected:
{
//wierd, shouldn't be trying to do this here
Disconnect(true);
returnVal = -1;
}
break;
}
if (returnVal == 0 && m_connectTimeout != 0 && m_connectTimer.isDone(m_connectTimeout))
{
Disconnect(false);
returnVal = -1;
}
else if (returnVal ==1/* && m_connectTimeout != 0*/)
{
//need to give, onConnect callback
if (m_manager->m_handler)
m_manager->m_handler->OnConnectRequest(this);
}
Release();
return returnVal;
}
TcpConnection::~TcpConnection()
{
if (m_recvBuff != NULL)
{
delete [] m_recvBuff;
}
while(m_head != NULL)
{
data_block *tmp = m_head;
m_head = m_head->m_next;
m_sendAllocator->returnBlock(tmp);
}
//TODO: need to notify app if are currently connected
}
void TcpConnection::Send(const char *data, unsigned int dataLen)
{
//add msg to buf
int totalLen = dataLen + sizeof(int);
if(m_status == StatusDisconnected)
{
return;
}
if (m_params.keepAliveDelay > 0 && m_aliveListId == m_manager->m_aliveList.m_listID)
{
m_aliveListId = m_manager->m_keepAliveList.m_listID;
if (m_prevKeepAliveConnection != NULL)
m_prevKeepAliveConnection->m_nextKeepAliveConnection = m_nextKeepAliveConnection;
if (m_nextKeepAliveConnection != NULL)
m_nextKeepAliveConnection->m_prevKeepAliveConnection = m_prevKeepAliveConnection;
if (m_manager->m_keepAliveList.m_beginList == this)
m_manager->m_keepAliveList.m_beginList = m_nextKeepAliveConnection;
m_nextKeepAliveConnection = m_manager->m_aliveList.m_beginList;
m_prevKeepAliveConnection = NULL;
if (m_manager->m_aliveList.m_beginList != NULL)
m_manager->m_aliveList.m_beginList->m_prevKeepAliveConnection = this;
m_manager->m_aliveList.m_beginList = this;
}
data_block *work = NULL;
// this connection has no send buffer. Get a block
if(!m_tail)
{
m_head = m_sendAllocator->getBlock();
m_tail = m_head;
}
work = m_tail;
//send message len first
unsigned nLen = htonl(totalLen);
unsigned lenLength = sizeof(int);
unsigned lenIndex = 0;
while(lenIndex < lenLength)
{
if ((lenLength - lenIndex) <= (work->m_totalSize - work->m_usedSize))
{
//size will fit in this block
memcpy(work->m_data + work->m_usedSize, (char *)(&nLen) + lenIndex, lenLength - lenIndex);
work->m_usedSize += (lenLength - lenIndex);
lenIndex += (lenLength - lenIndex);
}
else
{
//size will not fit in this block
memcpy(work->m_data + work->m_usedSize, (char *)(&nLen) + lenIndex, work->m_totalSize - work->m_usedSize);
lenIndex += work->m_totalSize - work->m_usedSize;
work->m_usedSize += work->m_totalSize - work->m_usedSize;
work->m_next = m_sendAllocator->getBlock();
work = work->m_next;
m_tail = work;
}
}
//now send message payload
unsigned messageIndex = 0;
while(messageIndex < dataLen)
{
if((dataLen - messageIndex) <= (work->m_totalSize - work->m_usedSize))
{
// data will fit in this block
memcpy(work->m_data + work->m_usedSize, data + messageIndex, (dataLen - messageIndex));
work->m_usedSize += (dataLen - messageIndex);
messageIndex += (dataLen - messageIndex);
}
else
{
// data will not fit in this block. Fill this block and get another block
memcpy(work->m_data + work->m_usedSize, data + messageIndex, work->m_totalSize - work->m_usedSize);
messageIndex += work->m_totalSize - work->m_usedSize;
work->m_usedSize += work->m_totalSize - work->m_usedSize;
work->m_next = m_sendAllocator->getBlock();
work = work->m_next;
m_tail = work;
}
}
return;
}
void TcpConnection::Disconnect(bool notifyApplication)
{
AddRef();
m_status = StatusDisconnected;
if (!m_wasConRemovedFromMgr)
{
m_manager->removeConnection(this);
m_wasConRemovedFromMgr = true;
}
if(m_socket != INVALID_SOCKET)
{
#if defined(WIN32)
closesocket(m_socket);
#else
close(m_socket);
#endif
m_socket = INVALID_SOCKET;
}
if (notifyApplication && m_handler)
m_handler->OnTerminated(this);
Release();
}
void TcpConnection::AddRef()
{
m_refCount++;
}
void TcpConnection::Release()
{
if (--m_refCount == 0)
{
//make sure manager knows I'm gone
if (m_status != StatusDisconnected)
Disconnect(false);
delete this;
}
}
int TcpConnection::processIncoming()
{
/**< returns < 0 if fatal error and socket has been closed,
=0 if read anything (full or partial message),
>0 if nothing to read now, or would block so shouldn't try again immediately. */
if (m_status != StatusConnected)
{
//wait until connect succeeds
return 1;
}
if (m_params.noDataTimeout > 0 && m_recvDataListId == m_manager->m_dataList.m_listID)
{
m_recvDataListId = m_manager->m_noDataList.m_listID;
if (m_prevRecvDataConnection != NULL)
m_prevRecvDataConnection->m_nextRecvDataConnection = m_nextRecvDataConnection;
if (m_nextRecvDataConnection != NULL)
m_nextRecvDataConnection->m_prevRecvDataConnection = m_prevRecvDataConnection;
if (m_manager->m_noDataList.m_beginList == this)
m_manager->m_noDataList.m_beginList = m_nextRecvDataConnection;
m_nextRecvDataConnection = m_manager->m_dataList.m_beginList;
m_prevRecvDataConnection = NULL;
if (m_manager->m_dataList.m_beginList != NULL)
m_manager->m_dataList.m_beginList->m_prevRecvDataConnection = this;
m_manager->m_dataList.m_beginList = this;
}
int newMsg = 0;
if (m_bytesRead < sizeof(int))
{
//new msg
newMsg = 1;
//printf("socket: %d\n", m_socket);
int ret = recv(m_socket, ((char *)(&m_bytesNeeded) + m_bytesRead),
4 - m_bytesRead, 0);
//fprintf(stderr, "READ: %d\n", ret);
if (ret == 0)
{
//We did a select, so there should be data. Socket was closed.
Disconnect();
return -1;
}
else if (ret == -1)
{
if (translateRecvSocketEror())
{
//fatal error
return -1;
}
else
{
//need to wait
return 1;
}
}
else
{
m_bytesRead += ret;
if (m_bytesRead < 4)
{
return 1;//need to wait
}
else
{
m_bytesNeeded = ntohl(m_bytesNeeded);
//printf("m_bytesNeeded = %i\n", m_bytesNeeded);
if (m_bytesNeeded == sizeof(int))
{
//keepalive, ignore
m_bytesRead = 0;
m_bytesNeeded = 0;
return 0;
}
else if (m_bytesNeeded < sizeof(int))
{
//major protocol violation
Disconnect();
return -1;
}
else if (m_params.maxRecvMessageSize == 0)
{
if (m_recvBuff!=NULL)
delete [] m_recvBuff;
m_recvBuff = new char[m_bytesNeeded-4];
}
else if (m_params.maxRecvMessageSize != 0 && (m_bytesNeeded-4) > m_params.maxRecvMessageSize)
{
//error, maxRecvMeessageSize exceeded, Disconnect
Disconnect();
return -1;
}
}
}
}
int msgBytesRead = m_bytesRead - 4;
int msgBytesNeeded = m_bytesNeeded - 4;
int ret = recv(m_socket, (char *)(m_recvBuff + msgBytesRead),
msgBytesNeeded - msgBytesRead, 0);
if (ret == 0 && !newMsg)
{
//We did a select, so there should be data. Socket was closed.
Disconnect();
return -1;
}
if (ret == -1)
{
if (translateRecvSocketEror())
{
//fatal error
return -1;
}
else
{
//need to wait
return 1;
}
} else
{
m_bytesRead += ret;
}
if (m_bytesRead == m_bytesNeeded)
{
m_bytesRead = 0;
m_bytesNeeded = 0;
if (m_handler)
{
AddRef();//could get deleted during this callback
m_handler->OnRoutePacket(this, (unsigned char *)m_recvBuff, msgBytesNeeded);
if (m_status == StatusDisconnected)
{
Release();
return -1;
}
Release();
}
//entire message received
return 0;
}
else
{
return 1;//couldn't get entire msg
}
}
int TcpConnection::processOutgoing()
{
/**< returns < 0 if fatal error and socket has been closed,
=0 if sent data, call again immediately if want to,
>0 may have sent data, but calling again would do no good because there is either no more data to send, or would block. */
if (m_status != StatusConnected)
{
//wait until connect succeeds
return 0;
}
int sendError = 1;
// If m_head is not null, then this connection has something to send
if(m_head)
{
int amt = ::send(m_socket, m_head->m_data + m_head->m_sentSize, m_head->m_usedSize - m_head->m_sentSize, 0);
if(amt < 0)
{
#ifdef WIN32
switch(WSAGetLastError())
{
case WSAEWOULDBLOCK:
case WSAEINTR:
case WSAEINPROGRESS:
case WSAEALREADY:
case WSA_IO_PENDING:
case WSA_NOT_ENOUGH_MEMORY:
case WSATRY_AGAIN:
//try again
sendError = 1;
break;
default:
//assume broken, Disconnect
Disconnect();
sendError = -1;
break;
}
#else //not WIN32
// error condition, EAGAIN is recoverable, otherwise raise an error condition. Break from loop
switch(errno)
{
case EAGAIN:
//try again
sendError = 1;
break;
default:
//assume broken, Disconnect
Disconnect();
sendError = -1;
break;
}
#endif
}
else if(static_cast<unsigned>(amt) < (m_head->m_usedSize - m_head->m_sentSize))
{
// partial send: trying to do anything more now would be a waste of time. Break from loop
m_head->m_sentSize += amt;
sendError = 1;
}
else if(amt == 0)
{
Disconnect();
sendError = -1;
// client closed connection
}
else
{
// everything was sent from this block. Return it to the pool, advance m_head. Attempt to continue
// sending
data_block *tmp = m_head;
if(m_tail == m_head)
{
m_tail = m_tail->m_next;
m_head = m_head->m_next;
}
else
{
m_head = m_head->m_next;
}
m_sendAllocator->returnBlock(tmp);
sendError = 0;
}
}
return sendError;
}
bool TcpConnection::translateRecvSocketEror()
{
/**< returns false if fatal error and socket has been closed,
true if should try again. */
bool fatalError=false;
#ifdef WIN32
switch(WSAGetLastError())
{
case WSAENOBUFS:
case WSAEINPROGRESS:
case WSAEINTR:
case WSAEWOULDBLOCK:
case WSABASEERR:
fatalError=false;
break;
case WSANOTINITIALISED:
case WSAENETDOWN:
case WSAEFAULT:
case WSAENOTCONN:
case WSAENETRESET:
case WSAENOTSOCK:
case WSAEOPNOTSUPP:
case WSAESHUTDOWN:
case WSAEMSGSIZE:
case WSAEINVAL:
case WSAECONNABORTED:
case WSAETIMEDOUT:
case WSAECONNRESET:
default:
//fatal
fatalError=true;
Disconnect();
break;
}
#else //not WIN32
switch(errno)
{
case EWOULDBLOCK:
case EINTR:
case ETIMEDOUT:
case ENOBUFS:
//try later
fatalError=false;
break;
case EBADF:
case ECONNRESET:
case EFAULT:
case EINVAL:
case ENOTCONN:
case ENOTSOCK:
case EOPNOTSUPP:
case EPIPE:
case EIO:
case ENOMEM:
case ENOSR:
default:
//fatal
fatalError=true;
Disconnect();
break;
}
#endif
return fatalError;
}
#ifdef EXTERNAL_DISTRO
};
#endif
@@ -0,0 +1,157 @@
#ifndef TCPCONNECTION_H
#define TCPCONNECTION_H
#include "TcpHandlers.h"
#include "TcpManager.h"
#include "IPAddress.h"
#include "TcpBlockAllocator.h"
#include "Clock.h"
#if defined(WIN32)
#include <winsock2.h>
typedef int socklen_t;
#else // for non-windows platforms (linux)
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#endif
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
/**
* @brief Manages a single connection.
*/
class TcpConnection
{
public:
/**
* @brief The connection status.
*/
enum Status {
StatusNegotiating, /**< Currently attempting to connect. */
StatusConnected, /**< Currently connected. */
StatusDisconnected /**< Currently disconnected. */
};
/**
* @brief Sets the handler object which will receive callback methods.
*
* To have the TcpConnection call your object directly when packets are received, and when the
* connection is disconnected, you simply need to derive your class
* (multiply if necessary) from TcpConnectionHandler, then you can use
* this method to set the object the TcpConnection will call as appropriate.
* default = NULL (no callbacks made)
*
* @param handler The object which will be called for notifications.
*/
void SetHandler(TcpConnectionHandler *handler){ m_handler = handler; }
/**
* @brief Returns the handler associated with this object.
*/
TcpConnectionHandler *GetHandler(){ return m_handler; }
/**
* @brief Returns the current status of this connection.
*/
Status GetStatus(){ return m_status; }
/**
* @brief Queues a message to be sent on this connection.
*/
void Send(const char *data, unsigned dataLen);
/**
* @brief Disconnects and recycles the socket.
*
* @param notifyApplication primarily used internally, but when set to 'true', it will cause the application
* to be called back via the onTerminated handler due to this call (the callback will not occur if the connection was
* already disconnected)
*/
void Disconnect(bool notifyApplication=true);
/**
* @brief Returns the ip on the other side of this connection.
*/
IPAddress GetDestinationIp(){ return m_destIP; }
/**
* @brief Returns the port on the other side of this conection.
*/
short GetDestinationPort(){ return m_destPort; }
/**
* @brief Standard AddRef/Release scheme
*/
void AddRef();
/**
* @brief Standard AddRef/Release scheme
*/
void Release();
bool wasRemovedFromMgr() { return m_wasConRemovedFromMgr; }
void setRemovedFromMgr() { m_wasConRemovedFromMgr = true; }
protected:
friend class TcpManager;
TcpConnection(TcpManager *tcpManager, TcpBlockAllocator *sendAlloc, TcpManager::TcpParams &params, const IPAddress &destIP, short destPort, unsigned timeout);
int finishConnect();/**< returns < 0 if fatal error and connect will not work, =0 if need more time, >0 if connect completed */
TcpConnection(TcpManager *tcpManager, TcpBlockAllocator *sendAlloc, TcpManager::TcpParams &params, SOCKET socket, const IPAddress &destIP, short destPort);
TcpConnection *m_nextConnection; /**< Double linked list imp. */
TcpConnection *m_prevConnection; /**< Double linked list imp. */
SOCKET m_socket;
int processOutgoing();/**< returns < 0 if fatal error and socket has been closed, =0 if sent data, call again immediately if want to, >0 may have sent data, but calling again would do no good because there is either no more data to send, or would block. */
int processIncoming();/**< returns < 0 if fatal error and socket has been closed, =0 if read anything (full or partial message), >0 if nothing to read now, or would block so shouldn't try again immediately. */
TcpConnection *m_nextKeepAliveConnection; /**< Double linked list imp. */
TcpConnection *m_prevKeepAliveConnection; /**< Double linked list imp. */
int m_aliveListId;
TcpConnection *m_nextRecvDataConnection;
TcpConnection *m_prevRecvDataConnection;
int m_recvDataListId;
private:
~TcpConnection();
void setOptions();
TcpManager *m_manager;
bool translateRecvSocketEror();
Status m_status;
TcpConnectionHandler *m_handler;
IPAddress m_destIP;
short m_destPort;
unsigned m_refCount;
TcpBlockAllocator *m_sendAllocator;
data_block *m_head;
data_block *m_tail;
unsigned m_bytesRead;
unsigned m_bytesNeeded;
TcpManager::TcpParams m_params;
char *m_recvBuff;
sockaddr_in m_addr;
unsigned m_connectTimeout;
Clock m_connectTimer;
bool m_wasConRemovedFromMgr;
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif //TCPCONNECTION_H
@@ -0,0 +1,50 @@
#ifndef TCPHANDLERS_H
#define TCPHANDLERS_H
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
class TcpConnection;
/**
* @brief Interface used by TcpManager class for notification to application of connection state/etc.
*
* Note: these callbacks will only be made when during a call to TcpManager::giveTime.
*/
class TcpManagerHandler
{
public:
/**
* @brief Callback made when a new connection has been established by the manager.
*/
virtual void OnConnectRequest(TcpConnection *con)=0;
};
/**
* @brief Interface used by TcpConnection class for notification to application of connection state/etc.
*
* Note: these callbacks will only be made when during a call to TcpManager::giveTime.
*/
class TcpConnectionHandler
{
public:
/**
* @brief Callback made when a new message has been received on the specified connection.
*/
virtual void OnRoutePacket(TcpConnection *con, const unsigned char *data, int dataLen)=0;
/**
* @brief Callback made when the specified connection has closed, or been closed.
*/
virtual void OnTerminated(TcpConnection *con)=0;
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif //TCPHANDLERS_H
@@ -0,0 +1,734 @@
#include "TcpManager.h"
#include <assert.h>
#include "IPAddress.h"
#include "TcpConnection.h"
#ifndef WIN32
#include <sys/poll.h>
#endif
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
TcpManager::TcpParams::TcpParams()
: port(0),
maxConnections(10),
incomingBufferSize(64*1024),
outgoingBufferSize(64*1024),
allocatorBlockSize(8*1024),
allocatorBlockCount(16),
maxRecvMessageSize(0),
keepAliveDelay(0),
noDataTimeout(0)
{
memset(bindAddress, 0, sizeof(bindAddress));
}
TcpManager::TcpParams::TcpParams(const TcpParams &cpy)
: port(cpy.port),
maxConnections(cpy.maxConnections),
incomingBufferSize(cpy.incomingBufferSize),
outgoingBufferSize(cpy.outgoingBufferSize),
allocatorBlockSize(cpy.allocatorBlockSize),
allocatorBlockCount(cpy.allocatorBlockCount),
maxRecvMessageSize(cpy.maxRecvMessageSize),
keepAliveDelay(cpy.keepAliveDelay),
noDataTimeout(cpy.noDataTimeout)
{
}
TcpManager::TcpManager(const TcpParams &params)
: m_handler(NULL),
m_keepAliveList(NULL, 1),
m_aliveList(NULL, 2),
m_noDataList(NULL, 1),
m_dataList(NULL, 2),
m_params(params),
m_refCount(1),
m_connectionList(NULL),
m_connectionListCount(0),
m_socket(INVALID_SOCKET),
m_boundAsServer(false),
m_allocator(params.allocatorBlockSize, params.allocatorBlockCount),
m_keepAliveTimer(),
m_noDataTimer()
{
if (params.keepAliveDelay > 0)
m_keepAliveTimer.start();
if (params.noDataTimeout > 0)
m_noDataTimer.start();
#if defined(WIN32)
WSADATA wsaData;
WSAStartup(MAKEWORD(1,1), &wsaData);
FD_ZERO(&m_permfds);//select only used on win32
#endif
}
TcpManager::~TcpManager()
{
#if defined(WIN32)
WSACleanup();
#endif
if (m_boundAsServer)
{
#if defined(WIN32)
closesocket(m_socket);
#else
close(m_socket);
#endif
}
while (m_connectionList != NULL)
{
TcpConnection *con = m_connectionList;
m_connectionList = m_connectionList->m_nextConnection;
con->Release();
m_connectionListCount--;
}
}
bool TcpManager::BindAsServer()
{
m_socket = socket(AF_INET, SOCK_STREAM, 0);
if (m_socket != INVALID_SOCKET)
{
#if defined(WIN32)
FD_SET(m_socket, &m_permfds);//the socket this server is listening on
unsigned long isNonBlocking = 1;
int outBufSize = m_params.outgoingBufferSize;
int inBufSize = m_params.incomingBufferSize;
int keepAlive = 1;
int reuseAddr = 1;
struct linger ld;
ld.l_onoff = 0;
ld.l_linger = 0;
if (ioctlsocket(m_socket, FIONBIO, &isNonBlocking) != 0
|| setsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, (char *)&outBufSize, sizeof(outBufSize)) != 0
|| setsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (char *)&inBufSize, sizeof(inBufSize)) != 0
|| setsockopt(m_socket, SOL_SOCKET, SO_KEEPALIVE, (char *)&keepAlive, sizeof(keepAlive)) != 0
|| setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&reuseAddr, sizeof(reuseAddr)) != 0
|| setsockopt(m_socket, SOL_SOCKET, SO_LINGER, (char *)&ld, sizeof(ld)) != 0 )
{
return false;
}
#else // linux is to remain the default compile mode
unsigned long isNonBlocking = 1;
unsigned long keepAlive = 1;
unsigned long outBufSize = m_params.outgoingBufferSize;
unsigned long inBufSize = m_params.incomingBufferSize;
unsigned long reuseAddr = 1;
struct linger ld;
ld.l_onoff = 0;
ld.l_linger = 0;
if (ioctl(m_socket, FIONBIO, &isNonBlocking) != 0
|| setsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, &outBufSize, sizeof(outBufSize)) != 0
|| setsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, &inBufSize, sizeof(inBufSize)) != 0
|| setsockopt(m_socket, SOL_SOCKET, SO_KEEPALIVE, &keepAlive, sizeof(keepAlive)) != 0
|| setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(reuseAddr)) != 0
|| setsockopt(m_socket, SOL_SOCKET, SO_LINGER, &ld, sizeof(ld)) != 0)
{
return false;
}
#endif
}
else
{
return false;
}
struct sockaddr_in addr_loc;
addr_loc.sin_family = AF_INET;
addr_loc.sin_port = htons(m_params.port);
addr_loc.sin_addr.s_addr = htonl(INADDR_ANY);
if (m_params.bindAddress[0] != 0)
{
unsigned long address = inet_addr(m_params.bindAddress);
if (address == INADDR_NONE)
{
struct hostent * lphp;
lphp = gethostbyname(m_params.bindAddress);
if (lphp != NULL)
addr_loc.sin_addr.s_addr = ((struct in_addr *)(lphp->h_addr))->s_addr;
}
else
{
addr_loc.sin_addr.s_addr = address;
}
}
if (bind(m_socket, (struct sockaddr *)&addr_loc, sizeof(addr_loc)) != 0)
{
return false;
}
if (listen(m_socket, 1000) != 0)
{
return false;
}
m_boundAsServer = true;
return true;
}
TcpConnection *TcpManager::acceptClient()
{
TcpConnection *newConn = NULL;
if (m_boundAsServer && m_connectionListCount < m_params.maxConnections)
{
sockaddr_in addr;
int addrLength = sizeof(addr);
SOCKET sock = ::accept(m_socket, (sockaddr *) &addr, (socklen_t *) &addrLength);
if (sock != INVALID_SOCKET)
{
newConn = new TcpConnection(this, &m_allocator, m_params, sock, IPAddress(addr.sin_addr.s_addr), ntohs(addr.sin_port));
addNewConnection(newConn);
if (m_handler != NULL)
{
m_handler->OnConnectRequest(newConn);
}
}
}
return newConn;
}
void TcpManager::SetHandler(TcpManagerHandler *handler)
{
m_handler = handler;
}
SOCKET TcpManager::getMaxFD()
{
#ifdef WIN32
return 0;//this param is not used on win32 for select, only on unix
#else
SOCKET maxfd = 0;
if (m_boundAsServer)
maxfd = m_socket+1;
TcpConnection *next = NULL;
for (TcpConnection *con = m_connectionList ; con != NULL ; con = next)
{
next = con->m_nextConnection;
if (con->GetStatus() != TcpConnection::StatusDisconnected && con->m_socket > maxfd)
{
maxfd = con->m_socket + 1;
}
}
return maxfd;
#endif
}
TcpConnection *TcpManager::getConnection(SOCKET fd)
{
TcpConnection *next = NULL;
for (TcpConnection *con = m_connectionList ; con != NULL ; con = next)
{
next = con->m_nextConnection;
if (con->m_socket == fd)
{
return con;
}
}
//if get here ,couldn't find it
return NULL;
}
bool TcpManager::GiveTime(unsigned maxTimeAcceptingConnections,unsigned maxSendTimePerConnection, unsigned maxRecvTimePerConnection)
{
bool processedIncoming = false;
if (maxTimeAcceptingConnections == 0 && maxSendTimePerConnection==0 && maxRecvTimePerConnection==0)
{
//they don't want to do anything now
return processedIncoming;
}
AddRef(); //keep a reference to ourself in case we callback to the application and the application releases us.
//first process outgoing on each connection, and finish establishing connections, if params say to
if (m_connectionListCount != 0 && maxSendTimePerConnection != 0)
{
// Send output from last heartbeat
TcpConnection *next = NULL;
for (TcpConnection *con = m_connectionList ; con != NULL ; con = next)
{
con->AddRef();
if (next) next->Release();
next = con->m_nextConnection;
if (next) next->AddRef();
if(con->GetStatus() == TcpConnection::StatusConnected)
{
Clock timer;
timer.start();
while(!timer.isDone(maxSendTimePerConnection))
{
int err = con->processOutgoing();
if (err > 0)
{
//couldn't finish processing last request, don't try more
break;
}
else if (err < 0)
{
break;
}
}
con->Release();
}
else if (con->GetStatus() == TcpConnection::StatusNegotiating)
{
if (con->finishConnect() < 0)
{
con->Release();
continue;
}
con->Release();
}
else //inactive client in client list????
{
removeConnection(con);
con->Release();
continue;
}
}
}
//process incoming messages (including connect requests)
if ((
m_boundAsServer //if in server mode and want to spend time accepting clients
&& maxTimeAcceptingConnections != 0
)
||
(
m_connectionListCount != 0 //if there are connections and want to spend time receiving on them
&& maxRecvTimePerConnection != 0
)
)
{
#ifdef WIN32
SOCKET maxfd = getMaxFD(); //re-calc maxfd every time select on WIN32
//select on all fd's
struct timeval timeout;
fd_set tmpfds;
tmpfds = m_permfds;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
int cnt = select(maxfd, &tmpfds, NULL, NULL, &timeout); // blocks for timeout
if (cnt > 0)
{
if (m_boundAsServer && maxTimeAcceptingConnections != 0)
{//activity on our socket means connect requests
//see if are new incoming clients
if (FD_ISSET(m_socket, &tmpfds))
{
//yep
Clock timer;
timer.start();
while (acceptClient() && !timer.isDone(maxTimeAcceptingConnections))
{
//loop
}
}
}
//process incoming client messages
if (maxRecvTimePerConnection != 0)
{
TcpConnection *next = NULL;
for (TcpConnection *con = m_connectionList ; con != NULL ; con = next)
{
con->AddRef();
if (next) next->Release();
next = con->m_nextConnection;
if (next) next->AddRef();
SOCKET fd = con->m_socket;
if (fd == INVALID_SOCKET)
{
//invalid socket in list?, check if is connecting, otherwise, Disconnect and discard
if (con->GetStatus() != TcpConnection::StatusNegotiating)
{
removeConnection(con);
con->Release();
continue;
}
}
if (FD_ISSET(fd, &tmpfds))
{
Clock timer;
timer.start();
while(!timer.isDone(maxRecvTimePerConnection) && con->GetStatus() == TcpConnection::StatusConnected)
{
int err = con->processIncoming();
if (err >= 0)
{
processedIncoming = true;
}
if (err > 0)
{
//couldn't finish processing last request, don't try more
break;
}
else if (err < 0)
{
break;
}
}//while(!timer...)
}//if (FD_ISSET...)
con->Release();
}//for (...)
} //maxRecvTimePerConnection != 0
}//cnt > 0
#else //on UNIX use poll
int numfds = m_connectionListCount;
int idx = 0;
if (m_boundAsServer)
{
numfds++;
idx++;
}
struct pollfd pollfds[numfds];
if (m_boundAsServer)
{
pollfds[0].fd = m_socket;
pollfds[0].events |= POLLIN;
}
TcpConnection *next = NULL;
for (TcpConnection *con = m_connectionList ; con != NULL ; con = next, idx++)
{
next = con->m_nextConnection;
pollfds[idx].fd = con->m_socket;
pollfds[idx].events |= POLLIN;
pollfds[idx].events |= POLLHUP;
}
int cnt = poll(pollfds, numfds, 1);
if(cnt == SOCKET_ERROR)
{
//poll not working?
//TODO: need to notify client somehow, don't think we can assume a fatal error here
}
else if (cnt > 0)
{
for (idx = 0; idx < numfds; idx++)
{
//find corresponding TcpConnection
//TODO: optimize, seriously, this is takes linear time, every time
TcpConnection *con = getConnection(pollfds[idx].fd);
if (pollfds[idx].revents & POLLIN)
{
if (m_boundAsServer && maxTimeAcceptingConnections != 0 && pollfds[idx].fd == m_socket)
{
//new incoming clients
Clock timer;
timer.start();
while (acceptClient() && !timer.isDone(maxTimeAcceptingConnections))
{
//loop
}
continue;//don't try to readmsgs from listening fd
}
//process regular msg(s)
if (con == NULL)
{
close(pollfds[idx].fd);
continue;
}
Clock timer;
timer.start();
con->AddRef();//so it can't get deleted while we are checking it's status
while(!timer.isDone(maxRecvTimePerConnection) && con->GetStatus() == TcpConnection::StatusConnected)
{
int err = con->processIncoming();
if (err >= 0)
{
processedIncoming = true;
}
if (err > 0)
{
//couldn't finish processing last request, don't try more
break;
}
else if (err < 0)
{
break;
}
}//while(!timer....)
con->Release();
}//if(pollfds[...
else if (pollfds[idx].revents & POLLHUP)
{
if (con == NULL)
{
close(pollfds[idx].fd);
continue;
}
//Disconnect client
con->Disconnect();
}
}//for (idx=0....
}//else if (cnt > 0)
#endif
}//wanted to process incoming messages or connect requests
//now process any keepalives, if time to do that
if (m_params.keepAliveDelay > 0 && m_keepAliveTimer.isDone(m_params.keepAliveDelay))
{
TcpConnection *next = NULL;
for (TcpConnection *con = m_keepAliveList.m_beginList ; con != NULL ; con = next)
{
con->AddRef();
if (next) next->Release();
next = con->m_nextKeepAliveConnection;
if (next) next->AddRef();
con->Send(NULL, 0); //note: this request will move the connection from the keepAliveList to the aliveList
con->Release();
}
//now move the complete alive list over to the keepalive list to reset those timers
m_keepAliveList.m_beginList = m_aliveList.m_beginList;
m_aliveList.m_beginList = NULL;
//switch id's for those connections that were in the alive list last go - around
int tmpID = m_aliveList.m_listID;
m_aliveList.m_listID = m_keepAliveList.m_listID;
m_keepAliveList.m_listID = tmpID;
m_keepAliveTimer.reset();
m_keepAliveTimer.start();
}
//now process any noDataCons, if time to do that
if (m_params.noDataTimeout > 0 && m_noDataTimer.isDone(m_params.noDataTimeout))
{
TcpConnection *next = NULL;
for (TcpConnection *con = m_noDataList.m_beginList ; con != NULL ; con = next)
{
con->AddRef();
if (next) next->Release();
next = con->m_nextRecvDataConnection;
if (next) next->AddRef();
//time to disconnect this guy
con->Disconnect();
con->Release();
}
//now move the complete data list over to the nodata list to reset those timers
m_noDataList.m_beginList = m_dataList.m_beginList;
m_dataList.m_beginList = NULL;
//switch id's for those connections that were in the data list last go - around
int tmpID = m_dataList.m_listID;
m_dataList.m_listID = m_noDataList.m_listID;
m_noDataList.m_listID = tmpID;
m_noDataTimer.reset();
m_noDataTimer.start();
}
Release();
return processedIncoming;
}
TcpConnection *TcpManager::EstablishConnection(const char *serverAddress, unsigned short serverPort, unsigned timeout)
{
if (m_boundAsServer)
{
//can't open outgoing connections when in server mode
// use a different TcpManager to do that
return NULL;
}
if (m_connectionListCount >= m_params.maxConnections)
return(NULL);
// get server address
unsigned long address = inet_addr(serverAddress);
if (address == INADDR_NONE)
{
struct hostent * lphp;
lphp = gethostbyname(serverAddress);
if (lphp == NULL)
return(NULL);
address = ((struct in_addr *)(lphp->h_addr))->s_addr;
}
IPAddress destIP(address);
TcpConnection *con = new TcpConnection(this, &m_allocator, m_params, destIP, serverPort, timeout);
con->AddRef();//for the client - to conform to UdpLibrary method
addNewConnection(con);
return con;
}
void TcpManager::addNewConnection(TcpConnection *con)
{
con->AddRef();
#ifdef WIN32 //uses select
if (con->m_socket != INVALID_SOCKET)
FD_SET(con->m_socket, &m_permfds);
#endif
con->m_nextConnection = m_connectionList;
con->m_prevConnection = NULL;
if (m_connectionList != NULL)
m_connectionList->m_prevConnection = con;
m_connectionList = con;
m_connectionListCount++;
con->m_nextKeepAliveConnection = m_aliveList.m_beginList;
con->m_prevKeepAliveConnection = NULL;
if (m_aliveList.m_beginList != NULL)
m_aliveList.m_beginList->m_prevKeepAliveConnection = con;
m_aliveList.m_beginList = con;
con->m_aliveListId = m_keepAliveList.m_listID;//start it out thinking it's already in the alive list, since it is
con->m_nextRecvDataConnection = m_dataList.m_beginList;
con->m_prevRecvDataConnection = NULL;
if (m_dataList.m_beginList != NULL)
m_dataList.m_beginList->m_prevRecvDataConnection = con;
m_dataList.m_beginList = con;
con->m_recvDataListId = m_noDataList.m_listID;//start it out thinking it's already in the data list, since it is
}
void TcpManager::removeConnection(TcpConnection *con)
{
if (!con->wasRemovedFromMgr())
{
con->setRemovedFromMgr();
m_connectionListCount--;
#ifdef WIN32 //select only used on win32
if (con->m_socket != INVALID_SOCKET)
{
FD_CLR(con->m_socket, &m_permfds);
}
#endif
if (con->m_prevConnection != NULL)
con->m_prevConnection->m_nextConnection = con->m_nextConnection;
if (con->m_nextConnection != NULL)
con->m_nextConnection->m_prevConnection = con->m_prevConnection;
if (m_connectionList == con)
m_connectionList = con->m_nextConnection;
con->m_nextConnection = NULL;
con->m_prevConnection = NULL;
if (con->m_prevKeepAliveConnection != NULL)
con->m_prevKeepAliveConnection->m_nextKeepAliveConnection = con->m_nextKeepAliveConnection;
if (con->m_nextKeepAliveConnection != NULL)
con->m_nextKeepAliveConnection->m_prevKeepAliveConnection = con->m_prevKeepAliveConnection;
if (m_aliveList.m_beginList == con)
m_aliveList.m_beginList = con->m_nextKeepAliveConnection;
else if (m_keepAliveList.m_beginList == con)
m_keepAliveList.m_beginList = con->m_nextKeepAliveConnection;
con->m_nextKeepAliveConnection = NULL;
con->m_prevKeepAliveConnection = NULL;
if (con->m_prevRecvDataConnection != NULL)
con->m_prevRecvDataConnection->m_nextRecvDataConnection = con->m_nextRecvDataConnection;
if (con->m_nextRecvDataConnection != NULL)
con->m_nextRecvDataConnection->m_prevRecvDataConnection = con->m_prevRecvDataConnection;
if (m_dataList.m_beginList == con)
m_dataList.m_beginList = con->m_nextRecvDataConnection;
else if (m_noDataList.m_beginList == con)
m_noDataList.m_beginList = con->m_nextRecvDataConnection;
con->m_nextRecvDataConnection = NULL;
con->m_prevRecvDataConnection = NULL;
con->Release();
}
}
void TcpManager::AddRef()
{
m_refCount++;
}
void TcpManager::Release()
{
if (--m_refCount == 0)
delete this;
}
IPAddress TcpManager::GetLocalIp() const
{
struct sockaddr_in addr_self;
memset(&addr_self, 0, sizeof(addr_self));
socklen_t len = sizeof(addr_self);
getsockname(m_socket, (struct sockaddr *)&addr_self, &len);
return(IPAddress(addr_self.sin_addr.s_addr));
}
unsigned int TcpManager::GetLocalPort() const
{
struct sockaddr_in addr_self;
memset(&addr_self, 0, sizeof(addr_self));
socklen_t len = sizeof(addr_self);
getsockname(m_socket, (struct sockaddr *)&addr_self, &len);
return(ntohs(addr_self.sin_port));
}
#ifdef EXTERNAL_DISTRO
};
#endif
@@ -0,0 +1,287 @@
#ifndef TCPMANAGER_H
#define TCPMANAGER_H
#include "TcpHandlers.h"
#include "TcpBlockAllocator.h"
#include "IPAddress.h"
#include "Clock.h"
#if defined(WIN32)
#include <winsock2.h>
typedef int socklen_t;
#else // for non-windows platforms (linux)
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
const int INVALID_SOCKET = 0xFFFFFFFF;
const int SOCKET_ERROR = 0xFFFFFFFF;
typedef int SOCKET;
#endif
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
class TcpConnection;
struct ConnectionList
{
ConnectionList(TcpConnection *con, int id) : m_beginList(con), m_listID(id) {}
TcpConnection *m_beginList;
int m_listID;
};
/**
* @brief The purpose of the TcpManager is to manage a set of connections that are coming in on a particular port.
*
*/
class TcpManager
{
public:
/** @brief Parameters for the TcpManager. */
struct TcpParams
{
/** @brief Simple constructor sets default values for members. */
TcpParams();
/** @brief Simple copy constructor. */
TcpParams(const TcpParams &cpy);
/**
* @brief Connection port number.
*
* this is the port number that this manager will use for all incoming and outgoing data. On the client side
* this is typically set to 0, which causes the manager object to randomly pick an available port. On the server
* side, this port should be set to a specific value as it will represent the port number that clients will use
* to connect to the server (ie. the listening port). It's generally a good idea to give the user on the client
* side the option of fixing this port number at a specific value as well as it is often necessary for them to
* do so in order to navigate company firewalls which may have specific port numbers open to them for this purpose.
* default = 0
*/
unsigned short port;
/**
* @ brief Server bind ip.
*
*/
char bindAddress[64];
/**
* @brief Maximum number of connections that can be established by this manager.
*
* this is the maximum number of connections that can be established by this manager, any incoming/outgoing connections
* over this limit will be refused. On the client side, this typically only needs to be set to 1, though there
* is little harm in setting this number larger.
* default = 10
*/
unsigned maxConnections;
/**
* @brief The size of the incoming socket buffer.
*
* The client will want to set this fairly small (32k or so), but the server
* will want to set this fairly large (512k)
* default = 64k
*/
unsigned incomingBufferSize;
/**
* @brief The size of the outgoing socket buffer.
*
* The client will want to set this fairly small (32k or so), but the server
* will want to set this fairly large (512k)
* default = 64k
*/
unsigned outgoingBufferSize;
/**
* @brief The block size of a single outgoing buffer memory allocator block.
*
* This param should allways be set at least as high as the maximum message size you
* expect to send (performance will suffer otherwise).
* default = 8K
*/
unsigned allocatorBlockSize;
/**
* @brief The number of block memory allocator 'blocks' created at a time.
*
* This is the number of blocks created for the buffer allocator for each
* TcpConnection opened by this manager. Since the block size should be
* the max size of an outgoing message, the recommended setting is: greater
* than the number of concurrent connections you expect to normally have open.
* default = 1024
*/
unsigned allocatorBlockCount;
/**
* @brief The maximum size that a recvd message is allowed to be.
*
* Really only here for protection, not required. If you set this, you can safeguard
* your client/server from receiving stray oversized messages. If a message on the socket
* specifies it's length at larger than this value, then the message is not read, and the connection
* is terminated. If the value is set to 0, then there is no max message size checking
* on incoming messages (this will also cary a performance hit, since every new message
* recieved will have to have a new buffer created if you don't specify a value here). Be careful
* not to set this too small, if you have messages that could exceed the value you set here
* they will be discarded, and the connection will be terminated without warning.
* default = 0
*/
unsigned maxRecvMessageSize;
unsigned keepAliveDelay;
unsigned noDataTimeout;
};
/**
* @brief
*/
TcpManager(const TcpParams &params);
/**
* @brief Use to specify a handler object to receive callbacks.
*
* To have the TcpManager call your object directly when connection requests come in, you
* simply need to derive your class (multiply if necessary) from TcpManagerHandler, then you can use
* this method to set the object the TcpManager will call as appropriate. The TcpConnection object
* also has a handler mechanism that replaces the other callback functions below, see TcpConnection::SetHandler
* default = NULL (no callbacks made)
*
* @param handler The object which will be called for manager related notifications.
*/
void SetHandler(TcpManagerHandler *handler);
/**
* @brief This function MUST be called on a regular basis in order to give the manager object time to service the socket and give time to various connection objects that may need processing time, etc.
*
* @param maxTimeAcceptingConnections The max amount of time in milliseconds to spend accepting new client connections.
* This parameter is only used if this manager has been bound as a server (bindAsServer).
* If you set this param to 0, it will not attempt to accept any new connections.
*
* @param giveConnectionsTime
* True if every connection opened on this manager is given time in this call, false if
* no connections are given time.
*
* @param maxSendTimePerConnection Max amount of time in milliseconds to spend on each client processing outgoing messages.
* A max of the specified amount of time will be spent on each and every individual connection. If you set
* this parametrer to 0, it will not process any outgoing messages on any clients. Note also that when attempting
* to establish new connections (via the EstablishConnection method), this parameter must be > 0 in order to
* complete the connection process for any connections that were still negotiating.
*
* @param maxRecvTimePerConnection Max amount of time in milliseconds to spend on each client processing incoming messages.
* A max of the specified amount of time will be spent on each and every individual connection. If you set
* this param to 0, it will not process any incoming messages on any clients.
* This is a good way to give the manager processing time for outgoing packets in situations
* where the application does not want to have to worry about processing incoming packets.
*
* @return true if any incoming packets were processed during this time slice, otherwise returns false
*/
bool GiveTime(unsigned maxTimeAcceptingConnections = 5, unsigned maxSendTimePerConnection = 5, unsigned maxRecvTimePerConnection = 5);
/**
* @brief Used to establish a connection to a server that is listening at the specified address and port.
*
* The serverAddress will do a DNS lookup as appropriate. This call will block long enough to resolve
* the DNS lookup, but then will return a TcpConnection object that will be in a StatusNegotiating
* state until the connection is actually established. The application must give the manager
* object time after calling EstablishConnection or else the negotiation process to establish the
* connection will never have time to actually occur. Typically the client establishing the connection
* will call EstablishConnection, then sit in a loop calling TcpManager::GiveTime and checking to see
* if the status of the returned TcpConnection object is changed from StatusNegotiating. This allows
* the application to look for the ESC key or timeout an attempted connection.
*
* @param serverAddress The address of the server to open a connection to.
*
* @param serverPort The port of the server to open a connection to.
*
* @param timeout How long to attempt connecting to the server (in milliseconds).
* Setting the timeout value to something greater than 0 will cause the TcpConnection object to change
* from a StatusNegotiating state to a StatusDisconnected state after the timeout has expired. It will also cause
* the connect-complete callback to be called if the connection is succesfull.
*
* @return A pointer to a TcpConnection object.
* NULL if the manager object has exceeded its maximum number of connections
* or if the serverAddress cannot be resolved to an IP address.
*/
TcpConnection *EstablishConnection(const char *serverAddress, unsigned short serverPort, unsigned timeout = 0);
/**
* @brief Binds this manager as a server which will listen for and accept incoming connections.
*
* @return 'true' if manager is able to bind succesfully, false otherwise.
*/
bool BindAsServer();
/**
* @brief Standard AddRef/Release scheme
*/
void AddRef();
/**
* @brief Standard AddRef/Release scheme
*/
void Release();
/**
* @brief Returns the ip address of this machine. If the machine is multi-homed, this value may be blank.
*/
IPAddress GetLocalIp() const;
/**
* @brief Returns the port the manager is actually using. This value will be the same as is specified in
* Params::port (or if Params::port was set to 0, this will be the dynamically assigned port number)
*/
unsigned int GetLocalPort() const;
protected:
friend class TcpConnection;
void removeConnection(TcpConnection *con);
TcpManagerHandler *m_handler;
ConnectionList m_keepAliveList;
ConnectionList m_aliveList;
ConnectionList m_noDataList;
ConnectionList m_dataList;
private:
~TcpManager();
TcpParams m_params;
int m_refCount;
TcpConnection *m_connectionList;
unsigned m_connectionListCount;
#ifdef WIN32
fd_set m_permfds; /**< Used for select on WIN32 if we are in server mode. Keeps track of all clients connected to us. */
#endif //WIN32
SOCKET m_socket;
bool m_boundAsServer;
TcpBlockAllocator m_allocator;
Clock m_keepAliveTimer;
Clock m_noDataTimer;
void addNewConnection(TcpConnection *con);
SOCKET getMaxFD();
TcpConnection *getConnection(SOCKET fd);
TcpConnection *acceptClient();
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif //TCPMANAGER_H
@@ -0,0 +1,535 @@
#include "Client.h"
#include <stdio.h>
#include <string>
#include <map>
using namespace CTService;
using namespace Plat_Unicode;
extern unsigned openRequests;
extern std::map<unsigned, unsigned> m_tests;
//-------------------------------------------
Client::Client(const char *hostName, const char *game)
: CTServiceAPI(hostName, game), m_connected(false)
//-------------------------------------------
{
printf("\nClient::Client()");
}
//-------------------------------------------
Client::~Client()
//-------------------------------------------
{
printf("\nClient::~Client()");
}
//-------------------------------------------
void Client::onConnect(const char *host, short port, short current, short max)
//-------------------------------------------
{
printf("\nConnect to %s:%d (%d of %d)", host, port, current, max);
m_connected = true;
}
//-------------------------------------------
void Client::onDisconnect(const char *host, short port, short current, short max)
//-------------------------------------------
{
printf("\nDisconnect from %s:%d (%d of %d)", host, port, current, max);
m_connected = false;
}
/*
//-------------------------------------------
void Client::onTest(const unsigned track, const int resultCode, const unsigned value, void *user)
//-------------------------------------------
{
printf("\n[onTest] track(%d) resultCode(%s) value(%d)", track, ResultString[resultCode], value);
openRequests--;
}
*/
//-------------------------------------------
void Client::onServerTest(unsigned server_track, const char *game, const char *param)
//-------------------------------------------
{
printf("\n[onServerTest] server_track(%d), game(%s) param(%s)", server_track, game, param);
#if TEST_MULTIPLE_SERVERS == 1
m_tests.insert(std::pair<unsigned, unsigned>(server_track, (unsigned)(time(0) + 3))); // 35 for fail
printf("\nQueuing send for server track = %d", server_track);
//replyTest(server_track, server_track * 100, "Test");
//openRequests++;
#endif
}
/*
//-------------------------------------------
void Client::onReplyTest(const unsigned track, const int resultCode, void *user)
//-------------------------------------------
{
printf("\n[onReplyTest] track(%d) resultCode(%s)", track, ResultString[resultCode]);
openRequests--;
}
*/
//-------------------------------------------
void Client::onRequestMoveStatus(unsigned server_track, const char *language, const unsigned transactionID)
//-------------------------------------------
{
printf("\n[onRequestMoveStatus] server_track(%d), language(%s), transID(%d)", server_track, language, transactionID);
unsigned gameStatus = CT_STATUS_UNKNOWN;
unsigned ctStatus = CT_RESULT_TIMEOUT;
Plat_Unicode::String reason = narrowToWide("Reason String Text");
if (transactionID == 7000)
{
gameStatus = CT_STATUS_COMPLETE;
ctStatus = CT_RESULT_SUCCESS;
}
else if (transactionID == 6000)
{
gameStatus = CT_STATUS_UNKNOWN;
ctStatus = CT_RESULT_SUCCESS;
}
else if (transactionID == 5000)
{
gameStatus = CT_STATUS_INPROGRESS;
ctStatus = CT_RESULT_SUCCESS;
}
replyMoveStatus(server_track, CT_STATUS_UNKNOWN, CT_RESULT_SUCCESS, reason.c_str(),(void *)"test");
openRequests++;
}
//-------------------------------------------
void Client::onReplyMoveStatus(const unsigned track, const int resultCode, void *user)
//-------------------------------------------
{
printf("\n[onReplyMoveStatus] track(%d) resultCode(%s)", track, ResultString[resultCode]);
openRequests--;
}
//-------------------------------------------
void Client::onRequestValidateMove(unsigned server_track, const char *language, const CTUnicodeChar *sourceServer,
const CTUnicodeChar *destServer, const CTUnicodeChar *sourceCharacter,
const CTUnicodeChar *destCharacter, const unsigned uid,
const unsigned destuid, bool withItems, bool override)
//-------------------------------------------
{
Plat_Unicode::String sServer = sourceServer;
Plat_Unicode::String dServer = destServer;
Plat_Unicode::String sCharacter = sourceCharacter;
Plat_Unicode::String dCharacter = destCharacter;
printf("\n[onRequestValidateMove] server_track(%d), language(%s), sourceServer(%s), destServer(%s), sourceChar(%s), destChar(%s), uid(%d), destuid(%d), withItems(%d), override(%d)",
server_track, language, wideToNarrow(sServer).c_str(), wideToNarrow(dServer).c_str(),
wideToNarrow(sCharacter).c_str(), wideToNarrow(dCharacter).c_str(), uid, destuid, withItems, override);
Plat_Unicode::String reason = narrowToWide("Player has a corpse");
Plat_Unicode::String reason2 = narrowToWide("SUCCESS");
Plat_Unicode::String reason3 = narrowToWide("Name Taken");
Plat_Unicode::String reason4 = narrowToWide("Game Server down for routine maitenence");
Plat_Unicode::String suggestedName = narrowToWide("Fippyxxx");
Plat_Unicode::String suggestedName2 = narrowToWide("");
if (!strcmp(wideToNarrow(sCharacter).c_str() , "Homer"))
{
replyValidateMove(server_track, CT_GAMERESULT_HARDERROR, reason.c_str(), suggestedName2.c_str(), (void *)"Test");
}
else if (!strcmp(wideToNarrow(dCharacter).c_str() , "Fippy"))
{
replyValidateMove(server_track, CT_GAMERESULT_NAME_ALREADY_TAKE, reason3.c_str(), suggestedName.c_str(), (void *)"Test");
}
else if (!strcmp(wideToNarrow(sCharacter).c_str() , "Bart"))
{
replyValidateMove(server_track, CT_GAMERESULT_SOFTERROR, reason4.c_str(), suggestedName2.c_str(), (void *)"Test");
}
else
replyValidateMove(server_track, CT_GAMERESULT_SUCCESS, reason2.c_str(), suggestedName2.c_str(), (void *)"Test");
openRequests++;
}
//-------------------------------------------
void Client::onReplyValidateMove(const unsigned track, const int resultCode, void *user)
//-------------------------------------------
{
printf("\n[onReplyValidateMove] track(%d) resultCode(%s)", track, ResultString[resultCode]);
openRequests--;
}
//-------------------------------------------
void Client::onRequestMove(unsigned server_track, const char *language, const CTUnicodeChar *sourceServer,
const CTUnicodeChar *destServer, const CTUnicodeChar *sourceCharacter,
const CTUnicodeChar *destCharacter, const unsigned uid,
const unsigned destuid, const unsigned transactionID, bool withItems, bool override)
//-------------------------------------------
{
Plat_Unicode::String sServer = sourceServer;
Plat_Unicode::String dServer = destServer;
Plat_Unicode::String sCharacter = sourceCharacter;
Plat_Unicode::String dCharacter = destCharacter;
printf("\n[onRequestMove] server_track(%d), language(%s), sourceServer(%s), destServer(%s), sourceChar(%s), destChar(%s), uid(%d), destuid(%d), transID(%d) withItems(%d) override(%d)",
server_track, language, wideToNarrow(sServer).c_str(), wideToNarrow(dServer).c_str(),
wideToNarrow(sCharacter).c_str(), wideToNarrow(dCharacter).c_str(), uid, destuid, transactionID, withItems, override);
// Plat_Unicode::String reason = narrowToWide("Character does not exist");
// replyMove(server_track, CT_GAMERESULT_HARDERROR, reason.c_str(), "Test");
if (!strcmp(wideToNarrow(sCharacter).c_str() , "HomerX"))
{
Plat_Unicode::String reason = narrowToWide("");
replyMove(server_track, CT_GAMERESULT_HARDERROR, reason.c_str(), (void *)"Test");
}
else if (!strcmp(wideToNarrow(sCharacter).c_str() , "MargeX"))
{
Plat_Unicode::String reason = narrowToWide("Player has a corpse");
replyMove(server_track, CT_GAMERESULT_HAS_CORPSE, reason.c_str(), (void *)"Test");
}
else if (!strcmp(wideToNarrow(sCharacter).c_str() , "BartX"))
{
Plat_Unicode::String reason = narrowToWide("Game Server down for routine maitenence");
replyMove(server_track, CT_GAMERESULT_SOFTERROR, reason.c_str(), (void *)"Test");
}
else
{
Plat_Unicode::String reason = narrowToWide("Order completed successfully");
replyMove(server_track, CT_GAMERESULT_SUCCESS, reason.c_str(), (void *)"Test");
}
// else
// {
// Plat_Unicode::String reason = narrowToWide("Player has a corpse");
// replyMove(server_track, CT_GAMERESULT_HAS_CORPSE, reason.c_str(), "Test");
// }
// Plat_Unicode::String reason = narrowToWide("World server is down");
// replyMove(server_track, CT_GAMERESULT_SOFTERROR, reason.c_str(), "Test");
openRequests++;
}
//-------------------------------------------
void Client::onReplyMove(const unsigned track, const int resultCode, void *user)
//-------------------------------------------
{
printf("\n[onReplyMove] track(%d) resultCode(%s)", track, ResultString[resultCode]);
openRequests--;
}
//-------------------------------------------
void Client::onRequestDelete(unsigned server_track, const char *language, const CTUnicodeChar *sourceServer,
const CTUnicodeChar *destServer, const CTUnicodeChar *sourceCharacter,
const CTUnicodeChar *destCharacter, const unsigned uid,
const unsigned destuid, const unsigned transactionID, bool withItems, bool override)
//-------------------------------------------
{
Plat_Unicode::String sServer = sourceServer;
Plat_Unicode::String dServer = destServer;
Plat_Unicode::String sCharacter = sourceCharacter;
Plat_Unicode::String dCharacter = destCharacter;
printf("\n[onRequestDelete] server_track(%d), language(%s), sourceServer(%s), destServer(%s), sourceChar(%s), destChar(%s), uid(%d), destuid(%d), transID(%d), withItems(%d), override(%d)",
server_track, language, wideToNarrow(sServer).c_str(), wideToNarrow(dServer).c_str(),
wideToNarrow(sCharacter).c_str(), wideToNarrow(dCharacter).c_str(), uid, destuid, transactionID, withItems, override);
// Plat_Unicode::String reason = narrowToWide("Character does not exist");
// replyMove(server_track, CT_GAMERESULT_HARDERROR, reason.c_str(), "Test");
if (!strcmp(wideToNarrow(sCharacter).c_str() , "HomerX"))
{
Plat_Unicode::String reason = narrowToWide("");
replyDelete(server_track, CT_GAMERESULT_HARDERROR, reason.c_str(), (void *)"Test");
}
else if (!strcmp(wideToNarrow(sCharacter).c_str() , "MargeX"))
{
Plat_Unicode::String reason = narrowToWide("Player has a corpse");
replyDelete(server_track, CT_GAMERESULT_HAS_CORPSE, reason.c_str(), (void *)"Test");
}
else if (!strcmp(wideToNarrow(sCharacter).c_str() , "BartX"))
{
Plat_Unicode::String reason = narrowToWide("Game Server down for routine maitenence");
replyDelete(server_track, CT_GAMERESULT_SOFTERROR, reason.c_str(), (void *)"Test");
}
else
{
Plat_Unicode::String reason = narrowToWide("Order completed successfully");
replyDelete(server_track, CT_GAMERESULT_SUCCESS, reason.c_str(), (void *)"Test");
}
// else
// {
// Plat_Unicode::String reason = narrowToWide("Player has a corpse");
// replyDelete(server_track, CT_GAMERESULT_HAS_CORPSE, reason.c_str(), "Test");
// }
// Plat_Unicode::String reason = narrowToWide("World server is down");
// replyDelete(server_track, CT_GAMERESULT_SOFTERROR, reason.c_str(), "Test");
openRequests++;
}
//-------------------------------------------
void Client::onReplyDelete(const unsigned track, const int resultCode, void *user)
//-------------------------------------------
{
printf("\n[onReplyDelete] track(%d) resultCode(%s)", track, ResultString[resultCode]);
openRequests--;
}
//-------------------------------------------
void Client::onRequestRestore(unsigned server_track, const char *language, const CTUnicodeChar *sourceServer,
const CTUnicodeChar *destServer, const CTUnicodeChar *sourceCharacter,
const CTUnicodeChar *destCharacter, const unsigned uid,
const unsigned destuid, const unsigned transactionID, bool withItems, bool override)
//-------------------------------------------
{
Plat_Unicode::String sServer = sourceServer;
Plat_Unicode::String dServer = destServer;
Plat_Unicode::String sCharacter = sourceCharacter;
Plat_Unicode::String dCharacter = destCharacter;
printf("\n[onRequestRestore] server_track(%d), language(%s), sourceServer(%s), destServer(%s), sourceChar(%s), destChar(%s), uid(%d), destuid(%d), transID(%d), withItems(%d), override(%d)",
server_track, language, wideToNarrow(sServer).c_str(), wideToNarrow(dServer).c_str(),
wideToNarrow(sCharacter).c_str(), wideToNarrow(dCharacter).c_str(), uid, destuid, transactionID, withItems, override);
// Plat_Unicode::String reason = narrowToWide("Character does not exist");
// replyMove(server_track, CT_GAMERESULT_HARDERROR, reason.c_str(), "Test");
if (!strcmp(wideToNarrow(sCharacter).c_str() , "HomerX"))
{
Plat_Unicode::String reason = narrowToWide("");
replyRestore(server_track, CT_GAMERESULT_HARDERROR, reason.c_str(), (void *)"Test");
}
else if (!strcmp(wideToNarrow(sCharacter).c_str() , "MargeX"))
{
Plat_Unicode::String reason = narrowToWide("Player has a corpse");
replyRestore(server_track, CT_GAMERESULT_HAS_CORPSE, reason.c_str(), (void *)"Test");
}
else if (!strcmp(wideToNarrow(sCharacter).c_str() , "BartX"))
{
Plat_Unicode::String reason = narrowToWide("Game Server down for routine maitenence");
replyRestore(server_track, CT_GAMERESULT_SOFTERROR, reason.c_str(), (void *)"Test");
}
else
{
Plat_Unicode::String reason = narrowToWide("Order completed successfully");
replyRestore(server_track, CT_GAMERESULT_SUCCESS, reason.c_str(), (void *)"Test");
}
// else
// {
// Plat_Unicode::String reason = narrowToWide("Player has a corpse");
// replyRestore(server_track, CT_GAMERESULT_HAS_CORPSE, reason.c_str(), "Test");
// }
// Plat_Unicode::String reason = narrowToWide("World server is down");
// replyRestore(server_track, CT_GAMERESULT_SOFTERROR, reason.c_str(), "Test");
openRequests++;
}
//-------------------------------------------
void Client::onReplyRestore(const unsigned track, const int resultCode, void *user)
//-------------------------------------------
{
printf("\n[onReplyRestore] track(%d) resultCode(%s)", track, ResultString[resultCode]);
openRequests--;
}
//-------------------------------------------
void Client::onRequestTransferAccount(unsigned server_track,
const unsigned uid,
const unsigned destuid,
const unsigned transactionID)
//-------------------------------------------
{
printf("\n[onRequestTransferAccount] server_track(%d), uid(%d), destuid(%d), transID(%d)",
server_track, uid, destuid, transactionID);
// Plat_Unicode::String reason = narrowToWide("Character does not exist");
// replyMove(server_track, CT_GAMERESULT_HARDERROR, reason.c_str(), "Test");
if (uid == 521281339)
{
Plat_Unicode::String reason = narrowToWide("Tavish is too cool to move");
replyTransferAccount(server_track, CT_GAMERESULT_HARDERROR, reason.c_str(), (void *)"Test");
}
else if (destuid == 549981672)
{
Plat_Unicode::String reason = narrowToWide("devula as a dest ain't cool, there is a corpse to be rezzed");
replyTransferAccount(server_track, CT_GAMERESULT_HAS_CORPSE, reason.c_str(), (void *)"Test");
}
else
{
Plat_Unicode::String reason = narrowToWide("Order completed successfully");
replyTransferAccount(server_track, CT_GAMERESULT_SUCCESS, reason.c_str(), (void *)"Test");
}
openRequests++;
}
//-------------------------------------------
void Client::onReplyTransferAccount(const unsigned track, const int resultCode, void *user)
//-------------------------------------------
{
printf("\n[onReplyTransferAccount] track(%d) resultCode(%s)", track, ResultString[resultCode]);
openRequests--;
}
//-------------------------------------------
void Client::onRequestCharacterList(unsigned server_track, const char *language, const CTUnicodeChar *server, const unsigned uid)
//-------------------------------------------
{
Plat_Unicode::String sServer = server;
printf("\n[onRequestCharacterList] server_track(%d), language(%s), server(%s), uid(%d)",
server_track, language, wideToNarrow(sServer).c_str(), uid);
if (!strcmp(wideToNarrow(sServer).c_str() , "Tribunal"))
{
CTServiceCharacter chars[1];
replyCharacterList(server_track, CT_RESULT_FAILURE, 0, chars, (void *)"Test");
}
else if (!strcmp(wideToNarrow(sServer).c_str() , "Hoth"))
{
CTServiceCharacter chars[1];
replyCharacterList(server_track, CT_RESULT_TIMEOUT, 0, chars, (void *)"Test");
}
else
{
CTServiceCharacter chars[3];
chars[0].SetCanRename(true);
chars[0].SetCanMove(true);
chars[0].SetCanTransfer(true);
chars[0].SetCharacter(narrowToWide("Fippy").c_str());
chars[0].SetRenameReason(narrowToWide("Rename Reason 1").c_str());
chars[0].SetMoveReason(narrowToWide("Move Reason 1").c_str());
chars[0].SetTransferReason(narrowToWide("Transfer Reason 1").c_str());
chars[1].SetCanRename(false);
chars[1].SetCanMove(false);
chars[1].SetCanTransfer(false);
chars[1].SetCharacter(narrowToWide("Melyssa").c_str());
chars[1].SetRenameReason(narrowToWide("Rename Reason 2").c_str());
chars[1].SetMoveReason(narrowToWide("Move Reason 2").c_str());
chars[1].SetTransferReason(narrowToWide("Transfer Reason 2").c_str());
chars[2].SetCanRename(true);
chars[2].SetCanMove(false);
chars[2].SetCanTransfer(true);
chars[2].SetCharacter(narrowToWide("Bald Eagle").c_str());
chars[2].SetRenameReason(narrowToWide("Rename Reason 3").c_str());
chars[2].SetMoveReason(narrowToWide("Move Reason 3").c_str());
chars[2].SetTransferReason(narrowToWide("Transfer Reason 3").c_str());
replyCharacterList(server_track, CT_RESULT_SUCCESS, 3, chars, (void *)"Test");
}
openRequests++;
}
//-------------------------------------------
void Client::onReplyCharacterList(const unsigned track, const int resultCode, void *user)
//-------------------------------------------
{
printf("\n[onReplyCharacterList] track(%d) resultCode(%s)", track, ResultString[resultCode]);
openRequests--;
}
//-------------------------------------------
void Client::onRequestServerList(unsigned server_track, const char *language)
//-------------------------------------------
{
printf("\n[onRequestServerList] server_track(%d), language(%s)", server_track, language);
if (strcmp(language, "en"))
{
CTServiceServer s[1];
replyServerList(server_track, CT_RESULT_FAILURE, 0, s, (void *)"Test");
}
else
{
CTServiceServer s[4];
s[0].SetCanRename(true);
s[0].SetCanMove(true);
s[0].SetCanTransfer(true);
s[0].SetServer(narrowToWide("Server1").c_str());
s[0].SetRenameReason(narrowToWide("Server Rename Reason 1").c_str());
s[0].SetMoveReason(narrowToWide("Server Move Reason 1").c_str());
s[0].SetTransferReason(narrowToWide("Server Transfer Reason 1").c_str());
s[1].SetCanRename(true);
s[1].SetCanMove(true);
s[1].SetCanTransfer(false);
s[1].SetServer(narrowToWide("Server2").c_str());
s[1].SetRenameReason(narrowToWide("Server Rename Reason 2").c_str());
s[1].SetMoveReason(narrowToWide("Server Move Reason 2").c_str());
s[1].SetTransferReason(narrowToWide("Server Transfer Reason 2").c_str());
s[2].SetCanRename(true);
s[2].SetCanMove(false);
s[2].SetCanTransfer(true);
s[2].SetServer(narrowToWide("Server3").c_str());
s[2].SetRenameReason(narrowToWide("Server Rename Reason 3").c_str());
s[2].SetMoveReason(narrowToWide("Server Move Reason 3").c_str());
s[2].SetTransferReason(narrowToWide("Server Transfer Reason 3").c_str());
s[3].SetCanRename(false);
s[3].SetCanMove(true);
s[3].SetCanTransfer(true);
s[3].SetServer(narrowToWide("Server4").c_str());
s[3].SetRenameReason(narrowToWide("Server Rename Reason 4").c_str());
s[3].SetMoveReason(narrowToWide("Server Move Reason 4").c_str());
s[3].SetTransferReason(narrowToWide("Server Transfer Reason 4").c_str());
replyServerList(server_track, CT_RESULT_SUCCESS, 4, s, (void *)"Test");
}
openRequests++;
}
//-------------------------------------------
void Client::onReplyServerList(const unsigned track, const int resultCode, void *user)
//-------------------------------------------
{
printf("\n[onReplyServerList] track(%d) resultCode(%s)", track, ResultString[resultCode]);
openRequests--;
}
//-------------------------------------------
void Client::onRequestDestinationServerList(unsigned server_track, const char *language, const CTUnicodeChar *character, const CTUnicodeChar *server)
//-------------------------------------------
{
Plat_Unicode::String ss = server;
Plat_Unicode::String c = character;
printf("\n[onRequestDestinationServerList] server_track(%d), language(%s), character(%s), server(%s)",
server_track, language, wideToNarrow(c).c_str(), wideToNarrow(ss).c_str());
if (strcmp(language, "en"))
{
CTServiceServer s[1];
replyServerList(server_track, CT_RESULT_FAILURE, 0, s, (void *)"Test");
}
else
{
CTServiceServer s[2];
s[0].SetCanRename(true);
s[0].SetCanMove(true);
s[0].SetCanTransfer(true);
s[0].SetServer(narrowToWide("Server1").c_str());
s[0].SetRenameReason(narrowToWide("Server Rename Reason 1").c_str());
s[0].SetMoveReason(narrowToWide("Server Move Reason 1").c_str());
s[0].SetTransferReason(narrowToWide("Server Transfer Reason 1").c_str());
s[1].SetCanRename(true);
s[1].SetCanMove(true);
s[1].SetCanTransfer(false);
s[1].SetServer(narrowToWide("Server2").c_str());
s[1].SetRenameReason(narrowToWide("Server Rename Reason 2").c_str());
s[1].SetMoveReason(narrowToWide("Server Move Reason 2").c_str());
s[1].SetTransferReason(narrowToWide("Server Transfer Reason 2").c_str());
replyDestinationServerList(server_track, CT_RESULT_SUCCESS, 2, s, (void *)"Test");
}
openRequests++;
}
//-------------------------------------------
void Client::onReplyDestinationServerList(const unsigned track, const int resultCode, void *user)
//-------------------------------------------
{
printf("\n[onReplyDestinationServerList] track(%d) resultCode(%s)", track, ResultString[resultCode]);
openRequests--;
}
@@ -0,0 +1,92 @@
#ifndef CLIENT_H
#define CLIENT_H
#include "CTServiceGameAPI/CTServiceAPI.h"
#include <Base/Platform.h>
#include <Unicode/UnicodeUtils.h>
#include "CTServiceGameAPI/CTCommon/RequestStrings.h"
using namespace CTService;
#define TEST_MULTIPLE_SERVERS 0
#define TEST_FUNCTIONS 0
#define ACT_AS_SERVER 1
#define GING_TEST_STATUS 1 // test OnRequestMoveStatus
#define GING_TEST_VALIDATE 2 // test OnRequestValidateMove
#define GING_TEST_MOVE 3 // test OnRequestMove
#define GING_TEST_CHARACTER 4 // test OnRequestCharacterList
#define GING_TEST_SERVER 5 // test OnRequestServerList
#define GING_TEST_DESTSERVER 6 // test OnRequestDestinationServerList
#define GING_TEST_DELETE 7 // test OnRequestDelete
#define GING_TEST_RESTORE 8 // test OnRequestRestore
#define GING_TEST_TRANSFER_ACCOUNT 9 // test OnRequestRestore
//----------------------------------------
class Client : public CTServiceAPI
//----------------------------------------
{
public:
Client(const char *hostName, const char *game);
virtual ~Client();
void onConnect(const char *host, const short port, const short current, const short max);
void onDisconnect(const char *host, const short port, const short current, const short max);
bool m_connected;
//callbacks
// void onTest(const unsigned track, const int resultCode, const unsigned value, void *user);
// void onReplyTest(const unsigned track, const int resultCode, void *user);
void onReplyMoveStatus(const unsigned track, const int resultCode, void *user);
void onReplyValidateMove(const unsigned track, const int resultCode, void *user);
void onReplyMove(const unsigned track, const int resultCode, void *user);
void onReplyDelete(const unsigned track, const int resultCode, void *user);
void onReplyRestore(const unsigned track, const int resultCode, void *user);
void onReplyTransferAccount(const unsigned track, const int resultCode, void *user);
void onReplyCharacterList(const unsigned track, const int resultCode, void *user);
void onReplyServerList(const unsigned track, const int resultCode, void *user);
void onReplyDestinationServerList(const unsigned track, const int resultCode, void *user);
void onServerTest(const unsigned server_track, const char *game, const char *param);
void onRequestMoveStatus(const unsigned server_track, const char *language,
const unsigned transactionID);
void onRequestValidateMove(const unsigned server_track, const char *language,
const CTUnicodeChar *sourceServer,
const CTUnicodeChar *destServer,
const CTUnicodeChar *sourceCharacter,
const CTUnicodeChar *destCharacter, const unsigned uid,
const unsigned destuid, bool withItems, bool override);
void onRequestMove(const unsigned server_track, const char *language,
const CTUnicodeChar *sourceServer,
const CTUnicodeChar *destServer,
const CTUnicodeChar *sourceCharacter,
const CTUnicodeChar *destCharacter, const unsigned uid,
const unsigned destuid, const unsigned transactionID, bool withItems, bool override);
void onRequestDelete(const unsigned server_track, const char *language,
const CTUnicodeChar *sourceServer,
const CTUnicodeChar *destServer,
const CTUnicodeChar *sourceCharacter,
const CTUnicodeChar *destCharacter, const unsigned uid,
const unsigned destuid, const unsigned transactionID, bool withItems, bool override);
void onRequestRestore(const unsigned server_track, const char *language,
const CTUnicodeChar *sourceServer,
const CTUnicodeChar *destServer,
const CTUnicodeChar *sourceCharacter,
const CTUnicodeChar *destCharacter, const unsigned uid,
const unsigned destuid, const unsigned transactionID, bool withItems, bool override);
void onRequestTransferAccount(const unsigned server_track,
const unsigned uid,
const unsigned destuid,
const unsigned transactionID);
void onRequestCharacterList(const unsigned server_track, const char *language,
const CTUnicodeChar *server, const unsigned uid);
void onRequestServerList(const unsigned server_track, const char *language);
void onRequestDestinationServerList(const unsigned server_track, const char *language,
const CTUnicodeChar *character, const CTUnicodeChar *server);
};
#endif
@@ -0,0 +1,154 @@
#include <stdio.h>
#pragma warning (disable: 4786)
#include "Client.h"
#ifdef WIN32
#include <winsock.h>
#include <conio.h>
#endif
using namespace CTService;
unsigned openRequests = 0;
CTServiceAPI *waitclient = NULL;
std::map<unsigned, unsigned> m_tests;
std::string game_code;
//--------------------------------------------
void wait()
//--------------------------------------------
{
while (openRequests > 0 || m_tests.size())
{
waitclient->process();
Base::sleep(1);
#if TEST_MULTIPLE_SERVERS == 1
for(std::map<unsigned, unsigned>::iterator iter = m_tests.begin(); iter != m_tests.end(); iter++)
{
if ((unsigned)time(0) > (*iter).second)
{
unsigned strack = (*iter).first;
printf("\nProcessing send for server track = %d (%d remain)", strack, m_tests.size() - 1);
waitclient->replyTest(strack, strack * 100, "Test");
openRequests++;
m_tests.erase(strack);
break;
}
}
#endif
}
}
//--------------------------------------------
int main(int argc, char *argv[])
//--------------------------------------------
{
if (argc < 2)
{
printf("\nParams required: <game code>\n");
while(1);
}
game_code = argv[1];
Client client("localhost:2000", game_code.c_str());
waitclient = &client;
printf("\nCreated Client object, game = %s", game_code.c_str());
while (!client.m_connected)
{
client.process();
Base::sleep(1);
}
#if ACT_AS_SERVER == 1
printf("\n\nListening for requests from server....\n");
while (1)
{
client.process();
Base::sleep(1);
}
#endif
//begin the testing !!
printf("\nCommencing Tests...\n");
#if TEST_FUNCTIONS == 1
std::string testString = "FIP1";
client.requestTest(testString.c_str(), GING_TEST_STATUS, (void *)"Test");
openRequests++;
wait();
client.requestTest(testString.c_str(), GING_TEST_MOVE, (void *)"Test");
openRequests++;
wait();
client.requestTest(testString.c_str(), GING_TEST_VALIDATE, (void *)"Test");
openRequests++;
wait();
client.requestTest(testString.c_str(), GING_TEST_CHARACTER, (void *)"Test");
openRequests++;
wait();
client.requestTest(testString.c_str(), GING_TEST_SERVER, (void *)"Test");
openRequests++;
wait();
client.requestTest(testString.c_str(), GING_TEST_DESTSERVER, (void *)"Test");
openRequests++;
wait();
#endif
#if TEST_MULTIPLE_SERVERS == 1
std::string testString = "FIP1";
client.requestTest(testString.c_str(), 10, (void *)"Test");
openRequests++;
testString = "FIP2";
client.requestTest(testString.c_str(), 100, (void *)"Test");
openRequests++;
testString = "FIP3";
client.requestTest(testString.c_str(), 1000, (void *)"Test");
openRequests++;
testString = "FIP4";
client.requestTest(testString.c_str(), 10000, (void *)"Test");
openRequests++;
testString = "FIP2";
client.requestTest(testString.c_str(), 10, (void *)"Test");
openRequests++;
testString = "FIP3";
client.requestTest(testString.c_str(), 100, (void *)"Test");
openRequests++;
testString = "FIP4";
client.requestTest(testString.c_str(), 1000, (void *)"Test");
openRequests++;
testString = "FIP1";
client.requestTest(testString.c_str(), 10000, (void *)"Test");
openRequests++;
testString = "FIP3";
client.requestTest(testString.c_str(), 10, (void *)"Test");
openRequests++;
testString = "FIP4";
client.requestTest(testString.c_str(), 100, (void *)"Test");
openRequests++;
testString = "FIP1";
client.requestTest(testString.c_str(), 1000, (void *)"Test");
openRequests++;
testString = "FIP2";
client.requestTest(testString.c_str(), 10000, (void *)"Test");
openRequests++;
testString = "FIP4";
client.requestTest(testString.c_str(), 10, (void *)"Test");
openRequests++;
testString = "FIP1";
client.requestTest(testString.c_str(), 100, (void *)"Test");
openRequests++;
testString = "FIP2";
client.requestTest(testString.c_str(), 1000, (void *)"Test");
openRequests++;
testString = "FIP3";
client.requestTest(testString.c_str(), 10000, (void *)"Test");
openRequests++;
wait();
#endif
wait();
return 0;
}
@@ -0,0 +1,142 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="TestClient"
ProjectGUID="{493B2E28-66F8-4628-84A9-43CF5485CFFE}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..,../.."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ws2_32.lib"
OutputFile="$(OutDir)/TestClient.exe"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/TestClient.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../../utils,../../CTCommon,../"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE,EXTERNAL_DISTRO;NAMESPACE=&quot;CTService&quot;"
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="ws2_32.lib"
OutputFile="$(OutDir)/TestClient.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath=".\Client.cpp">
</File>
<File
RelativePath=".\Main.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
<File
RelativePath=".\Client.h">
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
@@ -0,0 +1,9 @@
// ======================================================================
//
// FirstUnicode.cpp
// copyright (c) 2001 Sony Online Entertainment
//
// ======================================================================
#include "FirstUnicode.h"
@@ -0,0 +1,26 @@
// ======================================================================
//
// FirstUnicode.h
// copyright (c) 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_PlatFirstUnicode_H
#define INCLUDED_PlatFirstUnicode_H
// ======================================================================
// stl unref inline func removed
#ifdef WIN32
// C4514 unreferenced inline/local function has been removed
// C4786 'identifier' : identifier was truncated to 'number' characters in the debug information
#pragma warning (disable:4514 4786)
#endif
// ======================================================================
#endif
@@ -0,0 +1,26 @@
// ======================================================================
//
// Unicode.cpp
// copyright (c) 2001 Sony Online Entertainment
//
// ======================================================================
#include "FirstUnicode.h"
#include "Unicode.h"
// ======================================================================
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Plat_Unicode
{
};
#ifdef EXTERNAL_DISTRO
};
#endif
// ======================================================================
@@ -0,0 +1,58 @@
// ======================================================================
// Unicode.h
// copyright (c) 2001 Sony Online Entertainment
//
// jwatson
//
// Basic Unicode primitives and string handling/manipulating functions
// ======================================================================
#ifndef INCLUDED_PlatUnicode_H
#define INCLUDED_PlatUnicode_H
#if WIN32
#pragma warning (disable:4710)
#pragma warning (disable:4786)
// stl warning func not inlined
#pragma warning (disable:4514)
#endif
#include <string>
//-----------------------------------------------------------------
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Plat_Unicode
{
typedef unsigned short unicode_char_t;
/**
* Standard Unicode string is UTF-16
*/
typedef std::basic_string<unicode_char_t> String;
/**
* NarrowString is a ascii string.
*/
typedef std::string NarrowString;
const unicode_char_t whitespace [] = { ' ', '\n', '\r', '\t', 0 };
const unicode_char_t endlines [] = { '\r', '\n', 0 };
const char ascii_whitespace [] = { ' ', '\n', '\r', '\t', 0 };
const char ascii_endlines [] = { '\r', '\n', 0 };
};
#ifdef EXTERNAL_DISTRO
};
#endif
//-----------------------------------------------------------------
#endif
@@ -0,0 +1,267 @@
// ======================================================================
//
// UnicodeBlocks.cpp
// copyright (c) 2001 Sony Online Entertainment
//
// This contains Unicode 3.0 compliant Blocks.
//
// ======================================================================
#include "FirstUnicode.h"
#include "UnicodeBlocks.h"
// ======================================================================
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
using namespace Plat_Unicode::Blocks;
using Plat_Unicode::unicode_char_t;
//-----------------------------------------------------------------
const Plat_Unicode::Blocks::RawData Plat_Unicode::Blocks::Mapping::ms_defaultBlockData [] =
{
{ Basic_Latin, "Basic Latin",0x0000,0x007F },
{ Latin_1_Supplement,"Latin-1 Supplement",0x0080,0x00FF },
{ Latin_Extended_A, "Latin Extended-A",0x0100,0x017F },
{ Latin_Extended_B, "Latin Extended-B",0x0180,0x024F },
{ IPA_Extensions, "IPA Extensions",0x0250,0x02AF },
{ Spacing_Modifier_Letters, "Spacing Modifier Letters",0x02B0,0x02FF },
{ Combining_Diacritical_Marks, "Combining Diacritical Marks",0x0300,0x036F },
{ Greek, "Greek",0x0370,0x03FF },
{ Cyrillic, "Cyrillic",0x0400,0x04FF },
{ Armenian, "Armenian",0x0530,0x058F },
{ Hebrew, "Hebrew",0x0590,0x05FF },
{ Arabic, "Arabic",0x0600,0x06FF },
{ Syriac, "Syriac ",0x0700,0x074F },
{ Thaana, "Thaana",0x0780,0x07BF },
{ Devanagari, "Devanagari",0x0900,0x097F },
{ Bengali, "Bengali",0x0980,0x09FF },
{ Gurmukhi, "Gurmukhi",0x0A00,0x0A7F },
{ Gujarati, "Gujarati",0x0A80,0x0AFF },
{ Oriya, "Oriya",0x0B00,0x0B7F },
{ Tamil, "Tamil",0x0B80,0x0BFF },
{ Telugu, "Telugu",0x0C00,0x0C7F },
{ Kannada, "Kannada",0x0C80,0x0CFF },
{ Malayalam, "Malayalam",0x0D00,0x0D7F },
{ Sinhala, "Sinhala",0x0D80,0x0DFF },
{ Thai, "Thai",0x0E00,0x0E7F },
{ Lao, "Lao",0x0E80,0x0EFF },
{ Tibetan, "Tibetan",0x0F00,0x0FFF },
{ Myanmar, "Myanmar ",0x1000,0x109F },
{ Georgian, "Georgian",0x10A0,0x10FF },
{ Hangul_Jamo, "Hangul Jamo",0x1100,0x11FF },
{ Ethiopic, "Ethiopic",0x1200,0x137F },
{ Cherokee, "Cherokee",0x13A0,0x13FF },
{ Unified_Canadian_Aboriginal_Syllabics, "Unified Canadian Aboriginal Syllabics",0x1400,0x167F },
{ Ogham, "Ogham",0x1680,0x169F },
{ Runic, "Runic",0x16A0,0x16FF },
{ Khmer, "Khmer",0x1780,0x17FF },
{ Mongolian, "Mongolian",0x1800,0x18AF },
{ Latin_Extended_Additional, "Latin Extended Additional",0x1E00,0x1EFF },
{ Greek_Extended, "Greek Extended",0x1F00,0x1FFF },
{ General_Punctuation, "General Punctuation",0x2000,0x206F },
{ Superscripts_and_Subscripts, "Superscripts and Subscripts",0x2070,0x209F },
{ Currency_Symbols, "Currency Symbols",0x20A0,0x20CF },
{ Combining_Marks_for_Symbols, "Combining Marks for Symbols",0x20D0,0x20FF },
{ Letterlike_Symbols, "Letterlike Symbols",0x2100,0x214F },
{ Number_Forms, "Number Forms",0x2150,0x218F },
{ Arrows, "Arrows",0x2190,0x21FF },
{ Mathematical_Operators, "Mathematical Operators",0x2200,0x22FF },
{ Miscellaneous_Technical, "Miscellaneous Technical",0x2300,0x23FF },
{ Control_Pictures, "Control Pictures",0x2400,0x243F },
{ Optical_Character_Recognition, "Optical Character Recognition",0x2440,0x245F },
{ Enclosed_Alphanumerics, "Enclosed Alphanumerics",0x2460,0x24FF },
{ Box_Drawing, "Box Drawing",0x2500,0x257F },
{ Block_Elements, "Block Elements",0x2580,0x259F },
{ Geometric_Shapes, "Geometric Shapes",0x25A0,0x25FF },
{ Miscellaneous_Symbols, "Miscellaneous Symbols",0x2600,0x26FF },
{ Dingbats, "Dingbats",0x2700,0x27BF },
{ Braille_Patterns, "Braille Patterns",0x2800,0x28FF },
{ CJK_Radicals_Supplement, "CJK Radicals Supplement",0x2E80,0x2EFF },
{ Kangxi_Radicals, "Kangxi Radicals",0x2F00,0x2FDF },
{ Ideographic_Description_Characters, "Ideographic Description Characters",0x2FF0,0x2FFF },
{ CJK_Symbols_and_Punctuation, "CJK Symbols and Punctuation",0x3000,0x303F },
{ Hiragana, "Hiragana",0x3040,0x309F },
{ Katakana, "Katakana",0x30A0,0x30FF },
{ Bopomofo, "Bopomofo",0x3100,0x312F },
{ Hangul_Compatibility_Jamo, "Hangul Compatibility Jamo",0x3130,0x318F },
{ Kanbun, "Kanbun",0x3190,0x319F },
{ Bopomofo_Extended, "Bopomofo Extended",0x31A0,0x31BF },
{ Enclosed_CJK_Letters_and_Months, "Enclosed CJK Letters and Months",0x3200,0x32FF },
{ CJK_Compatibility, "CJK Compatibility",0x3300,0x33FF },
{ CJK_Unified_Ideographs_Extension_A, "CJK Unified Ideographs Extension A",0x3400,0x4DB5 },
{ CJK_Unified_Ideographs, "CJK Unified Ideographs",0x4E00,0x9FFF },
{ Yi_Syllables, "Yi Syllables",0xA000,0xA48F },
{ Yi_Radicals, "Yi Radicals",0xA490,0xA4CF },
{ Hangul_Syllables, "Hangul Syllables",0xAC00,0xD7A3 },
{ High_Surrogates, "High Surrogates",0xD800,0xDB7F },
{ High_Private_Use_Surrogates, "High Private Use Surrogates",0xDB80,0xDBFF },
{ Low_Surrogates, "Low Surrogates",0xDC00,0xDFFF },
{ Private_Use, "Private Use",0xE000,0xF8FF },
{ CJK_Compatibility_Ideographs, "CJK Compatibility Ideographs",0xF900,0xFAFF },
{ Alphabetic_Presentation_Forms, "Alphabetic Presentation Forms",0xFB00,0xFB4F },
{ Arabic_Presentation_Forms_A, "Arabic Presentation Forms-A",0xFB50,0xFDFF },
{ Combining_Half_Marks, "Combining Half Marks",0xFE20,0xFE2F },
{ CJK_Compatibility_Forms, "CJK Compatibility Forms",0xFE30,0xFE4F },
{ Small_Form_Variants, "Small Form Variants",0xFE50,0xFE6F },
{ Arabic_Presentation_Forms_B, "Arabic Presentation Forms-B",0xFE70,0xFEFE },
{ Specials_1, "Specials",0xFEFF,0xFEFF },
{ Halfwidth_and_Fullwidth_Forms, "Halfwidth and Fullwidth Forms",0xFF00,0xFFEF },
{ Specials_2, "Specials 2",0xFFF0,0xFFFD },
{ End_Block_Ids, "End Block Ids",0xFFFE,0xFFFF }
};
//-----------------------------------------------------------------
Mapping * Mapping::ms_singleton = 0;
//-----------------------------------------------------------------
/**
* Initialize the singleton. This must be called before mapping is used.
*/
void Mapping::initSingleton ()
{
explicitDestroy ();
ms_singleton = new Mapping (ms_defaultBlockData);
}
//-----------------------------------------------------------------
/**
* Destroys the singleton
*/
void Mapping::explicitDestroy ()
{
if (ms_singleton)
delete ms_singleton;
ms_singleton = 0;
}
//-----------------------------------------------------------------
/**
* Construct a Mapping from an array of RawData
*/
Mapping::Mapping (const RawData dataArray []) :
m_idMap (),
m_nameMap (),
m_errorData ()
{
size_t i = 0;
for (; dataArray [i].m_id != End_Block_Ids; ++i)
{
m_idMap [dataArray[i].m_id] = Data (dataArray [i]);
m_nameMap [dataArray[i].m_name] = Data (dataArray [i]);
}
m_errorData = Data (dataArray [i]);
}
//----------------------------------------------------------------------
/**
* Construct a complete set of code points in this block.
* @param idset should enter this function empty
*/
const std::set<unicode_char_t> & Data::generateFilteredIdSet (std::set<unicode_char_t> & idset) const
{
{
for (unicode_char_t i = m_start; i < m_end; ++i)
{
idset.insert (i);
}
}
for (RangeGroups_t::const_iterator iter = m_rangeGroups.begin (); iter != m_rangeGroups.end (); ++iter)
{
const RangeGroup & rg = *iter;
if (rg.m_isInclusive)
{
for (RangeGroup::Ranges_t::const_iterator rg_iter = rg.m_ranges.begin (); rg_iter != rg.m_ranges.end (); ++rg_iter)
{
for (unicode_char_t i = (*rg_iter).m_low; i <= (*rg_iter).m_high; ++i)
{
idset.insert (i);
}
}
}
else
{
for (RangeGroup::Ranges_t::const_iterator rg_iter = rg.m_ranges.begin (); rg_iter != rg.m_ranges.end (); ++rg_iter)
{
for (unicode_char_t i = (*rg_iter).m_low; i <= (*rg_iter).m_high; ++i)
{
idset.erase (i);
}
}
}
}
return idset;
}
//-----------------------------------------------------------------
/**
* Add a range group with a given string representation. Valid strings include hexadecimal numbers, dashes, and commas.
* @param inclusive indicates if this group should be additive or subtractive. It is an error to attempt to add code points outside the Block's gross range.
*/
bool Data::addRangeGroup (bool inclusive, const Plat_Unicode::NarrowString & str)
{
RangeGroup rg;
rg.m_isInclusive = inclusive;
size_t tokenStartPos = 0;
while (tokenStartPos != NarrowString::npos)
{
size_t tokenCommaPos = str.find_first_of (',', tokenStartPos);
size_t tokenDashPos = str.find_first_of ('-', tokenStartPos);
Range rng;
// this is a dashed range
if (tokenDashPos < tokenCommaPos)
{
rng.m_low = static_cast<unicode_char_t> (strtoul ( str.substr (tokenStartPos, tokenDashPos - tokenStartPos).c_str (), 0, 16));
tokenStartPos = str.find_first_not_of ('-', tokenDashPos);
if (tokenStartPos == NarrowString::npos)
return false;
rng.m_high = static_cast<unicode_char_t> (strtoul (str.substr (tokenStartPos, tokenCommaPos - tokenStartPos).c_str (), 0, 16));
}
else
{
rng.m_high = rng.m_low = static_cast<unicode_char_t> (strtoul ( str.substr (tokenStartPos, tokenCommaPos - tokenStartPos).c_str (), 0, 16));
}
rg.m_ranges.push_back (rng);
tokenStartPos = str.find_first_not_of (',', tokenCommaPos);
}
m_rangeGroups.push_back (rg);
return true;
};
#ifdef EXTERNAL_DISTRO
};
#endif
// ===================================================================== },
@@ -0,0 +1,404 @@
// ======================================================================
//
// UnicodeBlocks.h
// copyright (c) 2001 Sony Online Entertainment
//
// This contains Unicode 3.0 compliant Blocks.
//
// ======================================================================
#ifndef INCLUDED_PlatUnicodeBlocks_H
#define INCLUDED_PlatUnicodeBlocks_H
#if WIN32
// stl warning func not inlined
#pragma warning (disable:4710)
#pragma warning (disable:4786)
#endif
#include "Unicode.h"
#include <map>
#include <vector>
#include <set>
// ======================================================================
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Plat_Unicode
{
namespace Blocks
{
/**
* The enum values are precisely the beginning of the represented block range.
* These blocks are precisely the blocks defined by Unicode 3.0.
*/
enum Id
{
Basic_Latin = 0x0000,
Latin_1_Supplement = 0x0080,
Latin_Extended_A = 0x0100,
Latin_Extended_B = 0x0180,
IPA_Extensions = 0x0250,
Spacing_Modifier_Letters = 0x02B0,
Combining_Diacritical_Marks = 0x0300,
Greek = 0x0370,
Cyrillic = 0x0400,
Armenian = 0x0530,
Hebrew = 0x0590,
Arabic = 0x0600,
Syriac = 0x0700,
Thaana = 0x0780,
Devanagari = 0x0900,
Bengali = 0x0980,
Gurmukhi = 0x0A00,
Gujarati = 0x0A80,
Oriya = 0x0B00,
Tamil = 0x0B80,
Telugu = 0x0C00,
Kannada = 0x0C80,
Malayalam = 0x0D00,
Sinhala = 0x0D80,
Thai = 0x0E00,
Lao = 0x0E80,
Tibetan = 0x0F00,
Myanmar = 0x1000,
Georgian = 0x10A0,
Hangul_Jamo = 0x1100,
Ethiopic = 0x1200,
Cherokee = 0x13A0,
Unified_Canadian_Aboriginal_Syllabics = 0x1400,
Ogham = 0x1680,
Runic = 0x16A0,
Khmer = 0x1780,
Mongolian = 0x1800,
Latin_Extended_Additional = 0x1E00,
Greek_Extended = 0x1F00,
General_Punctuation = 0x2000,
Superscripts_and_Subscripts = 0x2070,
Currency_Symbols = 0x20A0,
Combining_Marks_for_Symbols = 0x20D0,
Letterlike_Symbols = 0x2100,
Number_Forms = 0x2150,
Arrows = 0x2190,
Mathematical_Operators = 0x2200,
Miscellaneous_Technical = 0x2300,
Control_Pictures = 0x2400,
Optical_Character_Recognition = 0x2440,
Enclosed_Alphanumerics = 0x2460,
Box_Drawing = 0x2500,
Block_Elements = 0x2580,
Geometric_Shapes = 0x25A0,
Miscellaneous_Symbols = 0x2600,
Dingbats = 0x2700,
Braille_Patterns = 0x2800,
CJK_Radicals_Supplement = 0x2E80,
Kangxi_Radicals = 0x2F00,
Ideographic_Description_Characters = 0x2FF0,
CJK_Symbols_and_Punctuation = 0x3000,
Hiragana = 0x3040,
Katakana = 0x30A0,
Bopomofo = 0x3100,
Hangul_Compatibility_Jamo = 0x3130,
Kanbun = 0x3190,
Bopomofo_Extended = 0x31A0,
Enclosed_CJK_Letters_and_Months = 0x3200,
CJK_Compatibility = 0x3300,
CJK_Unified_Ideographs_Extension_A = 0x3400,
CJK_Unified_Ideographs = 0x4E00,
Yi_Syllables = 0xA000,
Yi_Radicals = 0xA490,
Hangul_Syllables = 0xAC00,
High_Surrogates = 0xD800,
High_Private_Use_Surrogates = 0xDB80,
Low_Surrogates = 0xDC00,
Private_Use = 0xE000,
CJK_Compatibility_Ideographs = 0xF900,
Alphabetic_Presentation_Forms = 0xFB00,
Arabic_Presentation_Forms_A = 0xFB50,
Combining_Half_Marks = 0xFE20,
CJK_Compatibility_Forms = 0xFE30,
Small_Form_Variants = 0xFE50,
Arabic_Presentation_Forms_B = 0xFE70,
Specials_1 = 0xFEFF,
Halfwidth_and_Fullwidth_Forms = 0xFF00,
Specials_2 = 0xFFF0,
End_Block_Ids = 0xFFFE
};
//-----------------------------------------------------------------
/**
* A simple pair representing an inclusive range of values
*/
struct Range
{
unicode_char_t m_high;
unicode_char_t m_low;
};
//-----------------------------------------------------------------
/**
* A group of ranges that can be additive or subtractive (inclusive or non)
*/
struct RangeGroup
{
bool m_isInclusive;
typedef std::vector<Range> Ranges_t;
Ranges_t m_ranges;
};
//-----------------------------------------------------------------
/**
* RawData is a simple aggregate data struct used to construct the more complex Data objects
*/
struct RawData
{
Id m_id;
const char * m_name;
unicode_char_t m_start;
unicode_char_t m_end;
};
/**
* Data is the representation of a single Unicode block.
* Including the Id, name, gross start-end range, and a set of RangeGroups (usually subtractive)
*/
struct Data
{
Id m_id;
NarrowString m_name;
unicode_char_t m_start;
unicode_char_t m_end;
typedef std::vector <RangeGroup> RangeGroups_t;
RangeGroups_t m_rangeGroups;
explicit Data (const RawData & rhs);
Data ();
const std::set<unicode_char_t> & generateFilteredIdSet (std::set<unicode_char_t> & ) const;
bool addRangeGroup (bool inclusive, const NarrowString & str);
};
//-----------------------------------------------------------------
/**
* Singleton class.
*
* Mapping creates a method of mapping block Ids _or_ names to Block Data objects.
* @todo: Data objects are duplicate for each map, need to optimize.
*/
class Mapping
{
public:
explicit Mapping (const RawData dataArray[]);
static const Mapping & getDefaultMapping ();
static void explicitDestroy ();
typedef std::map <Id, Data> IdMap_t;
typedef std::map <NarrowString, Data> NameMap_t;
const Data & findBlock (Id id) const;
Data & findBlock (Id id);
const Data & findBlock (const NarrowString &) const;
const Data & findBlock (unicode_char_t code) const;
const IdMap_t & getIdMap () const;
bool addBlock (const Data & data);
static const RawData ms_defaultBlockData [];
private:
Mapping ();
Mapping (const Mapping & rhs);
Mapping & operator= (const Mapping & rhs);
static void initSingleton ();
static Mapping * ms_singleton;
IdMap_t m_idMap;
NameMap_t m_nameMap;
Data m_errorData;
};
//-----------------------------------------------------------------
/**
* Convert a RawData into a Data object
*/
inline Data::Data (const RawData & rhs) :
m_id (rhs.m_id),
m_name (rhs.m_name),
m_start (rhs.m_start),
m_end (rhs.m_end),
m_rangeGroups ()
{
}
//----------------------------------------------------------------------
/**
* Default constructor.
*/
inline Data::Data () :
m_id (End_Block_Ids),
m_name (),
m_start (0),
m_end (0),
m_rangeGroups ()
{
}
//-----------------------------------------------------------------
/**
* Static singleton accessor
*/
inline const Mapping & Mapping::getDefaultMapping ()
{
if (ms_singleton)
return *ms_singleton;
initSingleton ();
return *ms_singleton;
}
//-----------------------------------------------------------------
/**
* Add a block Data object to the mapping. If the block already exists
* in the mapping, the new data overwrites the old.
*/
inline bool Mapping::addBlock (const Data & data)
{
m_idMap [data.m_id] = data;
m_nameMap [data.m_name] = data;
return true;
}
//-----------------------------------------------------------------
/**
* Locate the block data by Id.
* @return a Data with End_Block_Ids Id if the block was not found
*/
inline const Data & Mapping::findBlock (Id id) const
{
const IdMap_t::const_iterator iter = m_idMap.find (id);
if (iter != m_idMap.end ())
return (*iter).second;
else
return m_errorData;
}
//-----------------------------------------------------------------
/**
* Locate the block data by Id.
* @return a Data with End_Block_Ids Id if the block was not found
*/
inline Data & Mapping::findBlock (Id id)
{
const IdMap_t::iterator iter = m_idMap.find (id);
if (iter != m_idMap.end ())
return (*iter).second;
else
return m_errorData;
}
//-----------------------------------------------------------------
/**
* Locate the block data by Name.
* @return a Data with End_Block_Ids Id if the block was not found
*/
inline const Data & Mapping::findBlock (const NarrowString & name) const
{
const NameMap_t::const_iterator iter = m_nameMap.find (name);
if (iter != m_nameMap.end ())
return (*iter).second;
else
return m_errorData;
}
//-----------------------------------------------------------------
/**
* Locate the block data by code point.
* @return a Data with End_Block_Ids Id if the block was not found. This only tests if the code point is in the gross range of the located block.
*/
inline const Data & Mapping::findBlock (unicode_char_t code) const
{
const IdMap_t::const_iterator iter = m_idMap.lower_bound (static_cast<Id>(code));
if (iter != m_idMap.end () && code <= (*iter).second.m_end)
return (*iter).second;
else
return m_errorData;
}
//-----------------------------------------------------------------
/**
* Gets the Id->Data map.
*/
inline const Mapping::IdMap_t & Mapping::getIdMap () const
{
return m_idMap;
}
//-----------------------------------------------------------------
/**
* Tests a character to see if belongs in an ideograph range
*/
inline bool isIdeograph (unicode_char_t code)
{
return ((code >= static_cast<unicode_char_t>(CJK_Unified_Ideographs_Extension_A) && code < static_cast<unicode_char_t>(Yi_Syllables)) ||
(code >= static_cast<unicode_char_t>(Hangul_Syllables) && code < static_cast<unicode_char_t>(CJK_Compatibility_Ideographs)));
}
} //-- namespace Blocks
}; // -- namespace Unicode
#ifdef EXTERNAL_DISTRO
};
#endif
// ======================================================================
#endif
@@ -0,0 +1,71 @@
#if defined (linux) && ((__GNUC__ == 3 && __GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL == 3) || (__GNUC__ == 2 && __GNUC_MINOR__ > 96))
#include <bits/char_traits.h>
#include "Unicode.h"
#ifdef EXTERNAL_DISTRO
using namespace NAMESPACE::Plat_Unicode;
#else
using namespace Plat_Unicode;
#endif
namespace std
{
void char_traits<unicode_char_t>::assign(unicode_char_t &__c1, const unicode_char_t &__c2)
{
__c1 = __c2;
}
bool char_traits<unicode_char_t>::eq(const unicode_char_t &__c1, const unicode_char_t &__c2)
{
return __c1 == __c2;
}
bool char_traits<unicode_char_t>::lt(const unicode_char_t &__c1, const unicode_char_t &__c2)
{
return __c1 < __c2;
}
unicode_char_t *char_traits<unicode_char_t>::copy(unicode_char_t *__s1, const unicode_char_t *__s2, size_t __n)
{
return(__n == 0 ? __s1 : (unicode_char_t*)memcpy(__s1, __s2, __n * sizeof(unicode_char_t)));
}
unicode_char_t *char_traits<unicode_char_t>::move(unicode_char_t *__s1, const unicode_char_t* __s2, size_t _Sz)
{
return (_Sz == 0 ? __s1 : (unicode_char_t*)memmove(__s1, __s2, _Sz * sizeof(unicode_char_t)));
}
const unicode_char_t *char_traits<unicode_char_t>::find(const unicode_char_t* __s, size_t __n, const unicode_char_t & __c)
{
for( ; __n > 0; ++__s, --__n)
if(eq(*__s, __c))
return __s;
return 0;
}
size_t char_traits<unicode_char_t>::length(const unicode_char_t *__s)
{
size_t __i;
for(__i = 0; !eq(__s[__i], 0); ++__i);
return __i;
}
unicode_char_t *char_traits<unicode_char_t>::assign(unicode_char_t *__s, size_t __n, unicode_char_t __c)
{
for(size_t __i = 0; __i < __n; ++__i)
__s[__i] = __c;
return __s;
}
int char_traits<unicode_char_t>::compare(const unicode_char_t *__s1, const unicode_char_t *__s2, size_t __n)
{
for(size_t __i = 0; __i < __n; ++__i)
if(!eq(__s1[__i], __s2[__i]))
return __s1[__i] < __s2[__i] ? -1 : 1;
return 0;
}
}
#endif
@@ -0,0 +1,71 @@
// ======================================================================
//
// Plat_UnicodeCharData.cpp
// copyright (c) 2001 Sony Online Entertainment
//
// This contains Plat_Unicode 3.0 compliant Character data formats
// The data is loaded dynamically from the Plat_UnicodeData.txt definition file
//
// ======================================================================
#include "FirstUnicode.h"
#include "UnicodeCharacterData.h"
// ======================================================================
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Plat_Unicode
{
//-----------------------------------------------------------------
#define CAT_NAME(s) { CharData::s, #s }
const CharData::CategoryName CharData::ms_categoryNames [] =
{
CAT_NAME (Lu), // Letter, Uppercase
CAT_NAME (Ll), // Letter, Lowercase
CAT_NAME (Lt), // Letter, Titlecase
CAT_NAME (Lm), // Letter, Modifier
CAT_NAME (Lo), // Letter, Other
CAT_NAME (Mn), // Mark, Non-Spacing
CAT_NAME (Mc), // Mark, Spacing Combining
CAT_NAME (Me), // Mark, Enclosing
CAT_NAME (Nd), // Number, Decimal Digit
CAT_NAME (Nl), // Number, Letter
CAT_NAME (No), // Number, Other
CAT_NAME (Pc), // Punctuation, Connector
CAT_NAME (Pd), // Punctuation, Dash
CAT_NAME (Ps), // Punctuation, Open
CAT_NAME (Pe), // Punctuation, Close
CAT_NAME (Pi), // Punctuation, Initial quote (may behave like Ps or Pe depending on usage)
CAT_NAME (Pf), // Punctuation, Final quote (may behave like Ps or Pe depending on usage)
CAT_NAME (Po), // Punctuation, Other
CAT_NAME (Sm), // Symbol, Math
CAT_NAME (Sc), // Symbol, Currency
CAT_NAME (Sk), // Symbol, Modifier
CAT_NAME (So), // Symbol, Other
CAT_NAME (Zs), // Separator, Space
CAT_NAME (Zl), // Separator, Line
CAT_NAME (Zp), // Separator, Paragraph
CAT_NAME (Cc), // Other, Control
CAT_NAME (Cf), // Other, Format
CAT_NAME (Cs), // Other, Surrogate
CAT_NAME (Co), // Other, Private Use
CAT_NAME (Cn) // Other, Not Assigned (no characters in the file have this property)
};
#undef CAT_NAME
};
#ifdef EXTERNAL_DISTRO
};
#endif
//-----------------------------------------------------------------
// ======================================================================
@@ -0,0 +1,125 @@
// ======================================================================
//
// UnicodeCharData.h
// copyright (c) 2001 Sony Online Entertainment
//
// This contains Unicode 3.0 compliant Character data formats
// The data is loaded dynamically from the UnicodeData.txt definition file
//
// ======================================================================
#ifndef INCLUDED_PlatUnicodeCharData_H
#define INCLUDED_PlatUnicodeCharData_H
#if WIN32
// stl warning func not inlined
#pragma warning (disable:4710)
#pragma warning (disable:4786)
#endif
// ======================================================================
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Plat_Unicode
{
typedef unsigned short unicode_char_t; //lint !e761 redundant typedef
struct CharData;
//-----------------------------------------------------------------
struct CharData
{
enum Category
{
Lu, // Letter, Uppercase
Ll, // Letter, Lowercase
Lt, // Letter, Titlecase
Lm, // Letter, Modifier
Lo, // Letter, Other
Mn, // Mark, Non-Spacing
Mc, // Mark, Spacing Combining
Me, // Mark, Enclosing
Nd, // Number, Decimal Digit
Nl, // Number, Letter
No, // Number, Other
Pc, // Punctuation, Connector
Pd, // Punctuation, Dash
Ps, // Punctuation, Open
Pe, // Punctuation, Close
Pi, // Punctuation, Initial quote (may behave like Ps or Pe depending on usage)
Pf, // Punctuation, Final quote (may behave like Ps or Pe depending on usage)
Po, // Punctuation, Other
Sm, // Symbol, Math
Sc, // Symbol, Currency
Sk, // Symbol, Modifier
So, // Symbol, Other
Zs, // Separator, Space
Zl, // Separator, Line
Zp, // Separator, Paragraph
Cc, // Other, Control
Cf, // Other, Format
Cs, // Other, Surrogate
Co, // Other, Private Use
Cn // Other, Not Assigned (no characters in the file have this property)
};
struct CategoryName
{
Category m_category;
const char * m_str;
};
static const CategoryName ms_categoryNames[];
unicode_char_t m_code;
Category m_category;
/**
* Note: this Unicode system only supports upper and lower case.
* Titlecase is considered uppercase. The case of a character
* is determined by its category (Lu,Ll,or Lt)
*/
unicode_char_t m_reverseCase;
bool isLowerCase () const;
bool isUpperCase () const;
unicode_char_t toUpper () const;
unicode_char_t toLower () const;
};
//-----------------------------------------------------------------
/**
* Is this character lowercase.
*/
inline bool CharData::isLowerCase () const
{
return m_category == Ll;
}
//-----------------------------------------------------------------
/**
* Returns true for upper and title case
*/
inline bool CharData::isUpperCase () const
{
return m_category == Lu || m_category == Lt;
}
};
#ifdef EXTERNAL_DISTRO
};
#endif
// ======================================================================
#endif
@@ -0,0 +1,360 @@
// ======================================================================
//
// UnicodeCharDataMap.cpp
// copyright (c) 2001 Sony Online Entertainment
//
// This contains Unicode 3.0 compliant Character data formats
// The data is loaded dynamically from the UnicodeData.txt definition file
//
// ======================================================================
#include "FirstUnicode.h"
#include "UnicodeCharacterDataMap.h"
#include "UnicodeBlocks.h"
#include "UnicodeCharacterData.h"
#include <cstdio>
#include <string>
#include <cassert>
// ======================================================================
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Plat_Unicode
{
CharDataMap * CharDataMap::ms_singleton = 0;
//-----------------------------------------------------------------
CharDataMap::CharDataMap () :
m_blockIds (),
m_contiguousData (0),
m_map (),
m_dataIsValid (false)
{
}
//-----------------------------------------------------------------
CharDataMap::~CharDataMap ()
{
m_map.clear ();
m_blockIds.clear ();
if (m_contiguousData)
{
delete[] m_contiguousData;
m_contiguousData = 0;
}
}
//-----------------------------------------------------------------
void CharDataMap::initSingleton ()
{
explicitDestroy ();
// TODO: default blocks?
ms_singleton = new CharDataMap ();
}
//-----------------------------------------------------------------
void CharDataMap::explicitDestroy ()
{
if (ms_singleton)
delete ms_singleton;
ms_singleton = 0;
}
//-----------------------------------------------------------------
namespace
{
typedef std::map <std::string, CharData::Category> CategoryMap_t;
//-----------------------------------------------------------------
/**
* Load a CharData from a string buffer representing a file.
* The bufpos is set to the beginning of a line after this method returns.
*/
inline bool populateDataFromBuffer (size_t desiredCode,
CharData & charData,
const std::string & buffer,
size_t & bufpos,
const CategoryMap_t & cmap)
{
size_t endpos = 0;
bool found = false;
do
{
size_t tokenNum = 0;
while ( (endpos = buffer.find ( ';', bufpos)) != std::string::npos ) //lint !e737 // loss of sign in promotion - STL bug
{
// code value
if (tokenNum == 0)
{
const size_t code = static_cast <size_t> (strtoul (buffer.substr (bufpos, endpos - bufpos).c_str (), 0, 16));
// we passed the desired line, so it must not exist
if (code > desiredCode)
return found;
// not there yet
else if (code < desiredCode)
break;
charData.m_code = static_cast<unicode_char_t> (code);
}
// General Category
else if (tokenNum == 2)
{
// all category codes are currently 2 characters long
if (endpos - bufpos > 2)
break;
const CategoryMap_t::const_iterator find_iter = cmap.find (buffer.substr (bufpos, 2));
if (find_iter == cmap.end ())
{
break;
}
else
charData.m_category = (*find_iter).second;
}
// Uppercase mapping
else if (charData.isLowerCase ())
{
if (tokenNum == 12)
{
if (endpos - bufpos > 1)
charData.m_reverseCase = static_cast<unicode_char_t> (strtoul (buffer.substr (bufpos, endpos - bufpos).c_str (), 0, 16));
found = true;
break;
}
}
// Lowercase mapping
else if (tokenNum == 13)
{
if (endpos - bufpos > 1)
charData.m_reverseCase = static_cast<unicode_char_t> (strtoul (buffer.substr (bufpos, endpos - bufpos).c_str (), 0, 16));
found = true;
break;
}
bufpos = endpos + 1;
++tokenNum;
}
}
while ( (bufpos = buffer.find ('\n', bufpos)) != std::string::npos && //lint !e737 // loss of sign in promotion - STL bug
(bufpos = buffer.find_first_not_of ('\n', bufpos + 1)) != std::string::npos); //lint !e737 // loss of sign in promotion - STL bug
return found;
}
}
//-----------------------------------------------------------------
/**
* Create a map of CharData's from a UnicodeData.txt standard Unicode 3.0 file, which has been packed into a buffer
*/
CharDataMap::ErrorCode CharDataMap::generateMapFromBuffer (const Blocks::Mapping & blockMapping, const std::string & str_buf)
{
m_dataIsValid = false;
m_map.clear ();
//-- create the category map for use by the inline population function
CategoryMap_t cmap;
{
size_t i = 0;
for (; CharData::ms_categoryNames [i].m_category != CharData::Cn; ++i)
{
cmap [CharData::ms_categoryNames [i].m_str] = CharData::ms_categoryNames [i].m_category;
}
}
typedef std::set<unicode_char_t> IdSet_t;
IdSet_t idSet;
{
for (BlockIdSet_t::const_iterator iter = m_blockIds.begin (); iter != m_blockIds.end (); ++iter)
{
const Blocks::Data & blockData = blockMapping.findBlock (*iter);
if (blockData.m_id != Blocks::End_Block_Ids)
{
blockData.generateFilteredIdSet (idSet);
}
}
}
//-- read all the desired chars from file.
//-- the file must be sorted by code
size_t bufpos = 0;
size_t validChars = 0;
{
for (IdSet_t::const_iterator iter = idSet.begin (); iter != idSet.end (); ++iter)
{
CharData * data = new CharData;
assert (data); //lint !e1924 // c-style cast. MSVC bug
data->m_reverseCase = 0;
if (populateDataFromBuffer (*iter, *data, str_buf, bufpos, cmap) == false)
{
delete data;
continue;
}
else
{
++validChars;
m_map[data->m_code] = data;
}
}
}
//--
//-- pack all the char data into a contiguous block of memory
//--
if (m_contiguousData)
delete[] m_contiguousData;
m_contiguousData = new CharData [validChars];
assert (m_contiguousData); //lint !e1924 // c-style cast. MSVC bug
size_t dataIndex = 0;
for (Map_t::iterator iter = m_map.begin (); iter != m_map.end (); ++iter, ++dataIndex)
{
m_contiguousData [dataIndex] = *(*iter).second;
delete (*iter).second;
(*iter).second = &m_contiguousData [dataIndex];
}
m_dataIsValid = true;
return ERR_SUCCESS;
}
//----------------------------------------------------------------------
/**
* Create a map of CharData's from a UnicodeData.txt standard Unicode 3.0 file, using cstdio
*/
CharDataMap::ErrorCode CharDataMap::generateMap (const Blocks::Mapping & blockMapping, const char * filename)
{
//-- load data from file as a big std::string
//-- read all the desired chars from file.
//-- the file must be sorted by code
FILE * fl = fopen (filename, "rb");
if (fl == 0)
{
return ERR_NO_FILE;
}
fseek (fl, 0, SEEK_END);
size_t fileLen = static_cast<size_t>(ftell (fl));
fseek (fl, 0, SEEK_SET);
char * buffer = new char [fileLen + 1];
buffer [fileLen] = 0;
assert (buffer); //lint !e1924 // c-style cast. MSVC bug
if (fread (buffer, fileLen, 1, fl) != 1)
{
delete[] buffer;
fclose (fl);
return ERR_READ_FAILED;
}
if (fclose (fl))
{
delete[] buffer;
return ERR_CLOSE_FAILED;
}
std::string str_buf (buffer, fileLen);
delete[] buffer;
return generateMapFromBuffer (blockMapping, str_buf);
}
//-----------------------------------------------------------------
/**
* Add a block Id that this CharacterDataMap is concerned with. Does not change the data map.
*/
void CharDataMap::addBlock (Blocks::Id id)
{
m_blockIds.insert (id);
}
//-----------------------------------------------------------------
/**
* Remove a block Id that this CharacterDataMap is concerned with. Does not change the data map.
*/
void CharDataMap::removeBlock (Blocks::Id id)
{
m_blockIds.erase (id);
}
//-----------------------------------------------------------------
/*
* Add a block Id that this CharacterDataMap is concerned with. Does not change the data map.
*/
void CharDataMap::clearBlocks ()
{
m_blockIds.clear ();
}
// ======================================================================
};
#ifdef EXTERNAL_DISTRO
};
#endif
@@ -0,0 +1,156 @@
// ======================================================================
//
// UnicodeCharDataMap.h
// copyright (c) 2001 Sony Online Entertainment
//
// This contains Unicode 3.0 compliant Character data formats
// The data is loaded dynamically from the UnicodeData.txt definition file
//
// ======================================================================
#ifndef INCLUDED_PlatUnicodeCharDataMap_H
#define INCLUDED_PlatUnicodeCharDataMap_H
#if WIN32
// stl warning func not inlined
#pragma warning (disable:4710)
#pragma warning (disable:4786)
#endif
#include <map>
#include <set>
#include "UnicodeBlocks.h"
// ======================================================================
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Plat_Unicode
{
struct CharData;
//-----------------------------------------------------------------
/**
* Singleton class that allows mapping from code points to CharData objects. This will be
* used to change case of characters, character category testing, etc...
* A CharacterDataMap has a set of Unicode::Block::Id's with which it is solely concerned.
* In this way, you may instantiate many different CharDataMaps if needed.
*/
class CharDataMap
{
public:
enum ErrorCode
{
ERR_SUCCESS = 0,
ERR_NO_FILE,
ERR_READ_FAILED,
ERR_CLOSE_FAILED,
ERR_CHAR_NOT_FOUND,
ERR_FILE_TOO_SHORT
};
typedef std::map <unicode_char_t, CharData *> Map_t;
static CharDataMap & getDefaultMap ();
static void explicitDestroy ();
CharDataMap ();
~CharDataMap ();
void addBlock (Blocks::Id id);
void removeBlock (Blocks::Id id);
void clearBlocks ();
ErrorCode generateMap (const Blocks::Mapping & blockMapping, const char * filename);
ErrorCode generateMapFromBuffer (const Blocks::Mapping & blockMapping, const std::string & str_buf);
bool isValid () const;
const CharData * findCharData (unicode_char_t code) const;
const Map_t & getMap () const;
private:
static void initSingleton ();
typedef std::set<Blocks::Id> BlockIdSet_t;
BlockIdSet_t m_blockIds;
CharData * m_contiguousData;
Map_t m_map;
bool m_dataIsValid;
static CharDataMap * ms_singleton;
};
//-----------------------------------------------------------------
/**
* Singleton accessor.
*/
inline CharDataMap & CharDataMap::getDefaultMap ()
{
if (ms_singleton)
return *ms_singleton;
initSingleton ();
return *ms_singleton;
}
//-----------------------------------------------------------------
/**
* Has the data been loaded successfully?
*/
inline bool CharDataMap::isValid () const
{
return m_dataIsValid;
}
//-----------------------------------------------------------------
/**
* Find a CharData for the given code point.
* @return null if no CharData exists for this code point
*/
inline const CharData * CharDataMap::findCharData (const unicode_char_t code) const
{
if (isValid ())
{
const Map_t::const_iterator iter = m_map.find (code);
if (iter != m_map.end ())
return (*iter).second;
}
return 0;
}
//-----------------------------------------------------------------
/**
* Get the data mapping
*/
inline const CharDataMap::Map_t & CharDataMap::getMap () const
{
return m_map;
}
};
#ifdef EXTERNAL_DISTRO
};
#endif
// ======================================================================
#endif
@@ -0,0 +1,285 @@
// ======================================================================
//
// Unicode.cpp
// copyright (c) 2001 Sony Online Entertainment
//
// ======================================================================
#include "FirstUnicode.h"
#include "UnicodeUtils.h"
#include <algorithm>
#if defined (linux)
#include <ctype.h>
#endif
// ======================================================================
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Plat_Unicode
{
//-----------------------------------------------------------------
/**
* Return by value a lowered version of nstr
*/
NarrowString toLower (const NarrowString & nstr)
{
NarrowString retval (nstr.c_str());
std::transform (retval.begin (), retval.end (), retval.begin (), tolower);
return retval;
}
//-----------------------------------------------------------------
/**
* Return by value an uppered version of nstr
*/
NarrowString toUpper (const NarrowString & nstr)
{
NarrowString retval (nstr);
std::transform (retval.begin (), retval.end (), retval.begin (), toupper);
return retval;
}
//-----------------------------------------------------------------
/**
* Return by value a lowered version of str.
* This currently only works properly with ASCII.
* @todo: implement this for all unicode blocks.
*/
String toLower (const String & nstr)
{
String retval (nstr);
std::transform (retval.begin (), retval.end (), retval.begin (), tolower);
return retval;
}
//-----------------------------------------------------------------
/**
* Return by value an uppered version of str.
* This currently only works properly with ASCII.
* @todo: implement this for all unicode blocks.
*/
String toUpper (const String & nstr)
{
String retval (nstr);
std::transform (retval.begin (), retval.end (), retval.begin (), toupper);
return retval;
}
//-----------------------------------------------------------------
/**
* Append src to dst, padding the field as needed, and truncating the field if desired.
*/
String & appendStringField (String & dst, const String & src, size_t width, FieldAlignment fa, unicode_char_t pad, bool truncate)
{
if (src.length () > width && truncate)
return dst.append (src.substr (0, width));
if (src.length () >= width)
return dst.append (src);
const size_t diff = width - src.length ();
if (fa == FA_RIGHT)
dst.append (diff, pad);
else if (fa == FA_CENTER)
dst.append (diff/2, pad);
dst.append (src);
if (fa == FA_LEFT)
dst.append (diff, pad);
else if (fa == FA_CENTER)
dst.append (diff - diff/2, pad);
return dst;
}
//-----------------------------------------------------------------
/**
* Find the first token in str, starting at pos. The value of the token is placed in the token field. endpos is updated to point past the token.
*/
bool getFirstToken (const String & str, size_t pos, size_t & endpos, String & token, const unicode_char_t * sepChars)
{
const size_t first_nonspace = str.find_first_not_of ( sepChars, pos );
if (first_nonspace != std::string::npos)
{
const size_t first_space = str.find_first_of (sepChars, first_nonspace );
if (first_space != std::string::npos)
token = str.substr (first_nonspace, first_space - first_nonspace);
else
token = str.substr (first_nonspace);
endpos = first_space;
return true;
}
return false;
}
//-----------------------------------------------------------------
/**
* Find the first token in str, starting at pos. The value of the token is placed in the token field. endpos is updated to point past the token.
*/
bool getFirstToken (const NarrowString & str, size_t pos, size_t & endpos, NarrowString & token, const char * sepChars)
{
const size_t first_nonspace = str.find_first_not_of ( sepChars, pos );
if (first_nonspace != std::string::npos)
{
const size_t first_space = str.find_first_of (sepChars, first_nonspace );
if (first_space != std::string::npos)
token = str.substr (first_nonspace, first_space - first_nonspace);
else
token = str.substr (first_nonspace);
endpos = first_space;
return true;
}
else
return false;
}
//-----------------------------------------------------------------
/**
* Find the nth token in str, starting at pos. The value of the token is placed in the token field. endpos is updated to point past the token.
* pos is updated to point to the first character of token in str.
*/
bool getNthToken (const String & str, const size_t n, size_t & pos, size_t & endpos, String & token, const unicode_char_t * sepChars)
{
size_t desired_first_nonspace = 0;
size_t space = 0;
//check for trivial case
if(n == 0)
desired_first_nonspace = pos;
else
{
for (size_t i = 0; i < n; ++i)
{
//find the first whitespace character
space = str.find_first_of ( sepChars, pos );
if (space == std::string::npos)
return false;
//now find the next non-whitespace character after it
desired_first_nonspace = str.find_first_not_of( sepChars, space );
if (desired_first_nonspace == std::string::npos)
return false;
pos = desired_first_nonspace;
}
}
//find the end of the token
const size_t first_space = str.find_first_of (sepChars, desired_first_nonspace );
//now get that token
if (first_space != std::string::npos)
token = str.substr (desired_first_nonspace, first_space - desired_first_nonspace);
else
token = str.substr (desired_first_nonspace);
endpos = desired_first_nonspace;
return true;
}
//-----------------------------------------------------------------
/**
* Find the nth token in str, starting at pos. The value of the token is placed in the token field. endpos is updated to point past the token.
* pos is updated to point to the first character of token in str.
*/
bool getNthToken (const NarrowString & str, const size_t n, size_t & pos, size_t & endpos, NarrowString & token, const char * sepChars)
{
size_t desired_first_nonspace = 0;
size_t space = 0;
//check for trivial case
if(n == 0)
desired_first_nonspace = pos;
else
{
for (size_t i = 0; i < n; ++i)
{
//find the first whitespace character
space = str.find_first_of ( sepChars, pos );
if (space == std::string::npos)
return false;
//now find the next non-whitespace character after it
desired_first_nonspace = str.find_first_not_of( sepChars, space );
if (desired_first_nonspace == std::string::npos)
return false;
pos = desired_first_nonspace;
}
}
//find the end of the token
const size_t first_space = str.find_first_of (sepChars, desired_first_nonspace );
//now get that token
if (first_space != std::string::npos)
token = str.substr (desired_first_nonspace, first_space - desired_first_nonspace);
else
token = str.substr (desired_first_nonspace);
endpos = desired_first_nonspace;
return true;
}
};
// ======================================================================
// Extensions to Base/Archive for String
// ======================================================================
namespace Base
{
void get(Base::ByteStream::ReadIterator& source, Plat_Unicode::String& target)
{
unsigned int size = 0;
get (source, size);
const unsigned char * const buf = source.getBuffer();
const Plat_Unicode::unicode_char_t * const ubuf = reinterpret_cast<const Plat_Unicode::unicode_char_t *>(buf);
target.assign (ubuf, ubuf + size);
const unsigned int readSize = size * sizeof (Plat_Unicode::unicode_char_t);
source.advance(readSize);
// printf("%d\n", target.size());
}
void put(Base::ByteStream& target, const Plat_Unicode::String& source)
{
const unsigned int size = source.size ();
put (target, size);
target.put (source.data(), size * sizeof (Plat_Unicode::unicode_char_t));
}
};
#ifdef EXTERNAL_DISTRO
};
#endif
@@ -0,0 +1,362 @@
// ======================================================================
//
// UnicodeUtils.h
// copyright (c) 2001 Sony Online Entertainment
//
// jwatson
//
// Basic Unicode string handling/manipulating functions
// ======================================================================
#ifndef INCLUDED_PlatUnicodeUtils_H
#define INCLUDED_PlatUnicodeUtils_H
#if WIN32
// stl warning func not inlined
#pragma warning (disable:4710)
#pragma warning (disable:4786)
#endif
#include "Unicode.h"
#include <Base/Archive.h>
#ifdef WIN32
#include <ctype.h>
#else
#include <wctype.h>
#endif
//-----------------------------------------------------------------
#ifdef EXTERNAL_DISTRO
namespace NAMESPACE
{
#endif
namespace Plat_Unicode
{
String narrowToWide (const NarrowString & nstr);
String & narrowToWide (const NarrowString & nstr, String & str); //lint !e1929 // function returning a reference
NarrowString wideToNarrow (const String & nstr);
NarrowString & wideToNarrow (const String & nstr, NarrowString & str); //lint !e1929 // function returning a reference
NarrowString toLower (const NarrowString & nstr);
NarrowString toUpper (const NarrowString & nstr);
String toLower (const String & nstr);
String toUpper (const String & nstr);
const String getTrim (const String & str, const unicode_char_t * white = whitespace);
String & trim (String & str, const unicode_char_t * white = whitespace);
bool getFirstToken (const String & str, size_t pos, size_t & endpos, String & token, const unicode_char_t * sepChars = whitespace);
bool getNthToken (const String & str, const size_t n, size_t & pos, size_t & endpos, String & token, const unicode_char_t * sepChars = whitespace);
size_t skipWhitespace (const String & str, size_t pos, const unicode_char_t * white = whitespace);
const NarrowString getTrim (const NarrowString & str, const char * white = ascii_whitespace);
NarrowString & trim (NarrowString & str, const char * white = ascii_whitespace);
bool getFirstToken (const NarrowString & str, size_t pos, size_t & endpos, NarrowString & token, const char * sepChars = ascii_whitespace);
bool getNthToken (const NarrowString & str, const size_t n, size_t & pos, size_t & endpos, NarrowString & token, const char * sepChars = ascii_whitespace);
size_t skipWhitespace (const NarrowString & str, size_t pos, const char * white = ascii_whitespace);
enum FieldAlignment
{
FA_LEFT,
FA_RIGHT,
FA_CENTER
};
String & appendStringField (String & dst, const String & src, size_t width, FieldAlignment fa = FA_LEFT, unicode_char_t pad = ' ', bool truncate = false);
String & appendStringField (String & dst, const NarrowString & src, size_t width, FieldAlignment fa = FA_LEFT, unicode_char_t pad = ' ', bool truncate = false);
/**
* Compare substrings of str2 and str1, each starting with pos and containing n characters
*/
/**
* Compares str1 and str2, where str1 is a String and str2 is templated,
* thus could be a std::string as well. Set reverseCompare to true if you
* want to begin comparison at end of string--a useful optimization if your
* strings tend to differ at the end.
*/
template <typename T> bool caseInsensitiveCompare (const String & str1, const T & str2, bool reverseCompare = false)
{
const size_t len1 = str1.size();
const size_t len2 = str2.size();
if (len1 != len2)
{
return false;
}
if (!reverseCompare)
{
for (size_t i = 0; i < len1; i++)
{
if ( towlower(str1[i]) != towlower(str2[i]) )
return false;
}
}
else
{
for (size_t i = len1; i > 0; i--)
{
if ( towlower(str1[i-1]) != towlower(str2[i-1]) )
return false;
}
}
return true;
}
/**
* Compares str1 and str2, where str1 is a String and str2 is templated,
* thus could be a std::string as well. Unlike caseInsensitiveCompare, this
* version returns an int for < or > comparisons, and comparison must start
* at the front. Note that this kind of comparison does not allow the shortcut
* of first comparing sizes--every character must be compared up to the last one.
*/
template <typename T> int caseInsensitiveCompareInt (const String & str1, const T & str2)
{
const size_t len1 = str1.size();
const size_t len2 = str2.size();
size_t len;
if (len1 < len2)
len = len1;
else
len = len2;
// iterate over smallest length
for (size_t i = 0; i < len; i++)
{
if ( towlower(str1[i]) < towlower(str2[i]) )
return -1;
else if ( towlower(str1[i]) > towlower(str2[i]) )
return 1;
}
// Equal so far, thus: if len1 < len2, the result is less-than, else
// if len1 = len2, the result is equal, else the result is greater-than.
if (len1 < len2)
return -1;
else if (len1 == len2)
return 0;
else
return 1;
}
/**
* Optimized implementation of isWhitespace. Must be kept in line with ::whitespace array
*/
template <typename T> bool isWhitespace (T c)
{
return c == ' ' || c == '\n' || c == '\r' || c == '\t';
}
/*
* @todo: uncomment when caseInsensitiveCompare matures
*
template <typename T> class CompareNoCasePredicate
{
public:
bool operator()( T & a, T & b ) const
{
return caseInsensitiveCompare (a, b) < 0;
};
};
template <typename T> class EqualsNoCasePredicate
{
public:
bool operator()( T & a, T & b ) const
{
return caseInsensitiveCompare (a, b) == 0;
};
};
*/
//-----------------------------------------------------------------
//-- implementation
//-----------------------------------------------------------------
//-----------------------------------------------------------------
/**
* Utility to convert a string and obtain the result by value
*/
inline String narrowToWide (const NarrowString & nstr)
{
// return String (nstr.begin (), nstr.end ()); // STLPort original
String s;
unsigned index = 0;
s.resize(nstr.size());
const NarrowString::const_iterator end = nstr.end();
for (NarrowString::const_iterator iter = nstr.begin(); iter != end; iter++)
{
s[index++] = *iter;
}
return s;
}
//-----------------------------------------------------------------
/**
* Utility to convert a string and obtain the result by reference
*/
inline String & narrowToWide (const NarrowString & nstr, String & str)
{
// return str.assign (nstr.begin (), nstr.end ()); // STLport original
unsigned index = 0;
str.resize(nstr.size());
const NarrowString::const_iterator end = nstr.end();
for (NarrowString::const_iterator iter = nstr.begin(); iter != end; iter++)
{
str[index++] = *iter;
}
return str;
}
//-----------------------------------------------------------------
/**
* Utility to convert a string and obtain the result by value
* This should only be used when the Unicode string is known to contain only 8 bit assignable values
*/
inline NarrowString wideToNarrow (const String & str)
{
// return NarrowString (str.begin (), str.end ()); // STLPort original
NarrowString s;
unsigned index = 0;
s.resize(str.size());
const String::const_iterator end = str.end();
for (String::const_iterator iter = str.begin(); iter != end; iter++)
{
s[index++] = (char)*iter;
}
return s;
}
//-----------------------------------------------------------------
/**
* Utility to convert a string and obtain the result by reference
* This should only be used when the Unicode string is known to contain only 8 bit assignable values
*/
inline NarrowString & wideToNarrow (const String & str, NarrowString & nstr)
{
// return nstr.assign (str.begin (), str.end ()); // STLPort original
unsigned index = 0;
nstr.resize(str.size());
const String::const_iterator end = str.end();
for (String::const_iterator iter = str.begin(); iter != end; iter++)
{
nstr[index++] = (char)*iter;
}
return nstr;
}
/**
* Get the trimmed version of str by value.
*/
inline const String getTrim (const String & str, const unicode_char_t * white)
{
const size_t first_nonspace = str.find_first_not_of ( white );
const size_t last_nonspace = str.find_last_not_of ( white );
return (first_nonspace == str.npos ? str : str.substr (first_nonspace, last_nonspace == str.npos ? last_nonspace : (last_nonspace - first_nonspace + 1)));
}
//-----------------------------------------------------------------
/**
* Trim the specified string and return a reference to it.
*/
inline String & trim (String & str, const unicode_char_t * white)
{
return (str = getTrim (str, white));
}
/**
* Get the trimmed version of str by value.
*/
inline const NarrowString getTrim (const NarrowString & str, const char * white)
{
const size_t first_nonspace = str.find_first_not_of ( white );
const size_t last_nonspace = str.find_last_not_of ( white );
return (first_nonspace == str.npos ? str : str.substr (first_nonspace, last_nonspace == str.npos ? last_nonspace : (last_nonspace - first_nonspace + 1)));
}
//-----------------------------------------------------------------
/**
* Trim the specified string and return a reference to it.
*/
inline NarrowString & trim (NarrowString & str, const char * white)
{
return (str = getTrim (str, white));
}
/**
* Return the first non-white position starting with pos. returns str.npos if there is no non-white characer after pos
*/
inline size_t skipWhitespace (const String & str, size_t pos, const unicode_char_t * white)
{
return str.find_first_not_of (white, pos);
}
//-----------------------------------------------------------------
/**
* Return the first non-white position starting with pos. returns str.npos if there is no non-white characer after pos
*/
inline size_t skipWhitespace (const NarrowString & str, size_t pos, const char * white)
{
return str.find_first_not_of (white, pos);
}
//-----------------------------------------------------------------
/**
* Append src to dst, padding the field as needed, and truncating the field if desired.
*/
inline String & appendStringField (String & dst, const NarrowString & src, size_t width, FieldAlignment fa, unicode_char_t pad, bool truncate)
{
return appendStringField (dst, narrowToWide (src), width, fa, pad, truncate);
}
// ======================================================================
};
// ======================================================================
// Extensions to Base/Archive for String
// ======================================================================
//class Base::ByteStream;
//-----------------------------------------------------------------------
namespace Base
{
extern void get(ByteStream::ReadIterator & source, Plat_Unicode::String & target);
extern void put(ByteStream & target, const Plat_Unicode::String & source);
//---------------------------------------------------------------------
// namespace Base
};
#ifdef EXTERNAL_DISTRO
};
#endif
#endif
@@ -0,0 +1,292 @@
#include <conio.h>
#include <time.h>
#include <stdio.h>
#include <map>
#include "CTServiceGameAPI/CTServiceAPI.h"
namespace CTService
{
class Client : public CTServiceAPI
{
public:
Client(const char *hostList, const char *game);
virtual ~Client();
virtual void onConnect(const char *host, const short port, const short current, const short max);
virtual void onDisconnect(const char *host, const short port, const short current, const short max);
virtual void onTest(const unsigned track, const int resultCode, const unsigned value, void *user);
virtual void onReplyTest(const unsigned track, const int resultCode, void *user);
virtual void onReplyMoveStatus(const unsigned track, const int resultCode, void *user);
virtual void onReplyValidateMove(const unsigned track, const int resultCode, void *user);
virtual void onReplyMove(const unsigned track, const int resultCode, void *user);
virtual void onReplyCharacterList(const unsigned track, const int resultCode, void *user);
virtual void onReplyServerList(const unsigned track, const int resultCode, void *user);
virtual void onReplyDestinationServerList(const unsigned track, const int resultCode, void *user);
virtual void onServerTest(const unsigned server_track, const char *game, const char *param);
virtual void onRequestMoveStatus(const unsigned server_track, const char *language,
const unsigned transactionID);
virtual void onRequestValidateMove(const unsigned server_track, const char *language,
const CTUnicodeChar *sourceServer,
const CTUnicodeChar *destServer,
const CTUnicodeChar *sourceCharacter,
const CTUnicodeChar *destCharacter, const unsigned uid,
const unsigned destuid, bool withItems);
virtual void onRequestMove(const unsigned server_track, const char *language,
const CTUnicodeChar *sourceServer,
const CTUnicodeChar *destServer,
const CTUnicodeChar *sourceCharacter,
const CTUnicodeChar *destCharacter, const unsigned uid,
const unsigned destuid, const unsigned transactionID, bool withItems);
virtual void onRequestCharacterList(const unsigned server_track, const char *language,
const CTUnicodeChar *server, const unsigned uid);
virtual void onRequestServerList(const unsigned server_track, const char *language);
virtual void onRequestDestinationServerList(const unsigned server_track, const char *language,
const CTUnicodeChar *character, const CTUnicodeChar *server);
std::map<unsigned, unsigned> mTransactionMap;
};
Client::Client(const char *hostList, const char *game) :
CTServiceAPI(hostList, game),
mTransactionMap()
{
}
Client::~Client()
{
}
void Client::onConnect(const char *host,
const short port,
const short current,
const short max)
{
printf("onConnect(%s, %u, %d, %d)\n",host,port,current,max);
}
void Client::onDisconnect(const char *host,
const short port,
const short current,
const short max)
{
printf("onDisconnect(%s, %u, %d, %d)\n",host,port,current,max);
}
void Client::onTest(const unsigned track,
const int resultCode,
const unsigned value,
void *user)
{
printf("onTest(%u, %d, %u, 0x%x)\n", track, resultCode, value, user);
}
void Client::onReplyTest(const unsigned track,
const int resultCode,
void *user)
{
printf("onReplyTest(%u, %d, 0x%x)\n", track, resultCode, user);
}
void Client::onReplyMoveStatus(const unsigned track,
const int resultCode,
void *user)
{
printf("onReplyMoveStatus(%u, %d, 0x%x)\n", track, resultCode, user);
}
void Client::onReplyValidateMove(const unsigned track,
const int resultCode,
void *user)
{
printf("onReplyValidateMove(%u, %d, 0x%x)\n", track, resultCode, user);
}
void Client::onReplyMove(const unsigned track,
const int resultCode,
void *user)
{
printf("onReplyMove(%u, %d, 0x%x)\n", track, resultCode, user);
}
void Client::onReplyCharacterList(const unsigned track,
const int resultCode,
void *user)
{
printf("onReplyCharacterList(%u, %d, 0x%x)\n", track, resultCode, user);
}
void Client::onReplyServerList(const unsigned track,
const int resultCode,
void *user)
{
printf("onReplyServerList(%u, %d, 0x%x)\n", track, resultCode, user);
}
void Client::onReplyDestinationServerList(const unsigned track,
const int resultCode,
void *user)
{
printf("onReplyDestinationServerList(%u, %d, 0x%x)\n", track, resultCode, user);
}
void Client::onServerTest(const unsigned server_track,
const char *game,
const char *param)
{
printf("onServerTest(%u, %s, %s)\n", server_track, game ? game : "(null)", param ? param : "(null)");
replyTest(server_track, 999, 0);
}
void Client::onRequestMoveStatus(const unsigned server_track,
const char *language,
const unsigned transactionID)
{
unsigned status;
unsigned result;
unsigned short * reason = L"makes me horny it does";
printf("#%x onRequestMoveStatus(%s, #%u)\n",
server_track,
language,
transactionID);
if (mTransactionMap.find(transactionID) != mTransactionMap.end())
{
status = CT_STATUS_COMPLETE;
result = mTransactionMap[transactionID];
}
else
{
status = CT_STATUS_UNKNOWN;
result = CT_GAMERESULT_SUCCESS;
}
replyMoveStatus(server_track, status, result, reason, 0);
}
void Client::onRequestValidateMove(const unsigned server_track,
const char *language,
const CTUnicodeChar *sourceServer,
const CTUnicodeChar *destServer,
const CTUnicodeChar *sourceCharacter,
const CTUnicodeChar *destCharacter,
const unsigned uid,
const unsigned destuid, bool withItems)
{
static resultArray[4] = {CT_GAMERESULT_SUCCESS, CT_GAMERESULT_SOFTERROR, CT_GAMERESULT_HARDERROR, CT_GAMERESULT_INVALID_NAME};
static resultIndex = 0;
printf("#%x onRequestValidateMove(%s): server(%S > %S) character (%S > %S) user(%u > %u) %s\n",
server_track,
language,
sourceServer,
destServer,
sourceCharacter,
destCharacter,
uid,
destuid,
withItems ? "/w items" : "/wo items");
int result = resultArray[(resultIndex++)%4];
unsigned short * reason = L"makes me horny it does";
unsigned short * suggested = L"yoda";
replyValidateMove(server_track, result, reason, suggested, 0);
}
void Client::onRequestMove(const unsigned server_track,
const char *language,
const CTUnicodeChar *sourceServer,
const CTUnicodeChar *destServer,
const CTUnicodeChar *sourceCharacter,
const CTUnicodeChar *destCharacter,
const unsigned uid,
const unsigned destuid,
const unsigned transactionID, bool withItems)
{
static resultArray[4] = {CT_GAMERESULT_SUCCESS, CT_GAMERESULT_SOFTERROR, CT_GAMERESULT_HARDERROR, CT_GAMERESULT_INVALID_NAME};
static resultIndex = 0;
printf("#%x onRequestMove(%s, #%u): server(%S > %S) character (%S > %S) user(%u > %u) %s\n",
server_track,
language,
transactionID,
sourceServer,
destServer,
sourceCharacter,
destCharacter,
uid,
destuid,
withItems ? "/w items" : "/wo items");
int result = resultArray[(resultIndex++)%4];
unsigned short * reason = L"makes me horny it does";
unsigned short * suggested = L"yoda";
mTransactionMap[transactionID] = result;
replyMove(server_track, result, reason, 0);
}
void Client::onRequestCharacterList(const unsigned server_track,
const char *language,
const CTUnicodeChar *server,
const unsigned uid)
{
CTServiceCharacter characters[4] =
{
L"wussup1",
L"wussup2",
L"wussup3",
L"wussup4"
};
printf("#%x onRequestCharacterList(%s, %S, %u)\n", server_track, language, server,uid);
replyCharacterList(server_track, CT_GAMERESULT_SUCCESS, 4, characters, 0);
}
void Client::onRequestServerList(const unsigned server_track,
const char *language)
{
CTServiceServer servers[4] =
{
L"crib1",
L"crib2",
L"crib3",
L"crib4"
};
printf("#%x onRequestServerList(%s)\n", server_track, language);
replyServerList(server_track, CT_GAMERESULT_SUCCESS, 4, servers, 0);
}
void Client::onRequestDestinationServerList(const unsigned server_track,
const char *language,
const CTUnicodeChar *character,
const CTUnicodeChar *server)
{
CTServiceServer servers[2] =
{
L"crib5",
L"crib6"
};
printf("#%x onRequestDestinationServerList(%s)\n", server_track, language);
replyDestinationServerList(server_track, CT_GAMERESULT_SUCCESS, 2, servers, 0);
}
}
int main()
{
char * hostList = "sdplatdev2:2000";
char * game = "SWG";
CTService::Client client(hostList, game);
while (!kbhit())
{
client.process();
}
return 0;
}
@@ -0,0 +1,101 @@
# Microsoft Developer Studio Project File - Name="test" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=test - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "test.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "test.mak" CFG="test - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "test - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "test - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "test - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "test - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../.." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 ws2_32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "test - Win32 Release"
# Name "test - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\main.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project