LogServer

This commit is contained in:
Anonymous
2014-01-16 20:38:03 -07:00
parent 2bcd8a262c
commit c76ba3f66a
20 changed files with 1539 additions and 0 deletions
+1
View File
@@ -1,3 +1,4 @@
add_subdirectory(LoginServer)
add_subdirectory(LogServer)
add_subdirectory(TaskManager)
@@ -0,0 +1,6 @@
cmake_minimum_required(VERSION 2.8)
project(LogServer)
add_subdirectory(src)
@@ -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()
@@ -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;
}
// ======================================================================
@@ -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();
}
// ======================================================================
@@ -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<uint16>(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
@@ -0,0 +1,51 @@
// ======================================================================
//
// DatabaseLogObserver.cpp
//
// Copyright 2002 Sony Online Entertainment
//
// ======================================================================
#include "FirstLogServer.h"
#include "DatabaseLogObserver.h"
#include "sharedLog/LogManager.h"
#include <string>
// ======================================================================
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
}
// ======================================================================
@@ -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
@@ -0,0 +1 @@
#include "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
@@ -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 <cstdio>
// ======================================================================
LogServer::LogServer() :
Singleton<LogServer>(),
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<LoggerConnection>(), 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<GameNetworkMessage const &>(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<int>(Os::getProcessId()),
reason));
REPORT_LOG(
true,
(
"LogServer (pid %d) shutdown, reason: %s\n",
static_cast<int>(Os::getProcessId()),
reason));
m_done = true;
}
}
// ======================================================================
@@ -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<LogServer>, 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
@@ -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();
}
// ======================================================================
@@ -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
@@ -0,0 +1,485 @@
#include "FirstLogServer.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#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(&params);
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)
{
}
@@ -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
@@ -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();
}
//-----------------------------------------------------------------------
@@ -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
@@ -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"
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
@@ -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;
}
// ======================================================================