Files
src-1.2/external/3rd/library/platform/projects/MonAPI2/MonitorAPI.cpp
T

603 lines
15 KiB
C++
Executable File

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "zlib.h"
#include "MonitorAPI.h"
// **********************************************************************************************
// **********************************************************************************************
// ********************************** DO NOT EDIT THIS FILE ***********************************
// **********************************************************************************************
// **********************************************************************************************
void set_bit(unsigned char p[], int bit) { p[bit >> 3] |= 1 << (bit & 0x7); }
void unset_bit(unsigned char p[], int bit) { p[bit >> 3] &= ~(1 << (bit & 0x7)); }
int get_bit(unsigned char p[], int bit) { return (p[bit >> 3] >> (bit & 0x7)) & 1; }
int ZEXPORT uncompress2(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);
////////////////////////////////////////
// Player implementation
////////////////////////////////////////
MonitorObject::MonitorObject(UdpConnection *con, CMonitorData *_gamedata, char *passwd, char **addressList, bool _bprint)
{
mbprint = _bprint;
mMonitorData = _gamedata;
mbAuthenticated = false;
mPasswd = passwd;
mAddressList = addressList;
mHierarchySent = false;
mSequence = 1;
mlastUpdateTime = 0;
mConnection = con;
mConnection->AddRef();
mConnection->SetHandler(this);
// Flag all the descriptions
mMark = new unsigned char[(mMonitorData->DataMax() / 8) + 2];
memset(mMark, 0, (mMonitorData->DataMax() / 8) + 2);
char hold[256];
if (mbprint)
{
fprintf(stderr, "MONITOR API CONNECTED: %s:%d\n",
mConnection->GetDestinationIp().GetAddress(hold),
mConnection->GetDestinationPort());
}
}
MonitorObject::~MonitorObject()
{
delete[] mMark;
if (mConnection)
{
mConnection->SetHandler(nullptr);
mConnection->Disconnect();
mConnection->Release();
}
}
void MonitorObject::OnTerminated(UdpConnection * /* con */)
{
char hold[214];
if (mConnection)
{
if (mbprint)
{
mConnection->GetDestinationIp().GetAddress(hold);
if (mbprint)
{
fprintf(stderr, "MONITOR API TERMINATE %s:%d %s - %s\n",
hold,
mConnection->GetDestinationPort(),
UdpConnection::DisconnectReasonText(mConnection->GetDisconnectReason()),
UdpConnection::DisconnectReasonText(mConnection->GetOtherSideDisconnectReason()));
}
}
mConnection->SetHandler(nullptr);
mConnection->Disconnect();
mConnection->Release();
mConnection = nullptr;
}
}
void MonitorObject::OnRoutePacket(UdpConnection * con, const unsigned char *data, int dataLen)
{
if (dataLen < 6)
{
if (mbprint)
fprintf(stderr, "MONITOR API: This should not happen, line %d\n", __LINE__);
}
simpleMessage msg(data);
if (con == nullptr)
{
if (mbprint)
fprintf(stderr, "MONITOR API: MonitorObject.OnRoutePacket, recived a nullptr connection.?\n");
return;
}
// ************************* Login Process ***************************
if (mbAuthenticated == false)
{
if (msg.getCommand() != MON_MSG_AUTH)
return;
if (processAuthRequest(data, dataLen) == false)
return;
mbAuthenticated = true;
return;
}
// ************************* Process Commands ***********************
switch (msg.getCommand())
{
// *********************** Game Server Processing ******************
case MON_MSG_QUERY_ELEMENTS:
if (mHierarchySent == true)
{
mMonitorData->processElementsRequest(con, mSequence, (char *)&data[6], dataLen, mlastUpdateTime);
mlastUpdateTime = (long)time(nullptr);
break;
}
// When the hierarchy has changed, fall through
case MON_MSG_QUERY_HIERARCHY_BLOCK:
if (mMonitorData->processHierarchyRequestBlock(con, mSequence) == false)
{
break;
}
mHierarchySent = true;
break;
case MON_MSG_QUERY_DESCRIPTION:
mMonitorData->processDescriptionRequest(con, mSequence, (char *)&data[6], dataLen, mMark);
break;
case MON_MSG_ERROR:
processError(data);
break;
default:
fprintf(stderr, "MONITOR API: unknown message type received from client [%x]\n", msg.getCommand());
break;
}
}
bool MonitorObject::checkAddress(const char * address)
{
int x = 0;
while (mAddressList[x])
{
if (strncmp(mAddressList[x], address, strlen(mAddressList[x])) == 0)
return true;
x++;
}
return false;
}
bool MonitorObject::checkPasswd(const char *passwd)
{
if (strcmp(mPasswd, passwd) == 0)
return true;
return false;
}
bool MonitorObject::processAuthRequest(const unsigned char * data, int /* dataLen */)
{
char reply;
stringMessage strMsg(data);
char addBuff[16] = { 0 };
char sendBuf[32];
int len;
reply = '1';
if (checkAddress(mConnection->GetDestinationIp().GetAddress(addBuff)) == false)
{
reply = '3';
}
else if (checkPasswd(strMsg.getData()) == false)
{
reply = '2';
}
memset(sendBuf, 0, sizeof(sendBuf));
len = 0;
packShort(sendBuf + len, len, (int16_t)MON_MSG_AUTHREPLY);
packShort(sendBuf + len, len, mSequence);
packShort(sendBuf + len, len, (int16_t)3);
packShort(sendBuf + len, len, (int16_t)CURRENT_API_VERSION);
packByte(sendBuf + len, len, reply);
mConnection->Send(cUdpChannelReliable1, sendBuf, 9);
return true;
}
void MonitorObject::DescriptionMark(int x, int mode)
{
if (mode == 0) set_bit(mMark, x); else unset_bit(mMark, x);
}
char * getErrorString(uint16_t errorCode)
{
if (errorCode == 0)
{
return "none";
}
else
{
switch (errorCode)
{
case INVALID_HEADER:
case INVALID_SEQUENCE:
case INVALID_MSG_LENGTH:
case INVALID_MSG_TYPE:
return "Invalid message";
case INVALID_AUTH_REQUEST:
return "Invalid authorization request";
case INVALID_ELEMENT_REQUEST:
case INVALID_HIERARCHY_REQUEST:
return "Invalid data request";
case INVALID_AUTH_REPLY:
return "Invalid reply to authentication request";
case INVALID_ELEMENT_REPLY:
case INVALID_HIERARCHY_REPLY:
return "Badly formatted data in dataReplyMessage";
case INVALID_ERROR_CODE:
return "Received invalid error message";
}
}
return "Undefined error code";
}
bool MonitorObject::processError(const unsigned char * data)
{
stringMessage strMsg(data);
uint16_t errCode = (uint16_t)atoi(strMsg.getData());
fprintf(stderr, "MONITOR API Error: %s\n", getErrorString(errCode));
return true;
}
///////////////////////////////////////
// MonitorManager implementation
////////////////////////////////////////
MonitorManager::MonitorManager(const char *configFile, CMonitorData *_gamedata, UdpManager *manager, bool _bprint)
{
mManager = manager;
mbprint = _bprint;
passString = nullptr;
mMonitorData = _gamedata;
mObjectCount = 0;
for (int x = 0; x < AUTHADDRESS_MAX; x++)
allowedAddressList[x] = 0;
loadAuthData(configFile);
}
MonitorManager::~MonitorManager()
{
int x;
x = 0;
while (allowedAddressList[x])
free(allowedAddressList[x++]);
free(passString);
for (int i = 0; i < mObjectCount; i++)
delete mObject[i];
}
void MonitorManager::OnConnectRequest(UdpConnection *con)
{
if (mObjectCount == CONNECTION_MAX)
{
if (con)
{
con->SetHandler(nullptr);
con->Disconnect();
con->Release();
}
if (mbprint)
fprintf(stderr, "MonitorAPI: Collector connection reached max (%d).\n", CONNECTION_MAX);
return;
}
AddObject(new MonitorObject(con, mMonitorData, passString, allowedAddressList, mbprint));
}
void MonitorManager::AddObject(MonitorObject *Object)
{
mObject[mObjectCount++] = Object;
}
void MonitorManager::GiveTime()
{
// check if the monitor object is no longer connected
for (int i = 0; i < mObjectCount; i++)
{
if (mObject[i]->mConnection == nullptr ||
mObject[i]->mConnection->GetStatus() == UdpConnection::cStatusDisconnected)
{
MonitorObject *o = mObject[i];
mObjectCount--;
memmove(&mObject[i], &mObject[i + 1], (mObjectCount - i) * sizeof(MonitorObject *));
i--;
delete o;
}
}
}
void MonitorManager::HierarchyChanged()
{
for (int i = 0; i < mObjectCount; i++)
mObject[i]->HeirarchyChanged();
}
void MonitorManager::DescriptionMark(int x, int mode)
{
for (int i = 0; i < mObjectCount; i++)
mObject[i]->DescriptionMark(x, mode);
}
bool MonitorManager::loadAuthData(const char * filename)
{
int nline;
int len;
int x;
char buffer[1024];
FILE *fp = fopen(filename, "r");
if (fp == nullptr)
{
fprintf(stderr, "Monitor API: could not open %s file\nTHIS FILE IS REQUIRED.\n", filename);
return false;
}
free(passString);
for (x = 0; x < AUTHADDRESS_MAX; x++)
{
if (allowedAddressList[x])
{
free(allowedAddressList[x]);
allowedAddressList[x] = 0;
}
}
nline = 0;
x = 0;
while (!feof(fp))
{
if (fgets(buffer, 1023, fp) != nullptr) {
// get rid of '\n' and '\r' for comparisons
strtok(buffer, "\r\n");
len = (int)strlen(buffer);
if (len > 0)
{
if (nline == 0)
{
passString = (char *)malloc(len + 1);
strcpy(passString, buffer);
}
else
{
allowedAddressList[x] = (char *)malloc(len + 1);
strcpy(allowedAddressList[x], buffer);
x++;
}
}
nline++;
}
}
// clean up
fclose(fp);
return true;
}
// ******************************************************************************************************
// ******************************************************************************************************
// ******************************************************************************************************
// ******************************************************************************************************
CMonitorAPI::CMonitorAPI(const char *configFile, uint16_t Port, bool _bprint, char *address, UdpManager * mang)
{
mbprint = _bprint;
mPort = Port;
mAddress = nullptr;
if (address)
{
mAddress = (char *)malloc(strlen(address) + 1);
strcpy(mAddress, address);
}
if (mang == nullptr)
{
UdpManager::Params params;
params.handler = nullptr;
params.maxConnections = CONNECTION_MAX;
params.outgoingBufferSize = 1000000;
params.noDataTimeout = 130000;
params.oldestUnacknowledgedTimeout = 120000;
params.processIcmpErrors = false;
params.port = mPort;
mManager = new UdpManager(&params);
mMonitorData = new CMonitorData();
}
mObjectManager = new MonitorManager(configFile, mMonitorData, mManager, mbprint);
mManager->SetHandler(mObjectManager);
if (mbprint)
fprintf(stderr, "MonitorAPI: started on port->%d\n", mPort);
}
CMonitorAPI::~CMonitorAPI()
{
free(mAddress);
delete mObjectManager;
mManager->Release();
delete mMonitorData;
}
void CMonitorAPI::Update()
{
if (mManager)
mManager->GiveTime();
if (mObjectManager)
mObjectManager->GiveTime();
}
int CMonitorAPI::add(const char *label, int id, int ping, const char *des)
{
int rnt;
rnt = mMonitorData->add(label, id, ping, des);
if (rnt)
mObjectManager->HierarchyChanged();
return rnt;
}
void CMonitorAPI::remove(int Id)
{
mMonitorData->remove(Id);
mObjectManager->HierarchyChanged();
}
void CMonitorAPI::setDescription(int Id, const char *Description)
{
int x;
int mode;
x = mMonitorData->setDescription(Id, Description, mode);
if (x == -1)
return;
mObjectManager->DescriptionMark(x, mode);
}
void CMonitorAPI::dump() { mMonitorData->dump(); }
//----------------------------------------------------------------
monMessage::monMessage() :command(0), sequence(0), size(0) {}
//----------------------------------------------------------------
monMessage::monMessage(int16_t cmd, int16_t seq, int16_t s) : command(cmd), sequence(seq), size(s) {}
//----------------------------------------------------------------
monMessage::monMessage(const unsigned char * source) : command(0), sequence(0), size(0)
{
int len;
len = 0;
unpackShort((char *)source + len, len, command);
unpackShort((char *)source + len, len, sequence);
unpackShort((char *)source + len, len, size);
}
//----------------------------------------------------------------
// monMessage::monMessage(const monMessage &copy):command(copy.command),sequence(copy.sequence),size(copy.size){}
//----------------------------------------------------------------
stringMessage::stringMessage(const unsigned char * source) :monMessage(source)
{
int size;
size = (int)strlen((char *)source + 6) + 1;
data = new char[size];
strcpy(data, (char *)source + 6); // Add six for the size of the header
}
//----------------------------------------------------------------
stringMessage::stringMessage(const uint16_t command, const uint16_t sequence, const uint16_t size, char * newData) :
monMessage(command, sequence, size)
{
data = new char[strlen(newData) + 1];
strncpy(data, newData, strlen(newData + 1));
}
//----------------------------------------------------------------
stringMessage::~stringMessage()
{
delete[] data;
data = 0;
}
//----------------------------------------------------------------
authReplyMessage::authReplyMessage(const unsigned char * source) :
monMessage(source)
{
int len = 6;
unpackShort((char *)source + len, len, version);
unpackByte((char *)source + len, len, data);
}
//----------------------------------------------------------------
authReplyMessage::authReplyMessage(const uint16_t command,
const uint16_t sequence,
const uint16_t size,
unsigned char newData) :
monMessage(command, sequence, size), data(newData), version() {}
//----------------------------------------------------------------
dataReplyMessage::dataReplyMessage(const unsigned char * source) :
monMessage(source)
{
data = new unsigned char[getSize() + 1];
memcpy(data, source + 6, getSize());
data[getSize()] = 0;
}
//----------------------------------------------------------------
dataReplyMessage::dataReplyMessage(const uint16_t command,
const uint16_t sequence,
const uint16_t size,
unsigned char * newData,
int newDataLen) :
monMessage(command, sequence, size)
{
data = new unsigned char[newDataLen];
memcpy(data, newData, newDataLen);
}
//----------------------------------------------------------------
dataReplyMessage::~dataReplyMessage()
{
delete[] data;
data = 0;
}
//----------------------------------------------------------------
simpleMessage::simpleMessage(const unsigned char * source) :monMessage(source) {}
//----------------------------------------------------------------
simpleMessage::simpleMessage(const uint16_t command,
const uint16_t sequence,
const uint16_t size) :
monMessage(command, sequence, size) {}
//----------------------------------------------------------------
simpleMessage::~simpleMessage() {}
//----------------------------------------------------------------
//----------------------------------------------------------------
dataBlockReplyMessage::dataBlockReplyMessage(const unsigned char * source) :
monMessage(source)
{
int err;
unsigned long S = 4000000;
unsigned char *p;
data = nullptr;
p = (unsigned char *)malloc(4000000);
memset(p, 0, 4000000);
err = uncompress(p, &S, (source + 6), (long)getSize());
if (Z_OK != err) { free(p); return; }
data = new unsigned char[S + 1];
memcpy(data, p, S);
setSize((uint16_t)S);
free(p);
}
//----------------------------------------------------------------
dataBlockReplyMessage::~dataBlockReplyMessage()
{
if (data)
{
delete[] data;
data = 0;
}
}