unsigned DataCompressor::DecompressAndAllocate( RakNet::BitStream * input, unsigned char **output ) { HuffmanEncodingTree tree; unsigned int bitsUsed, destinationSizeInBytes, decompressedBytes; unsigned int frequencyTable[ 256 ]; unsigned i; input->ReadCompressed(destinationSizeInBytes); for (i=0; i < 256; i++) input->ReadCompressed(frequencyTable[i]); input->AlignReadToByteBoundary(); if (input->Read(bitsUsed)==false) { // Read error #ifdef _DEBUG RakAssert(0); #endif return 0; } *output = (unsigned char*) rakMalloc_Ex(destinationSizeInBytes, __FILE__, __LINE__); tree.GenerateFromFrequencyTable(frequencyTable); decompressedBytes=tree.DecodeArray(input, bitsUsed, destinationSizeInBytes, *output ); RakAssert(decompressedBytes==destinationSizeInBytes); return destinationSizeInBytes; }
bool SystemAddressList::Load(const char *filename) { FILE *fp = NULL; unsigned long fileSize; if ( ( fp = fopen( filename, "rb" ) ) == 0 ) return false; fseek( fp, 0, SEEK_END ); fileSize = ftell( fp ); fseek( fp, 0, SEEK_SET ); if (fileSize==0) { fclose(fp); return false; } unsigned char *filedata = (unsigned char*) rakMalloc_Ex( fileSize, __FILE__, __LINE__ ); fread(filedata, fileSize, 1, fp); fclose(fp); RakNet::BitStream bs(filedata, fileSize, false); Deserialize(&bs); rakFree_Ex(filedata, __FILE__, __LINE__ ); return true; }
void FileList::AddFile(const char *filepath, const char *filename, FileListNodeContext context) { if (filepath == 0 || filename == 0) return; char *data; //std::fstream file; //file.open(filename, std::ios::in | std::ios::binary); FILE *fp = fopen(filepath, "rb"); if (fp == 0) return; fseek(fp, 0, SEEK_END); int length = ftell(fp); fseek(fp, 0, SEEK_SET); if (length > (int)((unsigned int) - 1 / 8)) { // If this assert hits, split up your file. You could also change BitSize_t in RakNetTypes.h to unsigned long long but this is not recommended for performance reasons RakAssert("Cannot add files over 536 MB" && 0); fclose(fp); return; } bool usedAlloca = false; if (length < MAX_ALLOCA_STACK_ALLOCATION) { data = (char*) alloca(length); usedAlloca = true; } else data = (char*) rakMalloc_Ex(length, __FILE__, __LINE__); fread(data, 1, length, fp); AddFile(filename, filepath, data, length, length, context); fclose(fp); if (usedAlloca == false) rakFree_Ex(data, __FILE__, __LINE__); }
void ThreadsafePacketLogger::AddToLog(const char *str) { char **msg = logMessages.WriteLock(); *msg = (char*) rakMalloc_Ex( strlen(str)+1, __FILE__, __LINE__ ); strcpy(*msg, str); logMessages.WriteUnlock(); }
void FileListTransfer::PushReference(SystemAddress systemAddress) { // Was previously using GetStatistics to get outgoing buffer size, but TCP with UnifiedSend doesn't have this unsigned int i=0; unsigned int bytesRead; char *dataBlocks[2]; int lengths[2]; RakNet::BitStream outBitstream; while (i < filesToPush.Size()) { if (filesToPush[i].systemAddress==systemAddress) { outBitstream.Reset(); outBitstream.Write((MessageID)ID_FILE_LIST_REFERENCE_PUSH); outBitstream.Write(filesToPush[i].fileListNode.context); outBitstream.Write(filesToPush[i].setID); stringCompressor->EncodeString(filesToPush[i].fileListNode.filename, 512, &outBitstream); outBitstream.WriteCompressed(filesToPush[i].setIndex); outBitstream.WriteCompressed(filesToPush[i].fileListNode.dataLengthBytes); // Original length in bytes // Read and send chunk. If done, delete at this index void *buff = rakMalloc_Ex(filesToPush[i].chunkSize, __FILE__, __LINE__); if (buff==0) { notifyOutOfMemory(__FILE__, __LINE__); continue; } bytesRead=filesToPush[i].incrementalReadInterface->GetFilePart(filesToPush[i].fileListNode.fullPathToFile, filesToPush[i].currentOffset, filesToPush[i].chunkSize, buff, filesToPush[i].fileListNode.context); outBitstream.WriteCompressed(filesToPush[i].currentOffset); filesToPush[i].currentOffset+=bytesRead; outBitstream.WriteCompressed(bytesRead); bool done = bytesRead!=filesToPush[i].chunkSize; outBitstream.Write(done); if (callback) { callback->OnFilePush(filesToPush[i].fileListNode.filename, filesToPush[i].fileListNode.fileLengthBytes, filesToPush[i].currentOffset-bytesRead, bytesRead, done, filesToPush[i].systemAddress); } dataBlocks[0]=(char*) outBitstream.GetData(); lengths[0]=outBitstream.GetNumberOfBytesUsed(); dataBlocks[1]=(char*) buff; lengths[1]=bytesRead; //rakPeerInterface->SendList(dataBlocks,lengths,2,filesToPush[i].packetPriority, RELIABLE_ORDERED, filesToPush[i].orderingChannel, filesToPush[i].systemAddress, false); SendListUnified(dataBlocks,lengths,2,filesToPush[i].packetPriority, RELIABLE_ORDERED, filesToPush[i].orderingChannel, filesToPush[i].systemAddress, false); if (done) { // Done RakNet::OP_DELETE_ARRAY(filesToPush[i].fileListNode.filename, __FILE__, __LINE__); filesToPush.RemoveAtIndex(i); } rakFree_Ex(buff, __FILE__, __LINE__ ); return; } else i++; } }
bool FileList::Deserialize(RakNet::BitStream *inBitStream) { bool b, dataLenNonZero = false, fileLenMatchesDataLen = false; char filename[512]; unsigned int fileListSize; FileListNode n; b = inBitStream->ReadCompressed(fileListSize); #ifdef _DEBUG RakAssert(b); RakAssert(fileListSize < 10000); #endif if (b == false || fileListSize > 10000) return false; // Sanity check Clear(); unsigned i; for (i = 0; i < fileListSize; i++) { inBitStream->ReadCompressed(n.context.op); inBitStream->ReadCompressed(n.context.fileId); stringCompressor->DecodeString((char*)filename, MAX_FILENAME_LENGTH, inBitStream); inBitStream->Read(dataLenNonZero); if (dataLenNonZero) { inBitStream->ReadCompressed(n.dataLengthBytes); // sanity check if (n.dataLengthBytes > 2000000000) { #ifdef _DEBUG RakAssert(n.dataLengthBytes <= 2000000000); #endif return false; } n.data = (char*) rakMalloc_Ex((size_t) n.dataLengthBytes, __FILE__, __LINE__); inBitStream->Read(n.data, n.dataLengthBytes); } else { n.dataLengthBytes = 0; n.data = 0; } b = inBitStream->Read(fileLenMatchesDataLen); if (fileLenMatchesDataLen) n.fileLengthBytes = (unsigned) n.dataLengthBytes; else b = inBitStream->ReadCompressed(n.fileLengthBytes); #ifdef _DEBUG RakAssert(b); #endif if (b == 0) { Clear(); return false; } n.filename = filename; n.fullPathToFile = filename; fileList.Insert(n, __FILE__, __LINE__); } return true; }
RakNet::RakString PostgreSQLInterface::GetEscapedString(const char *input) const { unsigned long len = (unsigned long) strlen(input); char *fn = (char*) rakMalloc_Ex(len*2+1,_FILE_AND_LINE_); int error; PQescapeStringConn(pgConn, fn, input, len, &error); RakNet::RakString output; // Use assignment so it doesn't parse printf escape strings output = fn; rakFree_Ex(fn,_FILE_AND_LINE_); return output; }
Packet* TCPInterface::AllocatePacket(unsigned dataSize) { Packet*p = RakNet::OP_NEW<Packet>(__FILE__,__LINE__); p->data=(unsigned char*) rakMalloc_Ex(dataSize,__FILE__,__LINE__); p->length=dataSize; p->bitSize=BYTES_TO_BITS(dataSize); p->deleteData=false; p->guid=UNASSIGNED_RAKNET_GUID; p->systemAddress=UNASSIGNED_SYSTEM_ADDRESS; p->systemAddress.systemIndex=(SystemIndex)-1; return p; }
void MessageFilter::SetAllowRPC(bool allow, const char *functionName, int filterSetID) { (void) allow; FilterSet *filterSet = GetFilterSetByID(filterSetID); bool objectExists; unsigned index = filterSet->allowedRPCs.GetIndexFromKey((char *const) functionName, &objectExists); if (objectExists == false) { char *str = (char*) rakMalloc_Ex(strlen(functionName) + 1, __FILE__, __LINE__); strcpy(str, functionName); filterSet->allowedRPCs.InsertAtIndex(str, index, __FILE__, __LINE__); } }
void TelnetTransport::SetSendPrefix(const char *prefix) { if (sendPrefix) { rakFree_Ex(sendPrefix, __FILE__, __LINE__ ); sendPrefix=0; } if (prefix) { sendPrefix = (char*) rakMalloc_Ex(strlen(prefix)+1, __FILE__, __LINE__); strcpy(sendPrefix, prefix); } }
void ConsoleServer::SetPrompt(const char *_prompt) { if (prompt) rakFree_Ex(prompt,__FILE__,__LINE__); if (_prompt && _prompt[0]) { size_t len = strlen(_prompt); prompt = (char*) rakMalloc_Ex(len+1,__FILE__,__LINE__); strcpy(prompt,_prompt); } else prompt=0; }
void FileList::AddFile(const char *filename, const char *fullPathToFile, const char *data, const unsigned dataLength, const unsigned fileLength, FileListNodeContext context, bool isAReference) { if (filename==0) return; if (strlen(filename)>MAX_FILENAME_LENGTH) { // Should be enough for anyone RakAssert(0); return; } // If adding a reference, do not send data RakAssert(isAReference==false || data==0); // Avoid duplicate insertions unless the data is different, in which case overwrite the old data unsigned i; for (i=0; i<fileList.Size();i++) { if (strcmp(fileList[i].filename, filename)==0) { if (fileList[i].fileLengthBytes==fileLength && fileList[i].dataLengthBytes==dataLength && (dataLength==0 || fileList[i].data==0 || memcmp(fileList[i].data, data, dataLength)==0 )) // Exact same file already here return; // File of the same name, but different contents, so overwrite rakFree_Ex(fileList[i].data, __FILE__, __LINE__ ); fileList.RemoveAtIndex(i); break; } } FileListNode n; // size_t fileNameLen = strlen(filename); if (dataLength && data) { n.data=(char*) rakMalloc_Ex( dataLength, __FILE__, __LINE__ ); memcpy(n.data, data, dataLength); } else n.data=0; n.dataLengthBytes=dataLength; n.fileLengthBytes=fileLength; n.isAReference=isAReference; n.context=context; n.filename=filename; n.fullPathToFile=fullPathToFile; fileList.Insert(n, __FILE__, __LINE__); }
void RakVoice::Init(unsigned short sampleRate, unsigned bufferSizeBytes) { // Record the parameters RakAssert(sampleRate==8000 || sampleRate==16000 || sampleRate==32000); this->sampleRate=sampleRate; this->bufferSizeBytes=bufferSizeBytes; bufferedOutputCount=bufferSizeBytes/SAMPLESIZE; bufferedOutput = (float*) rakMalloc_Ex(sizeof(float)*bufferedOutputCount, __FILE__, __LINE__); unsigned i; for (i=0; i < bufferedOutputCount; i++) bufferedOutput[i]=0.0f; zeroBufferedOutput=false; }
void FullyConnectedMesh::Startup(const char *password, int _passwordLength) { if (pw) rakFree_Ex(pw, __FILE__, __LINE__ ); if (password) { pw = (char*) rakMalloc_Ex( _passwordLength, __FILE__, __LINE__ ); memcpy(pw, password, _passwordLength); passwordLength=_passwordLength; } else pw=0; }
void ConnectionGraph::SetPassword(const char *password) { if (pw) { RakNet::OP_DELETE_ARRAY(pw, __FILE__, __LINE__); pw=0; } if (password && password[0]) { RakAssert(strlen(password)<256); pw=(char*) rakMalloc_Ex( strlen(password)+1, __FILE__, __LINE__ ); strcpy(pw, password); } }
PluginReceiveResult RakNetTransport2::OnReceive(Packet *packet) { switch (packet->data[0]) { case ID_TRANSPORT_STRING: { if (packet->length==sizeof(MessageID)) return RR_STOP_PROCESSING_AND_DEALLOCATE; Packet *p = RakNet::OP_NEW<Packet>(__FILE__,__LINE__); *p=*packet; p->bitSize-=8; p->length--; p->data=(unsigned char*) rakMalloc_Ex(p->length,__FILE__,__LINE__); memcpy(p->data, packet->data+1, p->length); packetQueue.Push(p, __FILE__, __LINE__ ); } return RR_STOP_PROCESSING_AND_DEALLOCATE; } return RR_CONTINUE_PROCESSING; }
bool PostgreSQLInterface::PQGetValueFromBinary(char **output, int *outputLength, PGresult *result, int rowIndex, const char *columnName) { int columnIndex = PQfnumber(result, columnName); if (columnIndex!=-1) { *outputLength=PQgetlength(result, rowIndex, columnIndex); if (*outputLength==0) { *output=0; return false; } else { *output = (char*) rakMalloc_Ex(*outputLength,_FILE_AND_LINE_); memcpy(*output, PQgetvalue(result, rowIndex, columnIndex), *outputLength); return true; } } else return false; }
bool WriteFileWithDirectories( const char *path, char *data, unsigned dataLength ) { int index; FILE *fp; char *pathCopy; int res; if ( path == 0 || path[ 0 ] == 0 ) return false; pathCopy = (char*) rakMalloc_Ex( strlen( path ) + 1, _FILE_AND_LINE_ ); strcpy( pathCopy, path ); // Ignore first / if there is one if (pathCopy[0]) { index = 1; while ( pathCopy[ index ] ) { if ( pathCopy[ index ] == '/' || pathCopy[ index ] == '\\') { pathCopy[ index ] = 0; #ifdef _WIN32 #pragma warning( disable : 4966 ) // mkdir declared deprecated by Microsoft in order to make it harder to be cross platform. I don't agree it's deprecated. res = mkdir( pathCopy ); #else res = mkdir( pathCopy, 0744 ); #endif if (res<0 && errno!=EEXIST && errno!=EACCES) { rakFree_Ex(pathCopy, _FILE_AND_LINE_ ); return false; } pathCopy[ index ] = '/'; } index++; } } if (data) { fp = fopen( path, "wb" ); if ( fp == 0 ) { rakFree_Ex(pathCopy, _FILE_AND_LINE_ ); return false; } fwrite( data, 1, dataLength, fp ); fclose( fp ); } else { #ifdef _WIN32 #pragma warning( disable : 4966 ) // mkdir declared deprecated by Microsoft in order to make it harder to be cross platform. I don't agree it's deprecated. res = mkdir( pathCopy ); #else res = mkdir( pathCopy, 0744 ); #endif if (res<0 && errno!=EEXIST) { rakFree_Ex(pathCopy, _FILE_AND_LINE_ ); return false; } } rakFree_Ex(pathCopy, _FILE_AND_LINE_ ); return true; }
bool FileListTransfer::DecodeFile(Packet *packet, bool fullFile) { FileListTransferCBInterface::OnFileStruct onFileStruct; RakNet::BitStream inBitStream(packet->data, packet->length, false); inBitStream.IgnoreBits(8); unsigned int partCount=0; unsigned int partTotal=0; unsigned int partLength=0; onFileStruct.fileData=0; if (fullFile==false) { // Disable endian swapping on reading this, as it's generated locally in ReliabilityLayer.cpp inBitStream.ReadBits( (unsigned char* ) &partCount, BYTES_TO_BITS(sizeof(partCount)), true ); inBitStream.ReadBits( (unsigned char* ) &partTotal, BYTES_TO_BITS(sizeof(partTotal)), true ); inBitStream.ReadBits( (unsigned char* ) &partLength, BYTES_TO_BITS(sizeof(partLength)), true ); inBitStream.IgnoreBits(8); // The header is appended to every chunk, which we continue to read after this statement block } inBitStream.Read(onFileStruct.context); inBitStream.Read(onFileStruct.setID); FileListReceiver *fileListReceiver; if (fileListReceivers.Has(onFileStruct.setID)==false) { return false; } fileListReceiver=fileListReceivers.Get(onFileStruct.setID); if (fileListReceiver->allowedSender!=packet->systemAddress) { #ifdef _DEBUG RakAssert(0); #endif return false; } #ifdef _DEBUG RakAssert(fileListReceiver->gotSetHeader==true); #endif if (stringCompressor->DecodeString(onFileStruct.fileName, 512, &inBitStream)==false) { #ifdef _DEBUG RakAssert(0); #endif return false; } inBitStream.ReadCompressed(onFileStruct.fileIndex); inBitStream.ReadCompressed(onFileStruct.finalDataLength); // Read header uncompressed so the data is byte aligned, for speed onFileStruct.compressedTransmissionLength=(unsigned int) onFileStruct.finalDataLength; if (fullFile) { // Support SendLists inBitStream.AlignReadToByteBoundary(); onFileStruct.fileData = (char*) rakMalloc_Ex( (size_t) onFileStruct.finalDataLength, __FILE__, __LINE__ ); inBitStream.Read((char*)onFileStruct.fileData, onFileStruct.finalDataLength); } onFileStruct.setCount=fileListReceiver->setCount; onFileStruct.setTotalCompressedTransmissionLength=fileListReceiver->setTotalCompressedTransmissionLength; onFileStruct.setTotalFinalLength=fileListReceiver->setTotalFinalLength; // User callback for this file. if (fullFile) { if (fileListReceiver->downloadHandler->OnFile(&onFileStruct)) rakFree_Ex(onFileStruct.fileData, __FILE__, __LINE__ ); fileListReceiver->filesReceived++; // If this set is done, free the memory for it. if ((int) fileListReceiver->setCount==fileListReceiver->filesReceived) { if (fileListReceiver->downloadHandler->OnDownloadComplete()==false) { fileListReceiver->downloadHandler->OnDereference(); if (fileListReceiver->deleteDownloadHandler) RakNet::OP_DELETE(fileListReceiver->downloadHandler, __FILE__, __LINE__); fileListReceivers.Delete(onFileStruct.setID); RakNet::OP_DELETE(fileListReceiver, __FILE__, __LINE__); } } } else { inBitStream.AlignReadToByteBoundary(); bool usedAlloca=false; char *firstDataChunk; unsigned int unreadBits = inBitStream.GetNumberOfUnreadBits(); unsigned int unreadBytes = BITS_TO_BYTES(unreadBits); if (unreadBytes>0) { #if !defined(_XBOX) && !defined(_X360) if (unreadBits < MAX_ALLOCA_STACK_ALLOCATION) { firstDataChunk = ( char* ) alloca( unreadBytes ); usedAlloca=true; } else #endif firstDataChunk = (char*) rakMalloc_Ex( unreadBytes, __FILE__, __LINE__ ); // Read partLength bytes, reported to OnFileProgress inBitStream.Read((char*)firstDataChunk, unreadBytes ); } else firstDataChunk=0; fileListReceiver->downloadHandler->OnFileProgress(&onFileStruct, partCount, partTotal, unreadBytes, firstDataChunk); if (usedAlloca==false) RakNet::OP_DELETE_ARRAY(firstDataChunk, __FILE__, __LINE__); } return true; }
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(); }
Packet* TelnetTransport::Receive( void ) { if (tcpInterface==0) return 0; Packet *p = tcpInterface->Receive(); if (p==0) return 0; /* if (p->data[0]==255) { unsigned i; for (i=0; i < p->length; i++) { RAKNET_DEBUG_PRINTF("%i ", p->data[i]); } RAKNET_DEBUG_PRINTF("\n"); tcpInterface->DeallocatePacket(p); return 0; } */ // Get this guy's cursor buffer. This is real bullcrap that I have to do this. unsigned i; TelnetClient *remoteClient=0; for (i=0; i < remoteClients.Size(); i++) { if (remoteClients[i]->systemAddress==p->systemAddress) remoteClient=remoteClients[i]; } //RakAssert(remoteClient); if (remoteClient==0) { tcpInterface->DeallocatePacket(p); return 0; } if (p->length==3 && p->data[0]==27 && p->data[1]==91 && p->data[2]==65) { if (remoteClient->lastSentTextInput[0]) { // Up arrow, return last string for (int i=0; remoteClient->textInput[i]; i++) remoteClient->textInput[i]=8; strcat(remoteClient->textInput, remoteClient->lastSentTextInput); tcpInterface->Send((const char *)remoteClient->textInput, strlen(remoteClient->textInput), p->systemAddress, false); strcpy(remoteClient->textInput,remoteClient->lastSentTextInput); remoteClient->cursorPosition=strlen(remoteClient->textInput); } return 0; } // 127 is delete - ignore that // 9 is tab // 27 is escape if (p->data[0]>=127 || p->data[0]==9 || p->data[0]==27) { tcpInterface->DeallocatePacket(p); return 0; } // Hack - I don't know what the hell this is about but cursor keys send 3 characters at a time. I can block these //Up=27,91,65 //Down=27,91,66 //Right=27,91,67 //Left=27,91,68 if (p->length==3 && p->data[0]==27 && p->data[1]==91 && p->data[2]>=65 && p->data[2]<=68) { tcpInterface->DeallocatePacket(p); return 0; } // Echo #ifdef ECHO_INPUT tcpInterface->Send((const char *)p->data, p->length, p->systemAddress, false); #endif bool gotLine; // Process each character in turn for (i=0; i < p->length; i++) { #ifdef ECHO_INPUT if (p->data[i]==8) { char spaceThenBack[2]; spaceThenBack[0]=' '; spaceThenBack[1]=8; tcpInterface->Send((const char *)spaceThenBack, 2, p->systemAddress, false); } #endif gotLine=ReassembleLine(remoteClient, p->data[i]); if (gotLine && remoteClient->textInput[0]) { Packet *reassembledLine = (Packet*) rakMalloc_Ex(sizeof(Packet), __FILE__, __LINE__); reassembledLine->length=(unsigned int) strlen(remoteClient->textInput); memcpy(remoteClient->lastSentTextInput, remoteClient->textInput, reassembledLine->length+1); RakAssert(reassembledLine->length < REMOTE_MAX_TEXT_INPUT); reassembledLine->data= (unsigned char*) rakMalloc_Ex( reassembledLine->length+1, __FILE__, __LINE__ ); memcpy(reassembledLine->data, remoteClient->textInput, reassembledLine->length); #ifdef _PRINTF_DEBUG memset(remoteClient->textInput, 0, REMOTE_MAX_TEXT_INPUT); #endif reassembledLine->data[reassembledLine->length]=0; reassembledLine->systemAddress=p->systemAddress; tcpInterface->DeallocatePacket(p); return reassembledLine; } } tcpInterface->DeallocatePacket(p); return 0; }
virtual PatchContext ApplyPatchBase(const char *oldFilePath, char **newFileContents, unsigned int *newFileSize, char *patchContents, unsigned int patchSize, uint32_t patchAlgorithm) { if (patchAlgorithm==0) { return ApplyPatchBSDiff(oldFilePath, newFileContents, newFileSize, patchContents, patchSize); } else { char WORKING_DIRECTORY[MAX_PATH]; GetTempPath(MAX_PATH, WORKING_DIRECTORY); if (WORKING_DIRECTORY[strlen(WORKING_DIRECTORY)-1]=='\\' || WORKING_DIRECTORY[strlen(WORKING_DIRECTORY)-1]=='/') WORKING_DIRECTORY[strlen(WORKING_DIRECTORY)-1]=0; char buff[128]; RakNet::TimeUS time = RakNet::GetTimeUS(); #if defined(_WIN32) sprintf(buff, "%I64u", time); #else sprintf(buff, "%llu", (long long unsigned int) time); #endif char pathToPatch1[MAX_PATH], pathToPatch2[MAX_PATH]; sprintf(pathToPatch1, "%s/patchClient_%s.tmp", WORKING_DIRECTORY, buff); FILE *fpPatch = fopen(pathToPatch1, "wb"); if (fpPatch==0) return PC_ERROR_PATCH_TARGET_MISSING; fwrite(patchContents, 1, patchSize, fpPatch); fclose(fpPatch); // Invoke xdelta // See https://code.google.com/p/xdelta/wiki/CommandLineSyntax char commandLine[512]; _snprintf(commandLine, sizeof(commandLine)-1, "-d -f -s %s %s/patchClient_%s.tmp %s/newFile_%s.tmp", oldFilePath, WORKING_DIRECTORY, buff, WORKING_DIRECTORY, buff); commandLine[511]=0; SHELLEXECUTEINFO shellExecuteInfo; shellExecuteInfo.cbSize = sizeof(SHELLEXECUTEINFO); shellExecuteInfo.fMask = SEE_MASK_NOASYNC | SEE_MASK_NO_CONSOLE; shellExecuteInfo.hwnd = NULL; shellExecuteInfo.lpVerb = "open"; shellExecuteInfo.lpFile = "xdelta3-3.0.6-win32.exe"; shellExecuteInfo.lpParameters = commandLine; shellExecuteInfo.lpDirectory = NULL; shellExecuteInfo.nShow = SW_SHOWNORMAL; shellExecuteInfo.hInstApp = NULL; ShellExecuteEx(&shellExecuteInfo); // // ShellExecute is blocking, but if it writes a file to disk that file is not always immediately accessible after it returns. And this only happens in release, and only when not running in the debugger // ShellExecute(NULL, "open", "xdelta3-3.0.6-win32.exe", commandLine, NULL, SW_SHOWNORMAL); sprintf(pathToPatch2, "%s/newFile_%s.tmp", WORKING_DIRECTORY, buff); fpPatch = fopen(pathToPatch2, "r+b"); RakNet::TimeUS stopWaiting = time + 60000000; while (fpPatch==0 && RakNet::GetTimeUS() < stopWaiting) { RakSleep(1000); fpPatch = fopen(pathToPatch2, "r+b"); } if (fpPatch==0) { printf("\nERROR: Could not open %s.\nerr=%i (%s)\narguments=%s\n", pathToPatch2, errno, strerror(errno), commandLine); return PC_ERROR_PATCH_TARGET_MISSING; } fseek(fpPatch, 0, SEEK_END); *newFileSize = ftell(fpPatch); fseek(fpPatch, 0, SEEK_SET); *newFileContents = (char*) rakMalloc_Ex(*newFileSize, _FILE_AND_LINE_); fread(*newFileContents, 1, *newFileSize, fpPatch); fclose(fpPatch); int unlinkRes1 = _unlink(pathToPatch1); int unlinkRes2 = _unlink(pathToPatch2); while ((unlinkRes1!=0 || unlinkRes2!=0) && RakNet::GetTimeUS() < stopWaiting) { RakSleep(1000); if (unlinkRes1!=0) unlinkRes1 = _unlink(pathToPatch1); if (unlinkRes2!=0) unlinkRes2 = _unlink(pathToPatch2); } if (unlinkRes1!=0) printf("\nWARNING: unlink %s failed.\nerr=%i (%s)\n", pathToPatch1, errno, strerror(errno)); if (unlinkRes2!=0) printf("\nWARNING: unlink %s failed.\nerr=%i (%s)\n", pathToPatch2, errno, strerror(errno)); return PC_WRITE_FILE; } }
bool MakePatch(const char *oldFile, const char *newFile, char **patch, unsigned int *patchLength, int *patchAlgorithm) { FILE *fpOld = fopen(oldFile, "rb"); fseek(fpOld, 0, SEEK_END); int contentLengthOld = ftell(fpOld); FILE *fpNew = fopen(newFile, "rb"); fseek(fpNew, 0, SEEK_END); int contentLengthNew = ftell(fpNew); if ((contentLengthOld < 33554432 && contentLengthNew < 33554432) || PATH_TO_XDELTA_EXE[0]==0) { // Use bsdiff, which does a good job but takes a lot of memory based on the size of the file *patchAlgorithm=0; bool b = MakePatchBSDiff(fpOld, contentLengthOld, fpNew, contentLengthNew, patch, patchLength); fclose(fpOld); fclose(fpNew); return b; } else { *patchAlgorithm=1; fclose(fpOld); fclose(fpNew); char buff[128]; RakNet::TimeUS time = RakNet::GetTimeUS(); #if defined(_WIN32) sprintf(buff, "%I64u", time); #else sprintf(buff, "%llu", (long long unsigned int) time); #endif // Invoke xdelta // See https://code.google.com/p/xdelta/wiki/CommandLineSyntax char commandLine[512]; _snprintf(commandLine, sizeof(commandLine)-1, "-f -s %s %s patchServer_%s.tmp", oldFile, newFile, buff); commandLine[511]=0; SHELLEXECUTEINFO shellExecuteInfo; shellExecuteInfo.cbSize = sizeof(SHELLEXECUTEINFO); shellExecuteInfo.fMask = SEE_MASK_NOASYNC | SEE_MASK_NO_CONSOLE; shellExecuteInfo.hwnd = NULL; shellExecuteInfo.lpVerb = "open"; shellExecuteInfo.lpFile = PATH_TO_XDELTA_EXE; shellExecuteInfo.lpParameters = commandLine; shellExecuteInfo.lpDirectory = WORKING_DIRECTORY; shellExecuteInfo.nShow = SW_SHOWNORMAL; shellExecuteInfo.hInstApp = NULL; ShellExecuteEx(&shellExecuteInfo); //ShellExecute(NULL, "open", PATH_TO_XDELTA_EXE, commandLine, WORKING_DIRECTORY, SW_SHOWNORMAL); char pathToPatch[MAX_PATH]; sprintf(pathToPatch, "%s/patchServer_%s.tmp", WORKING_DIRECTORY, buff); // r+ instead of r, because I want exclusive access in case xdelta is still working FILE *fpPatch = fopen(pathToPatch, "r+b"); RakNet::TimeUS stopWaiting = time + 60000000 * 5; while (fpPatch==0 && RakNet::GetTimeUS() < stopWaiting) { RakSleep(1000); fpPatch = fopen(pathToPatch, "r+b"); } if (fpPatch==0) return false; fseek(fpPatch, 0, SEEK_END); *patchLength = ftell(fpPatch); fseek(fpPatch, 0, SEEK_SET); *patch = (char*) rakMalloc_Ex(*patchLength, _FILE_AND_LINE_); fread(*patch, 1, *patchLength, fpPatch); fclose(fpPatch); int unlinkRes = _unlink(pathToPatch); while (unlinkRes!=0 && RakNet::GetTimeUS() < stopWaiting) { RakSleep(1000); unlinkRes = _unlink(pathToPatch); } if (unlinkRes!=0) printf("\nWARNING: unlink %s failed.\nerr=%i (%s)\n", pathToPatch, errno, strerror(errno)); return true; } }
void FileList::AddFilesFromDirectory(const char *applicationDirectory, const char *subDirectory, bool writeHash, bool writeData, bool recursive, FileListNodeContext context) { DataStructures::Queue<char*> dirList; char root[260]; char fullPath[520]; _finddata_t fileInfo; intptr_t dir; FILE *fp; char *dirSoFar, *fileData; dirSoFar=(char*) rakMalloc_Ex( 520, __FILE__, __LINE__ ); if (applicationDirectory) strcpy(root, applicationDirectory); else root[0]=0; int rootLen=(int)strlen(root); if (rootLen) { strcpy(dirSoFar, root); if (FixEndingSlash(dirSoFar)) rootLen++; } else dirSoFar[0]=0; if (subDirectory) { strcat(dirSoFar, subDirectory); FixEndingSlash(dirSoFar); } if (callback) callback->OnAddFilesFromDirectoryStarted(this, dirSoFar); // RAKNET_DEBUG_PRINTF("Adding files from directory %s\n",dirSoFar); dirList.Push(dirSoFar, __FILE__, __LINE__ ); while (dirList.Size()) { dirSoFar=dirList.Pop(); strcpy(fullPath, dirSoFar); // Changed from *.* to * for Linux compatibility strcat(fullPath, "*"); dir=_findfirst(fullPath, &fileInfo ); if (dir==-1) { _findclose(dir); rakFree_Ex(dirSoFar, __FILE__, __LINE__ ); unsigned i; for (i=0; i < dirList.Size(); i++) rakFree_Ex(dirList[i], __FILE__, __LINE__ ); return; } // RAKNET_DEBUG_PRINTF("Adding %s. %i remaining.\n", fullPath, dirList.Size()); if (callback) callback->OnDirectory(this, fullPath, dirList.Size()); do { // no guarantee these entries are first... if (strcmp("." , fileInfo.name) == 0 || strcmp("..", fileInfo.name) == 0) { continue; } if ((fileInfo.attrib & (_A_HIDDEN | _A_SUBDIR | _A_SYSTEM))==0) { strcpy(fullPath, dirSoFar); strcat(fullPath, fileInfo.name); fileData=0; if (callback) callback->OnFile(this, dirSoFar, fileInfo.name, fileInfo.size); if (writeData && writeHash) { fileData= (char*) rakMalloc_Ex( fileInfo.size+HASH_LENGTH, __FILE__, __LINE__ ); fp = fopen(fullPath, "rb"); fread(fileData+HASH_LENGTH, fileInfo.size, 1, fp); fclose(fp); unsigned int hash = SuperFastHash(fileData+HASH_LENGTH, fileInfo.size); if (RakNet::BitStream::DoEndianSwap()) RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &hash, sizeof(hash)); memcpy(fileData, &hash, HASH_LENGTH); // sha1.Reset(); // sha1.Update( ( unsigned char* ) fileData+HASH_LENGTH, fileInfo.size ); // sha1.Final(); // memcpy(fileData, sha1.GetHash(), HASH_LENGTH); // File data and hash AddFile((const char*)fullPath+rootLen, fullPath, fileData, fileInfo.size+HASH_LENGTH, fileInfo.size, context); } else if (writeHash) { // sha1.Reset(); // sha1.HashFile((char*)fullPath); // sha1.Final(); unsigned int hash = SuperFastHashFile(fullPath); if (RakNet::BitStream::DoEndianSwap()) RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &hash, sizeof(hash)); // Hash only // AddFile((const char*)fullPath+rootLen, (const char*)sha1.GetHash(), HASH_LENGTH, fileInfo.size, context); AddFile((const char*)fullPath+rootLen, fullPath, (const char*)&hash, HASH_LENGTH, fileInfo.size, context); } else if (writeData) { fileData= (char*) rakMalloc_Ex( fileInfo.size, __FILE__, __LINE__ ); fp = fopen(fullPath, "rb"); fread(fileData, fileInfo.size, 1, fp); fclose(fp); // File data only AddFile(fullPath+rootLen, fullPath, fileData, fileInfo.size, fileInfo.size, context); } else { // Just the filename AddFile(fullPath+rootLen, fullPath, 0, 0, fileInfo.size, context); } if (fileData) rakFree_Ex(fileData, __FILE__, __LINE__ ); } else if ((fileInfo.attrib & _A_SUBDIR) && (fileInfo.attrib & (_A_HIDDEN | _A_SYSTEM))==0 && recursive) { char *newDir=(char*) rakMalloc_Ex( 520, __FILE__, __LINE__ ); strcpy(newDir, dirSoFar); strcat(newDir, fileInfo.name); strcat(newDir, "/"); dirList.Push(newDir, __FILE__, __LINE__ ); } } while (_findnext(dir, &fileInfo ) != -1); _findclose(dir); rakFree_Ex(dirSoFar, __FILE__, __LINE__ ); } }
void FileListTransfer::OnReferencePush(Packet *packet, bool fullFile) { // fullFile is always true for TCP, since TCP does not return SPLIT_PACKET_NOTIFICATION RakNet::BitStream refPushAck; refPushAck.Write((MessageID)ID_FILE_LIST_REFERENCE_PUSH_ACK); SendUnified(&refPushAck,HIGH_PRIORITY, RELIABLE, 0, packet->systemAddress, false); FileListTransferCBInterface::OnFileStruct onFileStruct; RakNet::BitStream inBitStream(packet->data, packet->length, false); inBitStream.IgnoreBits(8); unsigned int partCount=0; unsigned int partTotal=1; unsigned int partLength=0; onFileStruct.fileData=0; if (fullFile==false) { // Disable endian swapping on reading this, as it's generated locally in ReliabilityLayer.cpp inBitStream.ReadBits( (unsigned char* ) &partCount, BYTES_TO_BITS(sizeof(partCount)), true ); inBitStream.ReadBits( (unsigned char* ) &partTotal, BYTES_TO_BITS(sizeof(partTotal)), true ); inBitStream.ReadBits( (unsigned char* ) &partLength, BYTES_TO_BITS(sizeof(partLength)), true ); inBitStream.IgnoreBits(8); // The header is appended to every chunk, which we continue to read after this statement block } inBitStream.Read(onFileStruct.context); inBitStream.Read(onFileStruct.setID); FileListReceiver *fileListReceiver; if (fileListReceivers.Has(onFileStruct.setID)==false) { return; } fileListReceiver=fileListReceivers.Get(onFileStruct.setID); if (fileListReceiver->allowedSender!=packet->systemAddress) { #ifdef _DEBUG RakAssert(0); #endif return; } #ifdef _DEBUG RakAssert(fileListReceiver->gotSetHeader==true); #endif if (stringCompressor->DecodeString(onFileStruct.fileName, 512, &inBitStream)==false) { #ifdef _DEBUG RakAssert(0); #endif return; } inBitStream.ReadCompressed(onFileStruct.fileIndex); inBitStream.ReadCompressed(onFileStruct.finalDataLength); unsigned int offset; unsigned int chunkLength; inBitStream.ReadCompressed(offset); inBitStream.ReadCompressed(chunkLength); // if (chunkLength==0) // return; bool lastChunk; inBitStream.Read(lastChunk); bool finished = lastChunk && fullFile; if (fullFile==false) fileListReceiver->partLength=partLength; FLR_MemoryBlock mb; if (fileListReceiver->pushedFiles.Has(onFileStruct.fileIndex)==false) { if (chunkLength > 1000000000 || onFileStruct.finalDataLength > 1000000000) { RakAssert("FileListTransfer::OnReferencePush: file too large" && 0); return; } mb.allocatedLength=onFileStruct.finalDataLength; mb.block = (char*) rakMalloc_Ex(onFileStruct.finalDataLength, __FILE__, __LINE__); if (mb.block==0) { notifyOutOfMemory(__FILE__, __LINE__); return; } fileListReceiver->pushedFiles.SetNew(onFileStruct.fileIndex, mb); } else mb=fileListReceiver->pushedFiles.Get(onFileStruct.fileIndex); if (offset+chunkLength > mb.allocatedLength) { // Overrun RakAssert("FileListTransfer::OnReferencePush: Write would overrun allocated block" && 0); return; } // Read header uncompressed so the data is byte aligned, for speed onFileStruct.compressedTransmissionLength=(unsigned int) onFileStruct.finalDataLength; unsigned int unreadBits = inBitStream.GetNumberOfUnreadBits(); unsigned int unreadBytes = BITS_TO_BYTES(unreadBits); unsigned int amountToRead; if (fullFile) amountToRead=chunkLength; else amountToRead=unreadBytes; inBitStream.AlignReadToByteBoundary(); if (fullFile || (rakPeerInterface->GetSplitMessageProgressInterval() != 0 && (int)partCount==rakPeerInterface->GetSplitMessageProgressInterval())) { inBitStream.Read(mb.block+offset, amountToRead); } onFileStruct.setCount=fileListReceiver->setCount; onFileStruct.setTotalCompressedTransmissionLength=fileListReceiver->setTotalCompressedTransmissionLength; onFileStruct.setTotalFinalLength=fileListReceiver->setTotalFinalLength; onFileStruct.fileData=mb.block; if (finished) { if (fileListReceiver->downloadHandler->OnFile(&onFileStruct)) rakFree_Ex(onFileStruct.fileData, __FILE__, __LINE__ ); fileListReceiver->pushedFiles.Delete(onFileStruct.fileIndex); fileListReceiver->filesReceived++; // If this set is done, free the memory for it. if ((int) fileListReceiver->setCount==fileListReceiver->filesReceived) { if (fileListReceiver->downloadHandler->OnDownloadComplete()==false) { fileListReceiver->downloadHandler->OnDereference(); fileListReceivers.Delete(onFileStruct.setID); if (fileListReceiver->deleteDownloadHandler) RakNet::OP_DELETE(fileListReceiver->downloadHandler, __FILE__, __LINE__); RakNet::OP_DELETE(fileListReceiver, __FILE__, __LINE__); } } } else { unsigned int totalNotifications; unsigned int currentNotificationIndex; unsigned int unreadBytes; if (rakPeerInterface==0 || rakPeerInterface->GetSplitMessageProgressInterval()==0) { totalNotifications = onFileStruct.finalDataLength / chunkLength + 1; currentNotificationIndex = offset / chunkLength; unreadBytes = mb.allocatedLength - ((offset+1)*chunkLength); } else { totalNotifications = onFileStruct.finalDataLength / fileListReceiver->partLength + 1; if (fullFile==false) currentNotificationIndex = (offset+partCount*fileListReceiver->partLength) / fileListReceiver->partLength ; else currentNotificationIndex = (offset+chunkLength) / fileListReceiver->partLength ; unreadBytes = onFileStruct.finalDataLength - ((currentNotificationIndex+1) * fileListReceiver->partLength); } fileListReceiver->downloadHandler->OnFileProgress(&onFileStruct, currentNotificationIndex, totalNotifications, unreadBytes, mb.block); } return; }
void FileList::PopulateDataFromDisk(const char *applicationDirectory, bool writeFileData, bool writeFileHash, bool removeUnknownFiles) { FILE *fp; char fullPath[512]; unsigned i; // CSHA1 sha1; i=0; while (i < fileList.Size()) { rakFree_Ex(fileList[i].data, __FILE__, __LINE__ ); strcpy(fullPath, applicationDirectory); FixEndingSlash(fullPath); strcat(fullPath,fileList[i].filename.C_String()); fp=fopen(fullPath, "rb"); if (fp) { if (writeFileHash || writeFileData) { fseek(fp, 0, SEEK_END); fileList[i].fileLengthBytes = ftell(fp); fseek(fp, 0, SEEK_SET); if (writeFileHash) { if (writeFileData) { // Hash + data so offset the data by HASH_LENGTH fileList[i].data=(char*) rakMalloc_Ex( fileList[i].fileLengthBytes+HASH_LENGTH, __FILE__, __LINE__ ); fread(fileList[i].data+HASH_LENGTH, fileList[i].fileLengthBytes, 1, fp); // sha1.Reset(); // sha1.Update((unsigned char*)fileList[i].data+HASH_LENGTH, fileList[i].fileLength); // sha1.Final(); unsigned int hash = SuperFastHash(fileList[i].data+HASH_LENGTH, fileList[i].fileLengthBytes); if (RakNet::BitStream::DoEndianSwap()) RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &hash, sizeof(hash)); // memcpy(fileList[i].data, sha1.GetHash(), HASH_LENGTH); memcpy(fileList[i].data, &hash, HASH_LENGTH); } else { // Hash only fileList[i].dataLengthBytes=HASH_LENGTH; if (fileList[i].fileLengthBytes < HASH_LENGTH) fileList[i].data=(char*) rakMalloc_Ex( HASH_LENGTH, __FILE__, __LINE__ ); else fileList[i].data=(char*) rakMalloc_Ex( fileList[i].fileLengthBytes, __FILE__, __LINE__ ); fread(fileList[i].data, fileList[i].fileLengthBytes, 1, fp); // sha1.Reset(); // sha1.Update((unsigned char*)fileList[i].data, fileList[i].fileLength); // sha1.Final(); unsigned int hash = SuperFastHash(fileList[i].data, fileList[i].fileLengthBytes); if (RakNet::BitStream::DoEndianSwap()) RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &hash, sizeof(hash)); // memcpy(fileList[i].data, sha1.GetHash(), HASH_LENGTH); memcpy(fileList[i].data, &hash, HASH_LENGTH); } } else { // Data only fileList[i].dataLengthBytes=fileList[i].fileLengthBytes; fileList[i].data=(char*) rakMalloc_Ex( fileList[i].fileLengthBytes, __FILE__, __LINE__ ); fread(fileList[i].data, fileList[i].fileLengthBytes, 1, fp); } fclose(fp); i++; } else { fileList[i].data=0; fileList[i].dataLengthBytes=0; } } else { if (removeUnknownFiles) { fileList.RemoveAtIndex(i); } else i++; } } }
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 RakVoice::OpenChannel(Packet *packet) { RakNet::BitStream in(packet->data, packet->length, false); in.IgnoreBits(8); FreeChannelMemory(packet->guid); VoiceChannel *channel=RakNet::OP_NEW<VoiceChannel>( __FILE__, __LINE__ ); channel->guid=packet->guid; channel->isSendingVoiceData=false; int sampleRate; in.Read(sampleRate); channel->remoteSampleRate=sampleRate; if (channel->remoteSampleRate!=8000 && channel->remoteSampleRate!=16000 && channel->remoteSampleRate!=32000) { #ifdef _DEBUG RakAssert(0); #endif RakNet::OP_DELETE(channel, __FILE__, __LINE__); return; } if (sampleRate==8000) channel->enc_state=speex_encoder_init(&speex_nb_mode); else if (sampleRate==16000) channel->enc_state=speex_encoder_init(&speex_wb_mode); else // 32000 channel->enc_state=speex_encoder_init(&speex_uwb_mode); if (channel->remoteSampleRate==8000) channel->dec_state=speex_decoder_init(&speex_nb_mode); else if (channel->remoteSampleRate==16000) channel->dec_state=speex_decoder_init(&speex_wb_mode); else // 32000 channel->dec_state=speex_decoder_init(&speex_uwb_mode); // make sure encoder and decoder are created RakAssert((channel->enc_state)&&(channel->dec_state)); int ret; ret=speex_encoder_ctl(channel->enc_state, SPEEX_GET_FRAME_SIZE, &channel->speexOutgoingFrameSampleCount); RakAssert(ret==0); channel->outgoingBuffer = (char*) rakMalloc_Ex(bufferSizeBytes * FRAME_OUTGOING_BUFFER_COUNT, __FILE__, __LINE__); channel->outgoingReadIndex=0; channel->outgoingWriteIndex=0; channel->bufferOutput=true; channel->outgoingMessageNumber=0; channel->copiedOutgoingBufferToBufferedOutput=false; ret=speex_decoder_ctl(channel->dec_state, SPEEX_GET_FRAME_SIZE, &channel->speexIncomingFrameSampleCount); RakAssert(ret==0); channel->incomingBuffer = (char*) rakMalloc_Ex(bufferSizeBytes * FRAME_INCOMING_BUFFER_COUNT, __FILE__, __LINE__); channel->incomingReadIndex=0; channel->incomingWriteIndex=0; channel->lastSend=0; channel->incomingMessageNumber=0; // Initialize preprocessor channel->pre_state = speex_preprocess_state_init(channel->speexOutgoingFrameSampleCount, sampleRate); RakAssert(channel->pre_state); // Set encoder default parameters SetEncoderParameter(channel->enc_state, SPEEX_SET_VBR, (defaultVBRState) ? 1 : 0 ); SetEncoderParameter(channel->enc_state, SPEEX_SET_COMPLEXITY, defaultEncoderComplexity); // Set preprocessor default parameters SetPreprocessorParameter(channel->pre_state, SPEEX_PREPROCESS_SET_DENOISE, (defaultDENOISEState) ? 1 : 2); SetPreprocessorParameter(channel->pre_state, SPEEX_PREPROCESS_SET_VAD, (defaultVADState) ? 1 : 2); voiceChannels.Insert(packet->guid, channel, true, __FILE__, __LINE__); }
Packet* PacketizedTCP::Receive( void ) { PushNotificationsToQueues(); unsigned int i; for (i=0; i < messageHandlerList.Size(); i++) messageHandlerList[i]->Update(); Packet *outgoingPacket=ReturnOutgoingPacket(); if (outgoingPacket) return outgoingPacket; Packet *incomingPacket; incomingPacket = TCPInterface::Receive(); unsigned int index; while (incomingPacket) { if (connections.Has(incomingPacket->systemAddress)) index = connections.GetIndexAtKey(incomingPacket->systemAddress); else index=(unsigned int) -1; if ((unsigned int)index==(unsigned int)-1) { DeallocatePacket(incomingPacket); incomingPacket = TCPInterface::Receive(); continue; } if (incomingPacket->deleteData==true) { // Came from network SystemAddress systemAddressFromPacket; if (index < connections.Size()) { DataStructures::ByteQueue *bq = connections[index]; // Buffer data bq->WriteBytes((const char*) incomingPacket->data,incomingPacket->length, __FILE__,__LINE__); systemAddressFromPacket=incomingPacket->systemAddress; PTCPHeader dataLength; // Peek the header to see if a full message is waiting bq->ReadBytes((char*) &dataLength,sizeof(PTCPHeader),true); if (RakNet::BitStream::DoEndianSwap()) RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &dataLength,sizeof(dataLength)); // Header indicates packet length. If enough data is available, read out and return one packet if (bq->GetBytesWritten()>=dataLength+sizeof(PTCPHeader)) { do { bq->IncrementReadOffset(sizeof(PTCPHeader)); outgoingPacket = RakNet::OP_NEW<Packet>(__FILE__, __LINE__); outgoingPacket->length=dataLength; outgoingPacket->bitSize=BYTES_TO_BITS(dataLength); outgoingPacket->guid=UNASSIGNED_RAKNET_GUID; outgoingPacket->systemAddress=systemAddressFromPacket; outgoingPacket->deleteData=false; // Did not come from the network outgoingPacket->data=(unsigned char*) rakMalloc_Ex(dataLength, __FILE__, __LINE__); if (outgoingPacket->data==0) { notifyOutOfMemory(__FILE__, __LINE__); RakNet::OP_DELETE(outgoingPacket,__FILE__,__LINE__); return 0; } bq->ReadBytes((char*) outgoingPacket->data,dataLength,false); waitingPackets.Push(outgoingPacket, __FILE__, __LINE__ ); // Peek the header to see if a full message is waiting if (bq->ReadBytes((char*) &dataLength,sizeof(PTCPHeader),true)) { if (RakNet::BitStream::DoEndianSwap()) RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &dataLength,sizeof(dataLength)); } else break; } while (bq->GetBytesWritten()>=dataLength+sizeof(PTCPHeader)); } else { unsigned int oldWritten = bq->GetBytesWritten()-incomingPacket->length; unsigned int newWritten = bq->GetBytesWritten(); // Return ID_DOWNLOAD_PROGRESS if (newWritten/65536!=oldWritten/65536) { outgoingPacket = RakNet::OP_NEW<Packet>(__FILE__, __LINE__); outgoingPacket->length=sizeof(MessageID) + sizeof(unsigned int)*2 + sizeof(unsigned int) + 65536; outgoingPacket->bitSize=BYTES_TO_BITS(incomingPacket->length); outgoingPacket->guid=UNASSIGNED_RAKNET_GUID; outgoingPacket->systemAddress=incomingPacket->systemAddress; outgoingPacket->deleteData=false; outgoingPacket->data=(unsigned char*) rakMalloc_Ex(outgoingPacket->length, __FILE__, __LINE__); if (outgoingPacket->data==0) { notifyOutOfMemory(__FILE__, __LINE__); RakNet::OP_DELETE(outgoingPacket,__FILE__,__LINE__); return 0; } outgoingPacket->data[0]=(MessageID)ID_DOWNLOAD_PROGRESS; unsigned int totalParts=dataLength/65536; unsigned int partIndex=newWritten/65536; unsigned int oneChunkSize=65536; memcpy(outgoingPacket->data+sizeof(MessageID), &partIndex, sizeof(unsigned int)); memcpy(outgoingPacket->data+sizeof(MessageID)+sizeof(unsigned int)*1, &totalParts, sizeof(unsigned int)); memcpy(outgoingPacket->data+sizeof(MessageID)+sizeof(unsigned int)*2, &oneChunkSize, sizeof(unsigned int)); bq->IncrementReadOffset(sizeof(PTCPHeader)); bq->ReadBytes((char*) outgoingPacket->data+sizeof(MessageID)+sizeof(unsigned int)*3,oneChunkSize,true); bq->DecrementReadOffset(sizeof(PTCPHeader)); waitingPackets.Push(outgoingPacket, __FILE__, __LINE__ ); } } } DeallocatePacket(incomingPacket); incomingPacket=0; } else waitingPackets.Push(incomingPacket, __FILE__, __LINE__ ); incomingPacket = TCPInterface::Receive(); } return ReturnOutgoingPacket(); }