Exemple #1
0
//--------------------------------------------------------------------------
void ClientAgent::Disconnect()
{
	BitStream kStream;
	kStream.Reset();
	kStream << VeUInt8(ID_CLIENT_FORCE_DISCONNECT);
	SendPacket(kStream);
}
Exemple #2
0
//--------------------------------------------------------------------------
void EntityS::SyncToClient()
{
	if(m_pkAgent)
	{
		if(m_kSyncDirty.Size())
		{
			BitStream kStream;
			kStream.Reset();
			kStream << VeUInt8(ID_CLIENT_ENTITY_UPDATE);
			kStream << (const VeChar8*)m_kName;
			VE_ASSERT(m_kSyncDirty.Size() <= VE_UINT16_MAX);
			kStream << VeUInt16(m_kSyncDirty.Size());
			m_kSyncDirty.BeginIterator();
			while(!m_kSyncDirty.IsEnd())
			{
				PropertySValue* pkValue = m_kSyncDirty.GetIterNode()->m_tContent;
				m_kSyncDirty.Next();
				VE_ASSERT(pkValue);
				kStream << pkValue->GetField();
				VE_ASSERT(pkValue->GetSize() <= 0xff);
				kStream.WriteAlignedBytesSafe((const VeChar8*)pkValue->GetClientData(), pkValue->GetClientSize(), VE_UINT8_MAX);
			}
			m_kSyncDirty.Clear();
			m_pkAgent->SendPacket(kStream);
		}
	}
}
void TexasPokerHallAgentC::S_ReqSyncTime()
{
	BitStream kStream;
	kStream.Reset();
	kStream << VeUInt8(ID_SERVER_GLOBAL_RPC);
	kStream << VeUInt8(SERVER_ReqSyncTime);
	SendPacket(kStream);
}
Exemple #4
0
//--------------------------------------------------------------------------
void EntityS::DestoryFromClient()
{
	if(m_pkAgent)
	{
		BitStream kStream;
		kStream.Reset();
		kStream << VeUInt8(ID_CLIENT_ENTITY_DESTORY);
		kStream << VEString(m_kName);
		m_pkAgent->SendPacket(kStream);
	}
}
///	</CODE-GENERATE>{EntitiesClientGetterImpl}
//--------------------------------------------------------------------------
///	<CODE-GENERATE>{GlobalServerFuncSend}
void TexasPokerHallAgentC::S_ReqLogin(const VeChar8* strPlayerUUID, const VeChar8* strChannel, const VeChar8* strDeviceName, const LanguageS& tLanguage, VeUInt8 u8VersionMajor, VeUInt8 u8VersionMinor)
{
	BitStream kStream;
	kStream.Reset();
	kStream << VeUInt8(ID_SERVER_GLOBAL_RPC);
	kStream << VeUInt8(SERVER_ReqLogin);
	kStream << strPlayerUUID;
	kStream << strChannel;
	kStream << strDeviceName;
	kStream << tLanguage;
	kStream << u8VersionMajor;
	kStream << u8VersionMinor;
	SendPacket(kStream);
}
Exemple #6
0
//--------------------------------------------------------------------------
void EntityS::SyncAllToClient()
{
	if(m_pkAgent)
	{
		BitStream kStream;
		kStream.Reset();
		kStream << VeUInt8(ID_CLIENT_ENTITY_UPDATE);
		kStream << (const VeChar8*)m_kName;
		VE_ASSERT(m_kSyncChildren.Size() <= VE_UINT16_MAX);
		kStream << VeUInt16(m_kSyncChildren.Size());
		for(VeUInt32 i(0); i < m_kSyncChildren.Size(); ++i)
		{
			PropertySValue* pkValue = m_kSyncChildren[i];
			kStream << pkValue->GetField();
			VE_ASSERT(pkValue->GetSize() <= 0xff);
			kStream.WriteAlignedBytesSafe((const VeChar8*)pkValue->GetClientData(), pkValue->GetClientSize(), VE_UINT8_MAX);
		}
		m_pkAgent->SendPacket(kStream);
	}
}
int ReliableOrderedConvertedTest::RunTest(DataStructures::List<RakString> params,bool isVerbose,bool noPauses)
{

	RakPeerInterface *sender, *receiver;
	unsigned int packetNumberSender[32],packetNumberReceiver[32], receivedPacketNumberReceiver, receivedTimeReceiver;
	char str[256];
	char ip[32];
	TimeMS sendInterval, nextSend, currentTime, quitTime;
	unsigned short remotePort, localPort;
	unsigned char streamNumberSender,streamNumberReceiver;
	BitStream bitStream;
	Packet *packet;
	bool doSend=false;

	for (int i=0; i < 32; i++)
	{
		packetNumberSender[i]=0;
		packetNumberReceiver[i]=0;

	}

	/*
	if (argc==2)
	{
	fp = fopen(argv[1],"wt");
	SetMalloc_Ex(LoggedMalloc);
	SetRealloc_Ex(LoggedRealloc);
	SetFree_Ex(LoggedFree);
	}
	else
	*/
	fp=0;
	destroyList.Clear(false,_FILE_AND_LINE_);

	sender =RakPeerInterface::GetInstance();
	destroyList.Push(	sender ,_FILE_AND_LINE_);
	//sender->ApplyNetworkSimulator(.02, 100, 50);

	/*
	if (str[0]==0)
	sendInterval=30;
	else
	sendInterval=atoi(str);*///possible future params

	sendInterval=30;

	/*
	printf("Enter remote IP: ");
	Gets(ip, sizeof(ip));
	if (ip[0]==0)*/
	strcpy(ip, "127.0.0.1");

	/*
	printf("Enter remote port: ");
	Gets(str, sizeof(str));
	if (str[0]==0)*/
	strcpy(str, "60000");
	remotePort=atoi(str);
	/*
	printf("Enter local port: ");
	Gets(str, sizeof(str));
	if (str[0]==0)*/
	strcpy(str, "0");
	localPort=atoi(str);

	if (isVerbose)
		printf("Connecting...\n");

	sender->Startup(1, &SocketDescriptor(localPort,0), 1);
	sender->Connect(ip, remotePort, 0, 0);

	receiver =RakPeerInterface::GetInstance();
	destroyList.Push(	receiver ,_FILE_AND_LINE_);

	/*
	printf("Enter local port: ");
	Gets(str, sizeof(str));
	if (str[0]==0)*/
	strcpy(str, "60000");
	localPort=atoi(str);

	if (isVerbose)
		printf("Waiting for connections...\n");

	receiver->Startup(32, &SocketDescriptor(localPort,0), 1);
	receiver->SetMaximumIncomingConnections(32);

	//	if (sender)
	//		sender->ApplyNetworkSimulator(128000, 50, 100);
	//	if (receiver)
	//		receiver->ApplyNetworkSimulator(128000, 50, 100);

	/*printf("How long to run this test for, in seconds?\n");
	Gets(str, sizeof(str));
	if (str[0]==0)*/
	strcpy(str, "12");

	currentTime = GetTimeMS();
	quitTime = atoi(str) * 1000 + currentTime;

	nextSend=currentTime;

	while (currentTime < quitTime)
		//while (1)
	{

		packet = sender->Receive();
		while (packet)
		{
			// PARSE TYPES
			switch(packet->data[0])
			{
			case ID_CONNECTION_REQUEST_ACCEPTED:
				if (isVerbose)
					printf("ID_CONNECTION_REQUEST_ACCEPTED\n");
				doSend=true;
				nextSend=currentTime;
				break;
			case ID_NO_FREE_INCOMING_CONNECTIONS:
				if (isVerbose)
					printf("ID_NO_FREE_INCOMING_CONNECTIONS\n");
				break;
			case ID_DISCONNECTION_NOTIFICATION:
				if (isVerbose)
					printf("ID_DISCONNECTION_NOTIFICATION\n");
				break;
			case ID_CONNECTION_LOST:
				if (isVerbose)
					printf("ID_CONNECTION_LOST\n");
				break;
			case ID_CONNECTION_ATTEMPT_FAILED:
				if (isVerbose)
					printf("Connection attempt failed\n");
				break;
			}

			sender->DeallocatePacket(packet);
			packet = sender->Receive();
		}

		while (doSend && currentTime > nextSend)
		{
			streamNumberSender=0;
			//	streamNumber = randomMT() % 32;
			// Do the send
			bitStream.Reset();
			bitStream.Write((unsigned char) (ID_USER_PACKET_ENUM+1));
			bitStream.Write(packetNumberSender[streamNumberSender]++);
			bitStream.Write(streamNumberSender);
			bitStream.Write(currentTime);
			char *pad;
			int padLength = (randomMT() % 5000) + 1;
			pad = new char [padLength];
			bitStream.Write(pad, padLength);
			delete [] pad;
			// Send on a random priority with a random stream
			// if (sender->Send(&bitStream, HIGH_PRIORITY, (PacketReliability) (RELIABLE + (randomMT() %2)) ,streamNumber, UNASSIGNED_SYSTEM_ADDRESS, true)==false)
			if (sender->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED ,streamNumberSender, UNASSIGNED_SYSTEM_ADDRESS, true)==false)
				packetNumberSender[streamNumberSender]--; // Didn't finish connecting yet?

			RakNetStatistics *rssSender;
			rssSender=sender->GetStatistics(sender->GetSystemAddressFromIndex(0));
			if (isVerbose)
				printf("Snd: %i.\n", packetNumberSender[streamNumberSender]);

			nextSend+=sendInterval;

			// Test halting
			//	if (rand()%20==0)
			//		nextSend+=1000;
		}

		packet = receiver->Receive();
		while (packet)
		{
			switch(packet->data[0])
			{
			case ID_NEW_INCOMING_CONNECTION:
				if (isVerbose)
					printf("ID_NEW_INCOMING_CONNECTION\n");
				break;
			case ID_DISCONNECTION_NOTIFICATION:
				if (isVerbose)
					printf("ID_DISCONNECTION_NOTIFICATION\n");
				break;
			case ID_CONNECTION_LOST:
				if (isVerbose)
					printf("ID_CONNECTION_LOST\n");
				break;
			case ID_USER_PACKET_ENUM+1:
				bitStream.Reset();
				bitStream.Write((char*)packet->data, packet->length);
				bitStream.IgnoreBits(8); // Ignore ID_USER_PACKET_ENUM+1
				bitStream.Read(receivedPacketNumberReceiver);
				bitStream.Read(streamNumberReceiver);
				bitStream.Read(receivedTimeReceiver);

				if (receivedPacketNumberReceiver!=packetNumberReceiver[streamNumberReceiver])
				{

					//WARNING: If you modify the below code make sure the whole string remains in bounds, sprintf will NOT do it for you. 
					//The error string is 512 in length

					//Note: Removed buffer checking because chance is insignificant, left code if wanted in future. Needs limits.h ISO C standard.

					/*
					int maxIntWorkingCopy= INT_MAX;

					int maxIntCharLen =0; 

					while (maxIntWorkingCopy>0)
					{maxIntCharLen++;
					maxIntWorkingCopy/=10;
					}

					if (strlen(lastError)>maxIntCharLen* 3 +27)//512 should be a good len for now
					{*/

					sprintf(lastError,"Expecting %i got %i (channel %i).",packetNumberReceiver[streamNumberReceiver], receivedPacketNumberReceiver, streamNumberReceiver);

					/*
					}
					else
					{
					sprintf(lastError,"Did not get what was expected. More details can be given if the error string buffer size is increased.");

					}*/

					if (isVerbose)
					{

						RakNetStatistics *rssSender,*rssReceiver;
						char message[2048];

						rssSender=sender->GetStatistics(sender->GetSystemAddressFromIndex(0));

						rssReceiver=receiver->GetStatistics(receiver->GetSystemAddressFromIndex(0));
						StatisticsToString(rssSender, message, 2);
						printf("Server stats %s\n", message);
						StatisticsToString(rssReceiver, message, 2);
						printf("Client stats%s", message);

						DebugTools::ShowError(lastError,!noPauses && isVerbose,__LINE__,__FILE__);
					}

					return 1;
				}
				else
					if (isVerbose)
					{
						printf("Got %i.Channel %i.Len %i.", packetNumberReceiver[streamNumberReceiver], streamNumberReceiver, packet->length);

						printf("Sent=%u Received=%u Diff=%i.\n", receivedTimeReceiver, currentTime, (int)currentTime - (int) receivedTimeReceiver);
					}

					packetNumberReceiver[streamNumberReceiver]++;
					break;
			}

			receiver->DeallocatePacket(packet);
			packet = receiver->Receive();
		}

		RakSleep(0);

		currentTime=GetTimeMS();
	}

	if (isVerbose)
	{

		RakNetStatistics *rssSender,*rssReceiver;
		char message[2048];

		rssSender=sender->GetStatistics(sender->GetSystemAddressFromIndex(0));

		rssReceiver=receiver->GetStatistics(receiver->GetSystemAddressFromIndex(0));
		StatisticsToString(rssSender, message, 2);
		printf("Server stats %s\n", message);
		StatisticsToString(rssReceiver, message, 2);
		printf("Client stats%s", message);
	}

	if (fp)
		fclose(fp);

	return 0;
}
Exemple #8
0
/*
What is being done here is having 8 peers all connect to eachother and be
connected. Then it check if they all connect. If so send data in ordered reliable mode for 100
loops.

Possible ideas for changes:
Possibly use rakpeerinterfaces GetSystemList() for number of 
connected peers instead of manually tracking. Would be slower though,
shouldn't be significant at this number but the recieve speed it part of the test.

Success conditions:
Peers connect and receive all packets in order.
No disconnections allowed in this version of the test.

Failure conditions:

If cannot connect to all peers for 20 seconds.
All packets are not recieved.
All packets are not in order.
Disconnection.
*/
int EightPeerTest::RunTest(DataStructures::List<RakString> params,bool isVerbose,bool noPauses)
{
	const int peerNum= 8;
	RakPeerInterface *peerList[peerNum];//A list of 8 peers
	int connectionAmount[peerNum];//Counter for me to keep track of connection requests and accepts
	int recievedFromList[peerNum][peerNum];//Counter for me to keep track of packets received
	int lastNumberReceivedFromList[peerNum][peerNum];//Counter for me to keep track of last recieved sequence number
	const int numPackets=100;
	Packet *packet;
	BitStream bitStream;
	destroyList.Clear(false,_FILE_AND_LINE_);

	//Initializations of the arrays
	for (int i=0;i<peerNum;i++)
	{
		peerList[i]=RakPeerInterface::GetInstance();
		destroyList.Push(peerList[i],_FILE_AND_LINE_);
		connectionAmount[i]=0;

		for (int j=0;j<peerNum;j++)
		{
			recievedFromList[i][j]=0;
			lastNumberReceivedFromList[i][j]=0;
		}

		peerList[i]->Startup(peerNum*2, &SocketDescriptor(60000+i,0), 1);
		peerList[i]->SetMaximumIncomingConnections(peerNum);

	}

	//Connect all the peers together
	for (int i=0;i<peerNum;i++)
	{
		for (int j=i+1;j<peerNum;j++)//Start at i+1 so don't connect two of the same together.
		{
			if (peerList[i]->Connect("127.0.0.1", 60000+j, 0,0)!=CONNECTION_ATTEMPT_STARTED)
			{
				if (isVerbose)
				{
					DebugTools::ShowError("Problem while calling connect. \n",!noPauses && isVerbose,__LINE__,__FILE__);

				}
				return 1;//This fails the test, don't bother going on.
			}
		}

	}

	TimeMS entryTime=GetTimeMS();//Loop entry time
	TimeMS finishTimer=GetTimeMS();
	bool initialConnectOver=false;//Our initial connect all has been done.

	for (int k=0;k<numPackets||GetTimeMS()-finishTimer<5000;)//Quit after we send 100 messages while connected, if not all connected and not failure, otherwise fail after 20 seconds and exit
	{
		bool allConnected=true;//Start true, only one failed case makes it all fail
		for (int i=0;i<peerNum;i++)//Make sure all peers are connected to eachother
		{
			if (connectionAmount[i]<peerNum-1)
			{
				allConnected=false;
			}
		}

		if (GetTimeMS()-entryTime>20000 &&!initialConnectOver &&!allConnected)//failed for 20 seconds
		{

			if (isVerbose)
				DebugTools::ShowError("Failed to connect to all peers after 20 seconds",!noPauses && isVerbose,__LINE__,__FILE__);
			return 2;
			break;
		}

		if (allConnected)
		{
			if(!initialConnectOver)
				initialConnectOver=true;
			if (k<numPackets)
			{
			for (int i=0;i<peerNum;i++)//Have all peers send a message to all peers
			{

				bitStream.Reset();

				bitStream.Write((unsigned char) (ID_USER_PACKET_ENUM+1));

				bitStream.Write(k);
				bitStream.Write(i);

				peerList[i]->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED ,0, UNASSIGNED_SYSTEM_ADDRESS, true);

			}
			}
			k++;
		}

		if (k>=numPackets-3)//This is our last 3 packets, give it time to send packet and arrive on interface, 2 seconds is more than enough 
		{
			RakSleep(300);
			if (k==numPackets)
			{
				finishTimer=GetTimeMS();
			}
		}

		for (int i=0;i<peerNum;i++)//Receive for all peers
		{
			if (allConnected)//If all connected try to make the data more visually appealing by bunching it in one receive
			{
				int waittime=0;
				do
				{
					packet=peerList[i]->Receive();
					waittime++;

					if (!packet)
					{
						RakSleep(1);

					}

					if (waittime>1000)//Check for packet every millisec and if one second has passed move on, don't block execution
					{
						break;
					}
				}
				while(!packet);//For testing purposes wait for packet a little while, go if not recieved
			}
			else//Otherwise just keep recieving quickly until connected
			{
				packet=peerList[i]->Receive();
			}
			if (isVerbose)
				printf("For peer %i with %i connected peers.\n",i,connectionAmount[i]);
			while(packet)
			{
				switch (packet->data[0])
				{
				case ID_REMOTE_DISCONNECTION_NOTIFICATION:
					if (isVerbose)
					{
						printf("Another client has disconnected.\n");
						DebugTools::ShowError("Test failed.\n",!noPauses && isVerbose,__LINE__,__FILE__);
					}
					return 3;
					break;
				case ID_REMOTE_CONNECTION_LOST:
					if (isVerbose)
					{
						printf("Another client has lost the connection.\n");
						DebugTools::ShowError("Test failed.\n",!noPauses && isVerbose,__LINE__,__FILE__);           
					}
					return 3;
					break;
				case ID_REMOTE_NEW_INCOMING_CONNECTION:
					if (isVerbose)              
						printf("Another client has connected.\n");
					break;
				case ID_CONNECTION_REQUEST_ACCEPTED:
					if (isVerbose)              
						printf("Our connection request has been accepted.\n");
					connectionAmount[i]++;

					break;
				case ID_CONNECTION_ATTEMPT_FAILED:

					if (isVerbose)
						DebugTools::ShowError("A connection has failed.\n Test failed.\n",!noPauses && isVerbose,__LINE__,__FILE__);
					return 2;
					break;

				case ID_NEW_INCOMING_CONNECTION:
					if (isVerbose)              
						printf("A connection is incoming.\n");
					connectionAmount[i]++;//For this test assume connection. Test will fail if connection fails.
					break;
				case ID_NO_FREE_INCOMING_CONNECTIONS://Should not happend
					if (isVerbose)    
					{
						printf("The server is full. This shouldn't happen in this test ever.\n");

						DebugTools::ShowError("Test failed.\n",!noPauses && isVerbose,__LINE__,__FILE__);
					}
					return 2;
					break;

				case ID_ALREADY_CONNECTED:
					if (isVerbose)              
						printf("Already connected\n");//Shouldn't happen

					break;

				case ID_DISCONNECTION_NOTIFICATION:
					if (isVerbose)
					{
						printf("We have been disconnected.\n");

						DebugTools::ShowError("Test failed.\n",!noPauses && isVerbose,__LINE__,__FILE__);
					}
					return 3;
					break;
				case ID_CONNECTION_LOST:
					allConnected=false;
					connectionAmount[i]--;
					if (isVerbose)
					{
						printf("Connection lost.\n");

						DebugTools::ShowError("Test failed.\n",!noPauses && isVerbose,__LINE__,__FILE__);
					}

					return 3;

					break;
				default:

					if (packet->data[0]==ID_USER_PACKET_ENUM+1)
					{
						int thePeerNum;
						int sequenceNum;
						bitStream.Reset();
						bitStream.Write((char*)packet->data, packet->length);
						bitStream.IgnoreBits(8);
						bitStream.Read(sequenceNum);
						bitStream.Read(thePeerNum);
						if (isVerbose)
							printf("Message %i from %i\n",sequenceNum,thePeerNum );

						if (thePeerNum>=0&&thePeerNum<peerNum)
						{
							if (lastNumberReceivedFromList[i][thePeerNum]==sequenceNum)
							{
								lastNumberReceivedFromList[i][thePeerNum]++;
							}
							else
							{
								if (isVerbose)
								{
									printf("Packets out of order");
									DebugTools::ShowError("Test failed.\n",!noPauses && isVerbose,__LINE__,__FILE__);

								}
								return 4;
							}
							recievedFromList[i][thePeerNum]++;}
					}
					break;
				}
				peerList[i]->DeallocatePacket(packet);
				// Stay in the loop as long as there are more packets.
				packet = peerList[i]->Receive();
			}
		}
		RakSleep(0);//If needed for testing
	}

	for (int i=0;i<peerNum;i++)
	{

		for (int j=0;j<peerNum;j++)
		{
			if (i!=j)
			{
				if (isVerbose)
					printf("%i recieved %i packets from %i\n",i,recievedFromList[i][j],j);
				if  (recievedFromList[i][j]!=numPackets)
				{
					if (isVerbose)
					{
						printf("Not all packets recieved. it was in reliable ordered mode so that means test failed or wait time needs increasing\n");

						DebugTools::ShowError("Test failed.\n",!noPauses && isVerbose,__LINE__,__FILE__);
					}
					return 5;

				}

			}
		}
	}

	printf("All packets recieved in order,pass\n");
	return 0;

}
void AutoPatcher::OnAutopatcherRequestFiles( Packet *packet )
{
	assert( rakPeerInterface || rakClientInterface || rakServerInterface );
	
	BitStream serializedFileDescriptor( ( char* ) packet->data, packet->length, false );
	BitStream outputBitStream;
	DownloadableFileDescriptor dfd;
	unsigned int numberOfFilesRequested;
	unsigned index, downloadableFilesIndex;
	unsigned char packetID;
	// Holds a copy of the pointers.  Don't deallocate them!
	BasicDataStructures::List<DownloadableFileDescriptor*> sendList;
	
	// Ignore ID_AUTOPATCHER_REQUEST_FILES
	serializedFileDescriptor.IgnoreBits( sizeof( unsigned char ) * 8 );
	
	if ( serializedFileDescriptor.ReadCompressed( numberOfFilesRequested ) == false )
	{
		// Invalid packet format. Should never get this unless it's a bug or someone is hacking
#ifdef _DEBUG
		assert( 0 );
#endif
		
		return ;
	}
	
	// Go through all the files requested in the packet.
	// If we allow download of it, add the descriptor to a send list which we
	// serialize and send back to the sender telling them what files they will get.
	// This is necessary because it is possible that cheaters will request files
	// not in the list or that files will be removed from downloadable status after an initial
	// successful request for it
	for ( index = 0; index < numberOfFilesRequested; index++ )
	{
		dfd.Clear();
		
		if ( dfd.DeserializeHeader( &serializedFileDescriptor ) == false )
		{
			assert( 0 ); // Error in packet header.  Should only get this from hackers or bugs
			return ;
		}
		
		for ( downloadableFilesIndex = 0; downloadableFilesIndex < downloadableFiles.size(); downloadableFilesIndex++ )
		{
			if ( strcmp( downloadableFiles[ downloadableFilesIndex ] ->filename, dfd.filename ) == 0 )
			{
				// Record that we are going to send this file to system requesting it
				sendList.insert( downloadableFiles[ downloadableFilesIndex ] );
				break;
			}
		}
	}
	
	packetID = ID_AUTOPATCHER_SET_DOWNLOAD_LIST;
	// Serialize the list of files we will send
	outputBitStream.Write( packetID );
	outputBitStream.WriteCompressed( sendList.size() );
	
	for ( index = 0; index < sendList.size(); index++ )
		sendList[ index ] ->SerializeHeader( &outputBitStream );
		
	// Send the list of files
	if ( rakServerInterface )
		rakServerInterface->Send( &outputBitStream, MEDIUM_PRIORITY, RELIABLE_ORDERED, orderingStream, packet->playerId, false );
	else
		if ( rakPeerInterface )
			rakPeerInterface->Send( &outputBitStream, MEDIUM_PRIORITY, RELIABLE_ORDERED, orderingStream, packet->playerId, false );
		else
			rakClientInterface->Send( &outputBitStream, MEDIUM_PRIORITY, RELIABLE_ORDERED, orderingStream );
			
	// The next step is to send the actual files.  We already know what files need to be sent -
	// The files specified by the descriptors in sendList.
	packetID = ID_AUTOPATCHER_WRITE_FILE;
	
	for ( index = 0; index < sendList.size(); index++ )
	{
		// We used outputBitStream earlier so don't forget to reset it
		outputBitStream.Reset();
		outputBitStream.Write( packetID );
		sendList[ index ] ->SerializeHeader( &outputBitStream );
		sendList[ index ] ->SerializeFileData( &outputBitStream );
		
		if ( rakServerInterface )
			rakServerInterface->Send( &outputBitStream, LOW_PRIORITY, RELIABLE_ORDERED, orderingStream, packet->playerId, false );
		else
			if ( rakPeerInterface )
				rakPeerInterface->Send( &outputBitStream, LOW_PRIORITY, RELIABLE_ORDERED, orderingStream, packet->playerId, false );
			else
				rakClientInterface->Send( &outputBitStream, LOW_PRIORITY, RELIABLE_ORDERED, orderingStream );
	}
}
void* rakVoiceThread( void* arguments )
#endif
{
    SpeexBits bits;
    char output[ 2000 ];
    int outputLength;
    unsigned char typeID;
    PlayerID id;
    BitStream b;
    int availableChunks;
    int MTU;
    int numberOfChunksPerSend;
    int i;
    unsigned long lastSendTime;
    CoderStateWithPlayerIDMapStruct *cswpims;
    lastSendTime = RakNet::GetTime();
    PlayerID target;

    RakVoice *rakVoice = ( RakVoice* ) arguments;

    numberOfChunksPerSend = rakVoice->blockSize / rakVoice->frame_size;

    speex_bits_init( &bits );

    MTU = rakVoice->peer->GetMTUSize();

    while ( rakVoice->init )
    {
        if ( rakVoice->writeCursor >= rakVoice->readCursor )
            availableChunks = rakVoice->writeCursor - rakVoice->readCursor;
        else
            availableChunks = RAK_VOICE_INPUT_LIST_BUFFER_SIZE - rakVoice->readCursor + rakVoice->writeCursor;

        while ( availableChunks >= numberOfChunksPerSend )
        {
            // Get a bit of a buffer before we start sending so we don't "grind" the data and get popping as data continually arrives and runs out

            if ( RakNet::GetTime() - lastSendTime > 1000 && availableChunks < numberOfChunksPerSend * 3 )
                break;

            // Grab data at the read cursor and encode it
            speex_bits_reset( &bits );

            target = rakVoice->targetedSendRecipient[ rakVoice->readCursor ];

            cswpims = rakVoice->GetCoderFromPlayerID( rakVoice->sampleRate, target, false );

            for ( i = 0; i < numberOfChunksPerSend; i++ )
            {
                // For each frame, call speex_encode
                speex_encode( cswpims->encoderState, rakVoice->inputList[ rakVoice->readCursor ], &bits );
                rakVoice->readCursor = ( rakVoice->readCursor + 1 ) % RAK_VOICE_INPUT_LIST_BUFFER_SIZE;
            }

            availableChunks -= numberOfChunksPerSend;

            // Write the encoded bitstream
            outputLength = speex_bits_write( ( SpeexBits* ) ( &bits ), output, 2000 );
#ifdef _DEBUG

            static bool printOnce = true;

            if ( printOnce == true && outputLength > MTU )
            {
                printf( "Warning - compressed data larger than MTU! This will result in split packets and poor speech.\nYou should use a lower blockSize in the call to Init.\n" );
                printOnce = false;
            }

            else if ( printOnce == true && outputLength < MTU / 4 )
            {
                printf( "Warning - compressed data smaller than 1/4 the MTU.  This is not an efficient use of bandwidth.\nYou might want to use a larger blockSize in the call to Init.\n" );
                printOnce = false;
            }

#endif

            b.Reset();

            typeID = ID_VOICE_PACKET;

            b.Write( typeID );

            b.Write( ( char* ) & target, sizeof( target ) );

            b.Write( rakVoice->bps ); // Write how many bits we are encoding the data with

            b.Write( rakVoice->sampleRate );  // Write the sampling rate

            id = rakVoice->peer->GetInternalID();

            b.Write( ( char* ) & id, sizeof( id ) ); // Write who is sending this packet

            b.Write( cswpims->nextPacketNumber ); // Write what speech packet number this is, so we can compensate for lost packets

            cswpims->nextPacketNumber++;

            b.Write( output, outputLength );


            /*
            // This is for showing memory usage
            printf("PCMQueue=%i PCMQueuePool=%i\ndecoderStateList=%i encoderStateList=%i\n",
            rakVoice->PCMQueue.size(),
            rakVoice->PCMQueuePool.size(),
            rakVoice->decoderStateList.size(),
            rakVoice->encoderStateList.size());
            */

            // THis was for testing as a feedback loop
            //if (target==rakVoice->peer->GetInternalID())
            // rakVoice->DecodeAndQueueSoundPacket((char*)b.GetData(), b.GetNumberOfBytesUsed());
            //else
            rakVoice->peer->Send( &b, HIGH_PRIORITY, RELIABLE_SEQUENCED, 0, target, false );

            lastSendTime = RakNet::GetTime();
        }

        // Send out a packet aggreggate roughly every x ms
#ifdef _WIN32
        Sleep( 30 );

#else

        usleep( 30 * 1000 );

#endif

    }

    speex_bits_destroy( &bits );
    return 0;
}