• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

LogCommandParser.cpp

Go to the documentation of this file.
00001 #include "NativeFeatureIncludes.h"
00002 #if _RAKNET_SUPPORT_LogCommandParser==1
00003 
00004 #include "LogCommandParser.h"
00005 #include "TransportInterface.h"
00006 #if !defined(_PS3) && !defined(__PS3__) && !defined(SN_TARGET_PS3)
00007 #include <memory.h>
00008 #endif
00009 #include <stdio.h>
00010 #include <string.h>
00011 #include <stdarg.h>
00012 
00013 #include "LinuxStrings.h"
00014 
00015 #ifdef _MSC_VER
00016 #pragma warning( push )
00017 #endif
00018 
00019 LogCommandParser::LogCommandParser()
00020 {
00021         RegisterCommand(CommandParserInterface::VARIABLE_NUMBER_OF_PARAMETERS,"Subscribe","[<ChannelName>] - Subscribes to a named channel, or all channels");
00022         RegisterCommand(CommandParserInterface::VARIABLE_NUMBER_OF_PARAMETERS,"Unsubscribe","[<ChannelName>] - Unsubscribes from a named channel, or all channels");
00023         memset(channelNames,0,sizeof(channelNames));
00024 }
00025 LogCommandParser::~LogCommandParser()
00026 {
00027 }
00028 bool LogCommandParser::OnCommand(const char *command, unsigned numParameters, char **parameterList, TransportInterface *transport, SystemAddress systemAddress, const char *originalString)
00029 {
00030         (void) originalString;
00031 
00032         if (strcmp(command, "Subscribe")==0)
00033         {
00034                 unsigned channelIndex;
00035                 if (numParameters==0)
00036                 {
00037                         Subscribe(systemAddress, 0);
00038                         transport->Send(systemAddress, "Subscribed to all channels.\r\n");
00039                 }
00040                 else if (numParameters==1)
00041                 {
00042                         if ((channelIndex=Subscribe(systemAddress, parameterList[0]))!=(unsigned)-1)
00043                         {
00044                                 transport->Send(systemAddress, "You are now subscribed to channel %s.\r\n", channelNames[channelIndex]);
00045                         }
00046                         else
00047                         {
00048                                 transport->Send(systemAddress, "Cannot find channel %s.\r\n", parameterList[0]);
00049                                 PrintChannels(systemAddress, transport);
00050                         }
00051                 }
00052                 else
00053                 {
00054                         transport->Send(systemAddress, "Subscribe takes either 0 or 1 parameters.\r\n");
00055                 }
00056         }
00057         else if (strcmp(command, "Unsubscribe")==0)
00058         {
00059                 unsigned channelIndex;
00060                 if (numParameters==0)
00061                 {
00062                         Unsubscribe(systemAddress, 0);
00063                         transport->Send(systemAddress, "Unsubscribed from all channels.\r\n");
00064                 }
00065                 else if (numParameters==1)
00066                 {
00067                         if ((channelIndex=Unsubscribe(systemAddress, parameterList[0]))!=(unsigned)-1)
00068                         {
00069                                 transport->Send(systemAddress, "You are now unsubscribed from channel %s.\r\n", channelNames[channelIndex]);
00070                         }
00071                         else
00072                         {
00073                                 transport->Send(systemAddress, "Cannot find channel %s.\r\n", parameterList[0]);
00074                                 PrintChannels(systemAddress, transport);
00075                         }
00076                 }
00077                 else
00078                 {
00079                         transport->Send(systemAddress, "Unsubscribe takes either 0 or 1 parameters.\r\n");
00080                 }
00081         }
00082 
00083         return true;
00084 }
00085 const char *LogCommandParser::GetName(void) const
00086 {
00087         return "Logger";
00088 }
00089 void LogCommandParser::SendHelp(TransportInterface *transport, SystemAddress systemAddress)
00090 {
00091         transport->Send(systemAddress, "The logger will accept user log data via the Log(...) function.\r\n");
00092         transport->Send(systemAddress, "Each log is associated with a named channel.\r\n");
00093         transport->Send(systemAddress, "You can subscribe to or unsubscribe from named channels.\r\n");
00094         PrintChannels(systemAddress, transport);
00095 }
00096 void LogCommandParser::AddChannel(const char *channelName)
00097 {
00098         unsigned channelIndex;
00099         channelIndex = GetChannelIndexFromName(channelName);
00100         // Each channel can only be added once.
00101         RakAssert(channelIndex==(unsigned)-1);
00102 
00103         unsigned i;
00104         for (i=0; i < 32; i++)
00105         {
00106                 if (channelNames[i]==0)
00107                 {
00108                         // Assuming a persistent static string.
00109                         channelNames[i]=channelName;
00110                         return;
00111                 }
00112         }
00113 
00114         // No more available channels - max 32 with this implementation where I save subscribed channels with bit operations
00115         RakAssert(0);
00116 }
00117 void LogCommandParser::WriteLog(const char *channelName, const char *format, ...)
00118 {
00119         if (channelName==0 || format==0)
00120                 return;
00121 
00122         unsigned channelIndex;
00123         channelIndex = GetChannelIndexFromName(channelName);
00124         if (channelIndex==(unsigned)-1)
00125         {
00126                 AddChannel(channelName);
00127         }
00128 
00129         char text[REMOTE_MAX_TEXT_INPUT];
00130         va_list ap;
00131         va_start(ap, format);
00132         _vsnprintf(text, REMOTE_MAX_TEXT_INPUT, format, ap);
00133         va_end(ap);
00134         text[REMOTE_MAX_TEXT_INPUT-1]=0;
00135 
00136         // Make sure that text ends in \r\n
00137         int textLen;
00138         textLen=(int)strlen(text);
00139         if (textLen==0)
00140                 return;
00141         if (text[textLen-1]=='\n')
00142         {
00143                 text[textLen-1]=0;
00144         }
00145         if (textLen < REMOTE_MAX_TEXT_INPUT-4)
00146                 strcat(text, "\r\n");
00147         else
00148         {
00149                 text[textLen-3]='\r';
00150                 text[textLen-2]='\n';
00151                 text[textLen-1]=0;
00152         }
00153 
00154         // For each user that subscribes to this channel, send to them.
00155         unsigned i;
00156         for (i=0; i < remoteUsers.Size(); i++)
00157         {
00158                 if (remoteUsers[i].channels & (1 << channelIndex))
00159                 {
00160                         trans->Send(remoteUsers[i].systemAddress, text);
00161                 }
00162         }
00163 }
00164 void LogCommandParser::PrintChannels(SystemAddress systemAddress, TransportInterface *transport) const
00165 {
00166         unsigned i;
00167         bool anyChannels=false;
00168         transport->Send(systemAddress, "CHANNELS:\r\n");
00169         for (i=0; i < 32; i++)
00170         {
00171                 if (channelNames[i])
00172                 {
00173                         transport->Send(systemAddress, "%i. %s\r\n", i+1,channelNames[i]);
00174                         anyChannels=true;
00175                 }
00176         }
00177         if (anyChannels==false)
00178                 transport->Send(systemAddress, "None.\r\n");
00179 }
00180 void LogCommandParser::OnNewIncomingConnection(SystemAddress systemAddress, TransportInterface *transport)
00181 {
00182         (void) systemAddress;
00183         (void) transport;
00184 }
00185 void LogCommandParser::OnConnectionLost(SystemAddress systemAddress, TransportInterface *transport)
00186 {
00187         (void) transport;
00188         Unsubscribe(systemAddress, 0);
00189 }
00190 unsigned LogCommandParser::Unsubscribe(SystemAddress systemAddress, const char *channelName)
00191 {
00192         unsigned i;
00193         for (i=0; i < remoteUsers.Size(); i++)
00194         {
00195                 if (remoteUsers[i].systemAddress==systemAddress)
00196                 {
00197                         if (channelName==0)
00198                         {
00199                                 // Unsubscribe from all and delete this user.
00200                                 remoteUsers[i]=remoteUsers[remoteUsers.Size()-1];
00201                                 remoteUsers.RemoveFromEnd();
00202                                 return 0;
00203                         }
00204                         else
00205                         {
00206                                 unsigned channelIndex;
00207                                 channelIndex = GetChannelIndexFromName(channelName);
00208                                 if (channelIndex!=(unsigned)-1)
00209                                 {
00210                                         remoteUsers[i].channels&=0xFFFF ^ (1<<channelIndex); // Unset this bit
00211                                 }
00212                                 return channelIndex;
00213                         }
00214                 }
00215         }
00216         return (unsigned)-1;
00217 }
00218 unsigned LogCommandParser::Subscribe(SystemAddress systemAddress, const char *channelName)
00219 {
00220         unsigned i;
00221         unsigned channelIndex=(unsigned)-1;
00222         if (channelName)
00223         {
00224                 channelIndex = GetChannelIndexFromName(channelName);
00225                 if (channelIndex==(unsigned)-1)
00226                         return channelIndex;
00227         }
00228 
00229         for (i=0; i < remoteUsers.Size(); i++)
00230         {
00231                 if (remoteUsers[i].systemAddress==systemAddress)
00232                 {
00233                         if (channelName)
00234                                 remoteUsers[i].channels|=1<<channelIndex; // Set this bit for an existing user
00235                         else
00236                                 remoteUsers[i].channels=0xFFFF;
00237                         return channelIndex;
00238                 }
00239         }
00240 
00241         // Make a new user
00242         SystemAddressAndChannel newUser;
00243         newUser.systemAddress = systemAddress;
00244         if (channelName)
00245                 newUser.channels=1<<channelIndex;
00246         else
00247                 newUser.channels=0xFFFF;
00248         remoteUsers.Insert(newUser, __FILE__, __LINE__);
00249         return channelIndex;
00250 }
00251 unsigned LogCommandParser::GetChannelIndexFromName(const char *channelName)
00252 {
00253         unsigned i;
00254         for (i=0; i < 32; i++)
00255         {
00256                 if (channelNames[i]==0)
00257                         return (unsigned) -1;
00258 
00259                 if (_stricmp(channelNames[i], channelName)==0)
00260                         return i;
00261         }
00262         return (unsigned)-1;
00263 }
00264 
00265 void LogCommandParser::OnTransportChange(TransportInterface *transport)
00266 {
00267         // I don't want users to have to pass TransportInterface *transport to Log.
00268         trans=transport;
00269 }
00270 
00271 #ifdef _MSC_VER
00272 #pragma warning( pop )
00273 #endif
00274 
00275 #endif // _RAKNET_SUPPORT_*

Generated on Thu Sep 30 2010 01:27:24 for RakNet by  doxygen 1.7.1