mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-12-24 22:43:34 +00:00
269 lines
6.8 KiB
C++
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
|