void RPC3::OnRPC3Call(SystemAddress systemAddress, unsigned char *data, unsigned int lengthInBytes) { RakNet::BitStream bs(data,lengthInBytes,false); DataStructures::StringKeyedHashIndex 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 && (networkIdManager=rakPeerInterface->GetNetworkIDManager())==0) { // Failed - Tried to call object member, however, networkIDManager system was never registered SendError(systemAddress, RPC_ERROR_NETWORK_ID_MANAGER_UNAVAILABLE, ""); return; } networkIdObject = (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->DecodeString(strIdentifier,512,&bs,0); bs.ReadCompressed(bitsOnStack); RakNet::BitStream serializedParameters; if (bitsOnStack>0) { serializedParameters.AddBitsAndReallocate(bitsOnStack); 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 // RakNet::BitStream outgoingBitstream; // outgoingBitstream.Write((MessageID)ID_AUTO_RPC_REMOTE_INDEX); // outgoingBitstream.Write(hasNetworkId); // outgoingBitstream.WriteCompressed(functionIndex); // stringCompressor->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 AutoRPC::OnRPCUnknownRemoteIndex(SystemAddress systemAddress, unsigned char *data, unsigned int lengthInBytes, RakNetTime timestamp) { char inputStack[ARPC_MAX_STACK_SIZE]; NetworkID networkId; bool hasNetworkId=false; unsigned int functionIndex; unsigned int bytesOnStack; int numberOfBitsUsed; char parameterCount; bool hasParameterCount=false; RakNet::BitStream extraData; RakNet::BitStream bs(data,lengthInBytes,false); bs.Read(hasParameterCount); if (hasParameterCount) bs.Read(parameterCount); bs.ReadCompressed(functionIndex); bs.ReadCompressed(numberOfBitsUsed); extraData.AddBitsAndReallocate(numberOfBitsUsed); bs.ReadBits(extraData.GetData(), numberOfBitsUsed, false); extraData.SetWriteOffset(numberOfBitsUsed); bs.Read(hasNetworkId); if (hasNetworkId) bs.Read(networkId); bs.ReadCompressed(bytesOnStack); bs.ReadAlignedBytes((unsigned char*) inputStack, bytesOnStack); unsigned outerIndex; if (remoteFunctions.Has(systemAddress)) { outerIndex = remoteFunctions.GetIndexAtKey(systemAddress); DataStructures::OrderedList<RPCIdentifier, RemoteRPCFunction, AutoRPC::RemoteRPCFunctionComp> *theList = remoteFunctions[outerIndex]; unsigned i; for (i=0; i < theList->Size(); i++) { if (theList->operator [](i).functionIndex==functionIndex) { RakNet::BitStream out; // Recover by resending the RPC with the function identifier string this time if (timestamp!=0) { out.Write((MessageID)ID_TIMESTAMP); out.Write(timestamp); } out.Write((MessageID)ID_AUTO_RPC_CALL); if (parameterCount>=0) { out.Write(true); out.Write(parameterCount); } else { out.Write(false); } out.WriteCompressed(numberOfBitsUsed); out.Write(&extraData); out.Write(hasNetworkId); if (hasNetworkId) out.Write(networkId); out.AlignWriteToByteBoundary(); out.Write(false); stringCompressor->EncodeString(theList->operator [](i).identifier.uniqueIdentifier, 512, &out, 0); out.WriteCompressed(bytesOnStack); out.WriteAlignedBytes((const unsigned char*) inputStack, bytesOnStack); SendUnified(&out, outgoingPriority, outgoingReliability, outgoingOrderingChannel, systemAddress, false); return; } } } // Failed to recover, inform the user Packet *p = rakPeerInterface->AllocatePacket(sizeof(MessageID)+sizeof(unsigned char)); RakNet::BitStream bs2(p->data, sizeof(MessageID)+sizeof(unsigned char), false); bs2.SetWriteOffset(0); bs2.Write((MessageID)ID_RPC_REMOTE_ERROR); bs2.Write((unsigned char)RPC_ERROR_FUNCTION_NO_LONGER_REGISTERED); stringCompressor->EncodeString("",256,&bs,0); p->systemAddress=systemAddress; rakPeerInterface->PushBackPacket(p, false); }