/* * Original work: Copyright (c) 2014, Oculus VR, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * RakNet License.txt file in the licenses directory of this source tree. An additional grant * of patent rights can be found in the RakNet Patents.txt file in the same directory. * * * Modified work: Copyright (c) 2017, SLikeSoft UG (haftungsbeschränkt) * * This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style * license found in the license.txt file in the root directory of this source tree. */ #include "RPC3.h" #include "slikenet/memoryoverride.h" #include "slikenet/assert.h" #include "slikenet/StringCompressor.h" #include "slikenet/BitStream.h" #include "slikenet/peerinterface.h" #include "slikenet/MessageIdentifiers.h" #include "slikenet/NetworkIDManager.h" #include using namespace SLNet; // int RPC3::RemoteRPCFunctionComp( const RPC3::RPCIdentifier &key, const RemoteRPCFunction &data ) // { // return strcmp(key.C_String(), data.identifier.C_String()); // } int SLNet::RPC3::LocalSlotObjectComp( const LocalSlotObject &key, const LocalSlotObject &data ) { if (key.callPriority>data.callPriority) return -1; if (key.callPriority==data.callPriority) { if (key.registrationCountGetMaximumNumberOfPeers(); systemIndex++) { systemAddr=rakPeerInterface->GetSystemAddressFromIndex(systemIndex); if (systemAddr!= SLNet::UNASSIGNED_SYSTEM_ADDRESS && systemAddr!=outgoingSystemAddress) { // if (GetRemoteFunctionIndex(systemAddr, uniqueIdentifier, &outerIndex, &innerIndex, isCall)) // { // // Write a number to identify the function if possible, for faster lookup and less bandwidth // bs.Write(true); // if (isCall) // bs.WriteCompressed(remoteFunctions[outerIndex]->operator [](innerIndex).functionIndex); // else // bs.WriteCompressed(remoteSlots[outerIndex]->operator [](innerIndex).functionIndex); // } // else // { // bs.Write(false); StringCompressor::Instance()->EncodeString(uniqueIdentifier, 512, &bs, 0); // } bs.WriteCompressed(serializedParameters->GetNumberOfBitsUsed()); // serializedParameters->PrintBits(); bs.WriteAlignedBytes((const unsigned char*) serializedParameters->GetData(), serializedParameters->GetNumberOfBytesUsed()); SendUnified(&bs, outgoingPriority, outgoingReliability, outgoingOrderingChannel, systemAddr, false); // Start writing again after ID_AUTO_RPC_CALL bs.SetWriteOffset(writeOffset); } } } else { systemAddr = outgoingSystemAddress; if (systemAddr!= SLNet::UNASSIGNED_SYSTEM_ADDRESS) { // if (GetRemoteFunctionIndex(systemAddr, uniqueIdentifier, &outerIndex, &innerIndex, isCall)) // { // // Write a number to identify the function if possible, for faster lookup and less bandwidth // bs.Write(true); // if (isCall) // bs.WriteCompressed(remoteFunctions[outerIndex]->operator [](innerIndex).functionIndex); // else // bs.WriteCompressed(remoteSlots[outerIndex]->operator [](innerIndex).functionIndex); // } // else // { // bs.Write(false); StringCompressor::Instance()->EncodeString(uniqueIdentifier, 512, &bs, 0); // } bs.WriteCompressed(serializedParameters->GetNumberOfBitsUsed()); bs.WriteAlignedBytes((const unsigned char*) serializedParameters->GetData(), serializedParameters->GetNumberOfBytesUsed()); SendUnified(&bs, outgoingPriority, outgoingReliability, outgoingOrderingChannel, systemAddr, false); } else return false; } return true; } void RPC3::OnAttach(void) { outgoingSystemAddress= SLNet::UNASSIGNED_SYSTEM_ADDRESS; outgoingNetworkID=UNASSIGNED_NETWORK_ID; incomingSystemAddress= SLNet::UNASSIGNED_SYSTEM_ADDRESS; } PluginReceiveResult RPC3::OnReceive(Packet *packet) { SLNet::Time timestamp=0; unsigned char packetIdentifier, packetDataOffset; if ( ( unsigned char ) packet->data[ 0 ] == ID_TIMESTAMP ) { if ( packet->length > sizeof( unsigned char ) + sizeof(SLNet::Time ) ) { packetIdentifier = ( unsigned char ) packet->data[ sizeof( unsigned char ) + sizeof(SLNet::Time ) ]; // Required for proper endian swapping SLNet::BitStream tsBs(packet->data+sizeof(MessageID),packet->length-1,false); tsBs.Read(timestamp); packetDataOffset=sizeof( unsigned char )*2 + sizeof(SLNet::Time ); } else return RR_STOP_PROCESSING_AND_DEALLOCATE; } else { packetIdentifier = ( unsigned char ) packet->data[ 0 ]; packetDataOffset=sizeof( unsigned char ); } switch (packetIdentifier) { case ID_RPC_PLUGIN: incomingTimeStamp=timestamp; incomingSystemAddress=packet->systemAddress; OnRPC3Call(packet->systemAddress, packet->data+packetDataOffset, packet->length-packetDataOffset); return RR_STOP_PROCESSING_AND_DEALLOCATE; // case ID_AUTO_RPC_REMOTE_INDEX: // OnRPCRemoteIndex(packet->systemAddress, packet->data+packetDataOffset, packet->length-packetDataOffset); // return RR_STOP_PROCESSING_AND_DEALLOCATE; } return RR_CONTINUE_PROCESSING; } void RPC3::OnRPC3Call(const SystemAddress &systemAddress, unsigned char *data, unsigned int lengthInBytes) { SLNet::BitStream bs(data,lengthInBytes,false); DataStructures::HashIndex functionIndex; LocalRPCFunction *lrpcf; bool hasParameterCount=false; char parameterCount; NetworkIDObject *networkIdObject; NetworkID networkId; bool hasNetworkId=false; // bool hasFunctionIndex=false; // unsigned int functionIndex; BitSize_t bitsOnStack; char strIdentifier[512]; incomingExtraData.Reset(); bs.Read(parameterCount); bs.Read(hasNetworkId); if (hasNetworkId) { bool readSuccess = bs.Read(networkId); RakAssert(readSuccess); RakAssert(networkId!=UNASSIGNED_NETWORK_ID); if (networkIdManager==0) { // Failed - Tried to call object member, however, networkIDManager system was never registered SendError(systemAddress, RPC_ERROR_NETWORK_ID_MANAGER_UNAVAILABLE, ""); return; } networkIdObject = networkIdManager->GET_OBJECT_FROM_ID(networkId); if (networkIdObject==0) { // Failed - Tried to call object member, object does not exist (deleted?) SendError(systemAddress, RPC_ERROR_OBJECT_DOES_NOT_EXIST, ""); return; } } else { networkIdObject=0; } bool isCall; bs.Read(isCall); bs.AlignReadToByteBoundary(); // bs.Read(hasFunctionIndex); // if (hasFunctionIndex) // bs.ReadCompressed(functionIndex); // else StringCompressor::Instance()->DecodeString(strIdentifier,512,&bs,0); bs.ReadCompressed(bitsOnStack); SLNet::BitStream serializedParameters; if (bitsOnStack>0) { serializedParameters.AddBitsAndReallocate(bitsOnStack); // BITS_TO_BYTES is correct, why did I change this? bs.ReadAlignedBytes(serializedParameters.GetData(), BITS_TO_BYTES(bitsOnStack)); serializedParameters.SetWriteOffset(bitsOnStack); } // if (hasFunctionIndex) // { // if ( // (isCall==true && functionIndex>localFunctions.Size()) || // (isCall==false && functionIndex>localSlots.Size()) // ) // { // // Failed - other system specified a totally invalid index // // Possible causes: Bugs, attempts to crash the system, requested function not registered // SendError(systemAddress, RPC_ERROR_FUNCTION_INDEX_OUT_OF_RANGE, ""); // return; // } // } // else { // Find the registered function with this str if (isCall) { // for (functionIndex=0; functionIndex < localFunctions.Size(); functionIndex++) // { // bool isObjectMember = boost::fusion::get<0>(localFunctions[functionIndex].functionPointer); // // boost::function<_RPC3::InvokeResultCodes (_RPC3::InvokeArgs)> functionPtr = boost::fusion::get<0>(localFunctions[functionIndex].functionPointer); // // if (isObjectMember == (networkIdObject!=0) && // strcmp(localFunctions[functionIndex].identifier.C_String(), strIdentifier)==0) // { // // SEND RPC MAPPING // SLNet::BitStream outgoingBitstream; // outgoingBitstream.Write((MessageID)ID_AUTO_RPC_REMOTE_INDEX); // outgoingBitstream.Write(hasNetworkId); // outgoingBitstream.WriteCompressed(functionIndex); // StringCompressor::Instance()->EncodeString(strIdentifier,512,&outgoingBitstream,0); // outgoingBitstream.Write(isCall); // SendUnified(&outgoingBitstream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, systemAddress, false); // break; // } // } functionIndex = localFunctions.GetIndexOf(strIdentifier); if (functionIndex.IsInvalid()) { SendError(systemAddress, RPC_ERROR_FUNCTION_NOT_REGISTERED, strIdentifier); return; } lrpcf = localFunctions.ItemAtIndex(functionIndex); bool isObjectMember = boost::fusion::get<0>(lrpcf->functionPointer); if (isObjectMember==true && networkIdObject==0) { // Failed - Calling C++ function as C function SendError(systemAddress, RPC_ERROR_CALLING_CPP_AS_C, strIdentifier); return; } if (isObjectMember==false && networkIdObject!=0) { // Failed - Calling C function as C++ function SendError(systemAddress, RPC_ERROR_CALLING_C_AS_CPP, strIdentifier); return; } } else { functionIndex = localSlots.GetIndexOf(strIdentifier); if (functionIndex.IsInvalid()) { SendError(systemAddress, RPC_ERROR_FUNCTION_NOT_REGISTERED, strIdentifier); return; } } } if (isCall) { bool isObjectMember = boost::fusion::get<0>(lrpcf->functionPointer); boost::function<_RPC3::InvokeResultCodes (_RPC3::InvokeArgs)> functionPtr = boost::fusion::get<1>(lrpcf->functionPointer); // int arity = boost::fusion::get<2>(localFunctions[functionIndex].functionPointer); // if (isObjectMember) // arity--; // this pointer if (functionPtr==0) { // Failed - Function was previously registered, but isn't registered any longer SendError(systemAddress, RPC_ERROR_FUNCTION_NO_LONGER_REGISTERED, strIdentifier); return; } // Boost doesn't support this for class members // if (arity!=parameterCount) // { // // Failed - The number of parameters that this function has was explicitly specified, and does not match up. // SendError(systemAddress, RPC_ERROR_INCORRECT_NUMBER_OF_PARAMETERS, localFunctions[functionIndex].identifier); // return; // } _RPC3::InvokeArgs functionArgs; functionArgs.bitStream=&serializedParameters; functionArgs.networkIDManager=networkIdManager; functionArgs.caller=this; functionArgs.thisPtr=networkIdObject; // serializedParameters.PrintBits(); _RPC3::InvokeResultCodes res2 = functionPtr(functionArgs); } else { InvokeSignal(functionIndex, &serializedParameters, false); } } void RPC3::InterruptSignal(void) { interruptSignal=true; } void RPC3::InvokeSignal(DataStructures::HashIndex functionIndex, SLNet::BitStream *serializedParameters, bool temporarilySetUSA) { if (functionIndex.IsInvalid()) return; SystemAddress lastIncomingAddress=incomingSystemAddress; if (temporarilySetUSA) incomingSystemAddress= SLNet::UNASSIGNED_SYSTEM_ADDRESS; interruptSignal=false; LocalSlot *localSlot = localSlots.ItemAtIndex(functionIndex); unsigned int i; _RPC3::InvokeArgs functionArgs; functionArgs.bitStream=serializedParameters; functionArgs.networkIDManager=networkIdManager; functionArgs.caller=this; i=0; while (i < localSlot->slotObjects.Size()) { if (localSlot->slotObjects[i].associatedObject!=UNASSIGNED_NETWORK_ID) { functionArgs.thisPtr = networkIdManager->GET_OBJECT_FROM_ID(localSlot->slotObjects[i].associatedObject); if (functionArgs.thisPtr==0) { localSlot->slotObjects.RemoveAtIndex(i); continue; } } else functionArgs.thisPtr=0; functionArgs.bitStream->ResetReadPointer(); bool isObjectMember = boost::fusion::get<0>(localSlot->slotObjects[i].functionPointer); boost::function<_RPC3::InvokeResultCodes (_RPC3::InvokeArgs)> functionPtr = boost::fusion::get<1>(localSlot->slotObjects[i].functionPointer); if (functionPtr==0) { if (temporarilySetUSA==false) { // Failed - Function was previously registered, but isn't registered any longer SendError(lastIncomingAddress, RPC_ERROR_FUNCTION_NO_LONGER_REGISTERED, localSlots.KeyAtIndex(functionIndex).C_String()); } return; } _RPC3::InvokeResultCodes res2 = functionPtr(functionArgs); // Not threadsafe if (interruptSignal==true) break; i++; } if (temporarilySetUSA) incomingSystemAddress=lastIncomingAddress; } // void RPC3::OnRPCRemoteIndex(const SystemAddress &systemAddress, unsigned char *data, unsigned int lengthInBytes) // { // // A remote system has given us their internal index for a particular function. // // Store it and use it from now on, to save bandwidth and search time // bool objectExists; // RakString strIdentifier; // unsigned int insertionIndex; // unsigned int remoteIndex; // RemoteRPCFunction newRemoteFunction; // SLNet::BitStream bs(data,lengthInBytes,false); // RPCIdentifier identifier; // bool isObjectMember; // bool isCall; // bs.Read(isObjectMember); // bs.ReadCompressed(remoteIndex); // bs.Read(strIdentifier); // bs.Read(isCall); // // if (strIdentifier.IsEmpty()) // return; // // DataStructures::OrderedList *theList; // if ( // (isCall==true && remoteFunctions.Has(systemAddress)) || // (isCall==false && remoteSlots.Has(systemAddress)) // ) // { // if (isCall==true) // theList = remoteFunctions.Get(systemAddress); // else // theList = remoteSlots.Get(systemAddress); // insertionIndex=theList->GetIndexFromKey(identifier, &objectExists); // if (objectExists==false) // { // newRemoteFunction.functionIndex=remoteIndex; // newRemoteFunction.identifier = strIdentifier; // theList->InsertAtIndex(newRemoteFunction, insertionIndex, _FILE_AND_LINE_ ); // } // } // else // { // theList = SLNet::OP_NEW >(_FILE_AND_LINE_); // // newRemoteFunction.functionIndex=remoteIndex; // newRemoteFunction.identifier = strIdentifier; // theList->InsertAtEnd(newRemoteFunction, _FILE_AND_LINE_ ); // // if (isCall==true) // remoteFunctions.SetNew(systemAddress,theList); // else // remoteSlots.SetNew(systemAddress,theList); // } // } void RPC3::OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason ) { // if (remoteFunctions.Has(systemAddress)) // { // DataStructures::OrderedList *theList = remoteFunctions.Get(systemAddress); // delete theList; // remoteFunctions.Delete(systemAddress); // } // // if (remoteSlots.Has(systemAddress)) // { // DataStructures::OrderedList *theList = remoteSlots.Get(systemAddress); // delete theList; // remoteSlots.Delete(systemAddress); // } } void RPC3::OnShutdown(void) { // Not needed, and if the user calls Shutdown inadvertantly, it unregisters his functions // Clear(); } void RPC3::Clear(void) { unsigned j; // for (j=0; j < remoteFunctions.Size(); j++) // { // DataStructures::OrderedList *theList = remoteFunctions[j]; // SLNet::OP_DELETE(theList,_FILE_AND_LINE_); // } // for (j=0; j < remoteSlots.Size(); j++) // { // DataStructures::OrderedList *theList = remoteSlots[j]; // SLNet::OP_DELETE(theList,_FILE_AND_LINE_); // } DataStructures::List keyList; DataStructures::List outputList; localSlots.GetAsList(outputList,keyList,_FILE_AND_LINE_); for (j=0; j < outputList.Size(); j++) { SLNet::OP_DELETE(outputList[j],_FILE_AND_LINE_); } localSlots.Clear(_FILE_AND_LINE_); DataStructures::List outputList2; localFunctions.GetAsList(outputList2,keyList,_FILE_AND_LINE_); for (j=0; j < outputList2.Size(); j++) { SLNet::OP_DELETE(outputList2[j],_FILE_AND_LINE_); } localFunctions.Clear(_FILE_AND_LINE_); // remoteFunctions.Clear(); // remoteSlots.Clear(); outgoingExtraData.Reset(); incomingExtraData.Reset(); } void RPC3::SendError(SystemAddress target, unsigned char errorCode, const char *functionName) { SLNet::BitStream bs; bs.Write((MessageID)ID_RPC_REMOTE_ERROR); bs.Write(errorCode); bs.WriteAlignedBytes((const unsigned char*) functionName,(const unsigned int) strlen(functionName)+1); SendUnified(&bs, HIGH_PRIORITY, RELIABLE_ORDERED, 0, target, false); } // bool RPC3::GetRemoteFunctionIndex(const SystemAddress &systemAddress, RPC3::RPCIdentifier identifier, unsigned int *outerIndex, unsigned int *innerIndex, bool isCall) // { // bool objectExists=false; // if (isCall) // { // if (remoteFunctions.Has(systemAddress)) // { // *outerIndex = remoteFunctions.GetIndexAtKey(systemAddress); // DataStructures::OrderedList *theList = remoteFunctions[*outerIndex]; // *innerIndex = theList->GetIndexFromKey(identifier, &objectExists); // } // } // else // { // if (remoteSlots.Has(systemAddress)) // { // *outerIndex = remoteFunctions.GetIndexAtKey(systemAddress); // DataStructures::OrderedList *theList = remoteSlots[*outerIndex]; // *innerIndex = theList->GetIndexFromKey(identifier, &objectExists); // } // } // return objectExists; // } DataStructures::HashIndex RPC3::GetLocalSlotIndex(const char *sharedIdentifier) { return localSlots.GetIndexOf(sharedIdentifier); } DataStructures::HashIndex RPC3::GetLocalFunctionIndex(RPC3::RPCIdentifier identifier) { return localFunctions.GetIndexOf(identifier.C_String()); }