DarkflameServer/thirdparty/raknet/Source/LogCommandParser.cpp
2021-12-05 18:54:36 +01:00

269 lines
6.8 KiB
C++

#include "LogCommandParser.h"
#include "TransportInterface.h"
#include <memory.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "LinuxStrings.h"
#ifdef _MSC_VER
#pragma warning( push )
#endif
LogCommandParser::LogCommandParser()
{
RegisterCommand(CommandParserInterface::VARIABLE_NUMBER_OF_PARAMETERS,"Subscribe","[<ChannelName>] - Subscribes to a named channel, or all channels");
RegisterCommand(CommandParserInterface::VARIABLE_NUMBER_OF_PARAMETERS,"Unsubscribe","[<ChannelName>] - Unsubscribes from a named channel, or all channels");
memset(channelNames,0,sizeof(channelNames));
}
LogCommandParser::~LogCommandParser()
{
}
bool LogCommandParser::OnCommand(const char *command, unsigned numParameters, char **parameterList, TransportInterface *transport, SystemAddress systemAddress, const char *originalString)
{
(void) originalString;
if (strcmp(command, "Subscribe")==0)
{
unsigned channelIndex;
if (numParameters==0)
{
Subscribe(systemAddress, 0);
transport->Send(systemAddress, "Subscribed to all channels.\r\n");
}
else if (numParameters==1)
{
if ((channelIndex=Subscribe(systemAddress, parameterList[0]))!=(unsigned)-1)
{
transport->Send(systemAddress, "You are now subscribed to channel %s.\r\n", channelNames[channelIndex]);
}
else
{
transport->Send(systemAddress, "Cannot find channel %s.\r\n", parameterList[0]);
PrintChannels(systemAddress, transport);
}
}
else
{
transport->Send(systemAddress, "Subscribe takes either 0 or 1 parameters.\r\n");
}
}
else if (strcmp(command, "Unsubscribe")==0)
{
unsigned channelIndex;
if (numParameters==0)
{
Unsubscribe(systemAddress, 0);
transport->Send(systemAddress, "Unsubscribed from all channels.\r\n");
}
else if (numParameters==1)
{
if ((channelIndex=Unsubscribe(systemAddress, parameterList[0]))!=(unsigned)-1)
{
transport->Send(systemAddress, "You are now unsubscribed from channel %s.\r\n", channelNames[channelIndex]);
}
else
{
transport->Send(systemAddress, "Cannot find channel %s.\r\n", parameterList[0]);
PrintChannels(systemAddress, transport);
}
}
else
{
transport->Send(systemAddress, "Unsubscribe takes either 0 or 1 parameters.\r\n");
}
}
return true;
}
const char *LogCommandParser::GetName(void) const
{
return "Logger";
}
void LogCommandParser::SendHelp(TransportInterface *transport, SystemAddress systemAddress)
{
transport->Send(systemAddress, "The logger will accept user log data via the Log(...) function.\r\n");
transport->Send(systemAddress, "Each log is associated with a named channel.\r\n");
transport->Send(systemAddress, "You can subscribe to or unsubscribe from named channels.\r\n");
PrintChannels(systemAddress, transport);
}
void LogCommandParser::AddChannel(const char *channelName)
{
unsigned channelIndex;
channelIndex = GetChannelIndexFromName(channelName);
// Each channel can only be added once.
assert(channelIndex==(unsigned)-1);
unsigned i;
for (i=0; i < 32; i++)
{
if (channelNames[i]==0)
{
// Assuming a persistent static string.
channelNames[i]=channelName;
return;
}
}
// No more available channels - max 32 with this implementation where I save subscribed channels with bit operations
assert(0);
}
void LogCommandParser::WriteLog(const char *channelName, const char *format, ...)
{
if (channelName==0 || format==0)
return;
unsigned channelIndex;
channelIndex = GetChannelIndexFromName(channelName);
if (channelIndex==(unsigned)-1)
{
AddChannel(channelName);
}
char text[REMOTE_MAX_TEXT_INPUT];
va_list ap;
va_start(ap, format);
_vsnprintf(text, REMOTE_MAX_TEXT_INPUT, format, ap);
va_end(ap);
text[REMOTE_MAX_TEXT_INPUT-1]=0;
// Make sure that text ends in \r\n
int textLen;
textLen=(int)strlen(text);
if (textLen==0)
return;
if (text[textLen-1]=='\n')
{
text[textLen-1]=0;
}
if (textLen < REMOTE_MAX_TEXT_INPUT-4)
strcat(text, "\r\n");
else
{
text[textLen-3]='\r';
text[textLen-2]='\n';
text[textLen-1]=0;
}
// For each user that subscribes to this channel, send to them.
unsigned i;
for (i=0; i < remoteUsers.Size(); i++)
{
if (remoteUsers[i].channels & (1 << channelIndex))
{
trans->Send(remoteUsers[i].systemAddress, text);
}
}
}
void LogCommandParser::PrintChannels(SystemAddress systemAddress, TransportInterface *transport) const
{
unsigned i;
bool anyChannels=false;
transport->Send(systemAddress, "CHANNELS:\r\n");
for (i=0; i < 32; i++)
{
if (channelNames[i])
{
transport->Send(systemAddress, "%i. %s\r\n", i+1,channelNames[i]);
anyChannels=true;
}
}
if (anyChannels==false)
transport->Send(systemAddress, "None.\r\n");
}
void LogCommandParser::OnNewIncomingConnection(SystemAddress systemAddress, TransportInterface *transport)
{
(void) systemAddress;
(void) transport;
}
void LogCommandParser::OnConnectionLost(SystemAddress systemAddress, TransportInterface *transport)
{
(void) transport;
Unsubscribe(systemAddress, 0);
}
unsigned LogCommandParser::Unsubscribe(SystemAddress systemAddress, const char *channelName)
{
unsigned i;
for (i=0; i < remoteUsers.Size(); i++)
{
if (remoteUsers[i].systemAddress==systemAddress)
{
if (channelName==0)
{
// Unsubscribe from all and delete this user.
remoteUsers[i]=remoteUsers[remoteUsers.Size()-1];
remoteUsers.RemoveFromEnd();
return 0;
}
else
{
unsigned channelIndex;
channelIndex = GetChannelIndexFromName(channelName);
if (channelIndex!=(unsigned)-1)
{
remoteUsers[i].channels&=0xFFFF ^ (1<<channelIndex); // Unset this bit
}
return channelIndex;
}
}
}
return (unsigned)-1;
}
unsigned LogCommandParser::Subscribe(SystemAddress systemAddress, const char *channelName)
{
unsigned i;
unsigned channelIndex=(unsigned)-1;
if (channelName)
{
channelIndex = GetChannelIndexFromName(channelName);
if (channelIndex==(unsigned)-1)
return channelIndex;
}
for (i=0; i < remoteUsers.Size(); i++)
{
if (remoteUsers[i].systemAddress==systemAddress)
{
if (channelName)
remoteUsers[i].channels|=1<<channelIndex; // Set this bit for an existing user
else
remoteUsers[i].channels=0xFFFF;
return channelIndex;
}
}
// Make a new user
SystemAddressAndChannel newUser;
newUser.systemAddress = systemAddress;
if (channelName)
newUser.channels=1<<channelIndex;
else
newUser.channels=0xFFFF;
remoteUsers.Insert(newUser);
return channelIndex;
}
unsigned LogCommandParser::GetChannelIndexFromName(const char *channelName)
{
unsigned i;
for (i=0; i < 32; i++)
{
if (channelNames[i]==0)
return (unsigned) -1;
if (_stricmp(channelNames[i], channelName)==0)
return i;
}
return (unsigned)-1;
}
void LogCommandParser::OnTransportChange(TransportInterface *transport)
{
// I don't want users to have to pass TransportInterface *transport to Log.
trans=transport;
}
#ifdef _MSC_VER
#pragma warning( pop )
#endif