diff --git a/engine/server/application/CMakeLists.txt b/engine/server/application/CMakeLists.txt index 9f743915..3e04c974 100644 --- a/engine/server/application/CMakeLists.txt +++ b/engine/server/application/CMakeLists.txt @@ -1,3 +1,4 @@ add_subdirectory(LoginServer) +add_subdirectory(LogServer) add_subdirectory(TaskManager) diff --git a/engine/server/application/LogServer/CMakeLists.txt b/engine/server/application/LogServer/CMakeLists.txt new file mode 100644 index 00000000..30b6d428 --- /dev/null +++ b/engine/server/application/LogServer/CMakeLists.txt @@ -0,0 +1,6 @@ + +cmake_minimum_required(VERSION 2.8) + +project(LogServer) + +add_subdirectory(src) diff --git a/engine/server/application/LogServer/src/CMakeLists.txt b/engine/server/application/LogServer/src/CMakeLists.txt new file mode 100644 index 00000000..dba6b646 --- /dev/null +++ b/engine/server/application/LogServer/src/CMakeLists.txt @@ -0,0 +1,89 @@ + +set(SHARED_SOURCES + shared/ConfigLogServer.cpp + shared/ConfigLogServer.h + shared/DatabaseLogObserver.cpp + shared/DatabaseLogObserver.h + shared/FirstLogServer.cpp + shared/FirstLogServer.h + shared/LoggerConnection.cpp + shared/LoggerConnection.h + shared/LoggingServerApi.cpp + shared/LoggingServerApi.h + shared/LoggingServerApiObserver.cpp + shared/LoggingServerApiObserver.h + shared/LogServer.cpp + shared/LogServer.h +) + +if(WIN32) + set(PLATFORM_SOURCES + win32/LoggingServerApiWrapper.cpp + win32/WinMain.cpp + ) +else() + set(PLATFORM_SOURCES + linux/main.cpp + ) +endif() + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/shared + ${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/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}/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/fileInterface/include/public + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/singleton/include + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicode/include + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicodeArchive/include/public + ${SWG_EXTERNALS_SOURCE_DIR}/3rd/library/udplibrary +) + +link_directories(${STLPORT_LIBDIR}) + +add_executable(LogServer + ${SHARED_SOURCES} + ${PLATFORM_SOURCES} +) + +target_link_libraries(LogServer + sharedCompression + sharedDebug + sharedFile + sharedFoundation + sharedLog + sharedMath + sharedMemoryManager + sharedMessageDispatch + sharedNetwork + sharedNetworkMessages + sharedRandom + sharedSynchronization + sharedThread + sharedUtility + serverNetworkMessages + serverUtility + archive + fileInterface + localization + localizationArchive + unicode + unicodeArchive + udplibrary + ${ZLIB_LIBRARY} +) + +if(WIN32) + target_link_libraries(LogServer mswsock ws2_32) +endif() diff --git a/engine/server/application/LogServer/src/linux/main.cpp b/engine/server/application/LogServer/src/linux/main.cpp new file mode 100644 index 00000000..539abab4 --- /dev/null +++ b/engine/server/application/LogServer/src/linux/main.cpp @@ -0,0 +1,54 @@ +// ====================================================================== +// +// main.cpp +// +// Copyright 2002 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedFoundation/FirstSharedFoundation.h" +#include "LogServer.h" + +#include "sharedCompression/SetupSharedCompression.h" +#include "sharedDebug/SetupSharedDebug.h" +#include "sharedFile/SetupSharedFile.h" +#include "sharedFoundation/Os.h" +#include "sharedFoundation/SetupSharedFoundation.h" +#include "sharedNetworkMessages/SetupSharedNetworkMessages.h" +#include "sharedThread/SetupSharedThread.h" + +// ====================================================================== + +int main(int argc, char **argv) +{ + SetupSharedThread::install(); + SetupSharedDebug::install(1024); + + //-- setup foundation + SetupSharedFoundation::Data setupFoundationData(SetupSharedFoundation::Data::D_game); + + setupFoundationData.lpCmdLine = ConvertCommandLine(argc, argv); + + SetupSharedFoundation::install(setupFoundationData); + + SetupSharedCompression::install(); + + SetupSharedFile::install(false); + SetupSharedNetworkMessages::install(); + + Os::setProgramName("LogServer"); + //-- setup server + LogServer::install(); + + //-- run server + LogServer::run(); + + LogServer::remove(); + SetupSharedFoundation::remove(); + SetupSharedThread::remove(); + + return 0; +} + +// ====================================================================== + diff --git a/engine/server/application/LogServer/src/shared/ConfigLogServer.cpp b/engine/server/application/LogServer/src/shared/ConfigLogServer.cpp new file mode 100644 index 00000000..61629d67 --- /dev/null +++ b/engine/server/application/LogServer/src/shared/ConfigLogServer.cpp @@ -0,0 +1,55 @@ +// ====================================================================== +// +// ConfigLogServer.cpp +// +// Copyright 2002 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLogServer.h" +#include "ConfigLogServer.h" +#include "serverUtility/ConfigServerUtility.h" +#include "sharedFoundation/ConfigFile.h" +#include "sharedNetwork/SetupSharedNetwork.h" + +// ====================================================================== + +ConfigLogServer::Data *ConfigLogServer::data = 0; + +#define KEY_INT(a,b) (data->a = ConfigFile::getKeyInt("LogServer", #a, b)) +#define KEY_STRING(a,b) (data->a = ConfigFile::getKeyString("LogServer", #a, b)) + +// ====================================================================== + +void ConfigLogServer::install() +{ + ConfigServerUtility::install(); + + SetupSharedNetwork::SetupData networkSetupData; + SetupSharedNetwork::getDefaultServerSetupData(networkSetupData); + SetupSharedNetwork::install(networkSetupData); + + data = new ConfigLogServer::Data; + + KEY_INT (logServicePort, 44467); + KEY_STRING (logServiceBindInterface, ""); + KEY_STRING (loggingServerApiAddress, "sdt-gp1"); + KEY_STRING (loggingServerApiLoginName, "MISCONFIGURED_LOG_SERVER_LOGIN_NAME"); + KEY_STRING (loggingServerApiPassword, "pacman"); + KEY_STRING (loggingServerApiDefaultDirectory, "swg"); + KEY_STRING (clusterName, "MISCONFIGURED_LOG_SERVER"); + KEY_INT (logServiceMaxConnections, 150); + KEY_INT (loggingServerApiQueueSize, 4096); +} + +// ---------------------------------------------------------------------- + +void ConfigLogServer::remove() +{ + delete data; + data = 0; + ConfigServerUtility::remove(); +} + +// ====================================================================== + diff --git a/engine/server/application/LogServer/src/shared/ConfigLogServer.h b/engine/server/application/LogServer/src/shared/ConfigLogServer.h new file mode 100644 index 00000000..b43e457f --- /dev/null +++ b/engine/server/application/LogServer/src/shared/ConfigLogServer.h @@ -0,0 +1,113 @@ +// ====================================================================== +// +// ConfigLogServer.h +// +// Copyright 2002 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_ConfigLogServer_H +#define INCLUDED_ConfigLogServer_H + +// ====================================================================== + +class ConfigLogServer +{ +public: + struct Data + { + int logServicePort; + const char * logServiceBindInterface; + const char * loggingServerApiAddress; + const char * loggingServerApiLoginName; + const char * loggingServerApiPassword; + const char * loggingServerApiDefaultDirectory; + const char * clusterName; + int logServiceMaxConnections; + int loggingServerApiQueueSize; + }; + + static void install(); + static void remove(); + + static int getLogServiceMaxConnections(); + static uint16 getLogServicePort(); + static const char * getLogServiceBindInterface(); + static const char * getLoggingServerApiAddress(); + static const char * getLoggingServerApiLoginName(); + static const char * getLoggingServerApiPassword(); + static const char * getLoggingServerApiDefaultDirectory(); + static const char * getClusterName(); + static int getLoggingServerApiQueueSize(); + +private: + static Data *data; +}; + +// ====================================================================== + +inline uint16 ConfigLogServer::getLogServicePort() +{ + return static_cast(data->logServicePort); +} + +//----------------------------------------------------------------------- + +inline const char * ConfigLogServer::getLogServiceBindInterface() +{ + return data->logServiceBindInterface; +} + +//----------------------------------------------------------------------- + +inline const char * ConfigLogServer::getLoggingServerApiAddress() +{ + return data->loggingServerApiAddress; +} + +//----------------------------------------------------------------------- + +inline const char * ConfigLogServer::getLoggingServerApiLoginName() +{ + return data->loggingServerApiLoginName; +} + +//----------------------------------------------------------------------- + +inline const char * ConfigLogServer::getLoggingServerApiPassword() +{ + return data->loggingServerApiPassword; +} + +//----------------------------------------------------------------------- + +inline const char * ConfigLogServer::getLoggingServerApiDefaultDirectory() +{ + return data->loggingServerApiDefaultDirectory; +} + +//----------------------------------------------------------------------- + +inline const char * ConfigLogServer::getClusterName() +{ + return data->clusterName; +} + +//----------------------------------------------------------------------- + +inline int ConfigLogServer::getLogServiceMaxConnections() +{ + return data->logServiceMaxConnections; +} + +//----------------------------------------------------------------------- + +inline int ConfigLogServer::getLoggingServerApiQueueSize() +{ + return data->loggingServerApiQueueSize; +} + +// ====================================================================== + +#endif + diff --git a/engine/server/application/LogServer/src/shared/DatabaseLogObserver.cpp b/engine/server/application/LogServer/src/shared/DatabaseLogObserver.cpp new file mode 100644 index 00000000..662f36bf --- /dev/null +++ b/engine/server/application/LogServer/src/shared/DatabaseLogObserver.cpp @@ -0,0 +1,51 @@ +// ====================================================================== +// +// DatabaseLogObserver.cpp +// +// Copyright 2002 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLogServer.h" +#include "DatabaseLogObserver.h" + +#include "sharedLog/LogManager.h" +#include + +// ====================================================================== + +void DatabaseLogObserver::install() +{ + LogManager::registerObserverType("db", create); +} + +// ---------------------------------------------------------------------- + +LogObserver *DatabaseLogObserver::create(std::string const &spec) +{ + UNREF(spec); + return new DatabaseLogObserver(); +} + +// ---------------------------------------------------------------------- + +DatabaseLogObserver::DatabaseLogObserver() : + LogObserver() +{ +} + +// ---------------------------------------------------------------------- + +DatabaseLogObserver::~DatabaseLogObserver() +{ +} + +// ---------------------------------------------------------------------- + +void DatabaseLogObserver::log(LogMessage const &) +{ + // TODO - implement this +} + +// ====================================================================== + diff --git a/engine/server/application/LogServer/src/shared/DatabaseLogObserver.h b/engine/server/application/LogServer/src/shared/DatabaseLogObserver.h new file mode 100644 index 00000000..9984b5cf --- /dev/null +++ b/engine/server/application/LogServer/src/shared/DatabaseLogObserver.h @@ -0,0 +1,39 @@ +// ====================================================================== +// +// DatabaseLogObserver.h +// +// Copyright 2002 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_DatabaseLogObserver_H +#define INCLUDED_DatabaseLogObserver_H + +// ====================================================================== + +#include "sharedLog/LogObserver.h" + +// ====================================================================== + +// A DatabaseLogObserver filters relevant messages and saves them as +// appropriate to a database. +class DatabaseLogObserver: public LogObserver +{ +public: + static void install(); + static LogObserver *create(std::string const &spec); + + DatabaseLogObserver(); + virtual ~DatabaseLogObserver(); + + virtual void log(LogMessage const &msg); + +private: + DatabaseLogObserver(DatabaseLogObserver const &); + DatabaseLogObserver &operator=(DatabaseLogObserver const &); +}; + +// ====================================================================== + +#endif // INCLUDED_DatabaseLogObserver_H + diff --git a/engine/server/application/LogServer/src/shared/FirstLogServer.cpp b/engine/server/application/LogServer/src/shared/FirstLogServer.cpp new file mode 100644 index 00000000..eb1d289a --- /dev/null +++ b/engine/server/application/LogServer/src/shared/FirstLogServer.cpp @@ -0,0 +1 @@ +#include "FirstLogServer.h" diff --git a/engine/server/application/LogServer/src/shared/FirstLogServer.h b/engine/server/application/LogServer/src/shared/FirstLogServer.h new file mode 100644 index 00000000..ebd3b386 --- /dev/null +++ b/engine/server/application/LogServer/src/shared/FirstLogServer.h @@ -0,0 +1,19 @@ +// ====================================================================== +// +// FirstLogServer.h +// +// Copyright 2002 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_FirstLogServer_H +#define INCLUDED_FirstLogServer_H + +// ====================================================================== + +#include "sharedFoundation/FirstSharedFoundation.h" + +// ====================================================================== + +#endif + diff --git a/engine/server/application/LogServer/src/shared/LogServer.cpp b/engine/server/application/LogServer/src/shared/LogServer.cpp new file mode 100644 index 00000000..f5658a39 --- /dev/null +++ b/engine/server/application/LogServer/src/shared/LogServer.cpp @@ -0,0 +1,159 @@ +// ====================================================================== +// +// LogServer.cpp +// +// Copyright 2002 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLogServer.h" +#include "LogServer.h" + +#include "ConfigLogServer.h" +#include "LoggerConnection.h" +#include "DatabaseLogObserver.h" +#include "LoggingServerApiObserver.h" +#include "sharedFoundation/Clock.h" +#include "sharedFoundation/Os.h" +#include "sharedLog/Log.h" +#include "sharedLog/SetupSharedLog.h" +#include "sharedNetwork/NetworkSetupData.h" +#include "sharedNetwork/Service.h" +#include "sharedNetworkMessages/GameNetworkMessage.h" +#include "sharedNetworkMessages/LogMessage.h" +#include "Archive/ByteStream.h" + +#include + +// ====================================================================== + +LogServer::LogServer() : + Singleton(), + MessageDispatch::Receiver(), + m_done(false), + m_logService(0) +{ + NetworkSetupData setup; + setup.port = ConfigLogServer::getLogServicePort(); + setup.maxConnections = ConfigLogServer::getLogServiceMaxConnections(); + setup.bindInterface = ConfigLogServer::getLogServiceBindInterface(); + + // set up the log service + m_logService = new Service(ConnectionAllocator(), setup); + connectToMessage("LogMessage"); +} + +// ---------------------------------------------------------------------- + +LogServer::~LogServer() +{ + if (m_logService) + { + delete m_logService; + m_logService = 0; + } +} + +// ---------------------------------------------------------------------- + +void LogServer::install() +{ + NetworkHandler::install(); + ConfigLogServer::install(); + + // tell the logger not to flush on writes when installing + SetupSharedLog::install("LogServer", false); + DatabaseLogObserver::install(); + LoggingServerApiObserver::install(); +} + +// ---------------------------------------------------------------------- + +void LogServer::remove() +{ + SetupSharedLog::remove(); + ConfigLogServer::remove(); + NetworkHandler::remove(); +} + +// ---------------------------------------------------------------------- + +void LogServer::run() +{ + LogServer::getInstance().mainLoop(); +} + +// ---------------------------------------------------------------------- + +void LogServer::mainLoop() +{ + unsigned long limit = 100; + unsigned long startTime; + + while (!m_done) + { + if (!Os::update()) + setDone("Os condition (Parent pid change)"); + + startTime = Clock::timeMs(); + + do + { + NetworkHandler::dispatch(); + LogManager::flush(); + Os::sleep(1); + NetworkHandler::update(); + } while (Clock::timeMs() - startTime < limit); + } + + // prevent shutdown issues from LogServer destructor running after LogServer::remove + delete m_logService; + m_logService = 0; +} + +// ---------------------------------------------------------------------- + +void LogServer::receiveMessage(MessageDispatch::Emitter const &source, MessageDispatch::MessageBase const &message) +{ + UNREF(source); + if (message.isType("LogMessage")) + { + Archive::ReadIterator ri = static_cast(message).getByteStream().begin(); + // Pass the text to the log manager to be observed - it has already been + // timestamped, etc. + LogManager::observeLogMessage(LogMessage(ri)); + } +} + +// ---------------------------------------------------------------------- + +void LogServer::setDone(char const *reasonfmt, ...) +{ + if (!m_done) + { + char reason[1024]; + va_list ap; + va_start(ap, reasonfmt); + _vsnprintf(reason, sizeof(reason), reasonfmt, ap); + reason[sizeof(reason)-1] = '\0'; + + LOG( + "ServerShutdown", + ( + "LogServer (pid %d) shutdown, reason: %s", + static_cast(Os::getProcessId()), + reason)); + + REPORT_LOG( + true, + ( + "LogServer (pid %d) shutdown, reason: %s\n", + static_cast(Os::getProcessId()), + reason)); + + m_done = true; + } +} + +// ====================================================================== + diff --git a/engine/server/application/LogServer/src/shared/LogServer.h b/engine/server/application/LogServer/src/shared/LogServer.h new file mode 100644 index 00000000..d7d8b45d --- /dev/null +++ b/engine/server/application/LogServer/src/shared/LogServer.h @@ -0,0 +1,48 @@ +// ====================================================================== +// +// LogServer.h +// +// Copyright 2002 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_LogServer_H +#define INCLUDED_LogServer_H + +// ====================================================================== + +#include "sharedMessageDispatch/Receiver.h" +#include "Singleton/Singleton.h" + +// ====================================================================== + +class Service; + +// ====================================================================== + +class LogServer: public Singleton, public MessageDispatch::Receiver +{ +public: + LogServer(); + ~LogServer(); + + static void install(); + static void remove(); + static void run(); + void mainLoop(); + void setDone(char const *reason, ...); + + virtual void receiveMessage(MessageDispatch::Emitter const &source, MessageDispatch::MessageBase const &message); + +private: + LogServer(LogServer const &); + LogServer &operator=(LogServer const &); + + bool m_done; + Service * m_logService; +}; + +// ====================================================================== + +#endif + diff --git a/engine/server/application/LogServer/src/shared/LoggerConnection.cpp b/engine/server/application/LogServer/src/shared/LoggerConnection.cpp new file mode 100644 index 00000000..c59af171 --- /dev/null +++ b/engine/server/application/LogServer/src/shared/LoggerConnection.cpp @@ -0,0 +1,42 @@ +// ====================================================================== +// +// LoggerConnection.cpp +// +// Copyright 2002 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLogServer.h" +#include "LoggerConnection.h" + +// ====================================================================== + +LoggerConnection::LoggerConnection(UdpConnectionMT * u, TcpClient * t) : + ServerConnection(u, t) +{ + REPORT_LOG(true, ("LoggerConnection created.\n")); +} + +// ---------------------------------------------------------------------- + +LoggerConnection::~LoggerConnection() +{ + REPORT_LOG(true, ("LoggerConnection destroyed.\n")); +} + +// ---------------------------------------------------------------------- + +void LoggerConnection::onConnectionClosed() +{ + ServerConnection::onConnectionClosed(); +} + +// ---------------------------------------------------------------------- + +void LoggerConnection::onConnectionOpened() +{ + ServerConnection::onConnectionOpened(); +} + +// ====================================================================== + diff --git a/engine/server/application/LogServer/src/shared/LoggerConnection.h b/engine/server/application/LogServer/src/shared/LoggerConnection.h new file mode 100644 index 00000000..5fb71e99 --- /dev/null +++ b/engine/server/application/LogServer/src/shared/LoggerConnection.h @@ -0,0 +1,36 @@ +// ====================================================================== +// +// LoggerConnection.h +// +// Copyright 2002 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_LoggerConnection_H +#define INCLUDED_LoggerConnection_H + +// ====================================================================== + +#include "serverUtility/ServerConnection.h" + +// ====================================================================== + +class LoggerConnection: public ServerConnection +{ +public: + LoggerConnection(UdpConnectionMT *, TcpClient *); + virtual ~LoggerConnection(); + + virtual void onConnectionClosed(); + virtual void onConnectionOpened(); + +private: + LoggerConnection(); + LoggerConnection(LoggerConnection const &); + LoggerConnection &operator=(LoggerConnection const &); +}; + +// ====================================================================== + +#endif + diff --git a/engine/server/application/LogServer/src/shared/LoggingServerApi.cpp b/engine/server/application/LogServer/src/shared/LoggingServerApi.cpp new file mode 100644 index 00000000..89591848 --- /dev/null +++ b/engine/server/application/LogServer/src/shared/LoggingServerApi.cpp @@ -0,0 +1,485 @@ +#include "FirstLogServer.h" + +#include +#include +#include +#include +#include +#include + +#include "LoggingServerApi.h" + + + +LoggingServerApi::LoggingServerApi(LoggingServerHandler *handler, int queueSize) +{ + mHandler = handler; + mQueueSize = queueSize; + mQueue = new QueueEntry[mQueueSize]; + mQueuePosition = 0; + mQueueCount = 0; + + mAuthenticated = false; + mLoginName[0] = 0; + mPassword[0] = 0; + mDefaultDirectory[0] = 0; + mConnection = NULL; + mUdpManager = NULL; + mTransaction = NULL; + mSessionId = int(time(NULL)); + mSessionSequence = 1; +} + +LoggingServerApi::~LoggingServerApi() +{ + if (mTransaction != NULL) + StopTransaction(); + + for (int i = 0; i < mQueueCount; i++) + { + int spot = (mQueuePosition + i) % mQueueSize; + mQueue[spot].packet->Release(); + } + delete[] mQueue; + + Disconnect(); +} + +void LoggingServerApi::Connect(const char *address, int port, const char *loginName, const char *password, const char *defaultDirectory) +{ + Disconnect(); + + strcpy(mLoginName, loginName); + strcpy(mPassword, password); + strcpy(mDefaultDirectory, defaultDirectory); + + UdpManager::Params params; + params.clockSyncDelay = 0; + params.crcBytes = 2; + params.hashTableSize = 10; + params.incomingBufferSize = 16 * 1024; + params.keepAliveDelay = 30000; + params.portAliveDelay = 0; + params.noDataTimeout = 91000; + params.maxConnections = 3; + params.maxRawPacketSize = 1460; + params.maxDataHoldTime = 0; + + params.outgoingBufferSize = 128 * 1024; + params.packetHistoryMax = 3; + params.port = 0; + params.pooledPacketMax = 1000; + params.reliable[0].maxInstandingPackets = 512; + params.reliable[0].maxOutstandingBytes = 128 * 1024; + params.reliable[0].congestionWindowMinimum = 50000; + params.reliable[0].maxOutstandingPackets = 512; + params.reliable[0].processOnSend = false; + mUdpManager = new UdpManager(¶ms); + + mConnection = mUdpManager->EstablishConnection(address, port, 30000); + if (mConnection != NULL) + mConnection->SetHandler(this); + mLoginSent = false; +} + +void LoggingServerApi::Disconnect() +{ + mAuthenticated = false; + mLoginName[0] = 0; + mPassword[0] = 0; + mDefaultDirectory[0] = 0; + + if (mConnection != NULL) + { + mConnection->Disconnect(); + mConnection->Release(); + mConnection = NULL; + } + + if (mUdpManager != NULL) + { + mUdpManager->Release(); + mUdpManager = NULL; + } +} + +void LoggingServerApi::Flush(int timeout) +{ + UdpMisc::ClockStamp startTime = UdpMisc::Clock(); + while (GetStatus() != cStatusDisconnected && UdpMisc::ClockElapsed(startTime) < timeout) + { + if (mConnection->TotalPendingBytes() == 0 && mQueueCount == 0) + break; + GiveTime(); + + UdpMisc::Sleep(10); + } + UdpMisc::Sleep(20); +} + +LoggingServerApi::Status LoggingServerApi::GetStatus() const +{ + if (mConnection != NULL) + { + switch (mConnection->GetStatus()) + { + case UdpConnection::cStatusConnected: + if (mAuthenticated) + return(cStatusConnected); + else + return(cStatusAuthenticating); + break; + case UdpConnection::cStatusNegotiating: + return(cStatusNegotiating); + default: + break; + } + } + return(cStatusDisconnected); +} + +void LoggingServerApi::OnRoutePacket(UdpConnection *, const uchar *data, int) +{ + switch(data[0]) + { + case cS2CPacketLoginConfirm: + { + mAuthenticated = data[1] ? true : false; + if (mAuthenticated) + { + // flush the queue on authentication. This sends not only any data that was queued before connecting + // but also any data that was sent in the last 3 minutes, just to ensure that it didn't get lost on the + // server side of things + FlushQueue(); + } + + if (mHandler != NULL) + mHandler->LshOnLoginConfirm(mAuthenticated); + break; + } + case cS2CPacketMonitor: + { + char *ptr = (char *)(data + 1); + int sessionId = UdpMisc::GetValue32(ptr); + ptr += 4; + int sequenceNumber = UdpMisc::GetValue32(ptr); + ptr += 4; + int typeCode = UdpMisc::GetValue32(ptr); + ptr += 4; + char *name = ptr; + ptr += strlen(ptr) + 1; + char *filename = ptr; + ptr += strlen(ptr) + 1; + char *message = ptr; + if (mHandler != NULL) + mHandler->LshOnMonitor(sessionId, sequenceNumber, name, filename, typeCode, message); + break; + } + case cS2CPacketFileList: + { + if (mHandler != NULL) + mHandler->LshOnFileList((char *)(data + 1)); + break; + } + default: + break; + } +} + +void LoggingServerApi::OnTerminated(UdpConnection *con) +{ + if(mHandler != NULL) + { + mHandler->LshOnTerminated( con->GetDisconnectReason() ); + } +} + +void LoggingServerApi::GiveTime() +{ + if (mConnection != NULL && mConnection->GetStatus() == UdpConnection::cStatusConnected) + { + if (!mLoginSent) + { + mLoginSent = true; + + // send login packet + char buf[1024]; + char *ptr = buf; + *ptr++ = cC2SPacketLogin; + strcpy(ptr, mLoginName); + ptr += strlen(mLoginName) + 1; + strcpy(ptr, mPassword); + ptr += strlen(mPassword) + 1; + strcpy(ptr, mDefaultDirectory); + ptr += strlen(mDefaultDirectory) + 1; + ptr += UdpMisc::PutValue32(ptr, mSessionId); + mConnection->Send(cUdpChannelReliable1, buf, ptr - buf); + } + } + + while (GetStatus() == cStatusConnected && mQueueCount > 0) + { + int spot = mQueuePosition % mQueueSize; + + // if entry was actually sent and it has been sitting in the queue long enough to be deleted + if (mQueue[spot].sentTime != 0 && UdpMisc::ClockElapsed(mQueue[spot].sentTime) > cSafetyQueueTime) + { + mQueue[spot].packet->Release(); + mQueue[spot].packet = NULL; + mQueuePosition++; + mQueueCount--; + } + else + { + break; + } + } + + if (mUdpManager != NULL) + { + mUdpManager->GiveTime(); + } +} + +void LoggingServerApi::StartTransaction() +{ + if (mTransaction == NULL) + mTransaction = new GroupLogicalPacket(); +} + +void LoggingServerApi::StopTransaction() +{ + if (mTransaction != NULL) + { + PacketSend(mTransaction); + mTransaction->Release(); + mTransaction = NULL; + } +} + +void LoggingServerApi::PacketSend(LogicalPacket *lp) +{ + // make room in queue + if (mQueueCount == mQueueSize) + { + int spot = mQueuePosition % mQueueSize; + mQueue[spot].packet->Release(); + mQueue[spot].packet = NULL; + mQueuePosition++; + mQueueCount--; + } + + // queue it + int spot = (mQueuePosition + mQueueCount) % mQueueSize; + lp->AddRef(); + mQueue[spot].packet = lp; + mQueue[spot].sentTime = 0; + mQueueCount++; + + // if possible, send it + if (GetStatus() == cStatusConnected) + { + mQueue[spot].sentTime = UdpMisc::Clock(); + mConnection->Send(cUdpChannelReliable1, lp); + } +} + + +void LoggingServerApi::Log16(const char *filename, int typeCode, const unsigned short *ucs2String) +{ + char buffer[32768]; + char * const ptr_end_buffer = &buffer[sizeof(buffer)]; + char *ptr = buffer; + *ptr++ = cC2SPacketLog16; + ptr += UdpMisc::PutValue32(ptr, typeCode); + strcpy(ptr, filename); + ptr += strlen(ptr) + 1; + + const unsigned short *rawPtr = ucs2String; + char *startPtr = ptr; + for (;;) + { + if (*rawPtr == '\n' || *rawPtr == 0) + { + if (ptr != startPtr) + { + ptr += UdpMisc::PutValue16(ptr, 0); // terminating zero + ptr += UdpMisc::PutValue32(ptr, mSessionSequence++); + LogPacket(buffer, ptr - buffer); + ptr = startPtr; + } + + if (*rawPtr == 0) + break; + } + else + { + // catch buffer overflow; we need to reserve 6 bytes + // at the end of the buffer for the terminating 0 + // and the sequence number (see above) + if ((ptr + 8) <= ptr_end_buffer) + ptr += UdpMisc::PutValue16(ptr, *rawPtr); + } + + rawPtr++; + } +} + +void LoggingServerApi::Log(const char *filename, int typeCode, const char *message, ...) +{ + char buffer[16384]; + char * const ptr_end_buffer = &buffer[sizeof(buffer)]; + char *ptr = buffer; + *ptr++ = cC2SPacketLog; + ptr += UdpMisc::PutValue32(ptr, typeCode); + strcpy(ptr, filename); + ptr += strlen(ptr) + 1; + + char rawString[16384]; + va_list marker; + va_start(marker, message); + _vsnprintf(rawString, sizeof(rawString), message, marker); + va_end(marker); + rawString[sizeof(rawString) - 1] = 0; + + char *rawPtr = rawString; + char *startPtr = ptr; + for (;;) + { + if (*rawPtr == '\n' || *rawPtr == 0) + { + if (ptr != startPtr) + { + *ptr++ = 0; + ptr += UdpMisc::PutValue32(ptr, mSessionSequence++); + LogPacket(buffer, ptr - buffer); + ptr = startPtr; + } + + if (*rawPtr == 0) + break; + } + else + { + // catch buffer overflow; we need to reserve 5 bytes + // at the end of the buffer for the terminating 0 + // and the sequence number (see above) + if ((ptr + 6) <= ptr_end_buffer) + *ptr++ = *rawPtr; + } + + rawPtr++; + } +} + +void LoggingServerApi::LogPacket(char *data, int len) +{ + if (mTransaction != NULL) + { + // add it to the transaction + mTransaction->AddPacket(data, len); + } + else + { + LogicalPacket *lp = CreatePacket(data, len); + PacketSend(lp); + lp->Release(); + } +} + +LogicalPacket *LoggingServerApi::CreatePacket(char *data, int dataLen) +{ + if (mUdpManager != NULL) + { + return(mUdpManager->CreatePacket(data, dataLen)); + } + + return(UdpMisc::CreateQuickLogicalPacket(data, dataLen)); +} + +void LoggingServerApi::FlushQueue() +{ + if (GetStatus() == cStatusConnected) + { + for (int i = 0; i < mQueueCount; i++) + { + int spot = (mQueuePosition + i) % mQueueSize; + mQueue[spot].sentTime = UdpMisc::Clock(); + mConnection->Send(cUdpChannelReliable1, mQueue[spot].packet); + } + } +} + +void LoggingServerApi::RequestMonitor(const char *filename, bool turnOn) +{ + if (GetStatus() == cStatusConnected) + { + char buffer[2048]; + char *ptr = buffer; + *ptr++ = cC2SPacketMonitor; + *ptr++ = turnOn; + strcpy(ptr, filename); + ptr += strlen(ptr) + 1; + mConnection->Send(cUdpChannelReliable1, buffer, ptr - buffer); + } +} + +void LoggingServerApi::RequestFileList() +{ + if (GetStatus() == cStatusConnected) + { + char buffer[10]; + char *ptr = buffer; + *ptr++ = cC2SPacketFileList; + mConnection->Send(cUdpChannelReliable1, buffer, ptr - buffer); + } +} + +void LoggingServerApi::GetStatistics(LoggingServerApiStatistics *stats) +{ + memset( stats, 0, sizeof( *stats) ); + UdpConnectionStatistics udpConnectionStats; + memset( &udpConnectionStats, 0, sizeof( udpConnectionStats ) ); + if( mConnection != NULL ) + { + mConnection->GetStats( &udpConnectionStats ); + stats->applicationPacketsReceived = udpConnectionStats.applicationPacketsReceived; + stats->applicationPacketsSent = udpConnectionStats.applicationPacketsSent; + stats->totalBytesReceived = udpConnectionStats.totalBytesReceived; + stats->totalBytesSent = udpConnectionStats.totalBytesSent; + stats->totalPacketsReceived = udpConnectionStats.totalPacketsReceived; + stats->totalPacketsSent = udpConnectionStats.totalPacketsSent; + + stats->totalTime = mConnection->ConnectionAge(); + } + + UdpManagerStatistics managerStats; + if( mUdpManager != NULL ) + { + mUdpManager->GetStats( &managerStats ); + udp_int64 iterations = managerStats.iterations; + int elapseTime = managerStats.elapsedTime; + + if( elapseTime != 0 ) + { + stats->iterationsPerSecond = (double)((iterations * 1000 )/(double)elapseTime); + } + mUdpManager->ResetStats(); + } +} + +void LoggingServerHandler::LshOnLoginConfirm(bool ) +{ +} + +void LoggingServerHandler::LshOnMonitor(int , int , const char * const, const char * const, int , const char * const) +{ +} + +void LoggingServerHandler::LshOnFileList(const char * const) +{ +} + +void LoggingServerHandler::LshOnTerminated(UdpConnection::DisconnectReason) +{ +} diff --git a/engine/server/application/LogServer/src/shared/LoggingServerApi.h b/engine/server/application/LogServer/src/shared/LoggingServerApi.h new file mode 100644 index 00000000..d0ed2ef3 --- /dev/null +++ b/engine/server/application/LogServer/src/shared/LoggingServerApi.h @@ -0,0 +1,104 @@ +#ifndef LOGGINGSERVERAPI_H +#define LOGGINGSERVERAPI_H + +#include "UdpLibrary.hpp" + +struct LoggingServerApiStatistics +{ + //These are all statistics from the UdpConnection object. + udp_int64 totalBytesSent; + udp_int64 totalBytesReceived; + udp_int64 totalPacketsSent; // total packets we have sent + udp_int64 totalPacketsReceived; // total packets we have received + udp_int64 applicationPacketsSent; + udp_int64 applicationPacketsReceived; + double iterationsPerSecond; + int totalTime; +}; + +class LoggingServerHandler; + +class LoggingServerApi : public UdpConnectionHandler +{ + public: + enum { cDefaultPort = 9877 }; + + enum Status { cStatusDisconnected, cStatusConnected, cStatusNegotiating, cStatusAuthenticating }; + + LoggingServerApi(LoggingServerHandler *handler, int queueSize = 4096); + virtual ~LoggingServerApi(); + + void Connect(const char *address, int port, const char *loginName, const char *password, const char *defaultDirectory); + void Disconnect(); + + void Flush(int timeout); // blocking call to flush the log (timeout is how long to try, in ms) + + Status GetStatus() const; + void GiveTime(); + void Log16(const char *filename, int typeCode, const unsigned short *ucs2String); // no formatting support, application will have to do that on it's own + void Log(const char *filename, int typeCode, const char *message, ...); // printf style formatting + + void StartTransaction(); + void StopTransaction(); + + void RequestMonitor(const char *filename, bool turnOn); + void RequestFileList(); + void GetStatistics(LoggingServerApiStatistics *stats); + + protected: + enum { cSafetyQueueTime = 3 * 60 * 1000 }; // 3 minutes + + LoggingServerHandler *mHandler; + UdpManager *mUdpManager; + bool mAuthenticated; + bool mLoginSent; + UdpConnection *mConnection; + char mLoginName[256]; + char mPassword[256]; + char mDefaultDirectory[256]; + GroupLogicalPacket *mTransaction; + int mSessionId; + int mSessionSequence; + + // queue system + struct QueueEntry + { + LogicalPacket *packet; + UdpMisc::ClockStamp sentTime; + }; + + QueueEntry *mQueue; + int mQueueSize; + int mQueueCount; + int mQueuePosition; + + + void FlushQueue(); + void PacketSend(LogicalPacket *lp); + void LogPacket(char *data, int len); + LogicalPacket *CreatePacket(char *data, int dataLen); + public: + // these are public so the server-application can see them + enum C2SPacket { cC2SPacketNotUsed, cC2SPacketLogin, cC2SPacketLog, cC2SPacketMonitor, cC2SPacketFileList, cC2SPacketLog16 }; + enum S2CPacket { cS2CPacketNotUsed, cS2CPacketLoginConfirm, cS2CPacketMonitor, cS2CPacketFileList }; + + virtual void OnRoutePacket(UdpConnection *con, const uchar *data, int dataLen); + virtual void OnTerminated(UdpConnection *con); +}; + +class LoggingServerHandler +{ + public: + virtual void LshOnLoginConfirm(bool authenticated); + virtual void LshOnMonitor(int sessionId, int sequenceNumber, const char * const name, const char * const filename, int typeCode, const char * const message); + virtual void LshOnFileList(const char * const fileList); + virtual void LshOnTerminated(UdpConnection::DisconnectReason disconnect); +}; + + + + + + +#endif + diff --git a/engine/server/application/LogServer/src/shared/LoggingServerApiObserver.cpp b/engine/server/application/LogServer/src/shared/LoggingServerApiObserver.cpp new file mode 100644 index 00000000..b73b62eb --- /dev/null +++ b/engine/server/application/LogServer/src/shared/LoggingServerApiObserver.cpp @@ -0,0 +1,128 @@ +// LoggingServerApiObserver.cpp +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +//----------------------------------------------------------------------- + +#include "FirstLogServer.h" +#include "ConfigLogServer.h" +#include "LoggingServerApiObserver.h" +#include "LoggingServerApi.h" +#include "sharedLog/LogManager.h" +#include "sharedNetworkMessages/LogMessage.h" +#include "UnicodeUtils.h" + +//----------------------------------------------------------------------- + +LoggingServerApiObserver::LoggingServerApiObserver() : +m_loggingServerApi(new LoggingServerApi(0, ConfigLogServer::getLoggingServerApiQueueSize())) +{ + m_loggingServerApi->Connect(ConfigLogServer::getLoggingServerApiAddress(), LoggingServerApi::cDefaultPort, ConfigLogServer::getLoggingServerApiLoginName(), ConfigLogServer::getLoggingServerApiPassword(), ConfigLogServer::getLoggingServerApiDefaultDirectory()); +} + +//----------------------------------------------------------------------- + +LoggingServerApiObserver::~LoggingServerApiObserver() +{ + flush(); + delete m_loggingServerApi; +} + +//----------------------------------------------------------------------- + +void LoggingServerApiObserver::install() +{ + LogManager::registerObserverType("LoggingServerApi", create); +} + +//----------------------------------------------------------------------- + +LogObserver * LoggingServerApiObserver::create(const std::string &) +{ + return new LoggingServerApiObserver(); +} + +//----------------------------------------------------------------------- + +void LoggingServerApiObserver::log(const LogMessage & msg) +{ + const char * procId = "\0"; + const char * channel = "\0"; + std::string fileName = "misc.txt"; + + if(!msg.getProcId().empty()) + procId = msg.getProcId().c_str(); + + if(! msg.getChannel().empty()) + channel = msg.getChannel().c_str(); + + std::string msgText; + + if(! msg.getText().empty()) + { + time_t now; + tm t; + + IGNORE_RETURN( time(&now) ); + IGNORE_RETURN( gmtime_r(&now, &t) ); + char dirBuf[128] = {"\0"}; + snprintf(dirBuf, sizeof(dirBuf), "%d/%d/%d/", t.tm_year + 1900, t.tm_mon + 1, t.tm_mday); + fileName = ConfigLogServer::getClusterName(); + fileName += "/"; + fileName += dirBuf; + + std::string splittext = msg.getText(); + if(splittext.find(":") != splittext.npos) + { + fileName += splittext.substr(0, splittext.find(":")) + ".txt"; + } + + msgText = splittext.substr(splittext.find(":") + 1); + + std::string u = Unicode::wideToNarrow(msg.getUnicodeAttach()); + + // If there is ANY Unicode, send the whole log as Unicode. If there is ONLY non-Unicode, then send the log non-Unicode. + + if (!msg.getUnicodeAttach().empty()) + { + Unicode::String text; + + if (!msgText.empty()) + { + text += Unicode::narrowToWide(msgText); + text += Unicode::narrowToWide(":"); + } + + text += msg.getUnicodeAttach().c_str(); + text += Unicode::narrowToWide("\0"); + + m_loggingServerApi->Log16(fileName.c_str(), 0, text.c_str()); + } + else if (!msgText.empty()) + { + m_loggingServerApi->Log(fileName.c_str(), 0, "%s\0", msgText.c_str()); + } + } +} + +//----------------------------------------------------------------------- + +void LoggingServerApiObserver::flush() +{ + m_loggingServerApi->Flush(1000); +} + +//----------------------------------------------------------------------- + +void LoggingServerApiObserver::update() +{ + if(m_loggingServerApi->GetStatus() == LoggingServerApi::cStatusDisconnected) + { + m_loggingServerApi->Connect(ConfigLogServer::getLoggingServerApiAddress(), LoggingServerApi::cDefaultPort, ConfigLogServer::getLoggingServerApiLoginName(), ConfigLogServer::getLoggingServerApiPassword(), ConfigLogServer::getLoggingServerApiDefaultDirectory()); + } + + m_loggingServerApi->GiveTime(); +} + +//----------------------------------------------------------------------- + diff --git a/engine/server/application/LogServer/src/shared/LoggingServerApiObserver.h b/engine/server/application/LogServer/src/shared/LoggingServerApiObserver.h new file mode 100644 index 00000000..bc6ebadd --- /dev/null +++ b/engine/server/application/LogServer/src/shared/LoggingServerApiObserver.h @@ -0,0 +1,38 @@ +// LoggingServerApiObserver.h +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +#ifndef _INCLUDED_LoggingServerApiObserver_H +#define _INCLUDED_LoggingServerApiObserver_H + +//----------------------------------------------------------------------- + +#include "sharedLog/LogObserver.h" + +class LoggingServerApi; + +//----------------------------------------------------------------------- + +class LoggingServerApiObserver : public LogObserver +{ +public: + static void install(); + static LogObserver *create(std::string const &spec); + + LoggingServerApiObserver(); + virtual ~LoggingServerApiObserver(); + + virtual void log(LogMessage const &msg); + virtual void flush(); + virtual void update(); + +private: + LoggingServerApiObserver & operator = (const LoggingServerApiObserver & rhs); + LoggingServerApiObserver(const LoggingServerApiObserver & source); + + LoggingServerApi * m_loggingServerApi; +}; + +//----------------------------------------------------------------------- + +#endif // _INCLUDED_LoggingServerApiObserver_H diff --git a/engine/server/application/LogServer/src/win32/LoggingServerApiWrapper.cpp b/engine/server/application/LogServer/src/win32/LoggingServerApiWrapper.cpp new file mode 100644 index 00000000..78b377f5 --- /dev/null +++ b/engine/server/application/LogServer/src/win32/LoggingServerApiWrapper.cpp @@ -0,0 +1,16 @@ +// LoggingServerApiWrapper.cpp +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +// This is a wrapper cpp to workaround PCH and RSP's. While a DSP +// may exclude a single file from using precompiled headers, the +// dsp builder has no way (I know of) to honor this behavior. +//----------------------------------------------------------------------- + +#include "FirstLogServer.h" +//#include "LoggingServerApi.cpp" + +//----------------------------------------------------------------------- + +//----------------------------------------------------------------------- + diff --git a/engine/server/application/LogServer/src/win32/WinMain.cpp b/engine/server/application/LogServer/src/win32/WinMain.cpp new file mode 100644 index 00000000..21d829c4 --- /dev/null +++ b/engine/server/application/LogServer/src/win32/WinMain.cpp @@ -0,0 +1,55 @@ +// ====================================================================== +// +// WinMain.cpp +// +// Copyright 2002 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLogServer.h" +#include "sharedFoundation/FirstSharedFoundation.h" +#include "LogServer.h" + +#include "sharedCompression/SetupSharedCompression.h" +#include "sharedDebug/SetupSharedDebug.h" +#include "sharedFile/SetupSharedFile.h" +#include "sharedFoundation/SetupSharedFoundation.h" +#include "sharedNetworkMessages/SetupSharedNetworkMessages.h" +#include "sharedThread/SetupSharedThread.h" + +// ====================================================================== + +int main(int argc, char **argv) +{ + SetupSharedThread::install(); + SetupSharedDebug::install(1024); + + //-- setup foundation + SetupSharedFoundation::Data setupFoundationData(SetupSharedFoundation::Data::D_game); + + setupFoundationData.argc = argc; + setupFoundationData.argv = argv; + setupFoundationData.createWindow = false; + setupFoundationData.clockUsesSleep = true; + + SetupSharedFoundation::install(setupFoundationData); + + SetupSharedCompression::install(); + + SetupSharedFile::install(false); + SetupSharedNetworkMessages::install(); + + //-- setup server + LogServer::install(); + + //-- run server + SetupSharedFoundation::callbackWithExceptionHandling(LogServer::run); + + LogServer::remove(); + SetupSharedFoundation::remove(); + SetupSharedThread::remove(); + + return 0; +} + +// ======================================================================