mirror of
https://github.com/dashr9230/SA-MP.git
synced 2024-12-22 14:37:29 +08:00
bcdbedc0be
* Add RakNet source files to the VS project
409 lines
11 KiB
C++
409 lines
11 KiB
C++
#include "FileListTransfer.h"
|
|
#include "DS_HuffmanEncodingTree.h"
|
|
#include "FileListTransferCBInterface.h"
|
|
#include "StringCompressor.h"
|
|
#include "FileList.h"
|
|
#include "DS_Queue.h"
|
|
#include "PacketEnumerations.h"
|
|
#include "NetworkTypes.h"
|
|
#include "RakPeerInterface.h"
|
|
#include <assert.h>
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma warning( push )
|
|
#endif
|
|
|
|
struct FileListTransfer::FileListReceiver
|
|
{
|
|
FileListTransferCBInterface *downloadHandler;
|
|
PlayerID allowedSender;
|
|
HuffmanEncodingTree tree;
|
|
unsigned short setID;
|
|
unsigned setCount;
|
|
unsigned setTotalCompressedTransmissionLength;
|
|
unsigned setTotalFinalLength;
|
|
bool gotSetHeader;
|
|
bool deleteDownloadHandler;
|
|
bool isCompressed;
|
|
};
|
|
|
|
FileListTransfer::FileListTransfer()
|
|
{
|
|
rakPeer=0;
|
|
setId=0;
|
|
DataStructures::Map<unsigned short, FileListReceiver*>::IMPLEMENT_DEFAULT_COMPARISON();
|
|
}
|
|
FileListTransfer::~FileListTransfer()
|
|
{
|
|
Clear();
|
|
}
|
|
unsigned short FileListTransfer::SetupReceive(FileListTransferCBInterface *handler, bool deleteHandler, PlayerID allowedSender)
|
|
{
|
|
if (rakPeer->GetIndexFromPlayerID(allowedSender)==-1)
|
|
return (unsigned short)-1;
|
|
FileListReceiver *receiver;
|
|
|
|
if (fileListReceivers.Has(setId))
|
|
{
|
|
receiver=fileListReceivers.Get(setId);
|
|
if (receiver->deleteDownloadHandler)
|
|
delete receiver->downloadHandler;
|
|
delete receiver;
|
|
fileListReceivers.Delete(setId);
|
|
}
|
|
|
|
unsigned short oldId;
|
|
receiver = new FileListReceiver;
|
|
receiver->downloadHandler=handler;
|
|
receiver->allowedSender=allowedSender;
|
|
receiver->gotSetHeader=false;
|
|
receiver->deleteDownloadHandler=deleteHandler;
|
|
fileListReceivers.Set(setId, receiver);
|
|
oldId=setId;
|
|
if (++setId==(unsigned short)-1)
|
|
setId=0;
|
|
return oldId;
|
|
}
|
|
|
|
void FileListTransfer::Send(FileList *fileList, RakPeerInterface *rakPeer, PlayerID recipient, unsigned short setID, PacketPriority priority, char orderingChannel, bool compressData)
|
|
{
|
|
RakNet::BitStream outBitstream, encodedData;
|
|
HuffmanEncodingTree tree;
|
|
unsigned int frequencyTable[ 256 ];
|
|
unsigned int i,j;
|
|
unsigned totalCompressedLength, totalLength;
|
|
DataStructures::Queue<FileListNode> compressedFiles;
|
|
FileListNode n;
|
|
|
|
if (compressData)
|
|
{
|
|
memset(frequencyTable,0,256*sizeof(unsigned int));
|
|
|
|
for (i=0; i < fileList->fileList.Size(); i++)
|
|
{
|
|
for (j=0; j < fileList->fileList[i].dataLength; j++)
|
|
{
|
|
++frequencyTable[(unsigned char)(fileList->fileList[i].data[j])];
|
|
}
|
|
}
|
|
|
|
tree.GenerateFromFrequencyTable(frequencyTable);
|
|
|
|
// Compress all the files, so we know the total compressed size to be sent
|
|
totalCompressedLength=totalLength=0;
|
|
for (i=0; i < fileList->fileList.Size(); i++)
|
|
{
|
|
encodedData.Reset();
|
|
// Why send compressed chunks if we are not sending the whole file?
|
|
assert(fileList->fileList[i].fileLength==fileList->fileList[i].fileLength);
|
|
tree.EncodeArray((unsigned char*)fileList->fileList[i].data, fileList->fileList[i].dataLength, &encodedData);
|
|
n.dataLength=encodedData.GetNumberOfBitsUsed();
|
|
totalCompressedLength+=BITS_TO_BYTES(n.dataLength);
|
|
totalLength+=fileList->fileList[i].fileLength;
|
|
n.data = new char[BITS_TO_BYTES(n.dataLength)];
|
|
memcpy(n.data, encodedData.GetData(), BITS_TO_BYTES(n.dataLength));
|
|
compressedFiles.Push(n);
|
|
}
|
|
}
|
|
|
|
// Write the chunk header, which contains the frequency table, the total number of files, and the total number of bytes
|
|
bool anythingToWrite;
|
|
outBitstream.Write((unsigned char)ID_FILE_LIST_TRANSFER_HEADER);
|
|
outBitstream.Write(setID);
|
|
anythingToWrite=fileList->fileList.Size()>0;
|
|
outBitstream.Write(anythingToWrite);
|
|
if (anythingToWrite)
|
|
{
|
|
if (compressData)
|
|
{
|
|
outBitstream.Write(true);
|
|
for (i=0; i < 256; i++)
|
|
outBitstream.WriteCompressed(frequencyTable[i]);
|
|
outBitstream.WriteCompressed(fileList->fileList.Size());
|
|
outBitstream.WriteCompressed(totalLength);
|
|
outBitstream.WriteCompressed(totalCompressedLength);
|
|
}
|
|
else
|
|
{
|
|
outBitstream.Write(false);
|
|
outBitstream.WriteCompressed(fileList->fileList.Size());
|
|
outBitstream.WriteCompressed(totalLength);
|
|
}
|
|
|
|
rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false);
|
|
|
|
// Send each possibly compressed file
|
|
for (i=0; i < compressedFiles.Size(); i++)
|
|
{
|
|
outBitstream.Reset();
|
|
outBitstream.Write((unsigned char)ID_FILE_LIST_TRANSFER_FILE);
|
|
outBitstream.Write(fileList->fileList[i].context);
|
|
outBitstream.Write(setID);
|
|
outBitstream.WriteCompressed(i);
|
|
outBitstream.WriteCompressed(fileList->fileList[i].dataLength); // Original length
|
|
if (compressData)
|
|
outBitstream.WriteCompressed(compressedFiles[i].dataLength); // Compressed bitlength }
|
|
stringCompressor->EncodeString(fileList->fileList[i].filename, 512, &outBitstream);
|
|
if (compressData)
|
|
{
|
|
outBitstream.WriteBits((const unsigned char*)compressedFiles[i].data, compressedFiles[i].dataLength);
|
|
delete [] compressedFiles[i].data;
|
|
}
|
|
else
|
|
outBitstream.WriteBits((const unsigned char*)fileList->fileList[i].data, fileList->fileList[i].dataLength);
|
|
|
|
rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false);
|
|
}
|
|
}
|
|
else
|
|
rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false);
|
|
}
|
|
|
|
bool FileListTransfer::DecodeSetHeader(Packet *packet)
|
|
{
|
|
unsigned i;
|
|
unsigned int frequencyTable[ 256 ];
|
|
bool anythingToWrite;
|
|
unsigned short setID;
|
|
RakNet::BitStream inBitStream(packet->data, packet->length, false);
|
|
inBitStream.IgnoreBits(8);
|
|
inBitStream.Read(setID);
|
|
FileListReceiver *fileListReceiver;
|
|
if (fileListReceivers.Has(setID)==false)
|
|
{
|
|
#ifdef _DEBUG
|
|
assert(0);
|
|
#endif
|
|
return false;
|
|
}
|
|
fileListReceiver=fileListReceivers.Get(setID);
|
|
if (fileListReceiver->allowedSender!=packet->playerId)
|
|
{
|
|
#ifdef _DEBUG
|
|
assert(0);
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
assert(fileListReceiver->gotSetHeader==false);
|
|
#endif
|
|
|
|
inBitStream.Read(anythingToWrite);
|
|
if (anythingToWrite)
|
|
{
|
|
inBitStream.Read(fileListReceiver->isCompressed);
|
|
if (fileListReceiver->isCompressed)
|
|
{
|
|
for (i=0; i < 256; i++)
|
|
inBitStream.ReadCompressed(frequencyTable[i]);
|
|
fileListReceiver->tree.GenerateFromFrequencyTable(frequencyTable);
|
|
inBitStream.ReadCompressed(fileListReceiver->setCount);
|
|
inBitStream.ReadCompressed(fileListReceiver->setTotalFinalLength);
|
|
if (inBitStream.ReadCompressed(fileListReceiver->setTotalCompressedTransmissionLength))
|
|
{
|
|
fileListReceiver->gotSetHeader=true;
|
|
return true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
inBitStream.ReadCompressed(fileListReceiver->setCount);
|
|
inBitStream.ReadCompressed(fileListReceiver->setTotalFinalLength);
|
|
fileListReceiver->setTotalCompressedTransmissionLength=fileListReceiver->setTotalFinalLength;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fileListReceiver->downloadHandler->OnFile(0, 0, 0, 0, 0, setID, 0, 0, 0, 0);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool FileListTransfer::DecodeFile(Packet *packet, bool fullFile)
|
|
{
|
|
unsigned char *decompressedFileData;
|
|
char fileName[512];
|
|
unsigned char context;
|
|
unsigned fileIndex, fileLength, compressedLength;
|
|
unsigned bitLength;
|
|
unsigned len;
|
|
unsigned short setID;
|
|
RakNet::BitStream inBitStream(packet->data, packet->length, false);
|
|
inBitStream.IgnoreBits(8);
|
|
|
|
unsigned int partCount;
|
|
unsigned int partTotal;
|
|
unsigned int partLength;
|
|
if (fullFile==false)
|
|
{
|
|
inBitStream.Read(partCount);
|
|
inBitStream.Read(partTotal);
|
|
inBitStream.Read(partLength);
|
|
inBitStream.IgnoreBits(8);
|
|
}
|
|
inBitStream.Read(context);
|
|
inBitStream.Read(setID);
|
|
FileListReceiver *fileListReceiver;
|
|
if (fileListReceivers.Has(setID)==false)
|
|
{
|
|
#ifdef _DEBUG
|
|
assert(0);
|
|
#endif
|
|
return false;
|
|
}
|
|
fileListReceiver=fileListReceivers.Get(setID);
|
|
if (fileListReceiver->allowedSender!=packet->playerId)
|
|
{
|
|
#ifdef _DEBUG
|
|
assert(0);
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
assert(fileListReceiver->gotSetHeader==true);
|
|
#endif
|
|
|
|
inBitStream.ReadCompressed(fileIndex);
|
|
inBitStream.ReadCompressed(fileLength);
|
|
if (fileListReceiver->isCompressed)
|
|
{
|
|
inBitStream.ReadCompressed(bitLength);
|
|
compressedLength=BITS_TO_BYTES(bitLength);
|
|
}
|
|
|
|
if (stringCompressor->DecodeString(fileName, 512, &inBitStream)==false)
|
|
{
|
|
#ifdef _DEBUG
|
|
assert(0);
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
if (fullFile)
|
|
{
|
|
decompressedFileData = new unsigned char [fileLength];
|
|
|
|
if (fileListReceiver->isCompressed)
|
|
{
|
|
len=fileListReceiver->tree.DecodeArray(&inBitStream, bitLength, fileLength, decompressedFileData);
|
|
if (len!=fileLength)
|
|
{
|
|
#ifdef _DEBUG
|
|
assert(0);
|
|
#endif
|
|
delete [] decompressedFileData;
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
inBitStream.Read((char*)decompressedFileData, fileLength);
|
|
}
|
|
|
|
|
|
// User callback for this file.
|
|
if (fullFile)
|
|
{
|
|
fileListReceiver->downloadHandler->OnFile(fileIndex, fileName, (char*)decompressedFileData, compressedLength, fileLength, setID, fileListReceiver->setCount, fileListReceiver->setTotalCompressedTransmissionLength, fileListReceiver->setTotalFinalLength, context);
|
|
delete [] decompressedFileData;
|
|
|
|
// If this set is done, free the memory for it.
|
|
if (fileListReceiver->setCount==fileIndex+1)
|
|
{
|
|
if (fileListReceiver->deleteDownloadHandler)
|
|
delete fileListReceiver->downloadHandler;
|
|
delete fileListReceiver;
|
|
fileListReceivers.Delete(setID);
|
|
}
|
|
|
|
}
|
|
else
|
|
fileListReceiver->downloadHandler->OnFileProgress(fileIndex, fileName, compressedLength, fileLength, setID, fileListReceiver->setCount, fileListReceiver->setTotalCompressedTransmissionLength, fileListReceiver->setTotalFinalLength, context, partCount, partTotal, partLength);
|
|
|
|
return true;
|
|
}
|
|
#ifdef _MSC_VER
|
|
#pragma warning( disable : 4100 ) // warning C4100: <variable name> : unreferenced formal parameter
|
|
#endif
|
|
PluginReceiveResult FileListTransfer::OnReceive(RakPeerInterface *peer, Packet *packet)
|
|
{
|
|
switch (packet->data[0])
|
|
{
|
|
case ID_CONNECTION_LOST:
|
|
case ID_DISCONNECTION_NOTIFICATION:
|
|
RemoveReceiver(packet->playerId);
|
|
break;
|
|
case ID_FILE_LIST_TRANSFER_HEADER:
|
|
DecodeSetHeader(packet);
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
case ID_FILE_LIST_TRANSFER_FILE:
|
|
DecodeFile(packet, true);
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
case ID_DOWNLOAD_PROGRESS:
|
|
if (packet->length>sizeof(MessageID)+sizeof(unsigned int)*3 &&
|
|
packet->data[sizeof(MessageID)+sizeof(unsigned int)*3]==ID_FILE_LIST_TRANSFER_FILE)
|
|
{
|
|
DecodeFile(packet, false);
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return RR_CONTINUE_PROCESSING;
|
|
}
|
|
#ifdef _MSC_VER
|
|
#pragma warning( disable : 4100 ) // warning C4100: <variable name> : unreferenced formal parameter
|
|
#endif
|
|
void FileListTransfer::OnDisconnect(RakPeerInterface *peer)
|
|
{
|
|
Clear();
|
|
}
|
|
void FileListTransfer::Clear(void)
|
|
{
|
|
unsigned i;
|
|
for (i=0; i < fileListReceivers.Size(); i++)
|
|
{
|
|
if (fileListReceivers[i]->deleteDownloadHandler)
|
|
delete fileListReceivers[i]->downloadHandler;
|
|
delete fileListReceivers[i];
|
|
}
|
|
fileListReceivers.Clear();
|
|
}
|
|
#ifdef _MSC_VER
|
|
#pragma warning( disable : 4100 ) // warning C4100: <variable name> : unreferenced formal parameter
|
|
#endif
|
|
void FileListTransfer::OnCloseConnection(RakPeerInterface *peer, PlayerID playerId)
|
|
{
|
|
RemoveReceiver(playerId);
|
|
}
|
|
|
|
void FileListTransfer::RemoveReceiver(PlayerID playerId)
|
|
{
|
|
unsigned i;
|
|
i=0;
|
|
while (i < fileListReceivers.Size())
|
|
{
|
|
if (fileListReceivers[i]->allowedSender==playerId)
|
|
{
|
|
if (fileListReceivers[i]->deleteDownloadHandler)
|
|
delete fileListReceivers[i]->downloadHandler;
|
|
delete fileListReceivers[i];
|
|
fileListReceivers.RemoveAtIndex(i);
|
|
}
|
|
else
|
|
i++;
|
|
}
|
|
}
|
|
void FileListTransfer::OnAttach(RakPeerInterface *peer)
|
|
{
|
|
rakPeer=peer;
|
|
|
|
}
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma warning( pop )
|
|
#endif
|