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
RPC4Plugin.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_RPC4Plugin==1
18
19 #include "slikenet/RPC4Plugin.h"
20 #include "slikenet/MessageIdentifiers.h"
21 #include "slikenet/peerinterface.h"
22 #include "slikenet/PacketizedTCP.h"
23 #include "slikenet/sleep.h"
24 #include "slikenet/defines.h"
25 #include "slikenet/DS_Queue.h"
26 //#include "slikenet/GetTime.h"
27 #include "slikenet/linux_adapter.h"
28 #include "slikenet/osx_adapter.h"
29
30 using namespace SLNet;
31
32 STATIC_FACTORY_DEFINITIONS(RPC4,RPC4);
33
34 struct GlobalRegistration
35 {
36 void ( *registerFunctionPointer ) (SLNet::BitStream *userData, Packet *packet );
37 void ( *registerBlockingFunctionPointer ) (SLNet::BitStream *userData, SLNet::BitStream *returnData, Packet *packet );
38 char functionName[RPC4_GLOBAL_REGISTRATION_MAX_FUNCTION_NAME_LENGTH];
39 MessageID messageId;
40 int callPriority;
41 };
42 static GlobalRegistration globalRegistrationBuffer[RPC4_GLOBAL_REGISTRATION_MAX_FUNCTIONS];
43 static unsigned int globalRegistrationIndex=0;
44
45 RPC4GlobalRegistration::RPC4GlobalRegistration(const char* uniqueID, void ( *functionPointer ) (SLNet::BitStream *userData, Packet *packet ))
46 {
47 RakAssert(globalRegistrationIndex!=RPC4_GLOBAL_REGISTRATION_MAX_FUNCTIONS);
48 unsigned int i;
49 for (i=0; uniqueID[i]; i++)
50 {
51 RakAssert(i<=RPC4_GLOBAL_REGISTRATION_MAX_FUNCTION_NAME_LENGTH-1);
52 globalRegistrationBuffer[globalRegistrationIndex].functionName[i]=uniqueID[i];
53 }
54 globalRegistrationBuffer[globalRegistrationIndex].registerFunctionPointer=functionPointer;
55 globalRegistrationBuffer[globalRegistrationIndex].registerBlockingFunctionPointer=0;
56 globalRegistrationBuffer[globalRegistrationIndex].callPriority=0xFFFFFFFF;
57 globalRegistrationIndex++;
58 }
59 RPC4GlobalRegistration::RPC4GlobalRegistration(const char* uniqueID, void ( *functionPointer ) (SLNet::BitStream *userData, Packet *packet ), int callPriority)
60 {
61 RakAssert(globalRegistrationIndex!=RPC4_GLOBAL_REGISTRATION_MAX_FUNCTIONS);
62 unsigned int i;
63 for (i=0; uniqueID[i]; i++)
64 {
65 RakAssert(i<=RPC4_GLOBAL_REGISTRATION_MAX_FUNCTION_NAME_LENGTH-1);
66 globalRegistrationBuffer[globalRegistrationIndex].functionName[i]=uniqueID[i];
67 }
68 globalRegistrationBuffer[globalRegistrationIndex].registerFunctionPointer=functionPointer;
69 globalRegistrationBuffer[globalRegistrationIndex].registerBlockingFunctionPointer=0;
70 RakAssert(callPriority!=(int) 0xFFFFFFFF);
71 globalRegistrationBuffer[globalRegistrationIndex].callPriority=callPriority;
72 globalRegistrationIndex++;
73 }
74 RPC4GlobalRegistration::RPC4GlobalRegistration(const char* uniqueID, void ( *functionPointer ) (SLNet::BitStream *userData, SLNet::BitStream *returnData, Packet *packet ))
75 {
76 RakAssert(globalRegistrationIndex!=RPC4_GLOBAL_REGISTRATION_MAX_FUNCTIONS);
77 unsigned int i;
78 for (i=0; uniqueID[i]; i++)
79 {
80 RakAssert(i<=RPC4_GLOBAL_REGISTRATION_MAX_FUNCTION_NAME_LENGTH-1);
81 globalRegistrationBuffer[globalRegistrationIndex].functionName[i]=uniqueID[i];
82 }
83 globalRegistrationBuffer[globalRegistrationIndex].registerFunctionPointer=0;
84 globalRegistrationBuffer[globalRegistrationIndex].registerBlockingFunctionPointer=functionPointer;
85 globalRegistrationIndex++;
86 }
87 RPC4GlobalRegistration::RPC4GlobalRegistration(const char* uniqueID, MessageID messageId)
88 {
89 RakAssert(globalRegistrationIndex!=RPC4_GLOBAL_REGISTRATION_MAX_FUNCTIONS);
90 unsigned int i;
91 for (i=0; uniqueID[i]; i++)
92 {
93 RakAssert(i<=RPC4_GLOBAL_REGISTRATION_MAX_FUNCTION_NAME_LENGTH-1);
94 globalRegistrationBuffer[globalRegistrationIndex].functionName[i]=uniqueID[i];
95 }
96 globalRegistrationBuffer[globalRegistrationIndex].registerFunctionPointer=0;
97 globalRegistrationBuffer[globalRegistrationIndex].registerBlockingFunctionPointer=0;
98 globalRegistrationBuffer[globalRegistrationIndex].messageId=messageId;
99 globalRegistrationIndex++;
100 }
101
102 enum RPC4Identifiers
103 {
104 ID_RPC4_CALL,
105 ID_RPC4_RETURN,
106 ID_RPC4_SIGNAL,
107 };
108 int RPC4::LocalSlotObjectComp( const LocalSlotObject &key, const LocalSlotObject &data )
109 {
110 if (key.callPriority>data.callPriority)
111 return -1;
112 if (key.callPriority==data.callPriority)
113 {
114 if (key.registrationCount<data.registrationCount)
115 return -1;
116 if (key.registrationCount==data.registrationCount)
117 return 0;
118 return 1;
119 }
120
121 return 1;
122 }
123 int RPC4::LocalCallbackComp(const MessageID &key, RPC4::LocalCallback* const &data )
124 {
125 if (key < data->messageId)
126 return -1;
127 if (key > data->messageId)
128 return 1;
129 return 0;
130 }
131
132 RPC4::RPC4()
133 {
134 gotBlockingReturnValue=false;
135 nextSlotRegistrationCount=0;
136 interruptSignal=false;
137 }
138 RPC4::~RPC4()
139 {
140 unsigned int i;
141 for (i=0; i < localCallbacks.Size(); i++)
142 {
143 SLNet::OP_DELETE(localCallbacks[i],_FILE_AND_LINE_);
144 }
145
146 DataStructures::List<SLNet::RakString> keyList;
147 DataStructures::List<LocalSlot*> outputList;
148 localSlots.GetAsList(outputList,keyList,_FILE_AND_LINE_);
149 unsigned int j;
150 for (j=0; j < outputList.Size(); j++)
151 {
152 SLNet::OP_DELETE(outputList[j],_FILE_AND_LINE_);
153 }
154 localSlots.Clear(_FILE_AND_LINE_);
155 }
156 bool RPC4::RegisterFunction(const char* uniqueID, void ( *functionPointer ) (SLNet::BitStream *userData, Packet *packet ))
157 {
158 DataStructures::HashIndex skhi = registeredNonblockingFunctions.GetIndexOf(uniqueID);
159 if (skhi.IsInvalid()==false)
160 return false;
161
162 registeredNonblockingFunctions.Push(uniqueID,functionPointer,_FILE_AND_LINE_);
163 return true;
164 }
165 void RPC4::RegisterSlot(const char *sharedIdentifier, void ( *functionPointer ) (SLNet::BitStream *userData, Packet *packet ), int callPriority)
166 {
167 LocalSlotObject lso(nextSlotRegistrationCount++, callPriority, functionPointer);
168 DataStructures::HashIndex idx = GetLocalSlotIndex(sharedIdentifier);
169 LocalSlot *localSlot;
170 if (idx.IsInvalid())
171 {
172 localSlot = SLNet::OP_NEW<LocalSlot>(_FILE_AND_LINE_);
173 localSlots.Push(sharedIdentifier, localSlot,_FILE_AND_LINE_);
174 }
175 else
176 {
177 localSlot=localSlots.ItemAtIndex(idx);
178 }
179 localSlot->slotObjects.Insert(lso,lso,true,_FILE_AND_LINE_);
180 }
181 bool RPC4::RegisterBlockingFunction(const char* uniqueID, void ( *functionPointer ) (SLNet::BitStream *userData, SLNet::BitStream *returnData, Packet *packet ))
182 {
183 DataStructures::HashIndex skhi = registeredBlockingFunctions.GetIndexOf(uniqueID);
184 if (skhi.IsInvalid()==false)
185 return false;
186
187 registeredBlockingFunctions.Push(uniqueID,functionPointer,_FILE_AND_LINE_);
188 return true;
189 }
190 void RPC4::RegisterLocalCallback(const char* uniqueID, MessageID messageId)
191 {
192 bool objectExists;
193 unsigned int index;
194 LocalCallback *lc;
195 SLNet::RakString str;
196 str=uniqueID;
197 index = localCallbacks.GetIndexFromKey(messageId,&objectExists);
198 if (objectExists)
199 {
200 lc = localCallbacks[index];
201 index = lc->functions.GetIndexFromKey(str,&objectExists);
202 if (objectExists==false)
203 lc->functions.InsertAtIndex(str,index,_FILE_AND_LINE_);
204 }
205 else
206 {
207 lc = SLNet::OP_NEW<LocalCallback>(_FILE_AND_LINE_);
208 lc->messageId=messageId;
209 lc->functions.Insert(str,str,false,_FILE_AND_LINE_);
210 localCallbacks.InsertAtIndex(lc,index,_FILE_AND_LINE_);
211 }
212 }
213 bool RPC4::UnregisterFunction(const char* uniqueID)
214 {
215 void ( *f ) (SLNet::BitStream *, Packet * );
216 return registeredNonblockingFunctions.Pop(f,uniqueID,_FILE_AND_LINE_);
217 }
218 bool RPC4::UnregisterBlockingFunction(const char* uniqueID)
219 {
220 void ( *f ) (SLNet::BitStream *, SLNet::BitStream *,Packet * );
221 return registeredBlockingFunctions.Pop(f,uniqueID,_FILE_AND_LINE_);
222 }
223 bool RPC4::UnregisterLocalCallback(const char* uniqueID, MessageID messageId)
224 {
225 bool objectExists;
226 unsigned int index, index2;
227 LocalCallback *lc;
228 SLNet::RakString str;
229 str=uniqueID;
230 index = localCallbacks.GetIndexFromKey(messageId,&objectExists);
231 if (objectExists)
232 {
233 lc = localCallbacks[index];
234 index2 = lc->functions.GetIndexFromKey(str,&objectExists);
235 if (objectExists)
236 {
237 lc->functions.RemoveAtIndex(index2);
238 if (lc->functions.Size()==0)
239 {
240 SLNet::OP_DELETE(lc,_FILE_AND_LINE_);
241 localCallbacks.RemoveAtIndex(index);
242 return true;
243 }
244 }
245 }
246 return false;
247 }
248 bool RPC4::UnregisterSlot(const char* sharedIdentifier)
249 {
250 DataStructures::HashIndex hi = localSlots.GetIndexOf(sharedIdentifier);
251 if (hi.IsInvalid()==false)
252 {
253 LocalSlot *ls = localSlots.ItemAtIndex(hi);
254 SLNet::OP_DELETE(ls, _FILE_AND_LINE_);
255 localSlots.RemoveAtIndex(hi, _FILE_AND_LINE_);
256 return true;
257 }
258
259 return false;
260 }
261 void RPC4::CallLoopback( const char* uniqueID, SLNet::BitStream * bitStream )
262 {
263 Packet *p=0;
264
265 DataStructures::HashIndex skhi = registeredNonblockingFunctions.GetIndexOf(uniqueID);
266
267 if (skhi.IsInvalid()==true)
268 {
269 if (rakPeerInterface)
270 p=AllocatePacketUnified(sizeof(MessageID)+sizeof(unsigned char)+(unsigned int) strlen(uniqueID)+1);
271 #if _RAKNET_SUPPORT_PacketizedTCP==1 && _RAKNET_SUPPORT_TCPInterface==1
272 else
273 p=tcpInterface->AllocatePacket(sizeof(MessageID)+sizeof(unsigned char)+(unsigned int) strlen(uniqueID)+1);
274 #endif
275
276 if (rakPeerInterface)
277 p->guid=rakPeerInterface->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS);
278 #if _RAKNET_SUPPORT_PacketizedTCP==1 && _RAKNET_SUPPORT_TCPInterface==1
279 else
280 p->guid=UNASSIGNED_RAKNET_GUID;
281 #endif
282
283 p->systemAddress=UNASSIGNED_SYSTEM_ADDRESS;
284 p->systemAddress.systemIndex=(SystemIndex)-1;
285 p->data[0]=ID_RPC_REMOTE_ERROR;
286 p->data[1]=RPC_ERROR_FUNCTION_NOT_REGISTERED;
287 strcpy_s((char*) p->data+2, p->length-2, uniqueID);
288
289 PushBackPacketUnified(p,false);
290
291 return;
292 }
293
294 SLNet::BitStream out;
295 out.Write((MessageID) ID_RPC_PLUGIN);
296 out.Write((MessageID) ID_RPC4_CALL);
297 out.WriteCompressed(uniqueID);
298 out.Write(false); // nonblocking
299 if (bitStream)
300 {
301 bitStream->ResetReadPointer();
302 out.AlignWriteToByteBoundary();
303 out.Write(bitStream);
304 }
305 if (rakPeerInterface)
306 p=AllocatePacketUnified(out.GetNumberOfBytesUsed());
307 #if _RAKNET_SUPPORT_PacketizedTCP==1 && _RAKNET_SUPPORT_TCPInterface==1
308 else
309 p=tcpInterface->AllocatePacket(out.GetNumberOfBytesUsed());
310 #endif
311
312 if (rakPeerInterface)
313 p->guid=rakPeerInterface->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS);
314 #if _RAKNET_SUPPORT_PacketizedTCP==1 && _RAKNET_SUPPORT_TCPInterface==1
315 else
316 p->guid=UNASSIGNED_RAKNET_GUID;
317 #endif
318 p->systemAddress=UNASSIGNED_SYSTEM_ADDRESS;
319 p->systemAddress.systemIndex=(SystemIndex)-1;
320 memcpy(p->data,out.GetData(),out.GetNumberOfBytesUsed());
321 PushBackPacketUnified(p,false);
322 return;
323 }
324 void RPC4::Call( const char* uniqueID, SLNet::BitStream * bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast )
325 {
326 SLNet::BitStream out;
327 out.Write((MessageID) ID_RPC_PLUGIN);
328 out.Write((MessageID) ID_RPC4_CALL);
329 out.WriteCompressed(uniqueID);
330 out.Write(false); // Nonblocking
331 if (bitStream)
332 {
333 bitStream->ResetReadPointer();
334 out.AlignWriteToByteBoundary();
335 out.Write(bitStream);
336 }
337 SendUnified(&out,priority,reliability,orderingChannel,systemIdentifier,broadcast);
338 }
339 bool RPC4::CallBlocking( const char* uniqueID, SLNet::BitStream * bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, SLNet::BitStream *returnData )
340 {
341 SLNet::BitStream out;
342 out.Write((MessageID) ID_RPC_PLUGIN);
343 out.Write((MessageID) ID_RPC4_CALL);
344 out.WriteCompressed(uniqueID);
345 out.Write(true); // Blocking
346 if (bitStream)
347 {
348 bitStream->ResetReadPointer();
349 out.AlignWriteToByteBoundary();
350 out.Write(bitStream);
351 }
352 RakAssert(returnData);
353 RakAssert(rakPeerInterface);
354 ConnectionState cs;
355 cs = rakPeerInterface->GetConnectionState(systemIdentifier);
356 if (cs!=IS_CONNECTED)
357 return false;
358
359 SendUnified(&out,priority,reliability,orderingChannel,systemIdentifier,false);
360
361 returnData->Reset();
362 blockingReturnValue.Reset();
363 gotBlockingReturnValue=false;
364 Packet *packet;
365 DataStructures::Queue<Packet*> packetQueue;
366 while (gotBlockingReturnValue==false)
367 {
368 // TODO - block, filter until gotBlockingReturnValue==true or ID_CONNECTION_LOST or ID_DISCONNECTION_NOTIFICXATION or ID_RPC_REMOTE_ERROR/RPC_ERROR_FUNCTION_NOT_REGISTERED
369 RakSleep(30);
370
371 packet=rakPeerInterface->Receive();
372
373 if (packet)
374 {
375 if (
376 (packet->data[0]==ID_CONNECTION_LOST || packet->data[0]==ID_DISCONNECTION_NOTIFICATION) &&
377 ((systemIdentifier.rakNetGuid!=UNASSIGNED_RAKNET_GUID && packet->guid==systemIdentifier.rakNetGuid) ||
378 (systemIdentifier.systemAddress!=UNASSIGNED_SYSTEM_ADDRESS && packet->systemAddress==systemIdentifier.systemAddress))
379 )
380 {
381 // Push back to head in reverse order
382 rakPeerInterface->PushBackPacket(packet,true);
383 while (packetQueue.Size())
384 rakPeerInterface->PushBackPacket(packetQueue.Pop(),true);
385 return false;
386 }
387 else if (packet->data[0]==ID_RPC_REMOTE_ERROR && packet->data[1]==RPC_ERROR_FUNCTION_NOT_REGISTERED)
388 {
389 SLNet::RakString functionName;
390 SLNet::BitStream bsIn(packet->data,packet->length,false);
391 bsIn.IgnoreBytes(2);
392 bsIn.Read(functionName);
393 if (functionName==uniqueID)
394 {
395 // Push back to head in reverse order
396 rakPeerInterface->PushBackPacket(packet,true);
397 while (packetQueue.Size())
398 rakPeerInterface->PushBackPacket(packetQueue.Pop(),true);
399 return false;
400 }
401 else
402 {
403 packetQueue.PushAtHead(packet,0,_FILE_AND_LINE_);
404 }
405 }
406 else
407 {
408 packetQueue.PushAtHead(packet,0,_FILE_AND_LINE_);
409 }
410 }
411 }
412
413 returnData->Write(blockingReturnValue);
414 returnData->ResetReadPointer();
415 return true;
416 }
417 void RPC4::Signal(const char *sharedIdentifier, SLNet::BitStream *bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast, bool invokeLocal)
418 {
419 SLNet::BitStream out;
420 out.Write((MessageID) ID_RPC_PLUGIN);
421 out.Write((MessageID) ID_RPC4_SIGNAL);
422 out.WriteCompressed(sharedIdentifier);
423 if (bitStream)
424 {
425 bitStream->ResetReadPointer();
426 out.AlignWriteToByteBoundary();
427 out.Write(bitStream);
428 }
429 SendUnified(&out,priority,reliability,orderingChannel,systemIdentifier,broadcast);
430
431 if (invokeLocal)
432 {
433 //TimeUS t1 = GetTimeUS();
434
435 DataStructures::HashIndex functionIndex;
436 functionIndex = localSlots.GetIndexOf(sharedIdentifier);
437 //TimeUS t2 = GetTimeUS();
438 if (functionIndex.IsInvalid())
439 return;
440
441 Packet p;
442 p.guid=rakPeerInterface->GetMyGUID();
443 p.systemAddress=rakPeerInterface->GetInternalID(UNASSIGNED_SYSTEM_ADDRESS);
444 p.wasGeneratedLocally=true;
445 SLNet::BitStream *bsptr, bstemp;
446 if (bitStream)
447 {
448 bitStream->ResetReadPointer();
449 p.length=bitStream->GetNumberOfBytesUsed();
450 p.bitSize=bitStream->GetNumberOfBitsUsed();
451 bsptr=bitStream;
452 }
453 else
454 {
455 p.length=0;
456 p.bitSize=0;
457 bsptr=&bstemp;
458 }
459
460 //TimeUS t3 = GetTimeUS();
461 InvokeSignal(functionIndex, bsptr, &p);
462 //TimeUS t4 = GetTimeUS();
463 //printf("b1: %I64d\n", t2-t1);
464 //printf("b2: %I64d\n", t3-t2);
465 //printf("b3: %I64d\n", t4-t3);
466 }
467 }
468 void RPC4::InvokeSignal(DataStructures::HashIndex functionIndex, SLNet::BitStream *serializedParameters, Packet *packet)
469 {
470 if (functionIndex.IsInvalid())
471 return;
472
473 //TimeUS t1 = GetTimeUS();
474 //TimeUS t2=0;
475 //TimeUS t3=0;
476
477 interruptSignal=false;
478 LocalSlot *localSlot = localSlots.ItemAtIndex(functionIndex);
479 unsigned int i;
480 i=0;
481 while (i < localSlot->slotObjects.Size())
482 {
483 //t2 = GetTimeUS();
484
485 localSlot->slotObjects[i].functionPointer(serializedParameters, packet);
486
487 //t3 = GetTimeUS();
488
489 // Not threadsafe
490 if (interruptSignal==true)
491 break;
492
493 serializedParameters->ResetReadPointer();
494
495 i++;
496 }
497
498 //TimeUS t4 = GetTimeUS();
499
500 //printf("b1: %I64d\n", t2-t1);
501 //printf("b2: %I64d\n", t3-t2);
502 //printf("b3: %I64d\n", t4-t3);
503 }
504 void RPC4::InterruptSignal(void)
505 {
506 interruptSignal=true;
507 }
508 void RPC4::OnAttach(void)
509 {
510 unsigned int i;
511 for (i=0; i < globalRegistrationIndex; i++)
512 {
513 if (globalRegistrationBuffer[i].registerFunctionPointer)
514 {
515 if (globalRegistrationBuffer[i].callPriority==(int)0xFFFFFFFF)
516 RegisterFunction(globalRegistrationBuffer[i].functionName, globalRegistrationBuffer[i].registerFunctionPointer);
517 else
518 RegisterSlot(globalRegistrationBuffer[i].functionName, globalRegistrationBuffer[i].registerFunctionPointer, globalRegistrationBuffer[i].callPriority);
519 }
520 else if (globalRegistrationBuffer[i].registerBlockingFunctionPointer)
521 RegisterBlockingFunction(globalRegistrationBuffer[i].functionName, globalRegistrationBuffer[i].registerBlockingFunctionPointer);
522 else
523 RegisterLocalCallback(globalRegistrationBuffer[i].functionName, globalRegistrationBuffer[i].messageId);
524 }
525 }
526 PluginReceiveResult RPC4::OnReceive(Packet *packet)
527 {
528 if (packet->data[0]==ID_RPC_PLUGIN)
529 {
530 SLNet::BitStream bsIn(packet->data,packet->length,false);
531 bsIn.IgnoreBytes(2);
532
533 if (packet->data[1]==ID_RPC4_CALL)
534 {
535 SLNet::RakString functionName;
536 bsIn.ReadCompressed(functionName);
537 bool isBlocking=false;
538 bsIn.Read(isBlocking);
539 if (isBlocking==false)
540 {
541 DataStructures::HashIndex skhi = registeredNonblockingFunctions.GetIndexOf(functionName.C_String());
542 if (skhi.IsInvalid())
543 {
544 SLNet::BitStream bsOut;
545 bsOut.Write((unsigned char) ID_RPC_REMOTE_ERROR);
546 bsOut.Write((unsigned char) RPC_ERROR_FUNCTION_NOT_REGISTERED);
547 bsOut.Write(functionName.C_String(),(unsigned int) functionName.GetLength()+1);
548 SendUnified(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false);
549 return RR_STOP_PROCESSING_AND_DEALLOCATE;
550 }
551
552 void ( *fp ) (SLNet::BitStream *, Packet * );
553 fp = registeredNonblockingFunctions.ItemAtIndex(skhi);
554 bsIn.AlignReadToByteBoundary();
555 fp(&bsIn,packet);
556 }
557 else
558 {
559 DataStructures::HashIndex skhi = registeredBlockingFunctions.GetIndexOf(functionName.C_String());
560 if (skhi.IsInvalid())
561 {
562 SLNet::BitStream bsOut;
563 bsOut.Write((unsigned char) ID_RPC_REMOTE_ERROR);
564 bsOut.Write((unsigned char) RPC_ERROR_FUNCTION_NOT_REGISTERED);
565 bsOut.Write(functionName.C_String(),(unsigned int) functionName.GetLength()+1);
566 SendUnified(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false);
567 return RR_STOP_PROCESSING_AND_DEALLOCATE;
568 }
569
570 void ( *fp ) (SLNet::BitStream *, SLNet::BitStream *, Packet * );
571 fp = registeredBlockingFunctions.ItemAtIndex(skhi);
572 SLNet::BitStream returnData;
573 bsIn.AlignReadToByteBoundary();
574 fp(&bsIn, &returnData, packet);
575
576 SLNet::BitStream out;
577 out.Write((MessageID) ID_RPC_PLUGIN);
578 out.Write((MessageID) ID_RPC4_RETURN);
579 returnData.ResetReadPointer();
580 out.AlignWriteToByteBoundary();
581 out.Write(returnData);
582 SendUnified(&out,IMMEDIATE_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false);
583 }
584 }
585 else if (packet->data[1]==ID_RPC4_SIGNAL)
586 {
587 SLNet::RakString sharedIdentifier;
588 bsIn.ReadCompressed(sharedIdentifier);
589 DataStructures::HashIndex functionIndex;
590 functionIndex = localSlots.GetIndexOf(sharedIdentifier);
591 SLNet::BitStream serializedParameters;
592 bsIn.AlignReadToByteBoundary();
593 bsIn.Read(&serializedParameters);
594 InvokeSignal(functionIndex, &serializedParameters, packet);
595 }
596 else
597 {
598 RakAssert(packet->data[1]==ID_RPC4_RETURN);
599 blockingReturnValue.Reset();
600 blockingReturnValue.Write(bsIn);
601 gotBlockingReturnValue=true;
602 }
603
604 return RR_STOP_PROCESSING_AND_DEALLOCATE;
605 }
606
607 bool objectExists;
608 unsigned int index, index2;
609 index = localCallbacks.GetIndexFromKey(packet->data[0],&objectExists);
610 if (objectExists)
611 {
612 LocalCallback *lc;
613 lc = localCallbacks[index];
614 for (index2=0; index2 < lc->functions.Size(); index2++)
615 {
616 SLNet::BitStream bsIn(packet->data, packet->length, false);
617
618 DataStructures::HashIndex skhi = registeredNonblockingFunctions.GetIndexOf(lc->functions[index2].C_String());
619 if (skhi.IsInvalid()==false)
620 {
621 void ( *fp ) (SLNet::BitStream *, Packet * );
622 fp = registeredNonblockingFunctions.ItemAtIndex(skhi);
623 bsIn.AlignReadToByteBoundary();
624 fp(&bsIn,packet);
625 }
626 }
627 }
628
629 return RR_CONTINUE_PROCESSING;
630 }
631 DataStructures::HashIndex RPC4::GetLocalSlotIndex(const char *sharedIdentifier)
632 {
633 return localSlots.GetIndexOf(sharedIdentifier);
634 }
635
636 #endif // _RAKNET_SUPPORT_*