SLikeNet 0.1.3

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
LogCommandParser.cpp
Go to the documentation of this file.
1 /*
2 * Original work: Copyright (c) 2014, Oculus VR, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * RakNet License.txt file in the licenses directory of this source tree. An additional grant
7 * of patent rights can be found in the RakNet Patents.txt file in the same directory.
8 *
9 *
10 * Modified work: Copyright (c) 2016-2017, SLikeSoft UG (haftungsbeschränkt)
11 *
12 * This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
13 * license found in the license.txt file in the root directory of this source tree.
14 */
15
16 #include "slikenet/NativeFeatureIncludes.h"
17 #if _RAKNET_SUPPORT_LogCommandParser==1
18
19 #include "slikenet/LogCommandParser.h"
20 #include "slikenet/TransportInterface.h"
21
22 #include <memory.h>
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdarg.h>
27
28 #include "slikenet/LinuxStrings.h"
29 #include "slikenet/linux_adapter.h"
30 #include "slikenet/osx_adapter.h"
31
32 using namespace SLNet;
33
34 STATIC_FACTORY_DEFINITIONS(LogCommandParser,LogCommandParser);
35
36 LogCommandParser::LogCommandParser()
37 {
38 RegisterCommand(CommandParserInterface::VARIABLE_NUMBER_OF_PARAMETERS,"Subscribe","[<ChannelName>] - Subscribes to a named channel, or all channels");
39 RegisterCommand(CommandParserInterface::VARIABLE_NUMBER_OF_PARAMETERS,"Unsubscribe","[<ChannelName>] - Unsubscribes from a named channel, or all channels");
40 memset(channelNames,0,sizeof(channelNames));
41 }
42 LogCommandParser::~LogCommandParser()
43 {
44 }
45 bool LogCommandParser::OnCommand(const char *command, unsigned numParameters, char **parameterList, TransportInterface *transport, const SystemAddress &systemAddress, const char *originalString)
46 {
47 (void) originalString;
48
49 if (strcmp(command, "Subscribe")==0)
50 {
51 unsigned channelIndex;
52 if (numParameters==0)
53 {
54 Subscribe(systemAddress, 0);
55 transport->Send(systemAddress, "Subscribed to all channels.\r\n");
56 }
57 else if (numParameters==1)
58 {
59 if ((channelIndex=Subscribe(systemAddress, parameterList[0]))!=(unsigned)-1)
60 {
61 transport->Send(systemAddress, "You are now subscribed to channel %s.\r\n", channelNames[channelIndex]);
62 }
63 else
64 {
65 transport->Send(systemAddress, "Cannot find channel %s.\r\n", parameterList[0]);
66 PrintChannels(systemAddress, transport);
67 }
68 }
69 else
70 {
71 transport->Send(systemAddress, "Subscribe takes either 0 or 1 parameters.\r\n");
72 }
73 }
74 else if (strcmp(command, "Unsubscribe")==0)
75 {
76 unsigned channelIndex;
77 if (numParameters==0)
78 {
79 Unsubscribe(systemAddress, 0);
80 transport->Send(systemAddress, "Unsubscribed from all channels.\r\n");
81 }
82 else if (numParameters==1)
83 {
84 if ((channelIndex=Unsubscribe(systemAddress, parameterList[0]))!=(unsigned)-1)
85 {
86 transport->Send(systemAddress, "You are now unsubscribed from channel %s.\r\n", channelNames[channelIndex]);
87 }
88 else
89 {
90 transport->Send(systemAddress, "Cannot find channel %s.\r\n", parameterList[0]);
91 PrintChannels(systemAddress, transport);
92 }
93 }
94 else
95 {
96 transport->Send(systemAddress, "Unsubscribe takes either 0 or 1 parameters.\r\n");
97 }
98 }
99
100 return true;
101 }
102 const char *LogCommandParser::GetName(void) const
103 {
104 return "Logger";
105 }
106 void LogCommandParser::SendHelp(TransportInterface *transport, const SystemAddress &systemAddress)
107 {
108 transport->Send(systemAddress, "The logger will accept user log data via the Log(...) function.\r\n");
109 transport->Send(systemAddress, "Each log is associated with a named channel.\r\n");
110 transport->Send(systemAddress, "You can subscribe to or unsubscribe from named channels.\r\n");
111 PrintChannels(systemAddress, transport);
112 }
113 void LogCommandParser::AddChannel(const char *channelName)
114 {
115 unsigned channelIndex=0;
116 channelIndex = GetChannelIndexFromName(channelName);
117 // Each channel can only be added once.
118 RakAssert(channelIndex==(unsigned)-1);
119
120 unsigned i;
121 for (i=0; i < 32; i++)
122 {
123 if (channelNames[i]==0)
124 {
125 // Assuming a persistent static string.
126 channelNames[i]=channelName;
127 return;
128 }
129 }
130
131 // No more available channels - max 32 with this implementation where I save subscribed channels with bit operations
132 RakAssert(0);
133 }
134 void LogCommandParser::WriteLog(const char *channelName, const char *format, ...)
135 {
136 if (channelName==0 || format==0)
137 return;
138
139 unsigned channelIndex;
140 channelIndex = GetChannelIndexFromName(channelName);
141 if (channelIndex==(unsigned)-1)
142 {
143 AddChannel(channelName);
144 }
145
146 char text[REMOTE_MAX_TEXT_INPUT];
147 va_list ap;
148 va_start(ap, format);
149 vsnprintf_s(text, REMOTE_MAX_TEXT_INPUT-1, format, ap);
150 va_end(ap);
151
152 // Make sure that text ends in \r\n
153 int textLen;
154 textLen=(int)strlen(text);
155 if (textLen==0)
156 return;
157 if (text[textLen-1]=='\n')
158 {
159 text[textLen-1]=0;
160 }
161 if (textLen < REMOTE_MAX_TEXT_INPUT-4)
162 strcat_s(text, "\r\n");
163 else
164 {
165 text[textLen-3]='\r';
166 text[textLen-2]='\n';
167 text[textLen-1]=0;
168 }
169
170 // For each user that subscribes to this channel, send to them.
171 unsigned i;
172 for (i=0; i < remoteUsers.Size(); i++)
173 {
174 if (remoteUsers[i].channels & (1 << channelIndex))
175 {
176 trans->Send(remoteUsers[i].systemAddress, text);
177 }
178 }
179 }
180 void LogCommandParser::PrintChannels(const SystemAddress &systemAddress, TransportInterface *transport) const
181 {
182 unsigned i;
183 bool anyChannels=false;
184 transport->Send(systemAddress, "CHANNELS:\r\n");
185 for (i=0; i < 32; i++)
186 {
187 if (channelNames[i])
188 {
189 transport->Send(systemAddress, "%i. %s\r\n", i+1,channelNames[i]);
190 anyChannels=true;
191 }
192 }
193 if (anyChannels==false)
194 transport->Send(systemAddress, "None.\r\n");
195 }
196 void LogCommandParser::OnNewIncomingConnection(const SystemAddress &systemAddress, TransportInterface *transport)
197 {
198 (void) systemAddress;
199 (void) transport;
200 }
201 void LogCommandParser::OnConnectionLost(const SystemAddress &systemAddress, TransportInterface *transport)
202 {
203 (void) transport;
204 Unsubscribe(systemAddress, 0);
205 }
206 unsigned LogCommandParser::Unsubscribe(const SystemAddress &systemAddress, const char *channelName)
207 {
208 unsigned i;
209 for (i=0; i < remoteUsers.Size(); i++)
210 {
211 if (remoteUsers[i].systemAddress==systemAddress)
212 {
213 if (channelName==0)
214 {
215 // Unsubscribe from all and delete this user.
216 remoteUsers[i]=remoteUsers[remoteUsers.Size()-1];
217 remoteUsers.RemoveFromEnd();
218 return 0;
219 }
220 else
221 {
222 unsigned channelIndex;
223 channelIndex = GetChannelIndexFromName(channelName);
224 if (channelIndex!=(unsigned)-1)
225 {
226 remoteUsers[i].channels&=0xFFFF ^ (1<<channelIndex); // Unset this bit
227 }
228 return channelIndex;
229 }
230 }
231 }
232 return (unsigned)-1;
233 }
234 unsigned LogCommandParser::Subscribe(const SystemAddress &systemAddress, const char *channelName)
235 {
236 unsigned i;
237 unsigned channelIndex=(unsigned)-1;
238 if (channelName)
239 {
240 channelIndex = GetChannelIndexFromName(channelName);
241 if (channelIndex==(unsigned)-1)
242 return channelIndex;
243 }
244
245 for (i=0; i < remoteUsers.Size(); i++)
246 {
247 if (remoteUsers[i].systemAddress==systemAddress)
248 {
249 if (channelName)
250 remoteUsers[i].channels|=1<<channelIndex; // Set this bit for an existing user
251 else
252 remoteUsers[i].channels=0xFFFF;
253 return channelIndex;
254 }
255 }
256
257 // Make a new user
258 SystemAddressAndChannel newUser;
259 newUser.systemAddress = systemAddress;
260 if (channelName)
261 newUser.channels=1<<channelIndex;
262 else
263 newUser.channels=0xFFFF;
264 remoteUsers.Insert(newUser, _FILE_AND_LINE_);
265 return channelIndex;
266 }
267 unsigned LogCommandParser::GetChannelIndexFromName(const char *channelName)
268 {
269 unsigned i;
270 for (i=0; i < 32; i++)
271 {
272 if (channelNames[i]==0)
273 return (unsigned) -1;
274
275 if (_stricmp(channelNames[i], channelName)==0)
276 return i;
277 }
278 return (unsigned)-1;
279 }
280
281 void LogCommandParser::OnTransportChange(TransportInterface *transport)
282 {
283 // I don't want users to have to pass TransportInterface *transport to Log.
284 trans=transport;
285 }
286
287 #endif // _RAKNET_SUPPORT_*