Skip to content

Commit

Permalink
Fixed sorting on splitted packages...
Browse files Browse the repository at this point in the history
  • Loading branch information
JoergBoehnel committed Jun 11, 2015
1 parent 1a16989 commit c15dd90
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 22 deletions.
56 changes: 35 additions & 21 deletions Source/ReliabilityLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,9 +252,9 @@ int RakNet::SplitPacketChannelComp( SplitPacketIdType const &key, SplitPacketCha
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;
Expand Down Expand Up @@ -298,6 +298,8 @@ return 0;
return 1;
}



//-------------------------------------------------------------------------------------------------------
// Constructor
//-------------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -474,10 +476,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.Get(j);
if (internalPacket != NULL)
{
FreeInternalPacketData(splitPacketChannelList[i]->splitPacketList.Get(j), _FILE_AND_LINE_);
ReleaseToInternalPacketPool(splitPacketChannelList[i]->splitPacketList.Get(j));
}
}
#if PREALLOCATE_LARGE_MESSAGES==1
if (splitPacketChannelList[i]->returnedPacket)
Expand Down Expand Up @@ -2241,6 +2247,7 @@ void ReliabilityLayer::Update( RakNetSocket2 *s, SystemAddress &systemAddress, i
//DeleteOldUnreliableSplitPackets( time );
}


//-------------------------------------------------------------------------------------------------------
// Writes a bitstream to the socket
//-------------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -3055,7 +3062,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
}
Expand Down Expand Up @@ -3138,7 +3145,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
Expand All @@ -3148,8 +3160,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)
Expand All @@ -3162,7 +3174,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));
Expand Down Expand Up @@ -3194,33 +3206,35 @@ InternalPacket * ReliabilityLayer::BuildPacketFromSplitPacketList( SplitPacketCh
// int splitPacketPartLength;

// Reconstruct
internalPacket = CreateInternalPacketCopy( splitPacketChannel->splitPacketList[0], 0, 0, time );
internalPacket = CreateInternalPacketCopy( splitPacketChannel->splitPacketList.Get(0), 0, 0, time );
internalPacket->dataBitLength=0;
for (j=0; j < splitPacketChannel->splitPacketList.Size(); j++)
internalPacket->dataBitLength+=splitPacketChannel->splitPacketList[j]->dataBitLength;
for (j=0; j < splitPacketChannel->splitPacketList.AllocSize(); j++)
internalPacket->dataBitLength+=splitPacketChannel->splitPacketList.Get(j)->dataBitLength;
// splitPacketPartLength=BITS_TO_BYTES(splitPacketChannel->firstPacket->dataBitLength);

internalPacket->data = (unsigned char*) rakMalloc_Ex( (size_t) BITS_TO_BYTES( internalPacket->dataBitLength ), _FILE_AND_LINE_ );
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.Get(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]);
FreeInternalPacketData(splitPacketChannel->splitPacketList.Get(j), _FILE_AND_LINE_ );
ReleaseToInternalPacketPool(splitPacketChannel->splitPacketList.Get(j));
}
RakNet::OP_DELETE(splitPacketChannel, __FILE__, __LINE__);

return internalPacket;
#endif
}


//-------------------------------------------------------------------------------------------------------
InternalPacket * ReliabilityLayer::BuildPacketFromSplitPacketList( SplitPacketIdType splitPacketId, CCTimeType time,
RakNetSocket2 *s, SystemAddress &systemAddress, RakNetRandom *rnr,
Expand All @@ -3238,7 +3252,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
Expand Down
76 changes: 75 additions & 1 deletion Source/ReliabilityLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,86 @@ class PluginInterface2;
class RakNetRandom;
typedef uint64_t reliabilityHeapWeightType;



class SortedSplittedPackets
{
private:
InternalPacket ** data;
unsigned int allocation_size;
unsigned int addedPacketsCount;
SplitPacketIdType packetId;

public:
SortedSplittedPackets()
{
data = NULL;
allocation_size = 0;
addedPacketsCount = 0;
}
~SortedSplittedPackets()
{
if (allocation_size > 0)
{
RakNet::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 = RakNet::OP_NEW_ARRAY<InternalPacket*>(allocation_size, file, line);
packetId = internalPacket->splitPacketId;

for (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);
if (data[internalPacket->splitPacketIndex] == NULL)
{
data[internalPacket->splitPacketIndex] = internalPacket;
++addedPacketsCount;
return true;
}
return false;
}

unsigned int AllocSize()
{
return allocation_size;
}
unsigned int AddedPacketsCount()
{
return addedPacketsCount;
}
InternalPacket * Get(unsigned int index)
{
RakAssert(data != NULL);
RakAssert(index < allocation_size);
return data[index];
}
SplitPacketIdType PacketId()
{
RakAssert(data != NULL);
return packetId;
}
};


// int SplitPacketIndexComp( SplitPacketIndexType const &key, InternalPacket* const &data );
struct SplitPacketChannel//<SplitPacketChannel>
{
CCTimeType lastUpdateTime;

DataStructures::List<InternalPacket*> splitPacketList;
SortedSplittedPackets splitPacketList;

#if PREALLOCATE_LARGE_MESSAGES==1
InternalPacket *returnedPacket;
Expand Down

3 comments on commit c15dd90

@Luke1410
Copy link

@Luke1410 Luke1410 commented on c15dd90 Mar 18, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've been made aware of this commit of yours by a user of our RakNet fork who created a pull request which is largely based on your commit (SLikeSoft#30). We understand that you contribute this commit under the RakNet license terms and believe this allows us to incorporate your pull request in our fork as well.
If you object to this opinion, please let us know (preferably by sending a mail to info @ slikesoft . com).

If you are fine with us having incorporated your contribution in SLikeNet, we'd like to offer you being namely added to the acknowledgment section in the accompanying readme. Please let us know if you'd like such an entry being added for you. The standard format of such entries would be:
[real name|GitHubAccount name]: [link to git hub profile page] (pull request: [list of related pull requests])

@JoergBoehnel
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello Luke,

please be aware that my changes probably only work with "PREALLOCATE_LARGE_MESSAGES == 0" as I have not changed or tested the "#if PREALLOCATE_LARGE_MESSAGES==1" code paths. So I'd advice you to test and fix that case as well.

Feel free to use my changes as you wish as long as it's in compliance with the RakNet license. There's no need to mention me.

Best wishes
Joerg Boehnel

@Luke1410
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the pointer. I've added a note on this for the review process of the patch.

Please sign in to comment.