예제 #1
0
void VariadicSQLParser::GetTypeMappingIndices( const char *format, DataStructures::List<IndexAndType> &indices )
{
	bool previousCharWasPercentSign;
	unsigned int i;
	unsigned int typeMappingIndex;
	indices.Clear(false, _FILE_AND_LINE_);
	unsigned int len = (unsigned int) strlen(format);
	previousCharWasPercentSign=false;
	for (i=0; i < len; i++)
	{
		if (previousCharWasPercentSign==true )
		{
			typeMappingIndex = GetTypeMappingIndex(format[i]);
			if (typeMappingIndex!=(unsigned int) -1)
			{
				IndexAndType iat;
				iat.strIndex=i-1;
				iat.typeMappingIndex=typeMappingIndex;
				indices.Insert(iat, _FILE_AND_LINE_ );
			}
		}

		previousCharWasPercentSign=format[i]=='%';
	}
}
void LightweightDatabaseServer::RemoveRowsFromIP(PlayerID playerId)
{
	// Remove rows for tables that do so on a system disconnect
	DatabaseTable *databaseTable;
	DataStructures::List<unsigned> removeList;
	DataStructures::Page<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> *cur;
	unsigned i,j;
	for (i=0; i < database.Size(); i++)
	{
		databaseTable=database[i];
		if (databaseTable->removeRowOnDisconnect)
		{
			DataStructures::BPlusTree<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> &rows = databaseTable->table.GetRows();
			cur = rows.GetListHead();
			while (cur)
			{
				// Mark dropped entities
				for (j=0; j < (unsigned)cur->size; j++)
				{
					if (RowHasIP(cur->data[j], playerId, databaseTable->systemIdColumnIndex))
						removeList.Insert(cur->keys[j]);
				}
				cur=cur->next;
			}

			for (j=0; j < removeList.Size(); j++)
				databaseTable->table.RemoveRow(removeList[i]);
			removeList.Clear(true);
		}
	}	
}
예제 #3
0
void StatisticsHistory::GetUniqueKeyList(DataStructures::List<RakString> &keys)
{
	keys.Clear(true, _FILE_AND_LINE_);

	for (unsigned int idx=0; idx < objects.Size(); idx++)
	{
		TrackedObject *to = objects[idx];
		DataStructures::List<TimeAndValueQueue*> itemList;
		DataStructures::List<RakNet::RakString> keyList;
		to->dataQueues.GetAsList(itemList, keyList, _FILE_AND_LINE_);
		for (unsigned int k=0; k < keyList.Size(); k++)
		{
			bool hasKey=false;
			for (unsigned int j=0; j < keys.Size(); j++)
			{
				if (keys[j]==keyList[k])
				{
					hasKey=true;
					break;
				}
			}

			if (hasKey==false)
				keys.Push(keyList[k], _FILE_AND_LINE_);
		}
	}
}
예제 #4
0
void FullyConnectedMesh2::GetVerifiedJoinAcceptedAdditionalData(Packet *packet, bool *thisSystemAccepted, DataStructures::List<RakNetGUID> &systemsAccepted, BitStream *additionalData)
{
	systemsAccepted.Clear(true, _FILE_AND_LINE_);

	RakNet::BitStream bsIn(packet->data, packet->length, false);
	bsIn.IgnoreBytes(sizeof(MessageID));
	RakNetGUID systemToAddGuid;
	bsIn.Read(systemToAddGuid);
	*thisSystemAccepted = systemToAddGuid == rakPeerInterface->GetMyGUID();
	unsigned short listSize;
	bsIn.Read(listSize);
	bsIn.IgnoreBytes(listSize*RakNetGUID::size());
	bsIn.Read(listSize);
	if (systemToAddGuid==rakPeerInterface->GetMyGUID())
	{
		for (unsigned short i=0; i < listSize; i++)
		{
			bsIn.Read(systemToAddGuid);
			systemsAccepted.Push(systemToAddGuid, _FILE_AND_LINE_);
		}
		systemsAccepted.Push(packet->guid, _FILE_AND_LINE_);
	}
	else
	{
		systemsAccepted.Push(systemToAddGuid, _FILE_AND_LINE_);
		bsIn.IgnoreBytes(listSize*RakNetGUID::size());
	}
	if (additionalData)
	{
		additionalData->Reset();
		additionalData->Write(bsIn);
	}
}
예제 #5
0
void GridSectorizer::GetEntries(DataStructures::List<void*>& intersectionList, const float minX, const float minY, const float maxX, const float maxY)
{
#ifdef _USE_ORDERED_LIST
	DataStructures::OrderedList<void*, void*>* cell;
#else
	DataStructures::List<void*>* cell;
#endif
	int xStart, yStart, xEnd, yEnd, xCur, yCur;
	unsigned index;
	xStart=WorldToCellXOffsetAndClamped(minX);
	yStart=WorldToCellYOffsetAndClamped(minY);
	xEnd=WorldToCellXOffsetAndClamped(maxX);
	yEnd=WorldToCellYOffsetAndClamped(maxY);

	intersectionList.Clear(true, _FILE_AND_LINE_);
	for (xCur=xStart; xCur <= xEnd; ++xCur)
	{
		for (yCur=yStart; yCur <= yEnd; ++yCur)
		{
			cell = grid+yCur*gridCellWidthCount+xCur;
			for (index=0; index < cell->Size(); ++index)
				intersectionList.Insert(cell->operator [](index), _FILE_AND_LINE_);
		}
	}
}
void FullyConnectedMesh2::GetParticipantList(DataStructures::List<RakNetGUID> &participantList)
{
	participantList.Clear(true, _FILE_AND_LINE_);
	unsigned int i;
	for (i=0; i < fcm2ParticipantList.Size(); i++)
		participantList.Push(fcm2ParticipantList[i].rakNetGuid, _FILE_AND_LINE_);
}
예제 #7
0
void TeamBalancer::GetOverpopulatedTeams(DataStructures::List<TeamId> &overpopulatedTeams, int maxTeamSize)
{
	overpopulatedTeams.Clear(true,_FILE_AND_LINE_);
	for (TeamId i=0; i < teamMemberCounts.Size(); i++)
	{
		if (teamMemberCounts[i]>=maxTeamSize)
			overpopulatedTeams.Push(i,_FILE_AND_LINE_);
	}
}
예제 #8
0
void FullyConnectedMesh2::GetVerifiedJoinRequiredProcessingList(RakNetGUID host, DataStructures::List<SystemAddress> &addresses, DataStructures::List<RakNetGUID> &guids)
{
	addresses.Clear(true, _FILE_AND_LINE_);
	guids.Clear(true, _FILE_AND_LINE_);

	unsigned int curIndex = GetJoinsInProgressIndex(host);
	if (curIndex!=(unsigned int) -1)
	{
		VerifiedJoinInProgress *vjip = joinsInProgress[curIndex];
		unsigned int j;
		for (j=0; j < vjip->members.Size(); j++)
		{
			if (vjip->members[j].joinInProgressState==JIPS_PROCESSING)
			{
				addresses.Push(vjip->members[j].systemAddress, _FILE_AND_LINE_);
				guids.Push(vjip->members[j].guid, _FILE_AND_LINE_);
			}
		}
	}
}
예제 #9
0
void NatPunchthrough::ConnectionRequest::GetAddressList(RakPeerInterface *rakPeer, DataStructures::List<SystemAddress> &fallbackAddresses, SystemAddress publicAddress, SystemAddress privateAddress, bool excludeConnected)
{
	SystemAddress fallback;
	fallbackAddresses.Clear(true);
	fallback.binaryAddress=publicAddress.binaryAddress;

	fallback.port=publicAddress.port;
	if (excludeConnected==false || rakPeer->IsConnected(fallback,true)==false)
		fallbackAddresses.Insert(fallback);

	if (privateAddress!=publicAddress && privateAddress!=UNASSIGNED_SYSTEM_ADDRESS && (excludeConnected==false ||rakPeer->IsConnected(privateAddress,true)==false))
		fallbackAddresses.Insert(privateAddress);

	fallback.port=publicAddress.port+1;
	if (excludeConnected==false || rakPeer->IsConnected(fallback,true)==false)
		fallbackAddresses.Insert(fallback);
	fallback.port=publicAddress.port+2;
	if (excludeConnected==false || rakPeer->IsConnected(fallback,true)==false)
		fallbackAddresses.Insert(fallback);

	fallback.port=rakPeer->GetInternalID().port;
	if (fallbackAddresses.GetIndexOf(fallback)==(unsigned) -1 && (excludeConnected==false || rakPeer->IsConnected(fallback,true)==false))
		fallbackAddresses.Insert(fallback);
	fallback.port=rakPeer->GetInternalID().port+1;
	if (fallbackAddresses.GetIndexOf(fallback)==(unsigned) -1 && (excludeConnected==false || rakPeer->IsConnected(fallback,true)==false))
		fallbackAddresses.Insert(fallback);
	fallback.port=rakPeer->GetInternalID().port+2;
	if (fallbackAddresses.GetIndexOf(fallback)==(unsigned) -1 && (excludeConnected==false || rakPeer->IsConnected(fallback,true)==false))
		fallbackAddresses.Insert(fallback);

	// Try to keep down the number of fallbacks or the router may run out of mappings
	/*
	fallback.port=publicAddress.port+3;
	if (excludeConnected==false || rakPeer->IsConnected(fallback,true)==false)
		fallbackAddresses.Insert(fallback);
	fallback.port=publicAddress.port+4;
	if (excludeConnected==false || rakPeer->IsConnected(fallback,true)==false)
		fallbackAddresses.Insert(fallback);

	fallback.port=rakPeer->GetInternalID().port+3;
	if (fallbackAddresses.GetIndexOf(fallback)==(unsigned) -1 && (excludeConnected==false || rakPeer->IsConnected(fallback,true)==false))
		fallbackAddresses.Insert(fallback);
	fallback.port=rakPeer->GetInternalID().port+4;
	if (fallbackAddresses.GetIndexOf(fallback)==(unsigned) -1 && (excludeConnected==false || rakPeer->IsConnected(fallback,true)==false))
		fallbackAddresses.Insert(fallback);
		*/

}
예제 #10
0
void LightweightDatabaseServer::RemoveRowsFromIP(SystemAddress systemAddress)
{
	// Remove rows for tables that do so on a system disconnect
	DatabaseTable *databaseTable;
	DataStructures::List<unsigned> removeList;
	DataStructures::Table::Row* row;
	DataStructures::Page<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> *cur;
	unsigned i,j;
	for (i=0; i < database.Size(); i++)
	{
		databaseTable=database[i];
		if ((unsigned int) databaseTable->SystemAddressColumnIndex!=(unsigned int)-1)
		{
			const DataStructures::BPlusTree<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> &rows = databaseTable->table.GetRows();
			cur = rows.GetListHead();
			while (cur)
			{
				// Mark dropped entities
				for (j=0; j < (unsigned)cur->size; j++)
				{
					if (RowHasIP(cur->data[j], systemAddress, databaseTable->SystemAddressColumnIndex))
					{
						if (databaseTable->removeRowOnDisconnect)
						{
							removeList.Insert(cur->keys[j], __FILE__, __LINE__);
						}
						else if (databaseTable->removeRowOnPingFailure)
						{
							row = cur->data[j];
							row->cells[databaseTable->nextPingSendColumnIndex]->i=(double)(RakNet::GetTime()+SEND_PING_INTERVAL+(randomMT()%1000));
						}
					}
				}
				cur=cur->next;
			}
		}

		for (j=0; j < removeList.Size(); j++)
			databaseTable->table.RemoveRow(removeList[j]);
		removeList.Clear(true, __FILE__,__LINE__);
	}
}
void FullyConnectedMesh2::GetHostOrder(DataStructures::List<RakNetGUID> &hostList)
{
	hostList.Clear(true, _FILE_AND_LINE_);

	if (ourFCMGuid==0 || fcm2ParticipantList.Size()==0)
	{
		hostList.Push(rakPeerInterface->GetMyGUID(), _FILE_AND_LINE_);
		return;
	}

	FCM2Participant fcm2;
	fcm2.fcm2Guid=ourFCMGuid;
	fcm2.rakNetGuid=rakPeerInterface->GetMyGUID();

	DataStructures::OrderedList<FCM2Participant, FCM2Participant, FCM2ParticipantComp> olist;
	olist.Insert(fcm2, fcm2, true, _FILE_AND_LINE_);
	for (unsigned int i=0; i < fcm2ParticipantList.Size(); i++)
		olist.Insert(fcm2ParticipantList[i], fcm2ParticipantList[i], true, _FILE_AND_LINE_);

	for (unsigned int i=0; i < olist.Size(); i++)
	{
		hostList.Push(olist[i].rakNetGuid, _FILE_AND_LINE_);
	}
}
예제 #12
0
void LightweightDatabaseServer::Update(void)
{
	RakNetTime time=0;
	DatabaseTable *databaseTable;
	DataStructures::Page<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> *cur;
	unsigned i,j;
	DataStructures::Table::Row* row;
	DataStructures::List<unsigned> removeList;
	SystemAddress systemAddress;

	// periodic ping if removing system that do not respond to pings.
	for (i=0; i < database.Size(); i++)
	{
		databaseTable=database[i];

		if (databaseTable->removeRowOnPingFailure)
		{
			// Reading the time is slow - only do it once if necessary.
			if (time==0)
				time = RakNet::GetTime();

			if (databaseTable->nextRowPingCheck < time)
			{
				databaseTable->nextRowPingCheck=time+1000+(randomMT()%1000);
				const DataStructures::BPlusTree<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> &rows = databaseTable->table.GetRows();
				cur = rows.GetListHead();
				while (cur)
				{
					// Mark dropped entities
					for (j=0; j < (unsigned)cur->size; j++)
					{
						row = cur->data[j];
						row->cells[databaseTable->SystemAddressColumnIndex]->Get((char*)&systemAddress, 0);
						if (rakPeerInterface->IsConnected(systemAddress)==false)
						{
							if (time > time - (unsigned int) row->cells[databaseTable->lastPingResponseColumnIndex]->i &&
								time - (unsigned int) row->cells[databaseTable->lastPingResponseColumnIndex]->i > (unsigned int) DROP_SERVER_INTERVAL)
							{
								removeList.Insert(cur->keys[j], __FILE__, __LINE__);
							}
							else
							{
								if (row->cells[databaseTable->nextPingSendColumnIndex]->i < (int) time)
								{
									char str1[64];
									systemAddress.ToString(false, str1);
									rakPeerInterface->Ping(str1, systemAddress.port, false);
									row->cells[databaseTable->nextPingSendColumnIndex]->i=(double)(time+SEND_PING_INTERVAL+(randomMT()%1000));
								}
							}
						}
					}
					cur=cur->next;
				}

				// Remove dropped entities
				for (j=0; j < removeList.Size(); j++)
					databaseTable->table.RemoveRow(removeList[i]);
				removeList.Clear(true, __FILE__,__LINE__);

			}
		}
	}
}
PGresult * PostgreSQLInterface::QueryVariadic( const char * input, ... )
{
	RakNet::RakString query;
	PGresult *result;
	DataStructures::List<VariadicSQLParser::IndexAndType> indices;
	if ( input==0 || input[0]==0 )
		return 0;

	// Lookup this query in the stored query table. If it doesn't exist, prepare it.
	RakNet::RakString inputStr;
	inputStr=input;
	unsigned int preparedQueryIndex;
	for (preparedQueryIndex=0; preparedQueryIndex < preparedQueries.Size(); preparedQueryIndex++)
	{
		if (preparedQueries[preparedQueryIndex].StrICmp(inputStr)==0)
			break;
	}

	// Find out how many params there are
	// Find out the type of each param (%f, %s)
	indices.Clear(false, _FILE_AND_LINE_);
	GetTypeMappingIndices( input, indices );

	if (preparedQueryIndex==preparedQueries.Size())
	{
//		if (indices.Size()>0)
//			query += " (";
		RakNet::RakString formatCopy;
		RakNet::RakString insertion;
		formatCopy=input;
		unsigned int i;
		unsigned int indexOffset=0;
		for (i=0; i < indices.Size(); i++)
		{
//			if (i!=0)
//				query += ",";
//			query+=typeMappings[indices[i].typeMappingIndex].type;
			formatCopy.SetChar(indices[i].strIndex+indexOffset, '$');
//			if (i < 9)
//				formatCopy.SetChar(indices[i].strIndex+1, i+1+'0');
//			else
			insertion=RakNet::RakString("%i::%s", i+1, VariadicSQLParser::GetTypeMappingAtIndex(indices[i].typeMappingIndex));
			formatCopy.SetChar(indices[i].strIndex+1+indexOffset, insertion);
			indexOffset+=(unsigned int) insertion.GetLength()-1;
		}
//		if (indices.Size()>0)
//			query += ")";
//		query += " AS ";
		query += formatCopy;
	//	query += ";\n";
		formatCopy+= ";\n";
		result = PQprepare(pgConn, RakNet::RakString("PGSQL_ExecuteVariadic_%i", preparedQueries.Size()), formatCopy.C_String(), indices.Size(), NULL);
		if (IsResultSuccessful(result, false))
		{
			PQclear(result);
			preparedQueries.Insert(inputStr, _FILE_AND_LINE_);
		}
		else
		{
			printf(formatCopy.C_String());
			printf("\n");
			printf(lastError);
			RakAssert(0);
			PQclear(result);
			return 0;
		}
	}

//	char *paramData[512];
//	int paramLength[512];
//	int paramFormat[512];

	va_list argptr;
	va_start(argptr, input);
	char **paramData;
	int *paramLength;
	int *paramFormat;
	ExtractArguments(argptr, indices, &paramData, &paramLength);
	paramFormat=RakNet::OP_NEW_ARRAY<int>(indices.Size(),_FILE_AND_LINE_);
	for (unsigned int i=0; i < indices.Size(); i++)
		paramFormat[i]=PQEXECPARAM_FORMAT_BINARY;
	result = PQexecPrepared(pgConn, RakNet::RakString("PGSQL_ExecuteVariadic_%i", preparedQueryIndex), indices.Size(), paramData, paramLength, paramFormat, PQEXECPARAM_FORMAT_BINARY );
	VariadicSQLParser::FreeArguments(indices, paramData, paramLength);
	RakNet::OP_DELETE_ARRAY(paramFormat,_FILE_AND_LINE_);
	va_end(argptr);

	if (IsResultSuccessful(result, false)==false)
	{
		printf(lastError);
		PQclear(result);
		return 0;
	}
	return result;
}
void LightweightDatabaseServer::Update(RakPeerInterface *peer)
{
	RakNetTime time=0;
	DatabaseTable *databaseTable;
	DataStructures::Page<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> *cur;
	unsigned i,j;
	DataStructures::Table::Row* row;
	DataStructures::List<unsigned> removeList;
	PlayerID playerId;

	// periodic ping if removing system that do not respond to pings.
	for (i=0; i < database.Size(); i++)
	{
		databaseTable=database[i];

		if (databaseTable->removeRowOnPingFailure)
		{
			// Reading the time is slow - only do it once if necessary.
			if (time==0)
				 time = RakNet::GetTime();

			if (databaseTable->nextRowPingCheck < time)
			{
				databaseTable->nextRowPingCheck=time+1000+(randomMT()%1000);
				DataStructures::BPlusTree<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> &rows = databaseTable->table.GetRows();
				cur = rows.GetListHead();
				while (cur)
				{
					// Mark dropped entities
					for (j=0; j < (unsigned)cur->size; j++)
					{
						row = cur->data[j];
						if (time - row->cells[databaseTable->lastPingResponseColumnIndex]->i > DROP_SERVER_INTERVAL)
							removeList.Insert(cur->keys[j]);
					}
					cur=cur->next;
				}

				// Remove dropped entities
				for (j=0; j < removeList.Size(); j++)
					databaseTable->table.RemoveRow(removeList[i]);
				removeList.Clear(true);

				cur = rows.GetListHead();
				// Ping remaining entities if they are not connected.  If they are connected just increase the ping interval.
				while (cur)
				{
					for (j=0; j < (unsigned)cur->size; j++)
					{
						row = cur->data[j];
						if (row->cells[databaseTable->nextPingSendColumnIndex]->i < (int) time)
						{
							row->cells[databaseTable->systemIdColumnIndex]->Get((char*)&playerId, 0);
							if (peer->GetIndexFromPlayerID(playerId)==-1)
							{
								peer->Ping(playerId.ToString(false), playerId.port, false);
							}
							else
							{
								// Consider the fact that they are connected to be a ping response
								row->cells[databaseTable->lastPingResponseColumnIndex]->i=time;
							}
							
							row->cells[databaseTable->nextPingSendColumnIndex]->i=time+SEND_PING_INTERVAL+(randomMT()%1000);
						}
					}
					cur=cur->next;
				}
			}
		}
	}
}
예제 #15
0
void NatPunchthrough::Update(RakPeerInterface *peer)
{
	(void) peer;
	if (connectionRequestList.Size())
	{
		RakNetTime time = RakNet::GetTime();
		RakNet::BitStream outBitstream;
		unsigned i;
		i=0;
		while (i < connectionRequestList.Size())
		{
			// Remove old connection requests that get no answer
			if (connectionRequestList[i]->timeoutTime < time)
			{
				rakFree(connectionRequestList[i]->passwordData);
				delete connectionRequestList[i];
				connectionRequestList.RemoveAtIndex(i);
				continue;
			}
			
			// If we are a facilitator, do pings
			if (connectionRequestList[i]->facilitatingConnection)
			{
				if (time >= connectionRequestList[i]->nextActionTime )
				{
					if (connectionRequestList[i]->pingCount < PING_COUNT)
					{
						// Ping
						connectionRequestList[i]->pingCount++;
						rakPeer->Ping(connectionRequestList[i]->receiverPublic);
						rakPeer->Ping(connectionRequestList[i]->senderPublic);
						connectionRequestList[i]->nextActionTime=time+PING_INTERVAL;
					}
					else if (connectionRequestList[i]->pingCount == PING_COUNT)
					{
						// Done pinging.  Wait till the next stage
						int receiverPing, senderPing;
						receiverPing=rakPeer->GetAveragePing(connectionRequestList[i]->receiverPublic);
						senderPing=rakPeer->GetAveragePing(connectionRequestList[i]->senderPublic);
						if (receiverPing > senderPing)
							connectionRequestList[i]->nextActionTime=(RakNetTime)(receiverPing*SEND_TIMESTAMP_DELAY_PING_MULTIPLE);
						else
							connectionRequestList[i]->nextActionTime=(RakNetTime)(senderPing*SEND_TIMESTAMP_DELAY_PING_MULTIPLE);
						connectionRequestList[i]->pingCount++;
					}
					else
					{
						// Send the timestamped message to both systems so they send datagrams to each other simultaneously
						int receiverPing, senderPing;
						RakNetTime delayTime;
						receiverPing=rakPeer->GetAveragePing(connectionRequestList[i]->receiverPublic);
						senderPing=rakPeer->GetAveragePing(connectionRequestList[i]->senderPublic);
						if (receiverPing > senderPing)
							delayTime=(RakNetTime)(receiverPing*SEND_PUNCHTHROUGH_DELAY_PING_MULTIPLE);
						else
							delayTime=(RakNetTime)(senderPing*SEND_PUNCHTHROUGH_DELAY_PING_MULTIPLE);

						if (delayTime < 500)
							delayTime=500;

						outBitstream.Reset();
						outBitstream.Write((MessageID)ID_TIMESTAMP);
						outBitstream.Write(time+delayTime);
						outBitstream.Write((MessageID)ID_NAT_CONNECT_AT_TIME);
						// A few poorly behaved NATs are known to scan the body of UDP datagrams for 4-byte fields that look like IP addresses, and translate them as they would the IP address fields in the IP header.
						outBitstream.Write(true);
						outBitstream.Write(rakPeer->GetInternalID(connectionRequestList[i]->receiverPublic));
						rakPeer->Send(&outBitstream, SYSTEM_PRIORITY, RELIABLE, 0, connectionRequestList[i]->senderPublic, false);

						outBitstream.Reset();
						outBitstream.Write((MessageID)ID_TIMESTAMP);
						outBitstream.Write(time+delayTime);
						outBitstream.Write((MessageID)ID_NAT_SEND_OFFLINE_MESSAGE_AT_TIME);
						// A few poorly behaved NATs are known to scan the body of UDP datagrams for 4-byte fields that look like IP addresses, and translate them as they would the IP address fields in the IP header.
						outBitstream.Write(true);
						outBitstream.Write(connectionRequestList[i]->senderPublic);
						outBitstream.Write(rakPeer->GetInternalID(connectionRequestList[i]->senderPublic));
						rakPeer->Send(&outBitstream, SYSTEM_PRIORITY, RELIABLE, 0, connectionRequestList[i]->receiverPublic, false);

						delete [] connectionRequestList[i]->passwordData;
						delete connectionRequestList[i];
						connectionRequestList.RemoveAtIndex(i);
						continue;
					}
				}	
			}
			// Else not a facilitator.  If nextActionTime is non-zero, connect or send the offline message
			else if (connectionRequestList[i]->nextActionTime && time >= connectionRequestList[i]->nextActionTime && connectionRequestList[i]->attemptedConnection==false)
			{
				ConnectionRequest *connectionRequest = connectionRequestList[i];
				DataStructures::List<SystemAddress> fallbackAddresses;
//				unsigned fallbackIndex;
				RakNet::BitStream oob;
				if (connectionRequest->receiverPublic!=UNASSIGNED_SYSTEM_ADDRESS)
				{
			//		fallbackAddresses.Clear();
			//		connectionRequest->GetAddressList(peer, fallbackAddresses, connectionRequest->senderPublic, connectionRequest->senderPrivate, true);
			//		for (unsigned fallbackIndex=0; fallbackIndex < fallbackAddresses.Size(); fallbackIndex++)
			//			peer->Ping(fallbackAddresses[fallbackIndex].ToString(false),fallbackAddresses[fallbackIndex].port,false);

					// Connect to this system.
					LogOut(FormatString("Connecting to public address %s\n", connectionRequest->receiverPublic.ToString(true)));
					rakPeer->Connect(connectionRequest->receiverPublic.ToString(false), connectionRequest->receiverPublic.port, connectionRequest->passwordData, connectionRequest->passwordDataLength);
					connectionRequest->attemptedConnection=true;

					/*
					if (connectionRequestList[i]->receiverPrivate==connectionRequestList[i]->receiverPublic)
					{
						// Otherwise done with this connection, as it's a normal connection attempt
						rakFree(connectionRequestList[i]->passwordData);
						delete connectionRequestList[i];
						connectionRequestList.RemoveAtIndex(i);
						continue;
					}
					*/
				}
				else
				{
					RakAssert(connectionRequestList[i]->senderPublic!=UNASSIGNED_SYSTEM_ADDRESS);

					// Send ID_NAT_ADVERTISE_RECIPIENT_PORT to all possible remote ports
					fallbackAddresses.Clear();
					connectionRequest->GetAddressList(peer, fallbackAddresses, connectionRequest->senderPublic, connectionRequest->senderPrivate, true);
					
					/// 04/13/08 I think if I send to all possible fallbacks in order it starts reusing external ports or else assigns them in a random way
					/// Sending 4X to each port in order did work however.
					/// Timing matches that of RakPeer's failure notices and retries
					if ((unsigned int) connectionRequestList[i]->recipientOfflineCount < fallbackAddresses.Size())
					{
						unsigned k;
						//for (k=0; k < 4; k++)
						for (k=0; k < (unsigned) connectionRequestList[i]->recipientOfflineCount && k < fallbackAddresses.Size(); k++)
						{
							oob.Write(ID_NAT_ADVERTISE_RECIPIENT_PORT);
							oob.Write(rakPeer->GetExternalID(connectionRequest->facilitator));
							// This is duplicated intentionally, since the first packet is often dropped
							peer->SendOutOfBand(fallbackAddresses[k].ToString(false),fallbackAddresses[k].port,ID_OUT_OF_BAND_INTERNAL,(const char*) oob.GetData(),oob.GetNumberOfBytesUsed(),0);
							peer->SendOutOfBand(fallbackAddresses[k].ToString(false),fallbackAddresses[k].port,ID_OUT_OF_BAND_INTERNAL,(const char*) oob.GetData(),oob.GetNumberOfBytesUsed(),0);
						}

						LogOut(FormatString("Recipient sending ID_OUT_OF_BAND_INTERNAL to %s\n", fallbackAddresses[connectionRequestList[i]->recipientOfflineCount].ToString(true)));
					}

					/*
					for (fallbackIndex=0; fallbackIndex < fallbackAddresses.Size(); fallbackIndex++)
					{
						// This follows a similar path to the sender connecting to us.
						// If this message arrives, it lets the sender know our external port.
						// The sender can then use this port instead of just going down the fallbackAddresses guessing.
						// This saves us if the recipient is impossible to connect to, but the sender is not.
						oob.Reset();
						oob.Write(ID_NAT_ADVERTISE_RECIPIENT_PORT);
						oob.Write(rakPeer->GetExternalID(connectionRequest->facilitator));
						peer->SendOutOfBand(fallbackAddresses[fallbackIndex].ToString(false),fallbackAddresses[fallbackIndex].port,ID_OUT_OF_BAND_INTERNAL,(const char*) oob.GetData(),oob.GetNumberOfBytesUsed(),0);

						// bool SendOutOfBand(const char *host, unsigned short remotePort, MessageID header, const char *data, BitSize_t dataLength, unsigned connectionSocketIndex=0 );
					}
					*/


//					LogOut(FormatString("Pinging %s\n", connectionRequest->senderPublic.ToString(true)));

				//	rakPeer->Connect(connectionRequestList[i]->senderPublic.ToString(false),connectionRequestList[i]->senderPublic.port,0,0,0);

					/*
					SystemAddress senderAddrWithFPort;
					SystemAddress senderAddrWithRPort;
					SystemAddress senderAddrWithIPort;
					senderAddrWithFPort=connectionRequestList[i]->senderPublic;
					senderAddrWithFPort.port=connectionRequestList[i]->facilitator.port;
					senderAddrWithRPort=connectionRequestList[i]->senderPublic;
					senderAddrWithRPort.port=rakPeer->GetExternalID(connectionRequestList[i]->facilitator).port;
					senderAddrWithIPort=connectionRequestList[i]->senderPublic;
					senderAddrWithIPort.port=rakPeer->GetInternalID().port;
					*/

				//	LogOut(FormatString("Recipient sending TTL %i hops to %s\n", TTL_HOPS, connectionRequestList[i]->senderPublic.ToString()));
				//	rakPeer->SendTTL(connectionRequestList[i]->senderPublic.ToString(false), connectionRequestList[i]->senderPublic.port, false);


					// Send offline message to this system, hopefully at the exact same time that system tries to connect to us.
//					rakPeer->Ping(connectionRequestList[i]->senderPublic.ToString(false), connectionRequestList[i]->senderPublic.port, false);
					/*
					rakPeer->Ping(senderAddrWithFPort.ToString(false), senderAddrWithFPort.port, false);
					rakPeer->Ping(senderAddrWithRPort.ToString(false), senderAddrWithRPort.port, false);
					rakPeer->Ping(senderAddrWithIPort.ToString(false), senderAddrWithIPort.port, false);
					*/

			//		if (connectionRequestList[i]->senderPrivate!=connectionRequestList[i]->senderPublic)
			//			rakPeer->Ping(connectionRequestList[i]->senderPrivate.ToString(false), connectionRequestList[i]->senderPrivate.port, false);

			//		LogOut(FormatString("Recipient sending TTL %i hops to %s\n", TTL_HOPS, connectionRequestList[i]->senderPublic.ToString(false)));
				//	peer->SendTTL(connectionRequestList[i]->senderPublic.ToString(false),connectionRequestList[i]->senderPublic.port, TTL_HOPS+connectionRequestList[i]->recipientOfflineCount, 0);
				//	peer->SendTTL(connectionRequestList[i]->senderPublic.ToString(false),connectionRequestList[i]->senderPublic.port+1, TTL_HOPS+connectionRequestList[i]->recipientOfflineCount, 0);
				//	peer->SendTTL(connectionRequestList[i]->senderPrivate.ToString(false),connectionRequestList[i]->senderPrivate.port, TTL_HOPS+connectionRequestList[i]->recipientOfflineCount, 0);

					connectionRequestList[i]->recipientOfflineCount++;
					if (connectionRequestList[i]->recipientOfflineCount==RECIPIENT_OFFLINE_MAX_COUNT)
					{
						rakFree(connectionRequestList[i]->passwordData);
						delete connectionRequestList[i];
						connectionRequestList.RemoveAtIndex(i);
					}
					else
					{
						connectionRequestList[i]->nextActionTime=time+RECIPIENT_OFFLINE_MESSAGE_INTERVAL;
					}

					continue;
				}
			}
			
			i++;
		}
	}
}
예제 #16
0
HTTPReadResult PHPDirectoryServer2::ProcessHTTPRead(RakNet::RakString httpRead)
{
	const char *c = (const char*) httpRead.C_String(); // current position
	HTTPReadResult resultCode=HTTP_RESULT_EMPTY;

	lastDownloadedTable.Clear();


	if (*c=='\n')
		c++;
	char buff[256];
	int buffIndex;
	bool isCommand=true;
	DataStructures::List<RakNet::RakString> columns;
	DataStructures::List<RakNet::RakString> values;
	RakNet::RakString curString;
	bool isComment=false;
	buffIndex=0;
	while(c && *c)
	{
		// 3 is comment
		if (*c=='\003')
		{
			isComment=!isComment;
			c++;
			continue;
		}
		if (isComment)
		{
			c++;
			continue;
		}

		// 1 or 2 separates fields
		// 4 separates rows
		if (*c=='\001')
		{
			if (isCommand)
			{
				buff[buffIndex]=0;
				columns.Push(RakString::NonVariadic(buff), _FILE_AND_LINE_);
				isCommand=false;
				if (buff[0]!=0)
					resultCode=HTTP_RESULT_GOT_TABLE;
			}
			else
			{
				buff[buffIndex]=0;
				values.Push(RakString::NonVariadic(buff), _FILE_AND_LINE_);
				isCommand=true;
			}
			buffIndex=0;
		}
		else if (*c=='\002')
		{
			buff[buffIndex]=0;
			buffIndex=0;
			values.Push(RakString::NonVariadic(buff), _FILE_AND_LINE_);
			isCommand=true;
			PushColumnsAndValues(columns, values);
			columns.Clear(true, _FILE_AND_LINE_);
			values.Clear(true, _FILE_AND_LINE_);

		}
		else
		{
			if (buffIndex<256-1)
				buff[buffIndex++]=*c;
		}
		c++;
	}
	if (buff[0] && columns.Size()==values.Size()+1)
	{
		buff[buffIndex]=0;
		values.Push(RakString::NonVariadic(buff), _FILE_AND_LINE_);
	}

	PushColumnsAndValues(columns, values);

	return resultCode;
}
예제 #17
0
int main(int argc, char *argv[])
{

	int returnVal;
	char str[512];
	int numTests=0;
	int testListSize=0;
	int passedTests=0;
	DataStructures::List <TestInterface*> testList;//Pointer list
	DataStructures::List <int> testResultList;//A list of pass and/or fail and the error codes
	DataStructures::List <RakString> testsToRun;//A list of tests to run
	DataStructures::List <int> testsToRunIndexes;//A list of tests to run by index

	//Add all the tests to the test list
	testList.Push(new EightPeerTest(),_FILE_AND_LINE_);
	testList.Push(new MaximumConnectTest(),_FILE_AND_LINE_);
	testList.Push(new PeerConnectDisconnectWithCancelPendingTest(),_FILE_AND_LINE_);
	testList.Push(new PeerConnectDisconnectTest(),_FILE_AND_LINE_);
	testList.Push(new ManyClientsOneServerBlockingTest(),_FILE_AND_LINE_);
	testList.Push(new ManyClientsOneServerNonBlockingTest(),_FILE_AND_LINE_);
	testList.Push(new ManyClientsOneServerDeallocateBlockingTest(),_FILE_AND_LINE_);
	testList.Push(new ReliableOrderedConvertedTest(),_FILE_AND_LINE_);
	testList.Push(new DroppedConnectionConvertTest(),_FILE_AND_LINE_);
	testList.Push(new ComprehensiveConvertTest(),_FILE_AND_LINE_);
	testList.Push(new CrossConnectionConvertTest(),_FILE_AND_LINE_);
	testList.Push(new PingTestsTest(),_FILE_AND_LINE_);
	testList.Push(new OfflineMessagesConvertTest(),_FILE_AND_LINE_);
	testList.Push(new LocalIsConnectedTest(),_FILE_AND_LINE_);
	testList.Push(new SecurityFunctionsTest(),_FILE_AND_LINE_);
	testList.Push(new ConnectWithSocketTest(),_FILE_AND_LINE_);
	testList.Push(new SystemAddressAndGuidTest(),_FILE_AND_LINE_);	
	testList.Push(new PacketAndLowLevelTestsTest(),_FILE_AND_LINE_);
	testList.Push(new MiscellaneousTestsTest(),_FILE_AND_LINE_);

	testListSize=testList.Size();

	bool isVerbose=true;
	bool disallowTestToPause=false;

	DataStructures::List<RakString> testcases;

	if (argc>1)//we have command line arguments
	{

		for (int p=1;p<argc;p++)
		{
			testsToRun.Push(argv[p],_FILE_AND_LINE_);

		}

	}

	DataStructures::List<RakString> noParamsList;

	if (testsToRun.Size()==0&&testsToRunIndexes.Size()==0)
	{
		numTests=testListSize;
		for(int i=0;i<testListSize;i++)
		{
			printf("\n\nRunning test %s.\n\n",testList[i]->GetTestName().C_String());
			returnVal=testList[i]->RunTest(noParamsList,isVerbose,disallowTestToPause);
			testList[i]->DestroyPeers();

			if (returnVal==0)
			{passedTests++;}
			else
			{
				printf("Test %s returned with error %s",testList[i]->GetTestName().C_String(),testList[i]->ErrorCodeToString(returnVal).C_String());
		
			}
		}

	}

	if (testsToRun.Size()!=0)//If string arguments convert to indexes.Suggestion: if speed becoms an issue keep a sorted list and binary search it
	{
		int TestsToRunSize= testsToRun.Size();

		RakString testName;
		for(int i=0;i<TestsToRunSize;i++)
		{
			testName=testsToRun[i];

			for(int j=0;j<testListSize;j++)
			{

				if (testList[j]->GetTestName().StrICmp(testName)==0)
				{

					testsToRunIndexes.Push(j,_FILE_AND_LINE_);

				}

			}

		}

	}

	if (testsToRunIndexes.Size()!=0)//Run selected indexes
	{
		numTests=testsToRunIndexes.Size();

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

			if (testsToRunIndexes[i]<testListSize)
			{

				printf("\n\nRunning test %s.\n\n",testList[testsToRunIndexes[i]]->GetTestName().C_String());
				returnVal=testList[testsToRunIndexes[i]]->RunTest(noParamsList,isVerbose,disallowTestToPause);
				testList[i]->DestroyPeers();

				if (returnVal==0)
				{passedTests++;}
				else
				{
					printf("Test %s returned with error %s",testList[testsToRunIndexes[i]]->GetTestName().C_String(),testList[testsToRunIndexes[i]]->ErrorCodeToString(returnVal).C_String());

				}
			}
		}
	}

	if (numTests>0)
	{
		printf("\nPassed %i out of %i tests.\n",passedTests,numTests);
	}

	printf("Press enter to continue \n");
	Gets(str, sizeof(str));
	//Cleanup
	int len=testList.Size();

	for (int i=0;i<len;i++)
	{
		delete testList[i];

	}
	testList.Clear(false,_FILE_AND_LINE_);

	return 0;
}