void RPC4::Call( const char* uniqueID, RakNet::BitStream * bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast ) { RakNet::BitStream out; out.Write((MessageID) ID_RPC_PLUGIN); out.Write((MessageID) ID_RPC4_CALL); out.WriteCompressed(uniqueID); out.Write(false); // Nonblocking if (bitStream) { bitStream->ResetReadPointer(); out.AlignWriteToByteBoundary(); out.Write(bitStream); } SendUnified(&out,priority,reliability,orderingChannel,systemIdentifier,broadcast); }
void RPC4::Signal(const char *sharedIdentifier, RakNet::BitStream *bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, bool broadcast, bool invokeLocal) { RakNet::BitStream out; out.Write((MessageID) ID_RPC_PLUGIN); out.Write((MessageID) ID_RPC4_SIGNAL); out.WriteCompressed(sharedIdentifier); if (bitStream) { bitStream->ResetReadPointer(); out.AlignWriteToByteBoundary(); out.Write(bitStream); } SendUnified(&out,priority,reliability,orderingChannel,systemIdentifier,broadcast); if (invokeLocal) { DataStructures::HashIndex functionIndex; functionIndex = localSlots.GetIndexOf(sharedIdentifier); if (functionIndex.IsInvalid()) return; Packet p; p.guid=rakPeerInterface->GetMyGUID(); p.systemAddress=rakPeerInterface->GetMyBoundAddress(0); p.wasGeneratedLocally=true; RakNet::BitStream *bsptr, bstemp; if (bitStream) { bitStream->ResetReadPointer(); p.length=bitStream->GetNumberOfBytesUsed(); p.bitSize=bitStream->GetNumberOfBitsUsed(); bsptr=bitStream; } else { p.length=0; p.bitSize=0; bsptr=&bstemp; } InvokeSignal(functionIndex, bsptr, &p); } }
PluginReceiveResult RPC4::OnReceive(Packet *packet) { if (packet->data[0]==ID_RPC_PLUGIN) { RakNet::BitStream bsIn(packet->data,packet->length,false); bsIn.IgnoreBytes(2); if (packet->data[1]==ID_RPC4_CALL) { RakNet::RakString functionName; bsIn.ReadCompressed(functionName); bool isBlocking; bsIn.Read(isBlocking); if (isBlocking==false) { DataStructures::HashIndex skhi = registeredNonblockingFunctions.GetIndexOf(functionName.C_String()); if (skhi.IsInvalid()) { RakNet::BitStream bsOut; bsOut.Write((unsigned char) ID_RPC_REMOTE_ERROR); bsOut.Write((unsigned char) RPC_ERROR_FUNCTION_NOT_REGISTERED); bsOut.Write(functionName.C_String(),(unsigned int) functionName.GetLength()+1); SendUnified(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false); return RR_STOP_PROCESSING_AND_DEALLOCATE; } void ( *fp ) ( RakNet::BitStream *, Packet * ); fp = registeredNonblockingFunctions.ItemAtIndex(skhi); bsIn.AlignReadToByteBoundary(); fp(&bsIn,packet); } else { DataStructures::HashIndex skhi = registeredBlockingFunctions.GetIndexOf(functionName.C_String()); if (skhi.IsInvalid()) { RakNet::BitStream bsOut; bsOut.Write((unsigned char) ID_RPC_REMOTE_ERROR); bsOut.Write((unsigned char) RPC_ERROR_FUNCTION_NOT_REGISTERED); bsOut.Write(functionName.C_String(),(unsigned int) functionName.GetLength()+1); SendUnified(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false); return RR_STOP_PROCESSING_AND_DEALLOCATE; } void ( *fp ) ( RakNet::BitStream *, RakNet::BitStream *, Packet * ); fp = registeredBlockingFunctions.ItemAtIndex(skhi); RakNet::BitStream returnData; bsIn.AlignReadToByteBoundary(); fp(&bsIn, &returnData, packet); RakNet::BitStream out; out.Write((MessageID) ID_RPC_PLUGIN); out.Write((MessageID) ID_RPC4_RETURN); returnData.ResetReadPointer(); out.AlignWriteToByteBoundary(); out.Write(returnData); SendUnified(&out,IMMEDIATE_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false); } } else { RakAssert(packet->data[1]==ID_RPC4_RETURN); blockingReturnValue.Reset(); blockingReturnValue.Read(bsIn); gotBlockingReturnValue=true; } return RR_STOP_PROCESSING_AND_DEALLOCATE; } bool objectExists; unsigned int index, index2; index = localCallbacks.GetIndexFromKey(packet->data[0],&objectExists); if (objectExists) { LocalCallback *lc; lc = localCallbacks[index]; for (index2=0; index2 < lc->functions.Size(); index2++) { RakNet::BitStream bsIn(packet->data, packet->length, false); DataStructures::HashIndex skhi = registeredNonblockingFunctions.GetIndexOf(lc->functions[index2].C_String()); if (skhi.IsInvalid()==false) { void ( *fp ) ( RakNet::BitStream *, Packet * ); fp = registeredNonblockingFunctions.ItemAtIndex(skhi); bsIn.AlignReadToByteBoundary(); fp(&bsIn,packet); } } } return RR_CONTINUE_PROCESSING; }
bool RPC4::CallBlocking( const char* uniqueID, RakNet::BitStream * bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel, const AddressOrGUID systemIdentifier, RakNet::BitStream *returnData ) { RakNet::BitStream out; out.Write((MessageID) ID_RPC_PLUGIN); out.Write((MessageID) ID_RPC4_CALL); out.WriteCompressed(uniqueID); out.Write(true); // Blocking if (bitStream) { bitStream->ResetReadPointer(); out.AlignWriteToByteBoundary(); out.Write(bitStream); } RakAssert(returnData); RakAssert(rakPeerInterface); ConnectionState cs; cs = rakPeerInterface->GetConnectionState(systemIdentifier); if (cs!=IS_CONNECTED && cs!=IS_LOOPBACK) return false; SendUnified(&out,priority,reliability,orderingChannel,systemIdentifier,false); returnData->Reset(); blockingReturnValue.Reset(); gotBlockingReturnValue=false; Packet *packet; DataStructures::Queue<Packet*> packetQueue; while (gotBlockingReturnValue==false) { // TODO - block, filter until gotBlockingReturnValue==true or ID_CONNECTION_LOST or ID_DISCONNECTION_NOTIFICXATION or ID_RPC_REMOTE_ERROR/RPC_ERROR_FUNCTION_NOT_REGISTERED RakSleep(30); packet=rakPeerInterface->Receive(); if (packet) { if ( (packet->data[0]==ID_CONNECTION_LOST || packet->data[0]==ID_DISCONNECTION_NOTIFICATION) && ((systemIdentifier.rakNetGuid!=UNASSIGNED_RAKNET_GUID && packet->guid==systemIdentifier.rakNetGuid) || (systemIdentifier.systemAddress!=UNASSIGNED_SYSTEM_ADDRESS && packet->systemAddress==systemIdentifier.systemAddress)) ) { // Push back to head in reverse order rakPeerInterface->PushBackPacket(packet,true); while (packetQueue.Size()) rakPeerInterface->PushBackPacket(packetQueue.Pop(),true); return false; } else if (packet->data[0]==ID_RPC_REMOTE_ERROR && packet->data[1]==RPC_ERROR_FUNCTION_NOT_REGISTERED) { RakNet::RakString functionName; RakNet::BitStream bsIn(packet->data,packet->length,false); bsIn.IgnoreBytes(2); bsIn.Read(functionName); if (functionName==uniqueID) { // Push back to head in reverse order rakPeerInterface->PushBackPacket(packet,true); while (packetQueue.Size()) rakPeerInterface->PushBackPacket(packetQueue.Pop(),true); return false; } else { packetQueue.PushAtHead(packet,0,_FILE_AND_LINE_); } } else { packetQueue.PushAtHead(packet,0,_FILE_AND_LINE_); } } } returnData->Read(blockingReturnValue); return true; }
void RPC4::CallLoopback( const char* uniqueID, RakNet::BitStream * bitStream ) { Packet *p=0; DataStructures::HashIndex skhi = registeredNonblockingFunctions.GetIndexOf(uniqueID); if (skhi.IsInvalid()==true) { if (rakPeerInterface) p=AllocatePacketUnified(sizeof(MessageID)+sizeof(unsigned char)+(unsigned int) strlen(uniqueID)+1); #if _RAKNET_SUPPORT_PacketizedTCP==1 && _RAKNET_SUPPORT_TCPInterface==1 else p=packetizedTCP->AllocatePacket(sizeof(MessageID)+sizeof(unsigned char)+(unsigned int) strlen(uniqueID)+1); #endif if (rakPeerInterface) p->guid=rakPeerInterface->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS); #if _RAKNET_SUPPORT_PacketizedTCP==1 && _RAKNET_SUPPORT_TCPInterface==1 else p->guid=UNASSIGNED_RAKNET_GUID; #endif p->systemAddress=UNASSIGNED_SYSTEM_ADDRESS; p->systemAddress.systemIndex=(SystemIndex)-1; p->data[0]=ID_RPC_REMOTE_ERROR; p->data[1]=RPC_ERROR_FUNCTION_NOT_REGISTERED; strcpy((char*) p->data+2, uniqueID); PushBackPacketUnified(p,false); return; } RakNet::BitStream out; out.Write((MessageID) ID_RPC_PLUGIN); out.Write((MessageID) ID_RPC4_CALL); out.WriteCompressed(uniqueID); out.Write(false); // nonblocking if (bitStream) { bitStream->ResetReadPointer(); out.AlignWriteToByteBoundary(); out.Write(bitStream); } if (rakPeerInterface) p=AllocatePacketUnified(out.GetNumberOfBytesUsed()); #if _RAKNET_SUPPORT_PacketizedTCP==1 && _RAKNET_SUPPORT_TCPInterface==1 else p=packetizedTCP->AllocatePacket(out.GetNumberOfBytesUsed()); #endif if (rakPeerInterface) p->guid=rakPeerInterface->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS); #if _RAKNET_SUPPORT_PacketizedTCP==1 && _RAKNET_SUPPORT_TCPInterface==1 else p->guid=UNASSIGNED_RAKNET_GUID; #endif p->systemAddress=UNASSIGNED_SYSTEM_ADDRESS; p->systemAddress.systemIndex=(SystemIndex)-1; memcpy(p->data,out.GetData(),out.GetNumberOfBytesUsed()); PushBackPacketUnified(p,false); return; }
void FileListTransfer::Send(FileList *fileList, RakPeerInterface *rakPeer, SystemAddress recipient, unsigned short setID, PacketPriority priority, char orderingChannel, bool compressData, IncrementalReadInterface *_incrementalReadInterface, unsigned int _chunkSize) { (void) compressData; if (callback) fileList->SetCallback(callback); unsigned int i, totalLength; RakNet::BitStream outBitstream; bool sendReference; char *dataBlocks[2]; int lengths[2]; totalLength=0; for (i=0; i < fileList->fileList.Size(); i++) { const FileListNode &fileListNode = fileList->fileList[i]; totalLength+=fileListNode.fileLengthBytes; } // Write the chunk header, which contains the frequency table, the total number of files, and the total number of bytes bool anythingToWrite; outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_HEADER); outBitstream.Write(setID); anythingToWrite=fileList->fileList.Size()>0; outBitstream.Write(anythingToWrite); if (anythingToWrite) { outBitstream.WriteCompressed(fileList->fileList.Size()); outBitstream.WriteCompressed(totalLength); if (rakPeer) rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); else SendUnified(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); for (i=0; i < fileList->fileList.Size(); i++) { outBitstream.Reset(); sendReference = fileList->fileList[i].isAReference && _incrementalReadInterface!=0; if (sendReference) { StoreForPush(fileList->fileList[i].context, setID, fileList->fileList[i].filename, fileList->fileList[i].fullPathToFile, i, fileList->fileList[i].fileLengthBytes, fileList->fileList[i].dataLengthBytes, recipient, priority, orderingChannel, _incrementalReadInterface, _chunkSize); continue; } outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_FILE); outBitstream.Write(fileList->fileList[i].context); outBitstream.Write(setID); stringCompressor->EncodeString(fileList->fileList[i].filename, 512, &outBitstream); outBitstream.WriteCompressed(i); outBitstream.WriteCompressed(fileList->fileList[i].dataLengthBytes); // Original length in bytes outBitstream.AlignWriteToByteBoundary(); dataBlocks[0]=(char*) outBitstream.GetData(); lengths[0]=outBitstream.GetNumberOfBytesUsed(); dataBlocks[1]=fileList->fileList[i].data; lengths[1]=fileList->fileList[i].dataLengthBytes; if (rakPeer) rakPeer->SendList(dataBlocks,lengths,2,priority, RELIABLE_ORDERED, orderingChannel, recipient, false); else SendListUnified(dataBlocks,lengths,2,priority, RELIABLE_ORDERED, orderingChannel, recipient, false); } } else { if (rakPeer) rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); else SendUnified(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); } }
void FileListTransfer::Send(FileList *fileList, RakPeerInterface *rakPeer, SystemAddress recipient, unsigned short setID, PacketPriority priority, char orderingChannel, bool compressData, IncrementalReadInterface *_incrementalReadInterface, unsigned int _chunkSize) { (void) compressData; if (callback) fileList->SetCallback(callback); unsigned int i, totalLength; RakNet::BitStream outBitstream; bool sendReference; const char *dataBlocks[2]; int lengths[2]; totalLength=0; for (i=0; i < fileList->fileList.Size(); i++) { const FileListNode &fileListNode = fileList->fileList[i]; totalLength+=fileListNode.fileLengthBytes; } // Write the chunk header, which contains the frequency table, the total number of files, and the total number of bytes bool anythingToWrite; outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_HEADER); outBitstream.Write(setID); anythingToWrite=fileList->fileList.Size()>0; outBitstream.Write(anythingToWrite); if (anythingToWrite) { outBitstream.WriteCompressed(fileList->fileList.Size()); outBitstream.WriteCompressed(totalLength); if (rakPeer) rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); else SendUnified(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); DataStructures::Queue<FileToPush*> filesToPush; for (i=0; i < fileList->fileList.Size(); i++) { sendReference = fileList->fileList[i].isAReference && _incrementalReadInterface!=0; if (sendReference) { FileToPush *fileToPush = RakNet::OP_NEW<FileToPush>(__FILE__,__LINE__); fileToPush->fileListNode.context=fileList->fileList[i].context; fileToPush->setIndex=i; fileToPush->fileListNode.filename=fileList->fileList[i].filename; fileToPush->fileListNode.fullPathToFile=fileList->fileList[i].fullPathToFile; fileToPush->fileListNode.fileLengthBytes=fileList->fileList[i].fileLengthBytes; fileToPush->fileListNode.dataLengthBytes=fileList->fileList[i].dataLengthBytes; // fileToPush->systemAddress=recipient; fileToPush->setID=setID; fileToPush->packetPriority=priority; fileToPush->orderingChannel=orderingChannel; fileToPush->currentOffset=0; fileToPush->incrementalReadInterface=_incrementalReadInterface; fileToPush->chunkSize=_chunkSize; filesToPush.Push(fileToPush,__FILE__,__LINE__); } else { outBitstream.Reset(); outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_FILE); outBitstream.Write(fileList->fileList[i].context); outBitstream.Write(setID); stringCompressor->EncodeString(fileList->fileList[i].filename, 512, &outBitstream); outBitstream.WriteCompressed(i); outBitstream.WriteCompressed(fileList->fileList[i].dataLengthBytes); // Original length in bytes outBitstream.AlignWriteToByteBoundary(); dataBlocks[0]=(char*) outBitstream.GetData(); lengths[0]=outBitstream.GetNumberOfBytesUsed(); dataBlocks[1]=fileList->fileList[i].data; lengths[1]=fileList->fileList[i].dataLengthBytes; SendListUnified(dataBlocks,lengths,2,priority, RELIABLE_ORDERED, orderingChannel, recipient, false); } } if (filesToPush.IsEmpty()==false) { FileToPushRecipient *ftpr=0; filesToPushAllSameAddressMutex.Lock(); for (unsigned int i=0; i < filesToPushAllSameAddress.Size(); i++) { if (filesToPushAllSameAddress[i]->systemAddress==recipient) { ftpr=filesToPushAllSameAddress[i]; break; } } if (ftpr==0) { ftpr = RakNet::OP_NEW<FileToPushRecipient>(__FILE__,__LINE__); ftpr->systemAddress=recipient; filesToPushAllSameAddress.Push(ftpr, __FILE__,__LINE__); } while (filesToPush.IsEmpty()==false) { ftpr->filesToPush.Push(filesToPush.Pop(), __FILE__,__LINE__); } filesToPushAllSameAddressMutex.Unlock(); SendIRIToAddress(recipient); return; } } else { if (rakPeer) rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); else SendUnified(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); } }
void FileListTransfer::SendIRIToAddress(SystemAddress systemAddress) { // Was previously using GetStatistics to get outgoing buffer size, but TCP with UnifiedSend doesn't have this unsigned int bytesRead; const char *dataBlocks[2]; int lengths[2]; unsigned int smallFileTotalSize=0; RakNet::BitStream outBitstream; filesToPushAllSameAddressMutex.Lock(); for (unsigned int ftpIndex=0; ftpIndex < filesToPushAllSameAddress.Size(); ftpIndex++) { FileToPushRecipient *ftpr = filesToPushAllSameAddress[ftpIndex]; if (ftpr->systemAddress==systemAddress) { FileToPush *ftp = ftpr->filesToPush.Peek(); // Read and send chunk. If done, delete at this index void *buff = rakMalloc_Ex(ftp->chunkSize, __FILE__, __LINE__); if (buff==0) { filesToPushAllSameAddressMutex.Unlock(); notifyOutOfMemory(__FILE__, __LINE__); return; } bytesRead=ftp->incrementalReadInterface->GetFilePart(ftp->fileListNode.fullPathToFile, ftp->currentOffset, ftp->chunkSize, buff, ftp->fileListNode.context); bool done = bytesRead!=ftp->chunkSize; while (done && ftp->currentOffset==0 && ftpr->filesToPush.Size()>=2 && smallFileTotalSize<ftp->chunkSize) { // Send all small files at once, rather than wait for ID_FILE_LIST_REFERENCE_PUSH. But at least one ID_FILE_LIST_REFERENCE_PUSH must be sent outBitstream.Reset(); outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_FILE); outBitstream.Write(ftp->fileListNode.context); outBitstream.Write(ftp->setID); stringCompressor->EncodeString(ftp->fileListNode.filename, 512, &outBitstream); outBitstream.WriteCompressed(ftp->setIndex); outBitstream.WriteCompressed(ftp->fileListNode.dataLengthBytes); // Original length in bytes outBitstream.AlignWriteToByteBoundary(); dataBlocks[0]=(char*) outBitstream.GetData(); lengths[0]=outBitstream.GetNumberOfBytesUsed(); dataBlocks[1]=(const char*) buff; lengths[1]=bytesRead; SendListUnified(dataBlocks,lengths,2,ftp->packetPriority, RELIABLE_ORDERED, ftp->orderingChannel, systemAddress, false); RakNet::OP_DELETE(ftp,__FILE__,__LINE__); ftpr->filesToPush.Pop(); smallFileTotalSize+=bytesRead; done = bytesRead!=ftp->chunkSize; ftp = ftpr->filesToPush.Peek(); bytesRead=ftp->incrementalReadInterface->GetFilePart(ftp->fileListNode.fullPathToFile, ftp->currentOffset, ftp->chunkSize, buff, ftp->fileListNode.context); } outBitstream.Reset(); outBitstream.Write((MessageID)ID_FILE_LIST_REFERENCE_PUSH); outBitstream.Write(ftp->fileListNode.context); outBitstream.Write(ftp->setID); stringCompressor->EncodeString(ftp->fileListNode.filename, 512, &outBitstream); outBitstream.WriteCompressed(ftp->setIndex); outBitstream.WriteCompressed(ftp->fileListNode.dataLengthBytes); // Original length in bytes outBitstream.WriteCompressed(ftp->currentOffset); ftp->currentOffset+=bytesRead; outBitstream.WriteCompressed(bytesRead); outBitstream.Write(done); if (callback) { callback->OnFilePush(ftp->fileListNode.filename, ftp->fileListNode.fileLengthBytes, ftp->currentOffset-bytesRead, bytesRead, done, systemAddress); } dataBlocks[0]=(char*) outBitstream.GetData(); lengths[0]=outBitstream.GetNumberOfBytesUsed(); dataBlocks[1]=(char*) buff; lengths[1]=bytesRead; //rakPeerInterface->SendList(dataBlocks,lengths,2,ftp->packetPriority, RELIABLE_ORDERED, ftp->orderingChannel, ftp->systemAddress, false); SendListUnified(dataBlocks,lengths,2,ftp->packetPriority, RELIABLE_ORDERED, ftp->orderingChannel, systemAddress, false); if (done) { // Done RakNet::OP_DELETE(ftp,__FILE__,__LINE__); ftpr->filesToPush.Pop(); if (ftpr->filesToPush.Size()==0) { RakNet::OP_DELETE(ftpr,__FILE__,__LINE__); filesToPushAllSameAddress.RemoveAtIndexFast(ftpIndex); } } rakFree_Ex(buff, __FILE__, __LINE__ ); break; } } filesToPushAllSameAddressMutex.Unlock(); }
bool RPC3::SendCallOrSignal(RakString uniqueIdentifier, char parameterCount, RakNet::BitStream *serializedParameters, bool isCall) { SystemAddress systemAddr; // unsigned int outerIndex; // unsigned int innerIndex; if (uniqueIdentifier.IsEmpty()) return false; RakNet::BitStream bs; if (outgoingTimestamp!=0) { bs.Write((MessageID)ID_TIMESTAMP); bs.Write(outgoingTimestamp); } bs.Write((MessageID)ID_AUTO_RPC_CALL); bs.Write(parameterCount); if (outgoingNetworkID!=UNASSIGNED_NETWORK_ID && isCall) { bs.Write(true); bs.Write(outgoingNetworkID); } else { bs.Write(false); } bs.Write(isCall); // This is so the call SetWriteOffset works bs.AlignWriteToByteBoundary(); BitSize_t writeOffset = bs.GetWriteOffset(); if (outgoingBroadcast) { unsigned systemIndex; for (systemIndex=0; systemIndex < rakPeerInterface->GetMaximumNumberOfPeers(); systemIndex++) { systemAddr=rakPeerInterface->GetSystemAddressFromIndex(systemIndex); if (systemAddr!=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->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); // Start writing again after ID_AUTO_RPC_CALL bs.SetWriteOffset(writeOffset); } } } else { systemAddr = outgoingSystemAddress; if (systemAddr!=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->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; }
PluginReceiveResult Router::OnReceive(Packet *packet) { if (packet->data[0]==ID_ROUTE_AND_MULTICAST || (packet->length>5 && packet->data[0]==ID_TIMESTAMP && packet->data[5]==ID_ROUTE_AND_MULTICAST)) { #ifdef _DO_PRINTF RAKNET_DEBUG_PRINTF("%i got routed message from %i\n", peer->GetExternalID(packet->systemAddress).port, packet->systemAddress.port); #endif RakNetTime timestamp; PacketPriority priority; PacketReliability reliability; unsigned char orderingChannel; SystemAddress originalSender; RakNet::BitStream out; BitSize_t outStartingOffset; unsigned int payloadBitLength; unsigned payloadWriteByteOffset; RakNet::BitStream incomingBitstream(packet->data, packet->length, false); incomingBitstream.IgnoreBits(8); if (packet->data[0]==ID_TIMESTAMP) { incomingBitstream.Read(timestamp); out.Write((MessageID)ID_TIMESTAMP); out.Write(timestamp); incomingBitstream.IgnoreBits(8); } // Read the send parameters unsigned char c; incomingBitstream.ReadCompressed(c); priority=(PacketPriority)c; incomingBitstream.ReadCompressed(c); reliability=(PacketReliability)c; incomingBitstream.ReadCompressed(orderingChannel); incomingBitstream.Read(payloadBitLength); out.Write((MessageID)ID_ROUTE_AND_MULTICAST); out.WriteCompressed((unsigned char)priority); out.WriteCompressed((unsigned char)reliability); out.WriteCompressed((unsigned char)orderingChannel); out.Write(payloadBitLength); out.AlignWriteToByteBoundary(); incomingBitstream.AlignReadToByteBoundary(); payloadWriteByteOffset=(unsigned int) BITS_TO_BYTES(out.GetWriteOffset()); out.Write(&incomingBitstream, payloadBitLength); // This write also does a read on incomingBitStream if (restrictByType) { RakNet::BitStream t(out.GetData()+payloadWriteByteOffset, sizeof(unsigned char), false); MessageID messageID; t.Read(messageID); if (allowedTypes.HasData(messageID)==false) return RR_STOP_PROCESSING_AND_DEALLOCATE; // Don't route restricted types } incomingBitstream.Read(originalSender); out.Write(originalSender); outStartingOffset=out.GetWriteOffset(); // Deserialize the root bool hasData=false; SystemAddress recipient; unsigned short numberOfChildren; incomingBitstream.Read(hasData); incomingBitstream.Read(recipient); // This should be our own address if (incomingBitstream.ReadCompressed(numberOfChildren)==false) { #ifdef _DEBUG RakAssert(0); #endif return RR_STOP_PROCESSING_AND_DEALLOCATE; } unsigned childIndex; bool childHasData=false; SystemAddress childRecipient; unsigned short childNumberOfChildren; SystemAddress immediateRecipient; immediateRecipient=UNASSIGNED_SYSTEM_ADDRESS; int pendingNodeCount=0; for (childIndex=0; childIndex < numberOfChildren; childIndex++) { while (pendingNodeCount!=-1) { // Copy out the serialized subtree for this child incomingBitstream.Read(childHasData); incomingBitstream.Read(childRecipient); if (!incomingBitstream.ReadCompressed(childNumberOfChildren)) return RR_STOP_PROCESSING_AND_DEALLOCATE; if (immediateRecipient==UNASSIGNED_SYSTEM_ADDRESS) { immediateRecipient=childRecipient; } pendingNodeCount+=childNumberOfChildren-1; out.Write(childHasData); out.Write(childRecipient); out.WriteCompressed(childNumberOfChildren); } #ifdef _DO_PRINTF RAKNET_DEBUG_PRINTF("%i routing to %i\n", peer->GetExternalID(packet->systemAddress).port, immediateRecipient.port); #endif // Send what we got so far SendUnified(&out, priority, reliability, orderingChannel, immediateRecipient, false); // Restart writing the per recipient data out.SetWriteOffset(outStartingOffset); // Reread the top level node immediateRecipient=UNASSIGNED_SYSTEM_ADDRESS; pendingNodeCount=0; } // Write the user payload to the packet struct if this is a destination and change the sender and return true if (hasData) { #ifdef _DO_PRINTF RAKNET_DEBUG_PRINTF("%i returning payload to user\n", peer->GetExternalID(packet->systemAddress).port); #endif if (packet->data[0]==ID_TIMESTAMP ) { memcpy( packet->data + sizeof(RakNetTime)+sizeof(unsigned char), out.GetData()+payloadWriteByteOffset, BITS_TO_BYTES(payloadBitLength) ); packet->bitSize=BYTES_TO_BITS(sizeof(RakNetTime)+sizeof(unsigned char))+payloadBitLength; } else { memcpy( packet->data, out.GetData()+payloadWriteByteOffset, BITS_TO_BYTES(payloadBitLength) ); packet->bitSize=payloadBitLength; } packet->length=(unsigned int) BITS_TO_BYTES(packet->bitSize); packet->systemAddress.systemIndex=(SystemIndex)-1; packet->systemAddress=originalSender; return RR_CONTINUE_PROCESSING; } // Absorb return RR_STOP_PROCESSING_AND_DEALLOCATE; } return RR_CONTINUE_PROCESSING; }
int SendIRIToAddressCB(FileListTransfer::ThreadData threadData, bool *returnOutput, void* perThreadData) { (void) perThreadData; FileListTransfer *fileListTransfer = threadData.fileListTransfer; SystemAddress systemAddress = threadData.systemAddress; *returnOutput=false; // Was previously using GetStatistics to get outgoing buffer size, but TCP with UnifiedSend doesn't have this unsigned int bytesRead; const char *dataBlocks[2]; int lengths[2]; unsigned int smallFileTotalSize=0; RakNet::BitStream outBitstream; unsigned int ftpIndex; fileListTransfer->fileToPushRecipientListMutex.Lock(); for (ftpIndex=0; ftpIndex < fileListTransfer->fileToPushRecipientList.Size(); ftpIndex++) { FileListTransfer::FileToPushRecipient *ftpr = fileListTransfer->fileToPushRecipientList[ftpIndex]; // Referenced by both ftpr and list ftpr->AddRef(); fileListTransfer->fileToPushRecipientListMutex.Unlock(); if (ftpr->systemAddress==systemAddress) { FileListTransfer::FileToPush *ftp = ftpr->filesToPush.Peek(); // Read and send chunk. If done, delete at this index void *buff = rakMalloc_Ex(ftp->chunkSize, _FILE_AND_LINE_); if (buff==0) { ftpr->Deref(); notifyOutOfMemory(_FILE_AND_LINE_); return 0; } // Read the next file chunk bytesRead=ftp->incrementalReadInterface->GetFilePart(ftp->fileListNode.fullPathToFile, ftp->currentOffset, ftp->chunkSize, buff, ftp->fileListNode.context); bool done = ftp->fileListNode.dataLengthBytes == ftp->currentOffset+bytesRead; while (done && ftp->currentOffset==0 && ftpr->filesToPush.Size()>=2 && smallFileTotalSize<ftp->chunkSize) { // Send all small files at once, rather than wait for ID_FILE_LIST_REFERENCE_PUSH. But at least one ID_FILE_LIST_REFERENCE_PUSH must be sent outBitstream.Reset(); outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_FILE); // outBitstream.Write(ftp->fileListNode.context); outBitstream << ftp->fileListNode.context; outBitstream.Write(ftp->setID); StringCompressor::Instance()->EncodeString(ftp->fileListNode.filename, 512, &outBitstream); outBitstream.WriteCompressed(ftp->setIndex); outBitstream.WriteCompressed(ftp->fileListNode.dataLengthBytes); // Original length in bytes outBitstream.AlignWriteToByteBoundary(); dataBlocks[0]=(char*) outBitstream.GetData(); lengths[0]=outBitstream.GetNumberOfBytesUsed(); dataBlocks[1]=(const char*) buff; lengths[1]=bytesRead; fileListTransfer->SendListUnified(dataBlocks,lengths,2,ftp->packetPriority, RELIABLE_ORDERED, ftp->orderingChannel, systemAddress, false); // LWS : fixed freed pointer reference // unsigned int chunkSize = ftp->chunkSize; RakNet::OP_DELETE(ftp,_FILE_AND_LINE_); ftpr->filesToPush.Pop(); smallFileTotalSize+=bytesRead; //done = bytesRead!=ftp->chunkSize; ftp = ftpr->filesToPush.Peek(); bytesRead=ftp->incrementalReadInterface->GetFilePart(ftp->fileListNode.fullPathToFile, ftp->currentOffset, ftp->chunkSize, buff, ftp->fileListNode.context); done = ftp->fileListNode.dataLengthBytes == ftp->currentOffset+bytesRead; } outBitstream.Reset(); outBitstream.Write((MessageID)ID_FILE_LIST_REFERENCE_PUSH); // outBitstream.Write(ftp->fileListNode.context); outBitstream << ftp->fileListNode.context; outBitstream.Write(ftp->setID); StringCompressor::Instance()->EncodeString(ftp->fileListNode.filename, 512, &outBitstream); outBitstream.WriteCompressed(ftp->setIndex); outBitstream.WriteCompressed(ftp->fileListNode.dataLengthBytes); // Original length in bytes outBitstream.WriteCompressed(ftp->currentOffset); ftp->currentOffset+=bytesRead; outBitstream.WriteCompressed(bytesRead); outBitstream.Write(done); for (unsigned int flpcIndex=0; flpcIndex < fileListTransfer->fileListProgressCallbacks.Size(); flpcIndex++) fileListTransfer->fileListProgressCallbacks[flpcIndex]->OnFilePush(ftp->fileListNode.filename, ftp->fileListNode.fileLengthBytes, ftp->currentOffset-bytesRead, bytesRead, done, systemAddress, ftp->setID); dataBlocks[0]=(char*) outBitstream.GetData(); lengths[0]=outBitstream.GetNumberOfBytesUsed(); dataBlocks[1]=(char*) buff; lengths[1]=bytesRead; //rakPeerInterface->SendList(dataBlocks,lengths,2,ftp->packetPriority, RELIABLE_ORDERED, ftp->orderingChannel, ftp->systemAddress, false); fileListTransfer->SendListUnified(dataBlocks,lengths,2,ftp->packetPriority, RELIABLE_ORDERED, ftp->orderingChannel, systemAddress, false); // Mutex state: FileToPushRecipient (ftpr) has AddRef. fileToPushRecipientListMutex not locked. if (done) { // Done unsigned short setId = ftp->setID; RakNet::OP_DELETE(ftp,_FILE_AND_LINE_); ftpr->filesToPush.Pop(); if (ftpr->filesToPush.Size()==0) { for (unsigned int flpcIndex=0; flpcIndex < fileListTransfer->fileListProgressCallbacks.Size(); flpcIndex++) fileListTransfer->fileListProgressCallbacks[flpcIndex]->OnFilePushesComplete(systemAddress, setId); // Remove ftpr from fileToPushRecipientList fileListTransfer->RemoveFromList(ftpr); } } // ftpr out of scope ftpr->Deref(); rakFree_Ex(buff, _FILE_AND_LINE_ ); return 0; } else { ftpr->Deref(); fileListTransfer->fileToPushRecipientListMutex.Lock(); } } fileListTransfer->fileToPushRecipientListMutex.Unlock(); return 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); }
bool AutoRPC::SendCall(const char *uniqueIdentifier, const char *stack, unsigned int bytesOnStack, char parameterCount) { SystemAddress systemAddr; RPCIdentifier identifier; unsigned int outerIndex; unsigned int innerIndex; if (uniqueIdentifier==0) return false; identifier.uniqueIdentifier=(char*) uniqueIdentifier; identifier.isObjectMember=(outgoingNetworkID!=UNASSIGNED_NETWORK_ID); RakNet::BitStream bs; if (outgoingTimestamp!=0) { bs.Write((MessageID)ID_TIMESTAMP); bs.Write(outgoingTimestamp); } bs.Write((MessageID)ID_AUTO_RPC_CALL); if (parameterCount>=0) { bs.Write(true); bs.Write(parameterCount); } else { bs.Write(false); } bs.WriteCompressed(outgoingExtraData.GetNumberOfBitsUsed()); bs.Write(&outgoingExtraData); if (outgoingNetworkID!=UNASSIGNED_NETWORK_ID) { bs.Write(true); bs.Write(outgoingNetworkID); } else { bs.Write(false); } // This is so the call SetWriteOffset works bs.AlignWriteToByteBoundary(); BitSize_t writeOffset = bs.GetWriteOffset(); SystemAddress outgoingSystemAddress; if (outgoingSystemIdentifier.rakNetGuid!=UNASSIGNED_RAKNET_GUID) outgoingSystemAddress = rakPeerInterface->GetSystemAddressFromGuid(outgoingSystemIdentifier.rakNetGuid); else outgoingSystemAddress = outgoingSystemIdentifier.systemAddress; if (outgoingBroadcast) { unsigned systemIndex; for (systemIndex=0; systemIndex < rakPeerInterface->GetMaximumNumberOfPeers(); systemIndex++) { systemAddr=rakPeerInterface->GetSystemAddressFromIndex(systemIndex); if (systemAddr!=UNASSIGNED_SYSTEM_ADDRESS && systemAddr!=outgoingSystemAddress) { if (GetRemoteFunctionIndex(systemAddr, identifier, &outerIndex, &innerIndex)) { // Write a number to identify the function if possible, for faster lookup and less bandwidth bs.Write(true); bs.WriteCompressed(remoteFunctions[outerIndex]->operator [](innerIndex).functionIndex); } else { bs.Write(false); stringCompressor->EncodeString(uniqueIdentifier, 512, &bs, 0); } bs.WriteCompressed(bytesOnStack); bs.WriteAlignedBytes((const unsigned char*) stack, bytesOnStack); SendUnified(&bs, outgoingPriority, outgoingReliability, outgoingOrderingChannel, systemAddr, false); // Start writing again after ID_AUTO_RPC_CALL bs.SetWriteOffset(writeOffset); } } } else { systemAddr = outgoingSystemAddress; if (systemAddr!=UNASSIGNED_SYSTEM_ADDRESS) { if (GetRemoteFunctionIndex(systemAddr, identifier, &outerIndex, &innerIndex)) { // Write a number to identify the function if possible, for faster lookup and less bandwidth bs.Write(true); bs.WriteCompressed(remoteFunctions[outerIndex]->operator [](innerIndex).functionIndex); } else { bs.Write(false); stringCompressor->EncodeString(uniqueIdentifier, 512, &bs, 0); } bs.WriteCompressed(bytesOnStack); bs.WriteAlignedBytes((const unsigned char*) stack, bytesOnStack); SendUnified(&bs, outgoingPriority, outgoingReliability, outgoingOrderingChannel, systemAddr, false); } else return false; } return true; }
void FileListTransfer::Send(FileList *fileList, RakNet::RakPeerInterface *rakPeer, SystemAddress recipient, unsigned short setID, PacketPriority priority, char orderingChannel, IncrementalReadInterface *_incrementalReadInterface, unsigned int _chunkSize) { for (unsigned int flpcIndex=0; flpcIndex < fileListProgressCallbacks.Size(); flpcIndex++) fileList->AddCallback(fileListProgressCallbacks[flpcIndex]); unsigned int i, totalLength; RakNet::BitStream outBitstream; bool sendReference; const char *dataBlocks[2]; int lengths[2]; totalLength=0; for (i=0; i < fileList->fileList.Size(); i++) { const FileListNode &fileListNode = fileList->fileList[i]; totalLength+=fileListNode.dataLengthBytes; } // Write the chunk header, which contains the frequency table, the total number of files, and the total number of bytes bool anythingToWrite; outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_HEADER); outBitstream.Write(setID); anythingToWrite=fileList->fileList.Size()>0; outBitstream.Write(anythingToWrite); if (anythingToWrite) { outBitstream.WriteCompressed(fileList->fileList.Size()); outBitstream.WriteCompressed(totalLength); if (rakPeer) rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); else SendUnified(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); DataStructures::Queue<FileToPush*> filesToPush; for (i=0; i < fileList->fileList.Size(); i++) { sendReference = fileList->fileList[i].isAReference && _incrementalReadInterface!=0; if (sendReference) { FileToPush *fileToPush = RakNet::OP_NEW<FileToPush>(_FILE_AND_LINE_); fileToPush->fileListNode.context=fileList->fileList[i].context; fileToPush->setIndex=i; fileToPush->fileListNode.filename=fileList->fileList[i].filename; fileToPush->fileListNode.fullPathToFile=fileList->fileList[i].fullPathToFile; fileToPush->fileListNode.fileLengthBytes=fileList->fileList[i].fileLengthBytes; fileToPush->fileListNode.dataLengthBytes=fileList->fileList[i].dataLengthBytes; // fileToPush->systemAddress=recipient; //fileToPush->setID=setID; fileToPush->packetPriority=priority; fileToPush->orderingChannel=orderingChannel; fileToPush->currentOffset=0; fileToPush->incrementalReadInterface=_incrementalReadInterface; fileToPush->chunkSize=_chunkSize; filesToPush.Push(fileToPush,_FILE_AND_LINE_); } else { outBitstream.Reset(); outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_FILE); outBitstream << fileList->fileList[i].context; // outBitstream.Write(fileList->fileList[i].context); outBitstream.Write(setID); StringCompressor::Instance()->EncodeString(fileList->fileList[i].filename, 512, &outBitstream); outBitstream.WriteCompressed(i); outBitstream.WriteCompressed(fileList->fileList[i].dataLengthBytes); // Original length in bytes outBitstream.AlignWriteToByteBoundary(); dataBlocks[0]=(char*) outBitstream.GetData(); lengths[0]=outBitstream.GetNumberOfBytesUsed(); dataBlocks[1]=fileList->fileList[i].data; lengths[1]=fileList->fileList[i].dataLengthBytes; SendListUnified(dataBlocks,lengths,2,priority, RELIABLE_ORDERED, orderingChannel, recipient, false); } } if (filesToPush.IsEmpty()==false) { FileToPushRecipient *ftpr; fileToPushRecipientListMutex.Lock(); for (unsigned int i=0; i < fileToPushRecipientList.Size(); i++) { if (fileToPushRecipientList[i]->systemAddress==recipient && fileToPushRecipientList[i]->setId==setId) { // ftpr=fileToPushRecipientList[i]; // ftpr->AddRef(); // break; RakAssert("setId already in use for this recipient" && 0); } } fileToPushRecipientListMutex.Unlock(); //if (ftpr==0) //{ ftpr = RakNet::OP_NEW<FileToPushRecipient>(_FILE_AND_LINE_); ftpr->systemAddress=recipient; ftpr->setId=setID; ftpr->refCount=2; // Allocated and in the list fileToPushRecipientList.Push(ftpr, _FILE_AND_LINE_); //} while (filesToPush.IsEmpty()==false) { ////ftpr->filesToPushMutex.Lock(); ftpr->filesToPush.Push(filesToPush.Pop(), _FILE_AND_LINE_); ////ftpr->filesToPushMutex.Unlock(); } // ftpr out of scope ftpr->Deref(); SendIRIToAddress(recipient, setID); return; } else { for (unsigned int flpcIndex=0; flpcIndex < fileListProgressCallbacks.Size(); flpcIndex++) fileListProgressCallbacks[flpcIndex]->OnFilePushesComplete(recipient, setID); } } else { for (unsigned int flpcIndex=0; flpcIndex < fileListProgressCallbacks.Size(); flpcIndex++) fileListProgressCallbacks[flpcIndex]->OnFilePushesComplete(recipient, setID); if (rakPeer) rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); else SendUnified(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false); } }