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
MessageFilter.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-2018, 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_MessageFilter==1
18
19 #include "slikenet/MessageFilter.h"
20 #include "slikenet/assert.h"
21 #include "slikenet/GetTime.h"
22 #include "slikenet/MessageIdentifiers.h"
23 #include "slikenet/assert.h"
24 #include "slikenet/peerinterface.h"
25 #include "slikenet/PacketizedTCP.h"
26 #include "slikenet/BitStream.h"
27
28 using namespace SLNet;
29
30 int SLNet::MessageFilterStrComp( char *const &key,char *const &data )
31 {
32 return strcmp(key,data);
33 }
34
35 int SLNet::FilterSetComp( const int &key, FilterSet * const &data )
36 {
37 if (key < data->filterSetID)
38 return -1;
39 else if (key==data->filterSetID)
40 return 0;
41 else
42 return 1;
43 }
44 STATIC_FACTORY_DEFINITIONS(MessageFilter,MessageFilter);
45
46 MessageFilter::MessageFilter()
47 {
48 whenLastTimeoutCheck= SLNet::GetTime();
49 }
50 MessageFilter::~MessageFilter()
51 {
52 Clear();
53 }
54 void MessageFilter::SetAutoAddNewConnectionsToFilter(int filterSetID)
55 {
56 autoAddNewConnectionsToFilter=filterSetID;
57 }
58 void MessageFilter::SetAllowMessageID(bool allow, int messageIDStart, int messageIDEnd,int filterSetID)
59 {
60 RakAssert(messageIDStart <= messageIDEnd);
61 FilterSet *filterSet = GetFilterSetByID(filterSetID);
62 int i;
63 for (i=messageIDStart; i <= messageIDEnd; ++i)
64 filterSet->allowedIDs[i]=allow;
65 }
66 void MessageFilter::SetAllowRPC4(bool allow, const char* uniqueID, int filterSetID)
67 {
68 FilterSet *filterSet = GetFilterSetByID(filterSetID);
69 bool objectExists;
70 unsigned int idx = filterSet->allowedRPC4.GetIndexFromKey(uniqueID, &objectExists);
71 if (allow)
72 {
73 if (objectExists==false)
74 {
75 filterSet->allowedRPC4.InsertAtIndex(uniqueID, idx, _FILE_AND_LINE_);
76 filterSet->allowedIDs[ID_RPC_PLUGIN]=true;
77 }
78 }
79 else
80 {
81 if (objectExists==true)
82 {
83 filterSet->allowedRPC4.RemoveAtIndex(idx);
84 if (filterSet->allowedRPC4.Size()==0)
85 {
86 filterSet->allowedIDs[ID_RPC_PLUGIN]=false;
87 }
88 }
89 }
90 }
91 void MessageFilter::SetActionOnDisallowedMessage(bool kickOnDisallowed, bool banOnDisallowed, SLNet::TimeMS banTimeMS, int filterSetID)
92 {
93 FilterSet *filterSet = GetFilterSetByID(filterSetID);
94 filterSet->kickOnDisallowedMessage=kickOnDisallowed;
95 filterSet->disallowedMessageBanTimeMS=banTimeMS;
96 filterSet->banOnDisallowedMessage=banOnDisallowed;
97 }
98 void MessageFilter::SetDisallowedMessageCallback(int filterSetID, void *userData, void (*invalidMessageCallback)(RakPeerInterface *peer, AddressOrGUID systemAddress, int filterSetID, void *userData, unsigned char messageID))
99 {
100 FilterSet *filterSet = GetFilterSetByID(filterSetID);
101 filterSet->invalidMessageCallback=invalidMessageCallback;
102 filterSet->disallowedCallbackUserData=userData;
103 }
104 void MessageFilter::SetTimeoutCallback(int filterSetID, void *userData, void (*invalidMessageCallback)(RakPeerInterface *peer, AddressOrGUID systemAddress, int filterSetID, void *userData))
105 {
106 FilterSet *filterSet = GetFilterSetByID(filterSetID);
107 filterSet->timeoutCallback=invalidMessageCallback;
108 filterSet->timeoutUserData=userData;
109 }
110 void MessageFilter::SetFilterMaxTime(int allowedTimeMS, bool banOnExceed, SLNet::TimeMS banTimeMS, int filterSetID)
111 {
112 FilterSet *filterSet = GetFilterSetByID(filterSetID);
113 filterSet->maxMemberTimeMS=allowedTimeMS;
114 filterSet->banOnFilterTimeExceed=banOnExceed;
115 filterSet->timeExceedBanTimeMS=banTimeMS;
116 }
117 int MessageFilter::GetSystemFilterSet(AddressOrGUID systemAddress)
118 {
119 // bool objectExists;
120 // unsigned index = systemList.GetIndexFromKey(systemAddress, &objectExists);
121 // if (objectExists==false)
122 // return -1;
123 // else
124 // return systemList[index].filter->filterSetID;
125
126 DataStructures::HashIndex index = systemList.GetIndexOf(systemAddress);
127 if (index.IsInvalid())
128 return -1;
129 else
130 return systemList.ItemAtIndex(index).filter->filterSetID;
131 }
132 void MessageFilter::SetSystemFilterSet(AddressOrGUID addressOrGUID, int filterSetID)
133 {
134 // Allocate this filter set if it doesn't exist.
135 RakAssert(addressOrGUID.IsUndefined()==false);
136 // bool objectExists;
137 // unsigned index = systemList.GetIndexFromKey(addressOrGUID, &objectExists);
138 // if (objectExists==false)
139 DataStructures::HashIndex index = systemList.GetIndexOf(addressOrGUID);
140 if (index.IsInvalid())
141 {
142 if (filterSetID<0)
143 return;
144
145 FilteredSystem filteredSystem;
146 filteredSystem.filter = GetFilterSetByID(filterSetID);
147 // filteredSystem.addressOrGUID=addressOrGUID;
148 filteredSystem.timeEnteredThisSet= SLNet::GetTimeMS();
149 // systemList.Insert(addressOrGUID, filteredSystem, true, _FILE_AND_LINE_);
150 systemList.Push(addressOrGUID,filteredSystem,_FILE_AND_LINE_);
151 }
152 else
153 {
154 if (filterSetID>=0)
155 {
156 FilterSet *filterSet = GetFilterSetByID(filterSetID);
157 systemList.ItemAtIndex(index).timeEnteredThisSet= SLNet::GetTimeMS();
158 systemList.ItemAtIndex(index).filter=filterSet;
159 }
160 else
161 {
162 systemList.RemoveAtIndex(index, _FILE_AND_LINE_);
163 }
164 }
165 }
166 unsigned MessageFilter::GetSystemCount(int filterSetID) const
167 {
168 if (filterSetID==-1)
169 {
170 return systemList.Size();
171 }
172 else
173 {
174 unsigned i;
175 unsigned count=0;
176 DataStructures::List< FilteredSystem > itemList;
177 DataStructures::List< AddressOrGUID > keyList;
178 systemList.GetAsList(itemList, keyList, _FILE_AND_LINE_);
179 for (i=0; i < itemList.Size(); i++)
180 if (itemList[i].filter->filterSetID==filterSetID)
181 ++count;
182 return count;
183 }
184 }
185 unsigned MessageFilter::GetFilterSetCount(void) const
186 {
187 return filterList.Size();
188 }
189 int MessageFilter::GetFilterSetIDByIndex(unsigned index)
190 {
191 return filterList[index]->filterSetID;
192 }
193 void MessageFilter::DeleteFilterSet(int filterSetID)
194 {
195 FilterSet *filterSet;
196 bool objectExists;
197 unsigned i,index;
198 index = filterList.GetIndexFromKey(filterSetID, &objectExists);
199 if (objectExists)
200 {
201 filterSet=filterList[index];
202 DeallocateFilterSet(filterSet);
203 filterList.RemoveAtIndex(index);
204
205 DataStructures::List< FilteredSystem > itemList;
206 DataStructures::List< AddressOrGUID > keyList;
207 systemList.GetAsList(itemList, keyList, _FILE_AND_LINE_);
208 for (i=0; i < itemList.Size(); i++)
209 {
210 if (itemList[i].filter==filterSet)
211 {
212 systemList.Remove(keyList[i], _FILE_AND_LINE_);
213 }
214 }
215
216 /*
217 // Don't reference this pointer any longer
218 i=0;
219 while (i < systemList.Size())
220 {
221 if (systemList[i].filter==filterSet)
222 systemList.RemoveAtIndex(i);
223 else
224 ++i;
225 }
226 */
227 }
228 }
229 void MessageFilter::Clear(void)
230 {
231 unsigned i;
232 systemList.Clear(_FILE_AND_LINE_);
233 for (i=0; i < filterList.Size(); i++)
234 DeallocateFilterSet(filterList[i]);
235 filterList.Clear(false, _FILE_AND_LINE_);
236 }
237 void MessageFilter::DeallocateFilterSet(FilterSet* filterSet)
238 {
239 SLNet::OP_DELETE(filterSet, _FILE_AND_LINE_);
240 }
241 FilterSet* MessageFilter::GetFilterSetByID(int filterSetID)
242 {
243 RakAssert(filterSetID>=0);
244 bool objectExists;
245 unsigned index;
246 index = filterList.GetIndexFromKey(filterSetID, &objectExists);
247 if (objectExists)
248 return filterList[index];
249 else
250 {
251 FilterSet *newFilterSet = SLNet::OP_NEW<FilterSet>( _FILE_AND_LINE_ );
252 memset(newFilterSet->allowedIDs, 0, MESSAGE_FILTER_MAX_MESSAGE_ID * sizeof(bool));
253 newFilterSet->banOnFilterTimeExceed=false;
254 newFilterSet->kickOnDisallowedMessage=false;
255 newFilterSet->banOnDisallowedMessage=false;
256 newFilterSet->disallowedMessageBanTimeMS=0;
257 newFilterSet->timeExceedBanTimeMS=0;
258 newFilterSet->maxMemberTimeMS=0;
259 newFilterSet->filterSetID=filterSetID;
260 newFilterSet->invalidMessageCallback=0;
261 newFilterSet->timeoutCallback=0;
262 newFilterSet->timeoutUserData=0;
263 filterList.Insert(filterSetID, newFilterSet, true, _FILE_AND_LINE_);
264 return newFilterSet;
265 }
266 }
267 void MessageFilter::OnInvalidMessage(FilterSet *filterSet, AddressOrGUID systemAddress, unsigned char messageID)
268 {
269 if (filterSet->invalidMessageCallback)
270 filterSet->invalidMessageCallback(rakPeerInterface, systemAddress, filterSet->filterSetID, filterSet->disallowedCallbackUserData, messageID);
271 if (filterSet->banOnDisallowedMessage && rakPeerInterface)
272 {
273 char str1[64];
274 systemAddress.systemAddress.ToString(false, str1, static_cast<size_t>(64));
275 rakPeerInterface->AddToBanList(str1, filterSet->disallowedMessageBanTimeMS);
276 }
277 if (filterSet->kickOnDisallowedMessage)
278 {
279 if (rakPeerInterface)
280 rakPeerInterface->CloseConnection(systemAddress, true, 0);
281 #if _RAKNET_SUPPORT_PacketizedTCP==1 && _RAKNET_SUPPORT_TCPInterface==1
282 else
283 tcpInterface->CloseConnection(systemAddress.systemAddress);
284 #endif
285 }
286 }
287 void MessageFilter::Update(void)
288 {
289 // Update all timers for all systems. If those systems' filter sets are expired, take the appropriate action.
290 SLNet::Time curTime = SLNet::GetTime();
291 if (GreaterThan(curTime - 1000, whenLastTimeoutCheck))
292 {
293 DataStructures::List< FilteredSystem > itemList;
294 DataStructures::List< AddressOrGUID > keyList;
295 systemList.GetAsList(itemList, keyList, _FILE_AND_LINE_);
296
297 unsigned int index;
298 for (index=0; index < itemList.Size(); index++)
299 {
300 if (itemList[index].filter &&
301 itemList[index].filter->maxMemberTimeMS>0 &&
302 curTime-itemList[index].timeEnteredThisSet >= itemList[index].filter->maxMemberTimeMS)
303 {
304 if (itemList[index].filter->timeoutCallback)
305 itemList[index].filter->timeoutCallback(rakPeerInterface, keyList[index], itemList[index].filter->filterSetID, itemList[index].filter->timeoutUserData);
306
307 if (itemList[index].filter->banOnFilterTimeExceed && rakPeerInterface)
308 {
309 char str1[64];
310 keyList[index].ToString(false, str1, 64);
311 rakPeerInterface->AddToBanList(str1, itemList[index].filter->timeExceedBanTimeMS);
312 }
313 if (rakPeerInterface)
314 rakPeerInterface->CloseConnection(keyList[index], true, 0);
315 #if _RAKNET_SUPPORT_PacketizedTCP==1 && _RAKNET_SUPPORT_TCPInterface==1
316 else
317 tcpInterface->CloseConnection(keyList[index].systemAddress);
318 #endif
319
320 systemList.Remove(keyList[index], _FILE_AND_LINE_);
321 }
322 }
323
324 whenLastTimeoutCheck=curTime+1000;
325 }
326 }
327 void MessageFilter::OnNewConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, bool isIncoming)
328 {
329 (void) systemAddress;
330 (void) rakNetGUID;
331 (void) isIncoming;
332
333 AddressOrGUID aog;
334 aog.rakNetGuid=rakNetGUID;
335 aog.systemAddress=systemAddress;
336
337 // New system, automatically assign to filter set if appropriate
338 if (autoAddNewConnectionsToFilter>=0 && systemList.HasData(aog)==false)
339 SetSystemFilterSet(aog, autoAddNewConnectionsToFilter);
340 }
341 void MessageFilter::OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
342 {
343 (void) rakNetGUID;
344 (void) lostConnectionReason;
345
346 AddressOrGUID aog;
347 aog.rakNetGuid=rakNetGUID;
348 aog.systemAddress=systemAddress;
349
350 // Lost system, remove from the list
351 systemList.Remove(aog, _FILE_AND_LINE_);
352 }
353 PluginReceiveResult MessageFilter::OnReceive(Packet *packet)
354 {
355 DataStructures::HashIndex index;
356 unsigned char messageId;
357
358 switch (packet->data[0])
359 {
360 case ID_NEW_INCOMING_CONNECTION:
361 case ID_CONNECTION_REQUEST_ACCEPTED:
362 case ID_CONNECTION_LOST:
363 case ID_DISCONNECTION_NOTIFICATION:
364 case ID_CONNECTION_ATTEMPT_FAILED:
365 case ID_NO_FREE_INCOMING_CONNECTIONS:
366 case ID_IP_RECENTLY_CONNECTED:
367 case ID_CONNECTION_BANNED:
368 case ID_INVALID_PASSWORD:
369 case ID_UNCONNECTED_PONG:
370 case ID_ALREADY_CONNECTED:
371 case ID_ADVERTISE_SYSTEM:
372 case ID_REMOTE_DISCONNECTION_NOTIFICATION:
373 case ID_REMOTE_CONNECTION_LOST:
374 case ID_REMOTE_NEW_INCOMING_CONNECTION:
375 case ID_DOWNLOAD_PROGRESS:
376 break;
377 default:
378 if (packet->data[0]==ID_TIMESTAMP)
379 {
380 if (packet->length<sizeof(MessageID) + sizeof(SLNet::TimeMS))
381 return RR_STOP_PROCESSING_AND_DEALLOCATE; // Invalid message
382 messageId=packet->data[sizeof(MessageID) + sizeof(SLNet::TimeMS)];
383 }
384 else
385 messageId=packet->data[0];
386 // If this system is filtered, check if this message is allowed. If not allowed, return RR_STOP_PROCESSING_AND_DEALLOCATE
387 // index = systemList.GetIndexFromKey(packet->addressOrGUID, &objectExists);
388 index = systemList.GetIndexOf(packet);
389 if (index.IsInvalid())
390 break;
391 if (systemList.ItemAtIndex(index).filter->allowedIDs[messageId]==false)
392 {
393 OnInvalidMessage(systemList.ItemAtIndex(index).filter, packet, packet->data[0]);
394 return RR_STOP_PROCESSING_AND_DEALLOCATE;
395 }
396 if (packet->data[0]==ID_RPC_PLUGIN)
397 {
398 SLNet::BitStream bsIn(packet->data,packet->length,false);
399 bsIn.IgnoreBytes(2);
400 SLNet::RakString functionName;
401 bsIn.ReadCompressed(functionName);
402 if (systemList.ItemAtIndex(index).filter->allowedRPC4.HasData(functionName)==false)
403 {
404 OnInvalidMessage(systemList.ItemAtIndex(index).filter, packet, packet->data[0]);
405 return RR_STOP_PROCESSING_AND_DEALLOCATE;
406 }
407 }
408
409 break;
410 }
411
412 return RR_CONTINUE_PROCESSING;
413 }
414
415 #endif // _RAKNET_SUPPORT_*