| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- /*
- * Copyright (c) 2014, Oculus VR, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- */
- #include "NativeFeatureIncludes.h"
- #if _RAKNET_SUPPORT_LogCommandParser==1
- #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
- using namespace RakNet;
- STATIC_FACTORY_DEFINITIONS(LogCommandParser,LogCommandParser);
- 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, const 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, const 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=0;
- channelIndex = GetChannelIndexFromName(channelName);
- // Each channel can only be added once.
- RakAssert(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
- RakAssert(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(const 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(const SystemAddress &systemAddress, TransportInterface *transport)
- {
- (void) systemAddress;
- (void) transport;
- }
- void LogCommandParser::OnConnectionLost(const SystemAddress &systemAddress, TransportInterface *transport)
- {
- (void) transport;
- Unsubscribe(systemAddress, 0);
- }
- unsigned LogCommandParser::Unsubscribe(const 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(const 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, _FILE_AND_LINE_);
- 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
- #endif // _RAKNET_SUPPORT_*
|