#include "LogCommandParser.h" #include "TransportInterface.h" #include #include #include #include #include "LinuxStrings.h" #ifdef _MSC_VER #pragma warning( push ) #endif LogCommandParser::LogCommandParser() { RegisterCommand(CommandParserInterface::VARIABLE_NUMBER_OF_PARAMETERS,"Subscribe","[] - Subscribes to a named channel, or all channels"); RegisterCommand(CommandParserInterface::VARIABLE_NUMBER_OF_PARAMETERS,"Unsubscribe","[] - 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<