• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

AutoRPC.cpp

Go to the documentation of this file.
00001 #include "NativeFeatureIncludes.h"
00002 #if _RAKNET_SUPPORT_AutoRPC==1
00003 
00004 #include "AutoRPC.h"
00005 #include "RakMemoryOverride.h"
00006 #include "RakAssert.h"
00007 #include "StringCompressor.h"
00008 #include "BitStream.h"
00009 //#include "Types.h"
00010 #include "RakPeerInterface.h"
00011 #include "MessageIdentifiers.h"
00012 #include "NetworkIDObject.h"
00013 #include "NetworkIDManager.h"
00014 #include <stdlib.h>
00015 
00016 using namespace RakNet;
00017 
00018 #ifdef _MSC_VER
00019 #pragma warning( push )
00020 #endif
00021 
00022 int AutoRPC::RemoteRPCFunctionComp( const RPCIdentifier &key, const RemoteRPCFunction &data )
00023 {
00024         if (key.isObjectMember==false && data.identifier.isObjectMember==true)
00025                 return -1;
00026         if (key.isObjectMember==true && data.identifier.isObjectMember==false)
00027                 return 1;
00028         return strcmp(key.uniqueIdentifier, data.identifier.uniqueIdentifier);
00029 }
00030 
00031 AutoRPC::AutoRPC()
00032 {
00033         currentExecution[0]=0;
00034         networkIdManager=0;
00035         outgoingTimestamp=0;
00036         outgoingPriority=HIGH_PRIORITY;
00037         outgoingReliability=RELIABLE_ORDERED;
00038         outgoingOrderingChannel=0;
00039         outgoingBroadcast=true;
00040         incomingTimeStamp=0;
00041         DataStructures::Map<SystemAddress, DataStructures::OrderedList<RPCIdentifier, RemoteRPCFunction, AutoRPC::RemoteRPCFunctionComp> *>::IMPLEMENT_DEFAULT_COMPARISON();
00042 }
00043 
00044 AutoRPC::~AutoRPC()
00045 {
00046         Clear();
00047 }
00048 void AutoRPC::SetNetworkIDManager(NetworkIDManager *idMan)
00049 {
00050         networkIdManager=idMan;
00051 }
00052 bool AutoRPC::RegisterFunction(const char *uniqueIdentifier, void *functionPtr, bool isObjectMember, char parameterCount)
00053 {
00054         if (uniqueIdentifier==0 || functionPtr==0)
00055         {
00056                 RakAssert(0);
00057                 return false;
00058         }
00059 
00060         RPCIdentifier identifier;
00061         identifier.isObjectMember=isObjectMember;
00062         identifier.uniqueIdentifier=(char*) uniqueIdentifier;
00063         unsigned localIndex = GetLocalFunctionIndex(identifier);
00064         // Already registered?
00065         if (localIndex!=(unsigned)-1 && localFunctions[localIndex].functionPtr!=0)
00066                 return false;
00067         if (localIndex!=(unsigned)-1)
00068         {
00069                 // Reenable existing
00070                 localFunctions[localIndex].functionPtr=functionPtr;
00071                 localFunctions[localIndex].parameterCount=parameterCount;
00072         }
00073         else
00074         {
00075                 // Add new
00076                 LocalRPCFunction func;
00077                 func.functionPtr=functionPtr;
00078                 func.identifier.isObjectMember=isObjectMember;
00079                 func.identifier.uniqueIdentifier = (char*) rakMalloc_Ex(strlen(uniqueIdentifier)+1, __FILE__, __LINE__);
00080                 func.parameterCount=parameterCount;
00081                 strcpy(func.identifier.uniqueIdentifier, uniqueIdentifier);
00082                 localFunctions.Insert(func, __FILE__, __LINE__);
00083         }
00084         return true;
00085 }
00086 bool AutoRPC::UnregisterFunction(const char *uniqueIdentifier, bool isObjectMember)
00087 {
00088         if (uniqueIdentifier==0)
00089         {
00090                 RakAssert(0);
00091                 return false;
00092         }
00093 
00094         RPCIdentifier identifier;
00095         identifier.isObjectMember=isObjectMember;
00096         identifier.uniqueIdentifier=(char*) uniqueIdentifier;
00097         unsigned localIndex = GetLocalFunctionIndex(identifier);
00098         // Not registered?
00099         if (localIndex==(unsigned)-1)
00100                 return false;
00101         // Leave the id in, in case the function is set again later. That way we keep the same remote index
00102         localFunctions[localIndex].functionPtr=0;
00103         return true;
00104 }
00105 void AutoRPC::SetTimestamp(RakNetTime timeStamp)
00106 {
00107         outgoingTimestamp=timeStamp;
00108 }
00109 void AutoRPC::SetSendParams(PacketPriority priority, PacketReliability reliability, char orderingChannel)
00110 {
00111         outgoingPriority=priority;
00112         outgoingReliability=reliability;
00113         outgoingOrderingChannel=orderingChannel;
00114 }
00115 void AutoRPC::SetRecipientAddress(AddressOrGUID systemIdentifier, bool broadcast)
00116 {
00117         outgoingSystemIdentifier=systemIdentifier;
00118         outgoingBroadcast=broadcast;
00119 }
00120 void AutoRPC::SetRecipientObject(NetworkID networkID)
00121 {
00122         outgoingNetworkID=networkID;
00123 }
00124 RakNet::BitStream *AutoRPC::SetOutgoingExtraData(void)
00125 {
00126         return &outgoingExtraData;
00127 }
00128 RakNetTime AutoRPC::GetLastSenderTimestamp(void) const
00129 {
00130         return incomingTimeStamp;
00131 }
00132 SystemAddress AutoRPC::GetLastSenderAddress(void) const
00133 {
00134         return incomingSystemAddress;
00135 }
00136 RakPeerInterface *AutoRPC::GetRakPeer(void) const
00137 {
00138         return rakPeerInterface;
00139 }
00140 const char *AutoRPC::GetCurrentExecution(void) const
00141 {
00142         return (const char *) currentExecution;
00143 }
00144 RakNet::BitStream *AutoRPC::GetIncomingExtraData(void)
00145 {
00146         return &incomingExtraData;
00147 }
00148 bool AutoRPC::SendCall(const char *uniqueIdentifier, const char *stack, unsigned int bytesOnStack, char parameterCount)
00149 {
00150         SystemAddress systemAddr;
00151         RPCIdentifier identifier;
00152         unsigned int outerIndex;
00153         unsigned int innerIndex;
00154 
00155         if (uniqueIdentifier==0)
00156                 return false;
00157 
00158         identifier.uniqueIdentifier=(char*) uniqueIdentifier;
00159         identifier.isObjectMember=(outgoingNetworkID!=UNASSIGNED_NETWORK_ID);
00160 
00161         RakNet::BitStream bs;
00162         if (outgoingTimestamp!=0)
00163         {
00164                 bs.Write((MessageID)ID_TIMESTAMP);
00165                 bs.Write(outgoingTimestamp);
00166         }
00167         bs.Write((MessageID)ID_AUTO_RPC_CALL);
00168         if (parameterCount>=0)
00169         {
00170                 bs.Write(true);
00171                 bs.Write(parameterCount);
00172         }
00173         else
00174         {
00175                 bs.Write(false);
00176         }
00177         bs.WriteCompressed(outgoingExtraData.GetNumberOfBitsUsed());
00178         bs.Write(&outgoingExtraData);
00179         if (outgoingNetworkID!=UNASSIGNED_NETWORK_ID)
00180         {
00181                 bs.Write(true);
00182                 bs.Write(outgoingNetworkID);
00183         }
00184         else
00185         {
00186                 bs.Write(false);
00187         }
00188         // This is so the call SetWriteOffset works
00189         bs.AlignWriteToByteBoundary();
00190         BitSize_t writeOffset = bs.GetWriteOffset();
00191         SystemAddress outgoingSystemAddress;
00192         if (outgoingSystemIdentifier.rakNetGuid!=UNASSIGNED_RAKNET_GUID)
00193                 outgoingSystemAddress = rakPeerInterface->GetSystemAddressFromGuid(outgoingSystemIdentifier.rakNetGuid);
00194         else
00195                 outgoingSystemAddress = outgoingSystemIdentifier.systemAddress;
00196         if (outgoingBroadcast)
00197         {
00198                 unsigned systemIndex;
00199                 for (systemIndex=0; systemIndex < rakPeerInterface->GetMaximumNumberOfPeers(); systemIndex++)
00200                 {
00201                         systemAddr=rakPeerInterface->GetSystemAddressFromIndex(systemIndex);
00202                         if (systemAddr!=UNASSIGNED_SYSTEM_ADDRESS && systemAddr!=outgoingSystemAddress)
00203                         {
00204                                 if (GetRemoteFunctionIndex(systemAddr, identifier, &outerIndex, &innerIndex))
00205                                 {
00206                                         // Write a number to identify the function if possible, for faster lookup and less bandwidth
00207                                         bs.Write(true);
00208                                         bs.WriteCompressed(remoteFunctions[outerIndex]->operator [](innerIndex).functionIndex);
00209                                 }
00210                                 else
00211                                 {
00212                                         bs.Write(false);
00213                                         stringCompressor->EncodeString(uniqueIdentifier, 512, &bs, 0);
00214                                 }
00215 
00216                                 bs.WriteCompressed(bytesOnStack);
00217                                 bs.WriteAlignedBytes((const unsigned char*) stack, bytesOnStack);
00218                                 SendUnified(&bs, outgoingPriority, outgoingReliability, outgoingOrderingChannel, systemAddr, false);
00219 
00220                                 // Start writing again after ID_AUTO_RPC_CALL
00221                                 bs.SetWriteOffset(writeOffset);
00222                         }
00223                 }
00224         }
00225         else
00226         {
00227                 systemAddr = outgoingSystemAddress;
00228                 if (systemAddr!=UNASSIGNED_SYSTEM_ADDRESS)
00229                 {
00230                         if (GetRemoteFunctionIndex(systemAddr, identifier, &outerIndex, &innerIndex))
00231                         {
00232                                 // Write a number to identify the function if possible, for faster lookup and less bandwidth
00233                                 bs.Write(true);
00234                                 bs.WriteCompressed(remoteFunctions[outerIndex]->operator [](innerIndex).functionIndex);
00235                         }
00236                         else
00237                         {
00238                                 bs.Write(false);
00239                                 stringCompressor->EncodeString(uniqueIdentifier, 512, &bs, 0);
00240                         }
00241 
00242                         bs.WriteCompressed(bytesOnStack);
00243                         bs.WriteAlignedBytes((const unsigned char*) stack, bytesOnStack);
00244                         SendUnified(&bs, outgoingPriority, outgoingReliability, outgoingOrderingChannel, systemAddr, false);
00245                 }
00246                 else
00247                         return false;
00248         }
00249         return true;
00250 }
00251 void AutoRPC::OnAttach(void)
00252 {
00253         outgoingSystemIdentifier.SetUndefined();
00254         outgoingNetworkID=UNASSIGNED_NETWORK_ID;
00255         incomingSystemAddress=UNASSIGNED_SYSTEM_ADDRESS;
00256 
00257 }
00258 PluginReceiveResult AutoRPC::OnReceive(Packet *packet)
00259 {
00260         RakNetTime timestamp=0;
00261         unsigned char packetIdentifier, packetDataOffset;
00262         if ( ( unsigned char ) packet->data[ 0 ] == ID_TIMESTAMP )
00263         {
00264                 if ( packet->length > sizeof( unsigned char ) + sizeof( RakNetTime ) )
00265                 {
00266                         packetIdentifier = ( unsigned char ) packet->data[ sizeof( unsigned char ) + sizeof( RakNetTime ) ];
00267                         // Required for proper endian swapping
00268                         RakNet::BitStream tsBs(packet->data+sizeof(MessageID),packet->length-1,false);
00269                         tsBs.Read(timestamp);
00270                         packetDataOffset=sizeof( unsigned char )*2 + sizeof( RakNetTime );
00271                 }
00272                 else
00273                         return RR_STOP_PROCESSING_AND_DEALLOCATE;
00274         }
00275         else
00276         {
00277                 packetIdentifier = ( unsigned char ) packet->data[ 0 ];
00278                 packetDataOffset=sizeof( unsigned char );
00279         }
00280 
00281         switch (packetIdentifier)
00282         {
00283         case ID_AUTO_RPC_CALL:
00284                 incomingTimeStamp=timestamp;
00285                 incomingSystemAddress=packet->systemAddress;
00286                 OnAutoRPCCall(packet->systemAddress, packet->data+packetDataOffset, packet->length-packetDataOffset);
00287                 return RR_STOP_PROCESSING_AND_DEALLOCATE;
00288         case ID_AUTO_RPC_REMOTE_INDEX:
00289                 OnRPCRemoteIndex(packet->systemAddress, packet->data+packetDataOffset, packet->length-packetDataOffset);
00290                 return RR_STOP_PROCESSING_AND_DEALLOCATE;
00291         case ID_AUTO_RPC_UNKNOWN_REMOTE_INDEX:
00292                 OnRPCUnknownRemoteIndex(packet->systemAddress, packet->data+packetDataOffset, packet->length-packetDataOffset, timestamp);
00293                 return RR_STOP_PROCESSING_AND_DEALLOCATE;               
00294         }
00295 
00296         return RR_CONTINUE_PROCESSING;
00297 }
00298 void AutoRPC::OnClosedConnection(SystemAddress systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
00299 {
00300         (void) rakNetGUID;
00301         (void) lostConnectionReason;
00302 
00303         if (remoteFunctions.Has(systemAddress))
00304         {
00305                 DataStructures::OrderedList<RPCIdentifier, RemoteRPCFunction, AutoRPC::RemoteRPCFunctionComp> *theList = remoteFunctions.Get(systemAddress);
00306                 unsigned i;
00307                 for (i=0; i < theList->Size(); i++)
00308                 {
00309                         if (theList->operator [](i).identifier.uniqueIdentifier)
00310                                 rakFree_Ex(theList->operator [](i).identifier.uniqueIdentifier, __FILE__, __LINE__ );
00311                 }
00312                 RakNet::OP_DELETE(theList, __FILE__, __LINE__);
00313                 remoteFunctions.Delete(systemAddress);
00314         }
00315 }
00316 void AutoRPC::OnAutoRPCCall(SystemAddress systemAddress, unsigned char *data, unsigned int lengthInBytes)
00317 {
00318         RakNet::BitStream bs(data,lengthInBytes,false);
00319 
00320         bool hasParameterCount=false;
00321         char parameterCount;
00322         char inputStack[ARPC_MAX_STACK_SIZE];
00323         NetworkIDObject *networkIdObject;
00324         NetworkID networkId;
00325         bool hasNetworkId=false;
00326         bool hasFunctionIndex=false;
00327         unsigned int functionIndex;
00328         unsigned int bytesOnStack;
00329         char strIdentifier[512];
00330         int numberOfBitsUsed;
00331         incomingExtraData.Reset();
00332         bs.Read(hasParameterCount);
00333         if (hasParameterCount)
00334                 bs.Read(parameterCount);
00335         else
00336                 parameterCount=-1;
00337         bs.ReadCompressed(numberOfBitsUsed);
00338         if (numberOfBitsUsed > (int) incomingExtraData.GetNumberOfBitsAllocated())
00339                 incomingExtraData.AddBitsAndReallocate(numberOfBitsUsed-(int) incomingExtraData.GetNumberOfBitsAllocated());
00340         bs.ReadBits(incomingExtraData.GetData(), numberOfBitsUsed, false);
00341         incomingExtraData.SetWriteOffset(numberOfBitsUsed);
00342 
00343 
00344 //      const unsigned int outputStackSize = ARPC_MAX_STACK_SIZE+128*4; // Enough padding to round up to 4 for each parameter, max 128 parameters
00345 //      char outputStack[outputStackSize];
00346 
00347         bs.Read(hasNetworkId);
00348         if (hasNetworkId)
00349         {
00350                 bs.Read(networkId);
00351                 if (networkIdManager==0 && (networkIdManager=rakPeerInterface->GetNetworkIDManager())==0)
00352                 {
00353                         // Failed - Tried to call object member, however, networkIDManager system was never registered
00354                         SendError(systemAddress, RPC_ERROR_NETWORK_ID_MANAGER_UNAVAILABLE, "");
00355                         return;
00356                 }
00357                 networkIdObject = networkIdManager->GET_OBJECT_FROM_ID<NetworkIDObject*>(networkId);
00358                 if (networkIdObject==0)
00359                 {
00360                         // Failed - Tried to call object member, object does not exist (deleted?)
00361                         SendError(systemAddress, RPC_ERROR_OBJECT_DOES_NOT_EXIST, "");
00362                         return;
00363                 }
00364         }
00365         else
00366         {
00367                 networkIdObject=0;
00368         }
00369         bs.AlignReadToByteBoundary();
00370         bs.Read(hasFunctionIndex);
00371         if (hasFunctionIndex)
00372                 bs.ReadCompressed(functionIndex);
00373         else
00374                 stringCompressor->DecodeString(strIdentifier,512,&bs,0);
00375         bs.ReadCompressed(bytesOnStack);
00376         bs.ReadAlignedBytes((unsigned char *) inputStack,bytesOnStack);
00377         if (hasFunctionIndex)
00378         {
00379                 if (functionIndex>localFunctions.Size())
00380                 {
00381                         // Failed - other system specified a totally invalid index
00382                         // Possible causes: Bugs, attempts to crash the system, requested function not registered
00383                         SendError(systemAddress, RPC_ERROR_FUNCTION_INDEX_OUT_OF_RANGE, "");
00384                         return;
00385                 }
00386                 // it was actually a mistake to implement ID_AUTO_RPC_UNKNOWN_REMOTE_INDEX. This hides the more relevant return code RPC_ERROR_FUNCTION_NO_LONGER_REGISTERED and more importantly can result in the calls being out of order since it takes extra communication steps.
00387                 /*
00388                 if (localFunctions[functionIndex].functionPtr==0)
00389                 {
00390                         // Failed - Function index lookup failure. Try passing back what was sent to us, and requesting the string
00391                         RakNet::BitStream out;
00392                         if (incomingTimeStamp!=0)
00393                         {
00394                                 out.Write((MessageID)ID_TIMESTAMP);
00395                                 out.Write(incomingTimeStamp);
00396                         }
00397                         out.Write((MessageID)ID_AUTO_RPC_UNKNOWN_REMOTE_INDEX);
00398                         if (parameterCount>=0)
00399                         {
00400                                 out.Write(true);
00401                                 out.Write(parameterCount);
00402                         }
00403                         else
00404                         {
00405                                 out.Write(false);
00406                         }
00407                         out.WriteCompressed(functionIndex);
00408                         out.WriteCompressed(numberOfBitsUsed);
00409                         out.Write(&incomingExtraData);
00410                         out.Write(hasNetworkId);
00411                         if (hasNetworkId)
00412                                 out.Write(networkId);
00413                         out.WriteCompressed(bytesOnStack);
00414                         out.WriteAlignedBytes((const unsigned char*) inputStack, bytesOnStack);
00415                         SendUnified(&out, HIGH_PRIORITY, RELIABLE_ORDERED, 0, systemAddress, false);
00416                         
00417                         return;
00418                 }
00419                 */
00420         }
00421         else
00422         {
00423                 // Find the registered function with this str
00424                 for (functionIndex=0; functionIndex < localFunctions.Size(); functionIndex++)
00425                 {
00426                         if (localFunctions[functionIndex].identifier.isObjectMember == (networkIdObject!=0) &&
00427                                 strcmp(localFunctions[functionIndex].identifier.uniqueIdentifier, strIdentifier)==0)
00428                         {
00429                                 // SEND RPC MAPPING
00430                                 RakNet::BitStream outgoingBitstream;
00431                                 outgoingBitstream.Write((MessageID)ID_AUTO_RPC_REMOTE_INDEX);
00432                                 outgoingBitstream.Write(hasNetworkId);
00433                                 outgoingBitstream.WriteCompressed(functionIndex);
00434                                 stringCompressor->EncodeString(strIdentifier,512,&outgoingBitstream,0);
00435                                 SendUnified(&outgoingBitstream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, systemAddress, false);
00436                                 break;
00437                         }
00438                 }
00439 
00440                 if (functionIndex==localFunctions.Size())
00441                 {
00442                         for (functionIndex=0; functionIndex < localFunctions.Size(); functionIndex++)
00443                         {
00444                                 if (strcmp(localFunctions[functionIndex].identifier.uniqueIdentifier, strIdentifier)==0)
00445                                 {
00446                                         if (localFunctions[functionIndex].identifier.isObjectMember==true && networkIdObject==0)
00447                                         {
00448                                                 // Failed - Calling C++ function as C function
00449                                                 SendError(systemAddress, RPC_ERROR_CALLING_CPP_AS_C, strIdentifier);
00450                                                 return;
00451                                         }
00452 
00453                                         if (localFunctions[functionIndex].identifier.isObjectMember==false && networkIdObject!=0)
00454                                         {
00455                                                 // Failed - Calling C++ function as C function
00456                                                 SendError(systemAddress, RPC_ERROR_CALLING_C_AS_CPP, strIdentifier);
00457                                                 return;
00458                                         }
00459                                 }
00460                         }
00461 
00462                         SendError(systemAddress, RPC_ERROR_FUNCTION_NOT_REGISTERED, strIdentifier);
00463                         return;
00464                 }
00465         }
00466 
00467         if (localFunctions[functionIndex].functionPtr==0)
00468         {
00469                 // Failed - Function was previously registered, but isn't registered any longer
00470                 SendError(systemAddress, RPC_ERROR_FUNCTION_NO_LONGER_REGISTERED, localFunctions[functionIndex].identifier.uniqueIdentifier);
00471                 return;
00472         }
00473 
00474         if (bytesOnStack > ARPC_MAX_STACK_SIZE)
00475         {
00476                 // Failed - Not enough bytes on predetermined stack. Shouldn't hit this since the sender also uses this value
00477                 SendError(systemAddress, RPC_ERROR_STACK_TOO_SMALL, localFunctions[functionIndex].identifier.uniqueIdentifier);
00478                 return;
00479         }
00480 
00481         if (localFunctions[functionIndex].parameterCount>=0 && parameterCount>=0 && parameterCount!=localFunctions[functionIndex].parameterCount)
00482         {
00483                 // Failed - The number of parameters that this function has was explicitly specified, and does not match up.
00484                 SendError(systemAddress, RPC_ERROR_INCORRECT_NUMBER_OF_PARAMETERS, localFunctions[functionIndex].identifier.uniqueIdentifier);
00485                 return;
00486         }
00487 
00488         
00489 //      unsigned int bytesWritten;
00490 //      unsigned char numParameters;
00491 //      unsigned int parameterLengths[64]; // 64 is arbitrary, just needs to be more than whatever might be serialized
00492 
00493 
00494         GenRPC::CallParams call;
00495 
00496         if (DeserializeParametersAndBuildCall(call, inputStack, bytesOnStack, this, networkIdObject)==false)
00497         {
00498                 // Failed - Couldn't deserialize
00499                 SendError(systemAddress, RPC_ERROR_STACK_DESERIALIZATION_FAILED, localFunctions[functionIndex].identifier.uniqueIdentifier);
00500                 return;
00501         }
00502 
00503         strncpy(currentExecution, localFunctions[functionIndex].identifier.uniqueIdentifier, sizeof(currentExecution)-1);
00504 
00505         if (!CallWithStack( call, localFunctions[functionIndex].functionPtr)){
00506                 // Failed - Couldn't deserialize
00507                 SendError(systemAddress, RPC_ERROR_STACK_DESERIALIZATION_FAILED, currentExecution);
00508                 return;
00509         }
00510 
00511 
00512         currentExecution[0]=0;
00513 }
00514 void AutoRPC::OnRPCRemoteIndex(SystemAddress systemAddress, unsigned char *data, unsigned int lengthInBytes)
00515 {
00516         // A remote system has given us their internal index for a particular function.
00517         // Store it and use it from now on, to save bandwidth and search time
00518         bool objectExists;
00519         char strIdentifier[512];
00520         unsigned int insertionIndex;
00521         unsigned int remoteIndex;
00522         RemoteRPCFunction newRemoteFunction;
00523         RakNet::BitStream bs(data,lengthInBytes,false);
00524         RPCIdentifier identifier;
00525         bs.Read(identifier.isObjectMember);
00526         bs.ReadCompressed(remoteIndex);
00527         stringCompressor->DecodeString(strIdentifier,512,&bs,0);
00528         identifier.uniqueIdentifier=strIdentifier;
00529 
00530         if (strIdentifier[0]==0)
00531                 return;
00532 
00533         DataStructures::OrderedList<RPCIdentifier, RemoteRPCFunction, AutoRPC::RemoteRPCFunctionComp> *theList;
00534         if (remoteFunctions.Has(systemAddress))
00535         {
00536                 theList = remoteFunctions.Get(systemAddress);
00537                 insertionIndex=theList->GetIndexFromKey(identifier, &objectExists);
00538                 if (objectExists==false)
00539                 {
00540                         newRemoteFunction.functionIndex=remoteIndex;
00541                         newRemoteFunction.identifier.isObjectMember=identifier.isObjectMember;
00542                         newRemoteFunction.identifier.uniqueIdentifier = (char*) rakMalloc_Ex(strlen(strIdentifier)+1, __FILE__, __LINE__);
00543                         strcpy(newRemoteFunction.identifier.uniqueIdentifier, strIdentifier);
00544                         theList->InsertAtIndex(newRemoteFunction, insertionIndex, __FILE__, __LINE__);
00545                 }
00546         }
00547         else
00548         {
00549                 theList = RakNet::OP_NEW<DataStructures::OrderedList<RPCIdentifier, RemoteRPCFunction, AutoRPC::RemoteRPCFunctionComp> >( __FILE__, __LINE__ );
00550 
00551                 newRemoteFunction.functionIndex=remoteIndex;
00552                 newRemoteFunction.identifier.isObjectMember=identifier.isObjectMember;
00553                 newRemoteFunction.identifier.uniqueIdentifier = (char*) rakMalloc_Ex(strlen(strIdentifier)+1, __FILE__, __LINE__);
00554                 strcpy(newRemoteFunction.identifier.uniqueIdentifier, strIdentifier);
00555                 theList->InsertAtEnd(newRemoteFunction, __FILE__, __LINE__);
00556 
00557                 remoteFunctions.SetNew(systemAddress,theList);
00558         }
00559 }
00560 void AutoRPC::OnRPCUnknownRemoteIndex(SystemAddress systemAddress, unsigned char *data, unsigned int lengthInBytes, RakNetTime timestamp)
00561 {
00562         char inputStack[ARPC_MAX_STACK_SIZE];
00563         NetworkID networkId;
00564         bool hasNetworkId=false;
00565         unsigned int functionIndex;
00566         unsigned int bytesOnStack;
00567         int numberOfBitsUsed;
00568         char parameterCount;
00569         bool hasParameterCount=false;
00570 
00571         RakNet::BitStream extraData;
00572         RakNet::BitStream bs(data,lengthInBytes,false);
00573         bs.Read(hasParameterCount);
00574         if (hasParameterCount)
00575                 bs.Read(parameterCount);
00576         bs.ReadCompressed(functionIndex);
00577         bs.ReadCompressed(numberOfBitsUsed);
00578         extraData.AddBitsAndReallocate(numberOfBitsUsed);
00579         bs.ReadBits(extraData.GetData(), numberOfBitsUsed, false);
00580         extraData.SetWriteOffset(numberOfBitsUsed);
00581         bs.Read(hasNetworkId);
00582         if (hasNetworkId)
00583                 bs.Read(networkId);
00584         bs.ReadCompressed(bytesOnStack);
00585         bs.ReadAlignedBytes((unsigned char*) inputStack, bytesOnStack);
00586 
00587         unsigned outerIndex;
00588         if (remoteFunctions.Has(systemAddress))
00589         {
00590                 outerIndex = remoteFunctions.GetIndexAtKey(systemAddress);
00591                 DataStructures::OrderedList<RPCIdentifier, RemoteRPCFunction, AutoRPC::RemoteRPCFunctionComp> *theList = remoteFunctions[outerIndex];
00592                 unsigned i;
00593                 for (i=0; i < theList->Size(); i++)
00594                 {
00595                         if (theList->operator [](i).functionIndex==functionIndex)
00596                         {
00597                                 RakNet::BitStream out;
00598                                 // Recover by resending the RPC with the function identifier string this time
00599                                 if (timestamp!=0)
00600                                 {
00601                                         out.Write((MessageID)ID_TIMESTAMP);
00602                                         out.Write(timestamp);
00603                                 }
00604                                 out.Write((MessageID)ID_AUTO_RPC_CALL);
00605                                 if (parameterCount>=0)
00606                                 {
00607                                         out.Write(true);
00608                                         out.Write(parameterCount);
00609                                 }
00610                                 else
00611                                 {
00612                                         out.Write(false);
00613                                 }                               
00614                                 out.WriteCompressed(numberOfBitsUsed);
00615                                 out.Write(&extraData);
00616                                 out.Write(hasNetworkId);
00617                                 if (hasNetworkId)
00618                                         out.Write(networkId);
00619                                 out.AlignWriteToByteBoundary();
00620                                 out.Write(false);
00621                                 stringCompressor->EncodeString(theList->operator [](i).identifier.uniqueIdentifier, 512, &out, 0);
00622                                 out.WriteCompressed(bytesOnStack);
00623                                 out.WriteAlignedBytes((const unsigned char*) inputStack, bytesOnStack);
00624                                 SendUnified(&out, outgoingPriority, outgoingReliability, outgoingOrderingChannel, systemAddress, false);
00625                                 return;
00626                         }
00627                 }
00628         }
00629 
00630         // Failed to recover, inform the user
00631         Packet *p = rakPeerInterface->AllocatePacket(sizeof(MessageID)+sizeof(unsigned char));
00632         RakNet::BitStream bs2(p->data, sizeof(MessageID)+sizeof(unsigned char), false);
00633         bs2.SetWriteOffset(0);
00634         bs2.Write((MessageID)ID_RPC_REMOTE_ERROR);
00635         bs2.Write((unsigned char)RPC_ERROR_FUNCTION_NO_LONGER_REGISTERED);
00636         stringCompressor->EncodeString("",256,&bs,0);
00637         p->systemAddress=systemAddress;
00638         rakPeerInterface->PushBackPacket(p, false);
00639 
00640 }
00641 void AutoRPC::SendError(SystemAddress target, unsigned char errorCode, const char *functionName)
00642 {
00643         RakNet::BitStream bs;
00644         bs.Write((MessageID)ID_RPC_REMOTE_ERROR);
00645         bs.Write(errorCode);
00646         stringCompressor->EncodeString(functionName,256,&bs,0);
00647         SendUnified(&bs, HIGH_PRIORITY, RELIABLE_ORDERED, 0, target, false);
00648 }
00649 void AutoRPC::OnRakPeerShutdown(void)
00650 {
00651         Clear();
00652 }
00653 void AutoRPC::Clear(void)
00654 {
00655         unsigned i,j;
00656         for (j=0; j < remoteFunctions.Size(); j++)
00657         {
00658                 DataStructures::OrderedList<RPCIdentifier, RemoteRPCFunction, AutoRPC::RemoteRPCFunctionComp> *theList = remoteFunctions[j];
00659                 for (i=0; i < theList->Size(); i++)
00660                 {
00661                         if (theList->operator [](i).identifier.uniqueIdentifier)
00662                                 rakFree_Ex(theList->operator [](i).identifier.uniqueIdentifier, __FILE__, __LINE__ );
00663                 }
00664                 RakNet::OP_DELETE(theList, __FILE__, __LINE__);
00665         }
00666         for (i=0; i < localFunctions.Size(); i++)
00667         {
00668                 if (localFunctions[i].identifier.uniqueIdentifier)
00669                         rakFree_Ex(localFunctions[i].identifier.uniqueIdentifier, __FILE__, __LINE__ );
00670         }
00671         localFunctions.Clear(false, __FILE__, __LINE__);
00672         remoteFunctions.Clear();
00673         outgoingExtraData.Reset();
00674         incomingExtraData.Reset();
00675 }
00676 unsigned AutoRPC::GetLocalFunctionIndex(AutoRPC::RPCIdentifier identifier)
00677 {
00678         unsigned i;
00679         for (i=0; i < localFunctions.Size(); i++)
00680         {
00681                 if (localFunctions[i].identifier.isObjectMember==identifier.isObjectMember &&
00682                         strcmp(localFunctions[i].identifier.uniqueIdentifier,identifier.uniqueIdentifier)==0)
00683                         return i;
00684         }
00685         return (unsigned) -1;
00686 }
00687 bool AutoRPC::GetRemoteFunctionIndex(SystemAddress systemAddress, AutoRPC::RPCIdentifier identifier, unsigned int *outerIndex, unsigned int *innerIndex)
00688 {
00689         bool objectExists=false;
00690         if (remoteFunctions.Has(systemAddress))
00691         {
00692                 *outerIndex = remoteFunctions.GetIndexAtKey(systemAddress);
00693                 DataStructures::OrderedList<RPCIdentifier, RemoteRPCFunction, AutoRPC::RemoteRPCFunctionComp> *theList = remoteFunctions[*outerIndex];
00694                 *innerIndex = theList->GetIndexFromKey(identifier, &objectExists);
00695         }
00696         return objectExists;
00697 }
00698 
00699 
00700 #ifdef _MSC_VER
00701 #pragma warning( pop )
00702 #endif
00703 
00704 #endif // _RAKNET_SUPPORT_*

Generated on Thu Sep 30 2010 01:27:21 for RakNet by  doxygen 1.7.1