void HuffmanEncodingTree::FreeMemory( void )
{
	if ( root == 0 )
		return ;

	// Use an in-order traversal to delete the tree
	DataStructures::Queue<HuffmanEncodingTreeNode *> nodeQueue;

	HuffmanEncodingTreeNode *node;

	nodeQueue.Push( root, _FILE_AND_LINE_  );

	while ( nodeQueue.Size() > 0 )
	{
		node = nodeQueue.Pop();

		if ( node->left )
			nodeQueue.Push( node->left, _FILE_AND_LINE_  );

		if ( node->right )
			nodeQueue.Push( node->right, _FILE_AND_LINE_  );

		RakNet::OP_DELETE(node, _FILE_AND_LINE_);
	}

	// Delete the encoding table
	for ( int i = 0; i < 256; i++ )
		rakFree_Ex(encodingTable[ i ].encoding, _FILE_AND_LINE_ );

	root = 0;
}
void HuffmanEncodingTree::FreeMemory( void )
{
	if ( root == 0 )
		return ;
		
	// Use an in-order traversal to delete the tree
	DataStructures::Queue<HuffmanEncodingTreeNode *> nodeQueue;
	
	HuffmanEncodingTreeNode *node;
	
	nodeQueue.Push( root );
	
	while ( nodeQueue.Size() > 0 )
	{
		node = nodeQueue.Pop();
		
		if ( node->left )
			nodeQueue.Push( node->left );
			
		if ( node->right )
			nodeQueue.Push( node->right );
			
		delete node;
	}
	
	// Delete the encoding table
	for ( int i = 0; i < 256; i++ )
		delete [] encodingTable[ i ].encoding;
		
	root = 0;
}
Example #3
0
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_AND_LINE_ );
	RakAssert(dirSoFar);

	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);
	}
	for (unsigned int flpcIndex=0; flpcIndex < fileListProgressCallbacks.Size(); flpcIndex++)
		fileListProgressCallbacks[flpcIndex]->OnAddFilesFromDirectoryStarted(this, dirSoFar);
	// RAKNET_DEBUG_PRINTF("Adding files from directory %s\n",dirSoFar);
	dirList.Push(dirSoFar, _FILE_AND_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_AND_LINE_ );
			unsigned i;
			for (i=0; i < dirList.Size(); i++)
				rakFree_Ex(dirList[i], _FILE_AND_LINE_ );
			return;
		}

//		RAKNET_DEBUG_PRINTF("Adding %s. %i remaining.\n", fullPath, dirList.Size());
		for (unsigned int flpcIndex=0; flpcIndex < fileListProgressCallbacks.Size(); flpcIndex++)
			fileListProgressCallbacks[flpcIndex]->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;

				for (unsigned int flpcIndex=0; flpcIndex < fileListProgressCallbacks.Size(); flpcIndex++)
					fileListProgressCallbacks[flpcIndex]->OnFile(this, dirSoFar, fileInfo.name, fileInfo.size);

				if (writeData && writeHash)
				{
					fp = fopen(fullPath, "rb");
					if (fp)
					{
						fileData= (char*) rakMalloc_Ex( fileInfo.size+HASH_LENGTH, _FILE_AND_LINE_ );
						RakAssert(fileData);
						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();
//					DR_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_AND_LINE_ );
					RakAssert(fileData);
					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_AND_LINE_ );
			}
			else if ((fileInfo.attrib & _A_SUBDIR) && (fileInfo.attrib & (_A_HIDDEN | _A_SYSTEM))==0 && recursive)
			{
				char *newDir=(char*) rakMalloc_Ex( 520, _FILE_AND_LINE_ );
				RakAssert(newDir);
				strcpy(newDir, dirSoFar);
				strcat(newDir, fileInfo.name);
				strcat(newDir, "/");
				dirList.Push(newDir, _FILE_AND_LINE_ );
			}

		} while (_findnext(dir, &fileInfo ) != -1);

		_findclose(dir);
		rakFree_Ex(dirSoFar, _FILE_AND_LINE_ );
	}

}
Example #4
0
void StatisticsHistory::TimeAndValueQueue::ResizeSampleSet( int maxSamples, DataStructures::Queue<StatisticsHistory::TimeAndValue> &histogram, SHDataCategory dataCategory, Time timeClipStart, Time timeClipEnd )
{
	histogram.Clear(_FILE_AND_LINE_);
	if (maxSamples==0)
		return;
	Time timeRange = GetTimeRange();
	if (timeRange==0)
		return;
	if (maxSamples==1)
	{
		StatisticsHistory::TimeAndValue tav;
		tav.time = timeRange;
		tav.val = GetRecentSum();
		histogram.Push(tav, _FILE_AND_LINE_);
		return;
	}
	Time interval = timeRange / maxSamples;
	if (interval==0)
		interval=1;
	unsigned int dataIndex;
	Time timeBoundary;
	StatisticsHistory::TimeAndValue currentSum;
	Time currentTime;
	SHValueType numSamples;
	Time endTime;
	
	numSamples=0;
	endTime = values[values.Size()-1].time;
	dataIndex=0;
	currentTime=values[0].time;
	currentSum.val=0;
	currentSum.time=values[0].time + interval / 2;
	timeBoundary = values[0].time + interval;
	while (timeBoundary <= endTime)
	{
		while (dataIndex < values.Size() && values[dataIndex].time <= timeBoundary)
		{
			currentSum.val += values[dataIndex].val;
			dataIndex++;
			numSamples++;
		}

		if (dataCategory==DC_CONTINUOUS)
		{
			if (dataIndex > 0 &&
				dataIndex < values.Size() &&
				values[dataIndex-1].time < timeBoundary &&
				values[dataIndex].time > timeBoundary)
			{
				SHValueType interpolatedValue = Interpolate(values[dataIndex-1], values[dataIndex], timeBoundary);
				currentSum.val+=interpolatedValue;
				numSamples++;
			}

			if (numSamples > 1)
			{
				currentSum.val /= numSamples;
			}
		}

		histogram.Push(currentSum, _FILE_AND_LINE_);
		currentSum.time=timeBoundary + interval / 2;
		timeBoundary += interval;
		currentSum.val=0;
		numSamples=0;
	}

	
	if ( timeClipStart!=0 && histogram.Size()>=1)
	{
		timeClipStart = histogram.Peek().time+timeClipStart;
		if (histogram.PeekTail().time < timeClipStart)
		{
			histogram.Clear(_FILE_AND_LINE_);
		}
		else if (histogram.Size()>=2 && histogram.Peek().time < timeClipStart)
		{
			StatisticsHistory::TimeAndValue tav;

			do
			{
				tav = histogram.Pop();

				if (histogram.Peek().time == timeClipStart)
				{
					break;
				}
				else if (histogram.Peek().time > timeClipStart)
				{
					StatisticsHistory::TimeAndValue tav2;
					tav2.val = StatisticsHistory::TimeAndValueQueue::Interpolate(tav, histogram.Peek(), timeClipStart);
					tav2.time=timeClipStart;
					histogram.PushAtHead(tav2, 0, _FILE_AND_LINE_);
					break;
				}
			} while (histogram.Size()>=2);
		}
	}

	if ( timeClipEnd!=0 && histogram.Size()>=1)
	{
		timeClipEnd = histogram.PeekTail().time-timeClipEnd;
		if (histogram.Peek().time > timeClipEnd)
		{
			histogram.Clear(_FILE_AND_LINE_);
		}
		else if (histogram.Size()>=2 && histogram.PeekTail().time > timeClipEnd)
		{
			StatisticsHistory::TimeAndValue tav;

			do
			{
				tav = histogram.PopTail();

				if (histogram.PeekTail().time == timeClipEnd)
				{
					break;
				}
				else if (histogram.PeekTail().time < timeClipEnd)
				{
					StatisticsHistory::TimeAndValue tav2;
					tav2.val = StatisticsHistory::TimeAndValueQueue::Interpolate(tav, histogram.PeekTail(), timeClipEnd);
					tav2.time=timeClipEnd;
					histogram.Push(tav2, _FILE_AND_LINE_);
					break;
				}
			} while (histogram.Size()>=2);
		}
	}
}
Example #5
0
void StatisticsHistory::TimeAndValueQueue::MergeSets( const TimeAndValueQueue *lhs, SHDataCategory lhsDataCategory, const TimeAndValueQueue *rhs, SHDataCategory rhsDataCategory, TimeAndValueQueue *output )
{
	// Two ways to merge:
	// 1. Treat rhs as just more data points.
	// 1A. Sums are just added. If two values have the same time, just put in queue twice
	// 1B. longTermLowest and longTermHighest are the lowest and highest of the two sets
	// 2. Add by time. If time for the other set is missing, calculate slope to extrapolate
	// 2A. Have to recalculate recentSum, recentSumOfSquares.
	// 2B. longTermSum, longTermCount, longTermLowest, longTermHighest are unknown

	if (lhs!=output)
	{
		output->key = lhs->key;
		output->timeToTrackValues = lhs->timeToTrackValues;
	}
	else
	{
		output->key = rhs->key;
		output->timeToTrackValues = rhs->timeToTrackValues;
	}

	unsigned int lhsIndex, rhsIndex;
	lhsIndex=0;
	rhsIndex=0;

	// I use local valuesOutput in case lhs==output || rhs==output
	DataStructures::Queue<TimeAndValue> valuesOutput;

	if (lhsDataCategory==StatisticsHistory::DC_DISCRETE && rhsDataCategory==StatisticsHistory::DC_DISCRETE)
	{
		while (rhsIndex < rhs->values.Size() && lhsIndex < lhs->values.Size())
		{
			if (rhs->values[rhsIndex].time < lhs->values[lhsIndex].time)
			{
				valuesOutput.Push(rhs->values[rhsIndex], _FILE_AND_LINE_ );
				rhsIndex++;
			}
			else if (rhs->values[rhsIndex].time > lhs->values[lhsIndex].time)
			{
				valuesOutput.Push(lhs->values[rhsIndex], _FILE_AND_LINE_ );
				lhsIndex++;
			}
			else
			{
				valuesOutput.Push(rhs->values[rhsIndex], _FILE_AND_LINE_ );
				rhsIndex++;
				valuesOutput.Push(lhs->values[rhsIndex], _FILE_AND_LINE_ );
				lhsIndex++;
			}
		}

		while (rhsIndex < rhs->values.Size())
		{
			valuesOutput.Push(rhs->values[rhsIndex], _FILE_AND_LINE_ );
			rhsIndex++;
		}
		while (lhsIndex < lhs->values.Size())
		{
			valuesOutput.Push(lhs->values[lhsIndex], _FILE_AND_LINE_ );
			lhsIndex++;
		}

		output->recentSum = lhs->recentSum + rhs->recentSum;
		output->recentSumOfSquares = lhs->recentSumOfSquares + rhs->recentSumOfSquares;
		output->longTermSum = lhs->longTermSum + rhs->longTermSum;
		output->longTermCount = lhs->longTermCount + rhs->longTermCount;
		if (lhs->longTermLowest < rhs->longTermLowest)
			output->longTermLowest = lhs->longTermLowest;
		else
			output->longTermLowest = rhs->longTermLowest;
		if (lhs->longTermHighest > rhs->longTermHighest)
			output->longTermHighest = lhs->longTermHighest;
		else
			output->longTermHighest = rhs->longTermHighest;
	}
	else
	{
		TimeAndValue lastTimeAndValueLhs, lastTimeAndValueRhs;
		lastTimeAndValueLhs.time=0;
		lastTimeAndValueLhs.val=0;
		lastTimeAndValueRhs.time=0;
		lastTimeAndValueRhs.val=0;
		SHValueType lastSlopeLhs=0;
		SHValueType lastSlopeRhs=0;
		Time timeSinceOppositeValue;

		TimeAndValue newTimeAndValue;

		while (rhsIndex < rhs->values.Size() && lhsIndex < lhs->values.Size())
		{
			if (rhs->values[rhsIndex].time < lhs->values[lhsIndex].time)
			{
				timeSinceOppositeValue = rhs->values[rhsIndex].time - lastTimeAndValueLhs.time;
				newTimeAndValue.val = rhs->values[rhsIndex].val + lastTimeAndValueLhs.val + lastSlopeLhs * timeSinceOppositeValue;
				newTimeAndValue.time = rhs->values[rhsIndex].time;
				lastTimeAndValueRhs = rhs->values[rhsIndex];
				if (rhsIndex>0 && rhs->values[rhsIndex].time != rhs->values[rhsIndex-1].time && rhsDataCategory==StatisticsHistory::DC_CONTINUOUS)
					lastSlopeRhs = (rhs->values[rhsIndex].val - rhs->values[rhsIndex-1].val) / (SHValueType) (rhs->values[rhsIndex].time - rhs->values[rhsIndex-1].time);
				rhsIndex++;
			}
			else if (lhs->values[lhsIndex].time < rhs->values[rhsIndex].time)
			{
				timeSinceOppositeValue = lhs->values[lhsIndex].time - lastTimeAndValueRhs.time;
				newTimeAndValue.val = lhs->values[lhsIndex].val + lastTimeAndValueRhs.val + lastSlopeRhs * timeSinceOppositeValue;
				newTimeAndValue.time = lhs->values[lhsIndex].time;
				lastTimeAndValueLhs = lhs->values[lhsIndex];
				if (lhsIndex>0 && lhs->values[lhsIndex].time != lhs->values[lhsIndex-1].time && lhsDataCategory==StatisticsHistory::DC_CONTINUOUS)
					lastSlopeLhs = (lhs->values[lhsIndex].val - lhs->values[lhsIndex-1].val) / (SHValueType) (lhs->values[lhsIndex].time - lhs->values[lhsIndex-1].time);
				lhsIndex++;
			}
			else
			{
				newTimeAndValue.val = lhs->values[lhsIndex].val + rhs->values[rhsIndex].val;
				newTimeAndValue.time = lhs->values[lhsIndex].time;
				lastTimeAndValueRhs = rhs->values[rhsIndex];
				lastTimeAndValueLhs = lhs->values[lhsIndex];
				if (rhsIndex>0 && rhs->values[rhsIndex].time != rhs->values[rhsIndex-1].time && rhsDataCategory==StatisticsHistory::DC_CONTINUOUS)
					lastSlopeRhs = (rhs->values[rhsIndex].val - rhs->values[rhsIndex-1].val) / (SHValueType) (rhs->values[rhsIndex].time - rhs->values[rhsIndex-1].time);
				if (lhsIndex>0 && lhs->values[lhsIndex].time != lhs->values[lhsIndex-1].time && lhsDataCategory==StatisticsHistory::DC_CONTINUOUS)
					lastSlopeLhs = (lhs->values[lhsIndex].val - lhs->values[lhsIndex-1].val) / (SHValueType) (lhs->values[lhsIndex].time - lhs->values[lhsIndex-1].time);
				lhsIndex++;
				rhsIndex++;
			}

			valuesOutput.Push(newTimeAndValue, _FILE_AND_LINE_ );
		}

		while (rhsIndex < rhs->values.Size())
		{
			timeSinceOppositeValue = rhs->values[rhsIndex].time - lastTimeAndValueLhs.time;
			newTimeAndValue.val = rhs->values[rhsIndex].val + lastTimeAndValueLhs.val + lastSlopeLhs * timeSinceOppositeValue;
			newTimeAndValue.time = rhs->values[rhsIndex].time;
			valuesOutput.Push(newTimeAndValue, _FILE_AND_LINE_ );
			rhsIndex++;
		}
		while (lhsIndex < lhs->values.Size())
		{
			timeSinceOppositeValue = lhs->values[lhsIndex].time - lastTimeAndValueRhs.time;
			newTimeAndValue.val = lhs->values[lhsIndex].val + lastTimeAndValueRhs.val + lastSlopeRhs * timeSinceOppositeValue;
			newTimeAndValue.time = lhs->values[lhsIndex].time;
			valuesOutput.Push(newTimeAndValue, _FILE_AND_LINE_ );
			lhsIndex++;
		}

		output->recentSum = 0;
		output->recentSumOfSquares = 0;
		for (unsigned int i=0; i < valuesOutput.Size(); i++)
		{
			output->recentSum += valuesOutput[i].val;
			output->recentSumOfSquares += valuesOutput[i].val * valuesOutput[i].val;
		}
	}

	output->values = valuesOutput;
}
void UDPForwarder::UpdateThreaded(void)
{
	fd_set      readFD;
	//fd_set exceptionFD;
	FD_ZERO(&readFD);
//	FD_ZERO(&exceptionFD);
	timeval tv;
	int selectResult;
	tv.tv_sec=0;
	tv.tv_usec=0;

	RakNet::TimeMS curTime = RakNet::GetTimeMS();

	SOCKET largestDescriptor=0;
	DataStructures::DefaultIndexType i;

	// Remove unused entries
	i=0;
	while (i < forwardList.GetSize())
	{
		if (curTime > forwardList[i]->timeLastDatagramForwarded && // Account for timestamp wrap
			curTime > forwardList[i]->timeLastDatagramForwarded+forwardList[i]->timeoutOnNoDataMS)
		{
			RakNet::OP_DELETE(forwardList[i],_FILE_AND_LINE_);
			forwardList.RemoveAtIndex(i,_FILE_AND_LINE_);
		}
		else
			i++;
	}

	if (forwardList.GetSize()==0)
		return;

	for (i=0; i < forwardList.GetSize(); i++)
	{
#ifdef _MSC_VER
#pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
#endif
		FD_SET(forwardList[i]->readSocket, &readFD);
//		FD_SET(forwardList[i]->readSocket, &exceptionFD);

		if (forwardList[i]->readSocket > largestDescriptor)
			largestDescriptor = forwardList[i]->readSocket;
	}

#if defined(_PS3) || defined(__PS3__) || defined(SN_TARGET_PS3)
                                                                    
#else
	selectResult=(int) select((int) largestDescriptor+1, &readFD, 0, 0, &tv);
#endif

	char data[ MAXIMUM_MTU_SIZE ];
	sockaddr_in sa;
	socklen_t len2;

	if (selectResult > 0)
	{
		DataStructures::Queue<ForwardEntry*> entriesToRead;
		ForwardEntry *feSource;

		for (i=0; i < forwardList.GetSize(); i++)
		{
			feSource = forwardList[i];
			// I do this because I'm updating the forwardList, and don't want to lose FD_ISSET as the list is no longer in order
			if (FD_ISSET(feSource->readSocket, &readFD))
				entriesToRead.Push(feSource,__FILE__,__LINE__);
		}

		while (entriesToRead.IsEmpty()==false)
		{
			feSource=entriesToRead.Pop();

			const int flag=0;
			int receivedDataLen, len=0;
			unsigned short portnum=0;
			len2 = sizeof( sa );
			sa.sin_family = AF_INET;
			receivedDataLen = recvfrom( feSource->readSocket, data, MAXIMUM_MTU_SIZE, flag, ( sockaddr* ) & sa, ( socklen_t* ) & len2 );
			portnum = ntohs( sa.sin_port );

			if (feSource->srcAndDest.source.binaryAddress==sa.sin_addr.s_addr)
			{
				if (feSource->updatedSourceAddress==false)
				{
					feSource->updatedSourceAddress=true;

					if (feSource->srcAndDest.source.port!=portnum)
					{
						// Remove both source and dest from list, update addresses, and reinsert in order
						DataStructures::DefaultIndexType sourceIndex, destIndex;
						SrcAndDest srcAndDest;
						srcAndDest.source=feSource->srcAndDest.destination;
						srcAndDest.destination=feSource->srcAndDest.source;
						destIndex=forwardList.GetIndexOf(srcAndDest);
						ForwardEntry *feDest = forwardList[destIndex];

						forwardList.RemoveAtIndex(destIndex,__FILE__,__LINE__);
						srcAndDest.source=feSource->srcAndDest.source;
						srcAndDest.destination=feSource->srcAndDest.destination;
						sourceIndex=forwardList.GetIndexOf(srcAndDest);
						forwardList.RemoveAtIndex(sourceIndex,__FILE__,__LINE__);

						feSource->srcAndDest.source.port=portnum;
						feDest->srcAndDest.destination.port=portnum;

						feSource->timeLastDatagramForwarded=curTime;
						feDest->timeLastDatagramForwarded=curTime;

						forwardList.Push(feSource,feSource->srcAndDest,__FILE__,__LINE__);
						forwardList.Push(feDest,feDest->srcAndDest,__FILE__,__LINE__);

					}
				}

				if (feSource->srcAndDest.source.port==portnum)
				{
					// Forward to destination
					len=0;
					sockaddr_in saOut;
					saOut.sin_port = htons( feSource->srcAndDest.destination.port ); // User port
					saOut.sin_addr.s_addr = feSource->srcAndDest.destination.binaryAddress;
					saOut.sin_family = AF_INET;
					do
					{
						len = sendto( feSource->writeSocket, data, receivedDataLen, 0, ( const sockaddr* ) & saOut, sizeof( saOut ) );
					}
					while ( len == 0 );

					feSource->timeLastDatagramForwarded=curTime;
				}
			}
		}
	}
}
void UDPForwarder::UpdateThreaded_Old(void)
{
	fd_set      readFD;
	//fd_set exceptionFD;
	FD_ZERO(&readFD);
	//	FD_ZERO(&exceptionFD);
	timeval tv;
	int selectResult;
	tv.tv_sec=0;
	tv.tv_usec=0;

	RakNet::TimeMS curTime = RakNet::GetTimeMS();

	SOCKET largestDescriptor=0;
	DataStructures::DefaultIndexType i;

	// Remove unused entries
	i=0;
	while (i < forwardList.GetSize())
	{
		if (curTime > forwardList[i]->timeLastDatagramForwarded && // Account for timestamp wrap
			curTime > forwardList[i]->timeLastDatagramForwarded+forwardList[i]->timeoutOnNoDataMS)
		{
			RakNet::OP_DELETE(forwardList[i],_FILE_AND_LINE_);
			forwardList.RemoveAtIndex(i,_FILE_AND_LINE_);
		}
		else
			i++;
	}

	if (forwardList.GetSize()==0)
		return;

	for (i=0; i < forwardList.GetSize(); i++)
	{
#ifdef _MSC_VER
#pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
#endif
		FD_SET(forwardList[i]->socket, &readFD);
		//		FD_SET(forwardList[i]->readSocket, &exceptionFD);

		if (forwardList[i]->socket > largestDescriptor)
			largestDescriptor = forwardList[i]->socket;
	}

#if defined(_PS3) || defined(__PS3__) || defined(SN_TARGET_PS3)
                                                                    
#else
	selectResult=(int) select((int) largestDescriptor+1, &readFD, 0, 0, &tv);
#endif

	char data[ MAXIMUM_MTU_SIZE ];
	sockaddr_in sa;
	socklen_t len2;

	if (selectResult > 0)
	{
		DataStructures::Queue<ForwardEntry*> entriesToRead;
		ForwardEntry *forwardEntry;

		for (i=0; i < forwardList.GetSize(); i++)
		{
			forwardEntry = forwardList[i];
			// I do this because I'm updating the forwardList, and don't want to lose FD_ISSET as the list is no longer in order
			if (FD_ISSET(forwardEntry->socket, &readFD))
				entriesToRead.Push(forwardEntry,_FILE_AND_LINE_);
		}

		while (entriesToRead.IsEmpty()==false)
		{
			forwardEntry=entriesToRead.Pop();

			const int flag=0;
			int receivedDataLen, len=0;
			unsigned short portnum=0;
			len2 = sizeof( sa );
			sa.sin_family = AF_INET;
			receivedDataLen = recvfrom( forwardEntry->socket, data, MAXIMUM_MTU_SIZE, flag, ( sockaddr* ) & sa, ( socklen_t* ) & len2 );

			if (receivedDataLen<0)
			{
#if defined(_WIN32) && defined(_DEBUG) && !defined(_XBOX) && !defined(X360)
				DWORD dwIOError = WSAGetLastError();

				if (dwIOError!=WSAECONNRESET && dwIOError!=WSAEINTR && dwIOError!=WSAETIMEDOUT)
				{
					LPVOID messageBuffer;
					FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
						NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),  // Default language
						( LPTSTR ) & messageBuffer, 0, NULL );
					// something has gone wrong here...
					RAKNET_DEBUG_PRINTF( "recvfrom failed:Error code - %d\n%s", dwIOError, messageBuffer );

					//Free the buffer.
					LocalFree( messageBuffer );
				}
#endif
				continue;
			}

			portnum = ntohs( sa.sin_port );
			if (forwardEntry->srcAndDest.source.address.addr4.sin_addr.s_addr==sa.sin_addr.s_addr && forwardEntry->updatedSourcePort==false && forwardEntry->srcAndDest.dest.GetPort()!=portnum)
			{
				forwardEntry->updatedSourcePort=true;

				if (forwardEntry->srcAndDest.source.GetPort()!=portnum)
				{
					DataStructures::DefaultIndexType index;
					SrcAndDest srcAndDest(forwardEntry->srcAndDest.dest, forwardEntry->srcAndDest.source);
					index=forwardList.GetIndexOf(srcAndDest);
					forwardList.RemoveAtIndex(index,_FILE_AND_LINE_);
					forwardEntry->srcAndDest.source.SetPort(portnum);
					forwardList.Push(forwardEntry,forwardEntry->srcAndDest,_FILE_AND_LINE_);
				}
			}

			if (forwardEntry->srcAndDest.source.address.addr4.sin_addr.s_addr==sa.sin_addr.s_addr && forwardEntry->srcAndDest.source.GetPort()==portnum)
			{
				// Forward to dest
				len=0;
				sockaddr_in saOut;
				saOut.sin_port = forwardEntry->srcAndDest.dest.GetPortNetworkOrder(); // User port
				saOut.sin_addr.s_addr = forwardEntry->srcAndDest.dest.address.addr4.sin_addr.s_addr;
				saOut.sin_family = AF_INET;
				do
				{
					len = sendto( forwardEntry->socket, data, receivedDataLen, 0, ( const sockaddr* ) & saOut, sizeof( saOut ) );
				}
				while ( len == 0 );

				// printf("1. Forwarding after %i ms\n", curTime-forwardEntry->timeLastDatagramForwarded);

				forwardEntry->timeLastDatagramForwarded=curTime;
			}

			if (forwardEntry->srcAndDest.dest.address.addr4.sin_addr.s_addr==sa.sin_addr.s_addr && forwardEntry->updatedDestPort==false && forwardEntry->srcAndDest.source.GetPort()!=portnum)
			{
				forwardEntry->updatedDestPort=true;

				if (forwardEntry->srcAndDest.dest.GetPort()!=portnum)
				{
					DataStructures::DefaultIndexType index;
					SrcAndDest srcAndDest(forwardEntry->srcAndDest.source, forwardEntry->srcAndDest.dest);
					index=forwardList.GetIndexOf(srcAndDest);
					forwardList.RemoveAtIndex(index,_FILE_AND_LINE_);
					forwardEntry->srcAndDest.dest.SetPort(portnum);
					forwardList.Push(forwardEntry,forwardEntry->srcAndDest,_FILE_AND_LINE_);
				}
			}

			if (forwardEntry->srcAndDest.dest.address.addr4.sin_addr.s_addr==sa.sin_addr.s_addr && forwardEntry->srcAndDest.dest.GetPort()==portnum)
			{
				// Forward to source
				len=0;
				sockaddr_in saOut;
				saOut.sin_port = forwardEntry->srcAndDest.source.GetPortNetworkOrder(); // User port
				saOut.sin_addr.s_addr = forwardEntry->srcAndDest.source.address.addr4.sin_addr.s_addr;
				saOut.sin_family = AF_INET;
				do
				{
					len = sendto( forwardEntry->socket, data, receivedDataLen, 0, ( const sockaddr* ) & saOut, sizeof( saOut ) );
				}
				while ( len == 0 );

				// printf("2. Forwarding after %i ms\n", curTime-forwardEntry->timeLastDatagramForwarded);

				forwardEntry->timeLastDatagramForwarded=curTime;
			}
		}
	}
}
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);
	}
}
int main()
{
	printf("This sample creates two Lobby2Clients.\n");
	printf("They both connect to the server and performs queued operations on startup.");
	printf("(RANKING AND CLANS NOT YET DONE).\n");
	printf("Difficulty: Advanced\n\n");

	RakNet::Lobby2ResultCodeDescription::Validate();

	/// Do all these operations in this order once we are logged in.
	/// This is for easier testing.
	/// This plan will create the database, register two users, and log them both in
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_System_CreateDatabase), _FILE_AND_LINE_ );
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_System_CreateTitle), _FILE_AND_LINE_ );

	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_CDKey_Add), _FILE_AND_LINE_ );
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_System_RegisterProfanity), _FILE_AND_LINE_ );
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Client_RegisterAccount), _FILE_AND_LINE_ );
	executionPlan.Push(AutoExecutionPlanNode(1, RakNet::L2MID_Client_RegisterAccount), _FILE_AND_LINE_ );
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_System_SetEmailAddressValidated), _FILE_AND_LINE_ );
	executionPlan.Push(AutoExecutionPlanNode(1, RakNet::L2MID_System_SetEmailAddressValidated), _FILE_AND_LINE_ );
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Client_Login), _FILE_AND_LINE_ );
	executionPlan.Push(AutoExecutionPlanNode(1, RakNet::L2MID_Client_Login), _FILE_AND_LINE_ );
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Emails_Send), _FILE_AND_LINE_ );
	executionPlan.Push(AutoExecutionPlanNode(1, RakNet::L2MID_Emails_Get), _FILE_AND_LINE_ );
// 	/// Create 2 clans
// 	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Clans_Create), _FILE_AND_LINE_ );
// 	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Clans_Create), _FILE_AND_LINE_ );
// 	// Invite to both
// 	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Clans_SendJoinInvitation), _FILE_AND_LINE_ );
// 	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Clans_SendJoinInvitation), _FILE_AND_LINE_ );
// 	executionPlan.Push(AutoExecutionPlanNode(1, RakNet::L2MID_Clans_RejectJoinInvitation), _FILE_AND_LINE_ );
// 	// Download invitations this clan has sent
// 	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Clans_DownloadInvitationList), _FILE_AND_LINE_ );

	/*

	executionPlan.Push(AutoExecutionPlanNode(1, RakNet::L2MID_Client_SetPresence), _FILE_AND_LINE_ );
	executionPlan.Push(AutoExecutionPlanNode(1, RakNet::L2MID_Client_GetAccountDetails), _FILE_AND_LINE_ );
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Client_PerTitleIntegerStorage), _FILE_AND_LINE_ );
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Client_PerTitleIntegerStorage), _FILE_AND_LINE_ );

	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Client_StartIgnore), _FILE_AND_LINE_ );
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Client_GetIgnoreList), _FILE_AND_LINE_ );

	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Friends_SendInvite), _FILE_AND_LINE_);
	executionPlan.Push(AutoExecutionPlanNode(1, RakNet::L2MID_Friends_AcceptInvite), _FILE_AND_LINE_);

	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Ranking_SubmitMatch));
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Ranking_SubmitMatch));
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Ranking_UpdateRating));
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Ranking_GetRating));
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Ranking_WipeRatings));
	*/
// 	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Clans_Create), _FILE_AND_LINE_ );
// 	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Clans_Get), _FILE_AND_LINE_ );
	/*
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Clans_SetProperties));
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Clans_SetMyMemberProperties));
	*/
	/*
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Clans_SendJoinInvitation));
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Clans_WithdrawJoinInvitation));
	executionPlan.Push(AutoExecutionPlanNode(1, RakNet::L2MID_Clans_DownloadInvitationList));
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Clans_SendJoinInvitation));
	executionPlan.Push(AutoExecutionPlanNode(1, RakNet::L2MID_Clans_RejectJoinInvitation));
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Clans_SendJoinInvitation));
	executionPlan.Push(AutoExecutionPlanNode(1, RakNet::L2MID_Clans_AcceptJoinInvitation));
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Clans_SetSubleaderStatus));
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Clans_SetMemberRank));
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Clans_GrantLeader));
	*/

	/*
	executionPlan.Push(AutoExecutionPlanNode(1, RakNet::L2MID_Clans_SendJoinRequest));
	executionPlan.Push(AutoExecutionPlanNode(1, RakNet::L2MID_Clans_WithdrawJoinRequest));
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Clans_AcceptJoinRequest));
	*/

//	executionPlan.Push(AutoExecutionPlanNode(1, RakNet::L2MID_Clans_SendJoinRequest));
//	executionPlan.Push(AutoExecutionPlanNode(1, RakNet::L2MID_Clans_DownloadRequestList));
	// TODO - test from here
	/*
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Clans_RejectJoinRequest));
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Clans_AcceptJoinRequest));
	executionPlan.Push(AutoExecutionPlanNode(1, RakNet::L2MID_Clans_SendJoinRequest));
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Clans_AcceptJoinRequest));
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Clans_KickAndBlacklistUser));
	executionPlan.Push(AutoExecutionPlanNode(1, RakNet::L2MID_Clans_SendJoinRequest));
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Clans_GetBlacklist));
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Clans_UnblacklistUser));
	executionPlan.Push(AutoExecutionPlanNode(1, RakNet::L2MID_Clans_SendJoinRequest));
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Clans_AcceptJoinRequest));
	executionPlan.Push(AutoExecutionPlanNode(0, RakNet::L2MID_Clans_GetMembers));
	*/

	/*
	// TODO
	L2MID_Clans_CreateBoard,
		L2MID_Clans_DestroyBoard,
		L2MID_Clans_CreateNewTopic,
		L2MID_Clans_ReplyToTopic,
		L2MID_Clans_RemovePost,
		L2MID_Clans_GetBoards,
		L2MID_Clans_GetTopics,
		L2MID_Clans_GetPosts,
		*/
	

	char ip[64], serverPort[30], clientPort[30];
	int i;
	for (i=0; i < NUM_CONNECTIONS; i++)
		rakPeer[i]=RakNet::RakPeerInterface::GetInstance();
	puts("Enter the rakPeer1 port to listen on");
	clientPort[0]=0;
	RakNet::SocketDescriptor socketDescriptor(atoi(clientPort),0);
	Gets(clientPort,sizeof(clientPort));
	if (clientPort[0]==0)
		strcpy(clientPort, "0");

	puts("Enter IP to connect to");;
	ip[0]=0;
	Gets(ip,sizeof(ip));
	if (ip[0]==0)
		strcpy(ip, "127.0.0.1");

	puts("Enter the port to connect to");
	serverPort[0]=0;
	Gets(serverPort,sizeof(serverPort));
	if (serverPort[0]==0)
		strcpy(serverPort, "61111");

	for (i=0; i < NUM_CONNECTIONS; i++)
	{
		rakPeer[i]->Startup(1,&socketDescriptor, 1);
		rakPeer[i]->Connect(ip, atoi(serverPort), 0,0);

		rakPeer[i]->AttachPlugin(&lobby2Client[i]);
		lobby2Client[i].SetMessageFactory(&messageFactory);
		lobby2Client[i].SetCallbackInterface(&callback[i]);
		testUserName[i]=RakNet::RakString("user%i", i);
	}

	RakNet::Packet *packet;
	// Loop for input
	while (1)
	{
		for (i=0; i < NUM_CONNECTIONS; i++)
		{
			RakNet::RakPeerInterface *peer = rakPeer[i];
			for (packet=peer->Receive(); packet; peer->DeallocatePacket(packet), packet=peer->Receive())
			{
				switch (packet->data[0])
				{
				case ID_DISCONNECTION_NOTIFICATION:
					// Connection lost normally
					printf("ID_DISCONNECTION_NOTIFICATION\n");
					break;
				case ID_ALREADY_CONNECTED:
					// Connection lost normally
					printf("ID_ALREADY_CONNECTED\n");
					break;
				case ID_CONNECTION_BANNED: // Banned from this server
					printf("We are banned from this server.\n");
					break;			
				case ID_CONNECTION_ATTEMPT_FAILED:
					printf("Connection attempt failed\n");
					break;
				case ID_NO_FREE_INCOMING_CONNECTIONS:
					// Sorry, the server is full.  I don't do anything here but
					// A real app should tell the user
					printf("ID_NO_FREE_INCOMING_CONNECTIONS\n");
					break;
				case ID_INVALID_PASSWORD:
					printf("ID_INVALID_PASSWORD\n");
					break;
				case ID_CONNECTION_LOST:
					// Couldn't deliver a reliable packet - i.e. the other system was abnormally
					// terminated
					printf("ID_CONNECTION_LOST\n");
					break;
				case ID_CONNECTION_REQUEST_ACCEPTED:
					// This tells the rakPeer1 they have connected
					printf("ID_CONNECTION_REQUEST_ACCEPTED\n");
					int j;
					for (j=0; j < NUM_CONNECTIONS; j++)
						lobby2Client[j].SetServerAddress(packet->systemAddress);
					if (i==NUM_CONNECTIONS-1)
					{
						PrintCommands(&messageFactory);
						printf("Enter instance number 1 to %i followed by command number.\n", NUM_CONNECTIONS);

						if (executionPlan.Size())
						{
							/// Execute the first command now that both clients have connected.
							AutoExecutionPlanNode aepn = executionPlan.Pop();
							ExecuteCommand(aepn.operation, RakNet::RakString("user%i", aepn.instanceNumber), aepn.instanceNumber);
						}
					}
					break;
				case ID_LOBBY2_SERVER_ERROR:
					{
						RakNet::BitStream bs(packet->data,packet->length,false);
						bs.IgnoreBytes(2); // ID_LOBBY2_SERVER_ERROR and error code
						printf("ID_LOBBY2_SERVER_ERROR: ");
						if (packet->data[1]==RakNet::L2SE_UNKNOWN_MESSAGE_ID)
						{
							unsigned int messageId;
							bs.Read(messageId);
							printf("L2SE_UNKNOWN_MESSAGE_ID %i", messageId);
						}
						else
							printf("Unknown");
						printf("\n");				
					}

					break;
				}
			}
		}
		
		
		// This sleep keeps RakNet responsive
		RakSleep(30);

		if (kbhit())
		{
			char ch = getch();
			if (ch <= '0' || ch > '9')
			{
				printf("Bad instance number\n");
				continue;
			}
			int instanceNumber = ch - 1 - '0';
			if (instanceNumber >= NUM_CONNECTIONS)
			{
				printf("Enter between 1 and %i to pick the instance of RakPeer to run\n", 1+NUM_CONNECTIONS);
				continue;
			}

			printf("Enter message number or 'quit' to quit.\n");
			char str[128];
			Gets(str, sizeof(str));
			if (_stricmp(str, "quit")==0)
			{
				printf("Quitting.\n");
				break;
			}
			else
			{
				int command = atoi(str);
				if (command <=0 || command > RakNet::L2MID_COUNT)
				{
					printf("Invalid message index %i. Commands:\n", command);
					PrintCommands(&messageFactory);
				}
				else
				{
					ExecuteCommand((RakNet::Lobby2MessageID)(command-1), RakNet::RakString("user%i", instanceNumber), instanceNumber);
				}
			}
		}
	}

	for (i=0; i < NUM_CONNECTIONS; i++)
		RakNet::RakPeerInterface::DestroyInstance(rakPeer[i]);
	return 0;
}
Example #10
0
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);
}
Example #11
0
void FileList::AddFilesFromDirectory(const char *applicationDirectory, const char *subDirectory, bool writeHash, bool writeData, bool recursive, unsigned char context)
{
#ifndef _COMPATIBILITY_2
	DataStructures::Queue<char*> dirList;
	char root[260];
	char fullPath[520];
	_finddata_t fileInfo;
	intptr_t dir;
	int file;
	FILE *fp;
	CSHA1 sha1;
	char *dirSoFar, *fileData;
	dirSoFar=new char[520];

	if (applicationDirectory)
		strcpy(root, applicationDirectory);
	else
		root[0]=0;

	int rootLen=(int)strlen(root);
	if (rootLen)
	{
		strcpy(dirSoFar, root);
		if (dirSoFar[strlen(dirSoFar)-1]!='/' && dirSoFar[strlen(dirSoFar)-1]!='\\')
		{
			strcat(dirSoFar, "/");
			rootLen++;
		}
	}
	else
		dirSoFar[0]=0;
	
	if (subDirectory)
	{
		strcat(dirSoFar, subDirectory);
		if (dirSoFar[strlen(dirSoFar)-1]!='/' && dirSoFar[strlen(dirSoFar)-1]!='\\')
		{
			strcat(dirSoFar, "/");
		}
	}
	dirList.Push(dirSoFar);
	while (dirList.Size())
	{
		dirSoFar=dirList.Pop();
		strcpy(fullPath, dirSoFar);
		strcat(fullPath, "*.*");
		dir=_findfirst(fullPath, &fileInfo ); // Read .
		if (dir==-1)
		{
			_findclose(dir);
			delete [] dirSoFar;
			unsigned i;
			for (i=0; i < dirList.Size(); i++)
				delete [] dirList[i];
			return;
		}
		file=_findnext(dir, &fileInfo ); // Read ..
		file=_findnext(dir, &fileInfo ); // Skip ..

		while (file!=-1)
		{
			if ((fileInfo.attrib & (_A_HIDDEN | _A_SUBDIR | _A_SYSTEM))==0)
			{
				strcpy(fullPath, dirSoFar);
				strcat(fullPath, fileInfo.name);
				if (writeData && writeHash)
					fileData= new char [fileInfo.size+SHA1_LENGTH];
				else
					fileData= new char [fileInfo.size];
				fp = fopen(fullPath, "rb");
				if (writeData && writeHash)
					fread(fileData+SHA1_LENGTH, fileInfo.size, 1, fp);
				else
					fread(fileData, fileInfo.size, 1, fp);
				fclose(fp);

				if (writeData && writeHash)
				{
					sha1.Reset();
					sha1.Update( ( unsigned char* ) fileData+SHA1_LENGTH, fileInfo.size );
					sha1.Final();
					memcpy(fileData, sha1.GetHash(), SHA1_LENGTH);
					AddFile((const char*)fullPath+rootLen, fileData, fileInfo.size+SHA1_LENGTH, fileInfo.size, context);
				}
				else if (writeHash)
				{
					sha1.Reset();
					sha1.Update( ( unsigned char* ) fileData, fileInfo.size );
					sha1.Final();
					AddFile((const char*)fullPath+rootLen, (const char*)sha1.GetHash(), SHA1_LENGTH, fileInfo.size, context);
				}
				else if (writeData)
				{
					AddFile(fullPath+rootLen, fileData, fileInfo.size, fileInfo.size, context);
				}
				else
					AddFile(fullPath+rootLen, 0, 0, fileInfo.size, context);

				delete [] fileData;
			}
			else if ((fileInfo.attrib & _A_SUBDIR) && (fileInfo.attrib & (_A_HIDDEN | _A_SYSTEM))==0 && recursive)
			{
				char *newDir=new char[520];
				strcpy(newDir, dirSoFar);
				strcat(newDir, fileInfo.name);
				strcat(newDir, "/");
				dirList.Push(newDir);
			}
			file=_findnext(dir, &fileInfo );
		}

		_findclose(dir);
		delete [] dirSoFar;
	}
#endif
}
Example #12
0
void FileListTransfer::Send(FileList *fileList, SLNet::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;
	SLNet::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 = SLNet::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 (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 = SLNet::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);
	}
}