diff --git a/Source/include/slikenet/ReliabilityLayer.h b/Source/include/slikenet/ReliabilityLayer.h index 08ffa2bfa..de37f34b4 100644 --- a/Source/include/slikenet/ReliabilityLayer.h +++ b/Source/include/slikenet/ReliabilityLayer.h @@ -60,6 +60,81 @@ namespace SLNet { +class SplitPacketSort +{ +private: + InternalPacket ** data; + unsigned int allocation_size; + unsigned int addedPacketsCount; + SplitPacketIdType packetId; + +public: + SplitPacketSort() + { + data = NULL; + allocation_size = 0; + addedPacketsCount = 0; + } + ~SplitPacketSort() + { + if(allocation_size) + OP_DELETE_ARRAY(data, _FILE_AND_LINE_); + } + + void Preallocate(InternalPacket * internalPacket, const char *file, unsigned int line) + { + RakAssert(data == NULL); + allocation_size = internalPacket->splitPacketCount; + data = OP_NEW_ARRAY(allocation_size, file, line); + packetId = internalPacket->splitPacketId; + + for(unsigned int i = 0; i < allocation_size; ++i) + data[i] = NULL; + } + + bool Add(InternalPacket * internalPacket, const char *file, unsigned int line) + { + RakAssert(data != NULL); + RakAssert(internalPacket->splitPacketIndex < allocation_size); + RakAssert(packetId == internalPacket->splitPacketId); + RakAssert(data[internalPacket->splitPacketIndex] == NULL); + + (void)file; + (void)line; + + if(data[internalPacket->splitPacketIndex] == NULL) + { + data[internalPacket->splitPacketIndex] = internalPacket; + ++addedPacketsCount; + return true; + } + return false; + } + + unsigned int AllocSize() const + { + return allocation_size; + } + + unsigned int AddedPacketsCount() const + { + return addedPacketsCount; + } + + InternalPacket *& operator[](unsigned int index) + { + RakAssert(data != NULL); + RakAssert(index < allocation_size); + return data[index]; + } + + SplitPacketIdType PacketId() const + { + RakAssert(data != NULL); + return packetId; + } +}; + /// Forward declarations class PluginInterface2; class RakNetRandom; @@ -70,7 +145,7 @@ struct SplitPacketChannel// { CCTimeType lastUpdateTime; - DataStructures::List splitPacketList; + SplitPacketSort splitPacketList; #if PREALLOCATE_LARGE_MESSAGES==1 InternalPacket *returnedPacket; diff --git a/Source/slikenet/VitaIncludes.h b/Source/slikenet/VitaIncludes.h index 6f3f570aa..14c6083d3 100644 --- a/Source/slikenet/VitaIncludes.h +++ b/Source/slikenet/VitaIncludes.h @@ -8,4 +8,4 @@ * Header file redirection to keep source compatibility with RakNet 4.082. */ -#include "../include/slikenet/VistaIncludes.h" +#include "../include/slikenet/VitaIncludes.h" diff --git a/Source/src/ReliabilityLayer.cpp b/Source/src/ReliabilityLayer.cpp index 7e8096856..2e6e418c1 100644 --- a/Source/src/ReliabilityLayer.cpp +++ b/Source/src/ReliabilityLayer.cpp @@ -251,9 +251,9 @@ int SLNet::SplitPacketChannelComp( SplitPacketIdType const &key, SplitPacketChan if (key == data->returnedPacket->splitPacketId) return 0; #else - if (key < data->splitPacketList[0]->splitPacketId) + if (key < data->splitPacketList.PacketId()) return -1; - if (key == data->splitPacketList[0]->splitPacketId) + if (key == data->splitPacketList.PacketId()) return 0; #endif return 1; @@ -473,10 +473,14 @@ void ReliabilityLayer::FreeThreadSafeMemory( void ) for (i=0; i < splitPacketChannelList.Size(); i++) { - for (j=0; j < splitPacketChannelList[i]->splitPacketList.Size(); j++) + for (j=0; j < splitPacketChannelList[i]->splitPacketList.AllocSize(); j++) { - FreeInternalPacketData(splitPacketChannelList[i]->splitPacketList[j], _FILE_AND_LINE_ ); - ReleaseToInternalPacketPool( splitPacketChannelList[i]->splitPacketList[j] ); + internalPacket = splitPacketChannelList[i]->splitPacketList[j]; + if(internalPacket != NULL) + { + FreeInternalPacketData(splitPacketChannelList[i]->splitPacketList[j], _FILE_AND_LINE_); + ReleaseToInternalPacketPool(splitPacketChannelList[i]->splitPacketList[j]); + } } #if PREALLOCATE_LARGE_MESSAGES==1 if (splitPacketChannelList[i]->returnedPacket) @@ -3071,7 +3075,7 @@ void ReliabilityLayer::InsertIntoSplitPacketList( InternalPacket * internalPacke newChannel->firstPacket=0; index=splitPacketChannelList.Insert(internalPacket->splitPacketId, newChannel, true, __FILE__,__LINE__); // Preallocate to the final size, to avoid runtime copies - newChannel->splitPacketList.Preallocate(internalPacket->splitPacketCount, __FILE__,__LINE__); + newChannel->splitPacketList.Preallocate(internalPacket, __FILE__,__LINE__); #endif } @@ -3154,7 +3158,12 @@ void ReliabilityLayer::InsertIntoSplitPacketList( InternalPacket * internalPacke } #else // Insert the packet into the SplitPacketChannel - splitPacketChannelList[index]->splitPacketList.Insert(internalPacket, __FILE__, __LINE__ ); + if(!splitPacketChannelList[index]->splitPacketList.Add(internalPacket, __FILE__, __LINE__)) + { + FreeInternalPacketData(internalPacket, _FILE_AND_LINE_); + ReleaseToInternalPacketPool(internalPacket); + return; + } splitPacketChannelList[index]->lastUpdateTime=time; // If the index is 0, then this is the first packet. Record this so it can be returned to the user with download progress @@ -3164,8 +3173,8 @@ void ReliabilityLayer::InsertIntoSplitPacketList( InternalPacket * internalPacke // Return download progress if we have the first packet, the list is not complete, and there are enough packets to justify it if (splitMessageProgressInterval && splitPacketChannelList[index]->firstPacket && - splitPacketChannelList[index]->splitPacketList.Size()!=splitPacketChannelList[index]->firstPacket->splitPacketCount && - (splitPacketChannelList[index]->splitPacketList.Size()%splitMessageProgressInterval)==0) + splitPacketChannelList[index]->splitPacketList.AddedPacketsCount()!=splitPacketChannelList[index]->firstPacket->splitPacketCount && + (splitPacketChannelList[index]->splitPacketList.AddedPacketsCount()%splitMessageProgressInterval)==0) { // Return ID_DOWNLOAD_PROGRESS // Write splitPacketIndex (SplitPacketIndexType) @@ -3178,7 +3187,7 @@ void ReliabilityLayer::InsertIntoSplitPacketList( InternalPacket * internalPacke progressIndicator->dataBitLength=BYTES_TO_BITS(length); progressIndicator->data[0]=(MessageID)ID_DOWNLOAD_PROGRESS; unsigned int temp; - temp=splitPacketChannelList[index]->splitPacketList.Size(); + temp=splitPacketChannelList[index]->splitPacketList.AddedPacketsCount(); memcpy(progressIndicator->data+sizeof(MessageID), &temp, sizeof(unsigned int)); temp=(unsigned int)internalPacket->splitPacketCount; memcpy(progressIndicator->data+sizeof(MessageID)+sizeof(unsigned int)*1, &temp, sizeof(unsigned int)); @@ -3212,7 +3221,7 @@ InternalPacket * ReliabilityLayer::BuildPacketFromSplitPacketList( SplitPacketCh // Reconstruct internalPacket = CreateInternalPacketCopy( splitPacketChannel->splitPacketList[0], 0, 0, time ); internalPacket->dataBitLength=0; - for (j=0; j < splitPacketChannel->splitPacketList.Size(); j++) + for (j=0; j < splitPacketChannel->splitPacketList.AllocSize(); j++) internalPacket->dataBitLength+=splitPacketChannel->splitPacketList[j]->dataBitLength; // splitPacketPartLength=BITS_TO_BYTES(splitPacketChannel->firstPacket->dataBitLength); @@ -3220,14 +3229,14 @@ InternalPacket * ReliabilityLayer::BuildPacketFromSplitPacketList( SplitPacketCh internalPacket->allocationScheme=InternalPacket::NORMAL; BitSize_t offset = 0; - for (j=0; j < splitPacketChannel->splitPacketList.Size(); j++) + for (j=0; j < splitPacketChannel->splitPacketList.AllocSize(); j++) { - splitPacket=splitPacketChannel->splitPacketList[j]; - memcpy(internalPacket->data + BITS_TO_BYTES(offset), splitPacket->data, (size_t)BITS_TO_BYTES(splitPacketChannel->splitPacketList[j]->dataBitLength)); - offset += splitPacketChannel->splitPacketList[j]->dataBitLength; + splitPacket = splitPacketChannel->splitPacketList[j]; + memcpy(internalPacket->data + BITS_TO_BYTES(offset), splitPacket->data, (size_t)BITS_TO_BYTES(splitPacket->dataBitLength)); + offset += splitPacket->dataBitLength; } - for (j=0; j < splitPacketChannel->splitPacketList.Size(); j++) + for (j=0; j < splitPacketChannel->splitPacketList.AllocSize(); j++) { FreeInternalPacketData(splitPacketChannel->splitPacketList[j], _FILE_AND_LINE_ ); ReleaseToInternalPacketPool(splitPacketChannel->splitPacketList[j]); @@ -3254,7 +3263,7 @@ InternalPacket * ReliabilityLayer::BuildPacketFromSplitPacketList( SplitPacketId #if PREALLOCATE_LARGE_MESSAGES==1 if (splitPacketChannel->splitPacketsArrived==splitPacketChannel->returnedPacket->splitPacketCount) #else - if (splitPacketChannel->splitPacketList.Size()==splitPacketChannel->splitPacketList[0]->splitPacketCount) + if (splitPacketChannel->splitPacketList.AllocSize()==splitPacketChannel->splitPacketList.AddedPacketsCount()) #endif { // Ack immediately, because for large files this can take a long time