예제 #1
0
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);
	}

}
예제 #2
0
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);

}