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);
	}
}
Example #2
0
unsigned int TeamBalancer::GetMemberIndexToSwitchTeams(const DataStructures::List<TeamId> &sourceTeamNumbers, TeamId targetTeamNumber)
{
	DataStructures::List<unsigned int> preferredSwapIndices;
	DataStructures::List<unsigned int> potentialSwapIndices;
	unsigned int i,j;
	for (j=0; j < sourceTeamNumbers.Size(); j++)
	{
		RakAssert(sourceTeamNumbers[j]!=targetTeamNumber);
		for (i=0; i < teamMembers.Size(); i++)
		{
			if (teamMembers[i].currentTeam==sourceTeamNumbers[j])
			{
				if (teamMembers[i].requestedTeam==targetTeamNumber)
					preferredSwapIndices.Push(i,_FILE_AND_LINE_);
				else
					potentialSwapIndices.Push(i,_FILE_AND_LINE_);
			}
		}
	}

	if (preferredSwapIndices.Size()>0)
	{
		return preferredSwapIndices[ randomMT() % preferredSwapIndices.Size() ];
	}
	else if (potentialSwapIndices.Size()>0)
	{
		return potentialSwapIndices[ randomMT() % potentialSwapIndices.Size() ];
	}
	else
	{
		return (unsigned int) -1;
	}
}
void SQLiteServerLoggerPlugin::CloseUnreferencedSessions(void)
{
	DataStructures::List<sqlite3 *> sessionNames;
	unsigned int j;
	for (j=0; j < loggedInSessions.Size(); j++)
	{
		if (sessionNames.GetIndexOf(loggedInSessions[j].referencedPointer)==-1)
			sessionNames.Push(loggedInSessions[j].referencedPointer, _FILE_AND_LINE_ );		
	}

	DataStructures::List<sqlite3*> unreferencedHandles;
	bool isReferenced;
	for (unsigned int i=0; i < dbHandles.GetSize(); i++)
	{
		if (dbHandles[i].dbAutoCreated)
		{
			j=0;
			isReferenced=false;
			for (j=0; j < sessionNames.Size(); j++)
			{
				if (sessionNames[j]==dbHandles[i].dbHandle)
				{
					isReferenced=true;
					break;
				}
			}

			if (isReferenced==false)
			{
				unreferencedHandles.Push(dbHandles[i].dbHandle,_FILE_AND_LINE_);
			}
		}
	}

	if (unreferencedHandles.Size())
	{
		sqlLoggerThreadPool.LockInput();
		if (sqlLoggerThreadPool.HasInputFast()==false)
		{
			RakSleep(100);
			while (sqlLoggerThreadPool.NumThreadsWorking()>0)
				RakSleep(30);
			for (unsigned int k=0; k < unreferencedHandles.Size(); k++)
			{
				RemoveDBHandle(unreferencedHandles[k], true);
			}
		}
		sqlLoggerThreadPool.UnlockInput();

		if (dbHandles.GetSize()==0)
			StopCPUSQLThreads();
	}
}
void ReleaseRoomFromCloud(void)
{
	RakNet::CloudKey cloudKey("ComprehensiveGame_Rooms",0);
	DataStructures::List<CloudKey> keys;
	keys.Push(cloudKey, _FILE_AND_LINE_);
	cloudClient->Release(keys, game->masterServerGuid);
}
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_);
}
Example #6
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_);
		}
	}
}
Example #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_);
	}
}
Example #8
0
bool StatisticsHistory::GetHistorySorted(uint64_t objectId, SHSortOperation sortType, DataStructures::List<StatisticsHistory::TimeAndValueQueue *> &values) const
{
	unsigned int idx = GetObjectIndex(objectId);
	if (idx == (unsigned int) -1)
		return false;
	TrackedObject *to = objects[idx];
	DataStructures::List<TimeAndValueQueue*> itemList;
	DataStructures::List<RakString> keyList;
	to->dataQueues.GetAsList(itemList,keyList,_FILE_AND_LINE_);
	Time curTime = GetTime();

	DataStructures::OrderedList<TimeAndValueQueue*, TimeAndValueQueue*,TimeAndValueQueueCompAsc> sortedQueues;
	for (unsigned int i=0; i < itemList.Size(); i++)
	{
		TimeAndValueQueue *tavq = itemList[i];
		tavq->CullExpiredValues(curTime);

		if (sortType == SH_SORT_BY_RECENT_SUM_ASCENDING || sortType == SH_SORT_BY_RECENT_SUM_DESCENDING)
			tavq->sortValue = tavq->GetRecentSum();
		else if (sortType == SH_SORT_BY_LONG_TERM_SUM_ASCENDING || sortType == SH_SORT_BY_LONG_TERM_SUM_DESCENDING)
			tavq->sortValue = tavq->GetLongTermSum();
		else if (sortType == SH_SORT_BY_RECENT_SUM_OF_SQUARES_ASCENDING || sortType == SH_SORT_BY_RECENT_SUM_OF_SQUARES_DESCENDING)
			tavq->sortValue = tavq->GetRecentSumOfSquares();
		else if (sortType == SH_SORT_BY_RECENT_AVERAGE_ASCENDING || sortType == SH_SORT_BY_RECENT_AVERAGE_DESCENDING)
			tavq->sortValue = tavq->GetRecentAverage();
		else if (sortType == SH_SORT_BY_LONG_TERM_AVERAGE_ASCENDING || sortType == SH_SORT_BY_LONG_TERM_AVERAGE_DESCENDING)
			tavq->sortValue = tavq->GetLongTermAverage();
		else if (sortType == SH_SORT_BY_RECENT_HIGHEST_ASCENDING || sortType == SH_SORT_BY_RECENT_HIGHEST_DESCENDING)
			tavq->sortValue = tavq->GetRecentHighest();
		else if (sortType == SH_SORT_BY_RECENT_LOWEST_ASCENDING || sortType == SH_SORT_BY_RECENT_LOWEST_DESCENDING)
			tavq->sortValue = tavq->GetRecentLowest();
		else if (sortType == SH_SORT_BY_LONG_TERM_HIGHEST_ASCENDING || sortType == SH_SORT_BY_LONG_TERM_HIGHEST_DESCENDING)
			tavq->sortValue = tavq->GetLongTermHighest();
		else
			tavq->sortValue = tavq->GetLongTermLowest();

		if (
			sortType == SH_SORT_BY_RECENT_SUM_ASCENDING ||
			sortType == SH_SORT_BY_LONG_TERM_SUM_ASCENDING ||
			sortType == SH_SORT_BY_RECENT_SUM_OF_SQUARES_ASCENDING ||
			sortType == SH_SORT_BY_RECENT_AVERAGE_ASCENDING ||
			sortType == SH_SORT_BY_LONG_TERM_AVERAGE_ASCENDING ||
			sortType == SH_SORT_BY_RECENT_HIGHEST_ASCENDING ||
			sortType == SH_SORT_BY_RECENT_LOWEST_ASCENDING ||
			sortType == SH_SORT_BY_LONG_TERM_HIGHEST_ASCENDING ||
			sortType == SH_SORT_BY_LONG_TERM_LOWEST_ASCENDING)
			sortedQueues.Insert(tavq, tavq, false, _FILE_AND_LINE_, TimeAndValueQueueCompAsc);
		else
			sortedQueues.Insert(tavq, tavq, false, _FILE_AND_LINE_, TimeAndValueQueueCompDesc);
	}

	for (unsigned int i=0; i < sortedQueues.Size(); i++)
		values.Push(sortedQueues[i], _FILE_AND_LINE_);
	return true;
}
// Upload details about the current game state to the cloud
// This is the responsibility of the system that initially created that room.
// If that system disconnects, the new host, as determined by FullyConnectedMesh2 will reupload the room
void PostRoomToCloud(void)
{
	BitStream bsOut;
	DataStructures::List<NATTypeDetectionResult> natTypes;
	for (unsigned int i=0; i < game->users.Size(); i++)
		natTypes.Push(game->users[i]->natType, _FILE_AND_LINE_);
	SerializeToBitStream(&bsOut, game->gameName, natTypes);
	RakNet::CloudKey cloudKey("ComprehensiveGame_Rooms",0);
	cloudClient->Post(&cloudKey, bsOut.GetData(), bsOut.GetNumberOfBytesUsed(), game->masterServerGuid);
	printf("Posted game session. In room.\n");
}
Example #10
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_);
			}
		}
	}
}
Example #11
0
void FullyConnectedMesh2::CategorizeVJIP(VerifiedJoinInProgress *vjip,
										 DataStructures::List<RakNetGUID> &participatingMembersOnClientSucceeded,
										 DataStructures::List<RakNetGUID> &participatingMembersOnClientFailed,
										 DataStructures::List<RakNetGUID> &participatingMembersNotOnClient,
										 DataStructures::List<RakNetGUID> &clientMembersNotParticipatingSucceeded,
										 DataStructures::List<RakNetGUID> &clientMembersNotParticipatingFailed)
{
	for (unsigned int i=0; i < vjip->members.Size(); i++)
		vjip->members[i].workingFlag=false;

	for (unsigned int i=0; i < fcm2ParticipantList.Size(); i++)
	{
		unsigned int j = GetVerifiedJoinInProgressMemberIndex(fcm2ParticipantList[i].rakNetGuid, vjip);
		if (j==(unsigned int)-1)
		{
			participatingMembersNotOnClient.Push(fcm2ParticipantList[i].rakNetGuid, _FILE_AND_LINE_);
		}
		else
		{
			if (vjip->members[j].joinInProgressState==JIPS_FAILED)
				participatingMembersOnClientFailed.Push(fcm2ParticipantList[i].rakNetGuid, _FILE_AND_LINE_);
			else
				participatingMembersOnClientSucceeded.Push(fcm2ParticipantList[i].rakNetGuid, _FILE_AND_LINE_);
			vjip->members[j].workingFlag=true;
		}
	}


	for (unsigned int j=0; j < vjip->members.Size(); j++)
	{
		if (vjip->members[j].workingFlag==false)
		{
			if (vjip->members[j].joinInProgressState==JIPS_FAILED)
				clientMembersNotParticipatingFailed.Push(vjip->members[j].guid, _FILE_AND_LINE_);
			else
				clientMembersNotParticipatingSucceeded.Push(vjip->members[j].guid, _FILE_AND_LINE_);
		}
	}
}
// Read roomName and a list of NATTypeDetectionResult from a bitStream
void DeserializeFromBitStream(RakNet::CloudQueryRow *row, RakString &roomName, DataStructures::List<NATTypeDetectionResult> &natTypes)
{
	RakNet::BitStream bsIn(row->data, row->length, false);
	bsIn.Read(roomName);
	unsigned short natTypesCount;
	bsIn.Read(natTypesCount);
	for (unsigned short i=0; i < natTypesCount; i++)
	{
		NATTypeDetectionResult ntdr;
		bsIn.ReadCasted<unsigned char>(ntdr);
		natTypes.Push(ntdr, _FILE_AND_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_);
	}
}
Example #14
0
TeamId TeamBalancer::MoveMemberThatWantsToJoinTeamInternal(TeamId teamId)
{
	DataStructures::List<TeamId> membersThatWantToJoinTheTeam;
	for (TeamId i=0; i < teamMembers.Size(); i++)
	{
		if (teamMembers[i].requestedTeam==teamId)
			membersThatWantToJoinTheTeam.Push(i,_FILE_AND_LINE_);
	}

	if (membersThatWantToJoinTheTeam.Size()>0)
	{
		TeamId oldTeam;
		unsigned int swappedMemberIndex = membersThatWantToJoinTheTeam[ randomMT() % membersThatWantToJoinTheTeam.Size() ];
		oldTeam=teamMembers[swappedMemberIndex].currentTeam;
		SwitchMemberTeam(swappedMemberIndex,teamId);
		NotifyTeamAssigment(swappedMemberIndex);
		return oldTeam;
	}
	return UNASSIGNED_TEAM_ID;
}
void ServerAndRoomBrowserData::WriteToTable(DataStructures::Table *table)
{
	table->Clear();
	DataStructures::Table::Cell cells[4];
	table->AddColumn("numPlayers", DataStructures::Table::NUMERIC);
	cells[0].Set((unsigned int) numPlayers);
	table->AddColumn("maxPlayers", DataStructures::Table::NUMERIC);
	cells[1].Set((unsigned int) maxPlayers);
	table->AddColumn("mapName", DataStructures::Table::STRING);
	cells[2].Set(mapName.C_String());
	table->AddColumn("roomName", DataStructures::Table::STRING); // "Room name" from RoomTypes.cpp, write this here?
	cells[3].Set(roomName.C_String());
	// The rooms plugin uses this table, and the rooms plugin automatically assigns a room id
//	table->AddColumn(DefaultRoomColumns::GetColumnName(DefaultRoomColumns::TC_ROOM_ID), DataStructures::Table::NUMERIC);
//	cells[4].Set((double) roomId.g);
	RakAssert(table->GetColumnCount()==4);
	DataStructures::List<DataStructures::Table::Cell*> initialCellValues;
	for (int i=0; i < 4; i++)
		initialCellValues.Push(&cells[i],_FILE_AND_LINE_);
	table->AddRow(table->GetRowCount(), initialCellValues, true);
}
Example #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;
}
Example #17
0
int main(void)
{
	printf("Tests the CloudServer and CloudClient plugins.\n");
	printf("Difficulty: Intermediate\n\n");

	MyCallback myCloudClientCallback;
	MyAllocator myCloudClientAllocator;
	RakNet::CloudServer cloudServer[CLOUD_SERVER_COUNT];
	RakNet::CloudClient cloudClient[CLOUD_CLIENT_COUNT];
	RakNet::RakPeerInterface *rakPeer[RAKPEER_COUNT];
	for (unsigned int i=0; i < RAKPEER_COUNT; i++)
	{
		rakPeer[i]=RakNet::RakPeerInterface::GetInstance();
		RakNet::SocketDescriptor sd(STARTING_PORT+i,0);
		rakPeer[i]->Startup(RAKPEER_COUNT,&sd,1);
	}

	for (unsigned int i=SERVER_1; i < RAKPEER_COUNT; i++)
	{
		rakPeer[i]->SetMaximumIncomingConnections(RAKPEER_COUNT);
	}
	for (unsigned int i=CLIENT_1, j=CLOUD_CLIENT_1; i < SERVER_1; i++, j++)
	{
		rakPeer[i]->AttachPlugin(&cloudClient[j]);
	}
	for (unsigned int i=SERVER_1, j=CLOUD_SERVER_1; i < RAKPEER_COUNT; i++, j++)
	{
		rakPeer[i]->AttachPlugin(&cloudServer[j]);
	}
	// Connect servers to each other
	for (unsigned int i=SERVER_1; i < RAKPEER_COUNT-1; i++)
	{
		for (unsigned int j=i+1; j < RAKPEER_COUNT; j++)
		{
			rakPeer[j]->Connect("127.0.0.1", STARTING_PORT+i, 0, 0);
		}
	}

	RakSleep(100);

	// Tell servers about each other
	for (unsigned int i=SERVER_1; i < RAKPEER_COUNT; i++)
	{
		unsigned short numberOfSystems;
		rakPeer[i]->GetConnectionList(0, &numberOfSystems);
		for (unsigned int j=0; j < numberOfSystems; j++)
		{
			cloudServer[i-SERVER_1].AddServer(rakPeer[i]->GetGUIDFromIndex(j));			
		}
	}

	// Connect clients to servers, assume equal counts
	for (unsigned int i=CLIENT_1; i < SERVER_1; i++)
	{
		rakPeer[i]->Connect("127.0.0.1", STARTING_PORT+SERVER_1+i, 0, 0);
	}


	printf("'A' to upload data set 1 from client 1 to server 1.\n");
	printf("'B' to upload data set 1 from client 2 to server 2.\n");
	printf("'C' to upload data set 2 from client 1 to server 1.\n");
	printf("'D' to download data sets 1 and 2 from client 1 from server 1.\n");
	printf("'E' To release data set 1 and 2 from client 1 to server 1.\n");
	printf("'F' To subscribe to data sets 1 and 2 from client 2 to server 2.\n");
	printf("'G' To unsubscribe to data sets 1 and 2 from client 2 to server 2.\n");
	printf("'H' To release data set 1 and 2 from client 2 to server 2.\n");
	printf("'Y' to disconnect client 1.\n");
	RakNet::Packet *packet;
	while (1)
	{
		char command;
		if (kbhit())
		{
			command=getch();
			if (command=='a' || command=='A')
			{
				printf("Uploading data set 1 from client 1\n");
				RakNet::CloudKey dataKey1;
				dataKey1.primaryKey="ApplicationName";
				dataKey1.secondaryKey=1;
				cloudClient[CLOUD_CLIENT_1].Post(&dataKey1, (const unsigned char*) "DS1C1S1", (uint32_t) strlen("DS1C1S1")+1, rakPeer[CLIENT_1]->GetGUIDFromIndex(0));
			}
			else if (command=='b' || command=='B')
			{
				printf("Uploading data set 1 from client 2\n");
				RakNet::CloudKey dataKey1;
				dataKey1.primaryKey="ApplicationName";
				dataKey1.secondaryKey=1;
				cloudClient[CLOUD_CLIENT_2].Post(&dataKey1, (const unsigned char*) "DS1C2S2", (uint32_t) strlen("DS1C2S2")+1, rakPeer[CLIENT_2]->GetGUIDFromIndex(0));
			}
			else if (command=='c' || command=='C')
			{
				printf("Uploading data set 2 from client 2\n");
				RakNet::CloudKey dataKey1;
				dataKey1.primaryKey="ApplicationName";
				dataKey1.secondaryKey=2;
				cloudClient[CLOUD_CLIENT_1].Post(&dataKey1, (const unsigned char*) "DS2C2S1", (uint32_t) strlen("DS2C2S1")+1, rakPeer[CLIENT_1]->GetGUIDFromIndex(0));
			}
			else if (command=='d' || command=='D')
			{
				printf("Downloading data sets 1 and 2 from client 1\n");
				RakNet::CloudKey dataKey1;
				dataKey1.primaryKey="ApplicationName";
				dataKey1.secondaryKey=1;

				RakNet::CloudQuery keyQuery;
				keyQuery.keys.Push(RakNet::CloudKey("ApplicationName", 1), _FILE_AND_LINE_);
				keyQuery.keys.Push(RakNet::CloudKey("ApplicationName", 2), _FILE_AND_LINE_);
				keyQuery.maxRowsToReturn=0;
				keyQuery.startingRowIndex=0;
				keyQuery.subscribeToResults=false;

				cloudClient[CLOUD_CLIENT_1].Get(&keyQuery, rakPeer[CLIENT_1]->GetGUIDFromIndex(0));
			}
			else if (command=='e' || command=='E')
			{
				printf("Releasing data sets 1 and 2 from client 1\n");
				DataStructures::List<RakNet::CloudKey> keys;
				keys.Push(RakNet::CloudKey("ApplicationName", 1), _FILE_AND_LINE_);
				keys.Push(RakNet::CloudKey("ApplicationName", 2), _FILE_AND_LINE_);
				cloudClient[CLOUD_CLIENT_1].Release(keys, rakPeer[CLIENT_1]->GetGUIDFromIndex(0));
			}
			else if (command=='f' || command=='F')
			{
				printf("Subscribing to data sets 1 and 2 from client 2 to server 2.\n");

				RakNet::CloudQuery keyQuery;
				keyQuery.keys.Push(RakNet::CloudKey("ApplicationName", 1), _FILE_AND_LINE_);
				keyQuery.keys.Push(RakNet::CloudKey("ApplicationName", 2), _FILE_AND_LINE_);
				keyQuery.maxRowsToReturn=0;
				keyQuery.startingRowIndex=0;
				keyQuery.subscribeToResults=true;

				DataStructures::List<RakNet::RakNetGUID> specificSystems;
				specificSystems.Push(rakPeer[CLIENT_1]->GetMyGUID(), _FILE_AND_LINE_);

				cloudClient[CLOUD_CLIENT_2].Get(&keyQuery, specificSystems, rakPeer[CLIENT_2]->GetGUIDFromIndex(0));
			}
			else if (command=='g' || command=='G')
			{
				printf("Unsubscribing to data sets 1 and 2 from client 2 to server 2.\n");

				DataStructures::List<RakNet::CloudKey> keys;
				keys.Push(RakNet::CloudKey("ApplicationName", 1), _FILE_AND_LINE_);
				keys.Push(RakNet::CloudKey("ApplicationName", 2), _FILE_AND_LINE_);
				DataStructures::List<RakNet::RakNetGUID> specificSystems;
				specificSystems.Push(rakPeer[CLIENT_1]->GetMyGUID(), _FILE_AND_LINE_);

				cloudClient[CLOUD_CLIENT_2].Unsubscribe(keys, specificSystems, rakPeer[CLIENT_2]->GetGUIDFromIndex(0));
			}
			else if (command=='h' || command=='H')
			{
				printf("Releasing data sets 1 and 2 from client 2\n");
				DataStructures::List<RakNet::CloudKey> keys;
				keys.Push(RakNet::CloudKey("ApplicationName", 1), _FILE_AND_LINE_);
				keys.Push(RakNet::CloudKey("ApplicationName", 2), _FILE_AND_LINE_);
				cloudClient[CLOUD_CLIENT_2].Unsubscribe(keys, rakPeer[CLIENT_2]->GetGUIDFromIndex(0));
			}
			else if (command=='y' || command=='Y')
			{
				printf("Disconnecting client 1\n");
				rakPeer[CLIENT_1]->Shutdown(100);
			}
		}
		for (unsigned int rakPeerInstanceIndex=0; rakPeerInstanceIndex < RAKPEER_COUNT; rakPeerInstanceIndex++)
		{
			for (packet = rakPeer[rakPeerInstanceIndex]->Receive(); packet; rakPeer[rakPeerInstanceIndex]->DeallocatePacket(packet), packet = rakPeer[rakPeerInstanceIndex]->Receive())
			{
				printf("Instance %i: ", rakPeerInstanceIndex);
				switch (packet->data[0])
				{
				case ID_DISCONNECTION_NOTIFICATION:
					printf("ID_DISCONNECTION_NOTIFICATION\n");
					break;
				case ID_NEW_INCOMING_CONNECTION:
					printf("ID_NEW_INCOMING_CONNECTION\n");
					break;
				case ID_ALREADY_CONNECTED:
					printf("ID_ALREADY_CONNECTED\n");
					break;
				case ID_INCOMPATIBLE_PROTOCOL_VERSION:
					printf("ID_INCOMPATIBLE_PROTOCOL_VERSION\n");
					break;
				case ID_REMOTE_DISCONNECTION_NOTIFICATION:
					printf("ID_REMOTE_DISCONNECTION_NOTIFICATION\n"); 
					break;
				case ID_REMOTE_CONNECTION_LOST:
					printf("ID_REMOTE_CONNECTION_LOST\n");
					break;
				case ID_REMOTE_NEW_INCOMING_CONNECTION:
					printf("ID_REMOTE_NEW_INCOMING_CONNECTION\n");
					break;
				case ID_CONNECTION_BANNED:
					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:
					printf("ID_NO_FREE_INCOMING_CONNECTIONS\n");
					break;
				case ID_INVALID_PASSWORD:
					printf("ID_INVALID_PASSWORD\n");
					break;
				case ID_CONNECTION_LOST:
					printf("ID_CONNECTION_LOST\n");
					break;
				case ID_CONNECTION_REQUEST_ACCEPTED:
					printf("ID_CONNECTION_REQUEST_ACCEPTED\n");
					break;
				case ID_CLOUD_GET_RESPONSE:
					cloudClient[rakPeerInstanceIndex].OnGetReponse(packet, &myCloudClientCallback, &myCloudClientAllocator);
					break;
				case ID_CLOUD_SUBSCRIPTION_NOTIFICATION:
					cloudClient[rakPeerInstanceIndex].OnSubscriptionNotification(packet, &myCloudClientCallback, &myCloudClientAllocator);
					break;
				default:
					printf("Packet ID %i\n", packet->data[0]);
				}
			}
		}

		RakSleep(30);
	}

	for (unsigned int i=0; i < RAKPEER_COUNT; i++)
	{
		RakNet::RakPeerInterface::DestroyInstance(rakPeer[i]);
	}

	return 0;
}
SQLiteServerLoggerPlugin::SQLThreadOutput ExecSQLLoggingThread(SQLiteServerLoggerPlugin::SQLThreadInput sqlThreadInput, bool *returnOutput, void* perThreadData)
{
	SQLiteServerLoggerPlugin::CPUThreadOutputNode *cpuOutputNode = sqlThreadInput.cpuOutputNode;
	SQLPreparedStatements *preparedStatements = (SQLPreparedStatements*) perThreadData;

	*returnOutput=true;
	SQLiteServerLoggerPlugin::SQLThreadOutput sqlThreadOutput;
	sqlThreadOutput.cpuOutputNode=cpuOutputNode;
	sqlite3 *dbHandle = sqlThreadInput.dbHandle;
//	sqlite3_stmt *statement;
	char *errorMsg;
	
	sqlite3_exec(dbHandle,"BEGIN TRANSACTION", 0, 0, 0);
	
	int rc;
	if (cpuOutputNode->isFunctionCall)
	{
		if (preparedStatements->selectNameFromMaster==0)
		{
			// Create function tables if they are not there already
			if (sqlite3_prepare_v2(
				dbHandle, 
				"SELECT name FROM sqlite_master WHERE type='table' AND name="FUNCTION_CALL_TABLE" ",
				-1,
				&preparedStatements->selectNameFromMaster,
				0
				)!=SQLITE_OK)
			{
				RakAssert("Failed PRAGMA table_info for function tables in SQLiteServerLoggerPlugin.cpp" && 0);
				for (int i=0; i < cpuOutputNode->parameterCount; i++)
					cpuOutputNode->parameterList[i].Free();
				sqlite3_exec(dbHandle,"END TRANSACTION", 0, 0, 0);
				return sqlThreadOutput;
			}
		}
		 rc = sqlite3_step(preparedStatements->selectNameFromMaster);
		sqlite3_reset(preparedStatements->selectNameFromMaster);

		if (rc!=SQLITE_ROW)
		{
			// Create table if it isn't there already
			rc = sqlite3_exec(dbHandle,"CREATE TABLE "FUNCTION_CALL_TABLE" (functionId_pk INTEGER PRIMARY KEY, "FUNCTION_CALL_FRIENDLY_TEXT" TEXT, functionName TEXT, "FILE_COLUMN" TEXT, "LINE_COLUMN" INTEGER, "TICK_COUNT_COLUMN" INTEGER, "AUTO_IP_COLUMN" TEXT, "TIMESTAMP_TEXT_COLUMN" TIMESTAMP DATE DEFAULT (datetime('now','localtime')), "TIMESTAMP_NUMERIC_COLUMN" NUMERIC )", 0, 0, &errorMsg);
			RakAssert(rc==SQLITE_OK);
			sqlite3_free(errorMsg);
			// See sqlDataTypeNames for *val
			rc = sqlite3_exec(dbHandle,"CREATE TABLE "FUNCTION_CALL_PARAMETERS_TABLE" (fcpId_pk INTEGER PRIMARY KEY, functionId_fk integer NOT NULL, value TEXT, FOREIGN KEY (functionId_fk) REFERENCES "FUNCTION_CALL_TABLE" (functionId_pk))", 0, 0, &errorMsg);
			RakAssert(rc==SQLITE_OK);
			sqlite3_free(errorMsg);
		}
		else
		{
			// Table already there
		}

		// Insert into function calls
		int parameterCountIndex;
		RakNet::RakString functionCallFriendlyText("%s(", cpuOutputNode->tableName.C_String());
		for (parameterCountIndex=0; parameterCountIndex < cpuOutputNode->parameterCount; parameterCountIndex++)
		{
			if (parameterCountIndex!=0)
				functionCallFriendlyText+=", ";
			switch (cpuOutputNode->parameterList[parameterCountIndex].type)
			{
			case SQLLPDT_POINTER:
				if (cpuOutputNode->parameterList[parameterCountIndex].size==4)
					functionCallFriendlyText+=RakNet::RakString("%p", cpuOutputNode->parameterList[parameterCountIndex].data.i);
				else
					functionCallFriendlyText+=RakNet::RakString("%p", cpuOutputNode->parameterList[parameterCountIndex].data.ll);
				break;
			case SQLLPDT_INTEGER:
				switch (cpuOutputNode->parameterList[parameterCountIndex].size)
				{
				case 1:
					functionCallFriendlyText+=RakNet::RakString("%i", cpuOutputNode->parameterList[parameterCountIndex].data.c);
					break;
				case 2:
					functionCallFriendlyText+=RakNet::RakString("%i", cpuOutputNode->parameterList[parameterCountIndex].data.s);
					break;
				case 4:
					functionCallFriendlyText+=RakNet::RakString("%i", cpuOutputNode->parameterList[parameterCountIndex].data.i);
					break;
				case 8:
					functionCallFriendlyText+=RakNet::RakString("%i", cpuOutputNode->parameterList[parameterCountIndex].data.ll);
					break;
				}
				break;
			case SQLLPDT_REAL:
				if (cpuOutputNode->parameterList[parameterCountIndex].size==sizeof(float))
					functionCallFriendlyText+=RakNet::RakString("%f", cpuOutputNode->parameterList[parameterCountIndex].data.f);
				else
					functionCallFriendlyText+=RakNet::RakString("%d", cpuOutputNode->parameterList[parameterCountIndex].data.d);
				break;
			case SQLLPDT_TEXT:
				functionCallFriendlyText+='"';
				if (cpuOutputNode->parameterList[parameterCountIndex].size>0)
					functionCallFriendlyText.AppendBytes(cpuOutputNode->parameterList[parameterCountIndex].data.cptr, cpuOutputNode->parameterList[parameterCountIndex].size);
				functionCallFriendlyText+='"';
				break;
			case SQLLPDT_IMAGE:
				functionCallFriendlyText+=RakNet::RakString("<%i byte image>", cpuOutputNode->parameterList[parameterCountIndex].size, cpuOutputNode->parameterList[parameterCountIndex].data.cptr);
				break;
			case SQLLPDT_BLOB:
				functionCallFriendlyText+=RakNet::RakString("<%i byte binary>", cpuOutputNode->parameterList[parameterCountIndex].size, cpuOutputNode->parameterList[parameterCountIndex].data.cptr);
				break;
			}
		}

		functionCallFriendlyText+=");";
		
		if (preparedStatements->insertIntoFunctionCalls==0)
		{
			rc = sqlite3_prepare_v2(dbHandle, "INSERT INTO "FUNCTION_CALL_TABLE" ("FUNCTION_CALL_FRIENDLY_TEXT", "FILE_COLUMN", "LINE_COLUMN", "TICK_COUNT_COLUMN", "AUTO_IP_COLUMN", "TIMESTAMP_NUMERIC_COLUMN" ,functionName) VALUES (?,?,?,?,?,?,?)", -1, &preparedStatements->insertIntoFunctionCalls, 0);
			if (rc!=SQLITE_DONE && rc!=SQLITE_OK)
			{
				RakAssert("Failed INSERT INTO "FUNCTION_CALL_PARAMETERS_TABLE" in SQLiteServerLoggerPlugin.cpp" && 0);
			}
		}
		sqlite3_bind_text(preparedStatements->insertIntoFunctionCalls, 1, functionCallFriendlyText.C_String(), -1, SQLITE_TRANSIENT);
		sqlite3_bind_text(preparedStatements->insertIntoFunctionCalls, 2, cpuOutputNode->file.C_String(), -1, SQLITE_TRANSIENT);
		sqlite3_bind_int(preparedStatements->insertIntoFunctionCalls, 3, cpuOutputNode->line);
		sqlite3_bind_int(preparedStatements->insertIntoFunctionCalls, 4, cpuOutputNode->tickCount);
		sqlite3_bind_text(preparedStatements->insertIntoFunctionCalls, 5, cpuOutputNode->ipAddressString, -1, SQLITE_TRANSIENT);
		sqlite3_bind_int(preparedStatements->insertIntoFunctionCalls, 6, (uint32_t) (cpuOutputNode->clientSendingTime));
		sqlite3_bind_text(preparedStatements->insertIntoFunctionCalls, 7, cpuOutputNode->tableName.C_String(), -1, SQLITE_TRANSIENT);
		rc = sqlite3_step(preparedStatements->insertIntoFunctionCalls);
		sqlite3_reset(preparedStatements->insertIntoFunctionCalls);
		if (rc!=SQLITE_DONE && rc!=SQLITE_OK)
		{
			RakAssert("Failed binding parameters to functionCalls in SQLiteServerLoggerPlugin.cpp" && 0);
		}
//		sqlite3_finalize(statement);

//		RakNet::RakString insertIntoFunctionCallsQuery("INSERT INTO 'functionCalls' ("FUNCTION_CALL_FRIENDLY_TEXT", "FILE_COLUMN", "LINE_COLUMN", "TICK_COUNT_COLUMN",functionName) VALUES ('%s','%s',%i,%i,'%s') ", functionCallFriendlyText.C_String(), file.C_String(), line, tickCount,tableName.C_String());
//		rc = sqlite3_exec(dbHandle,insertIntoFunctionCallsQuery.C_String(), 0, 0, &errorMsg);
//		RakAssert(rc==SQLITE_OK);
//		sqlite3_free(errorMsg);
		// Read last row id
		// Requires that this thread has its own connection
		sqlite3_int64 lastRowId = sqlite3_last_insert_rowid(dbHandle);

		if (preparedStatements->insertIntoFunctionCallParameters==0)
		{
			rc = sqlite3_prepare_v2(dbHandle, "INSERT INTO functionCallParameters (functionId_fk, value) VALUES (?,?);", -1, &preparedStatements->insertIntoFunctionCallParameters, 0);
			RakAssert(rc==SQLITE_OK);
			sqlite3_bind_int64(preparedStatements->insertIntoFunctionCallParameters, 1, lastRowId);
		}

		// Insert into parameters table
		for (parameterCountIndex=0; parameterCountIndex < cpuOutputNode->parameterCount; parameterCountIndex++)
		{
			switch (cpuOutputNode->parameterList[parameterCountIndex].type)
			{
			case SQLLPDT_POINTER:
			case SQLLPDT_INTEGER:
				switch (cpuOutputNode->parameterList[parameterCountIndex].size)
				{
				case 1:
					sqlite3_bind_int(preparedStatements->insertIntoFunctionCallParameters, 2, cpuOutputNode->parameterList[parameterCountIndex].data.c);
					break;
				case 2:
					sqlite3_bind_int(preparedStatements->insertIntoFunctionCallParameters, 2, cpuOutputNode->parameterList[parameterCountIndex].data.s);
					break;
				case 4:
					sqlite3_bind_int(preparedStatements->insertIntoFunctionCallParameters, 2, cpuOutputNode->parameterList[parameterCountIndex].data.i);
					break;
				case 8:
					sqlite3_bind_int64(preparedStatements->insertIntoFunctionCallParameters, 2, cpuOutputNode->parameterList[parameterCountIndex].data.ll);
					break;
				}
				break;
			case SQLLPDT_REAL:
				if (cpuOutputNode->parameterList[parameterCountIndex].size==sizeof(float))
					sqlite3_bind_double(preparedStatements->insertIntoFunctionCallParameters, 2, cpuOutputNode->parameterList[parameterCountIndex].data.f);
				else
					sqlite3_bind_double(preparedStatements->insertIntoFunctionCallParameters, 2, cpuOutputNode->parameterList[parameterCountIndex].data.d);
				break;
			case SQLLPDT_TEXT:
				sqlite3_bind_text(preparedStatements->insertIntoFunctionCallParameters, 2, cpuOutputNode->parameterList[parameterCountIndex].data.cptr, cpuOutputNode->parameterList[parameterCountIndex].size, 0);
				break;
			case SQLLPDT_IMAGE:
			case SQLLPDT_BLOB:
				sqlite3_bind_blob(preparedStatements->insertIntoFunctionCallParameters, 2, cpuOutputNode->parameterList[parameterCountIndex].data.vptr, cpuOutputNode->parameterList[parameterCountIndex].size, DeleteBlobOrText);
				cpuOutputNode->parameterList[parameterCountIndex].DoNotFree();
				break;
			default:
				RakAssert("Hit invalid default in case label in SQLiteServerLoggerPlugin.cpp" && 0);
			}
			rc = sqlite3_step(preparedStatements->insertIntoFunctionCallParameters);
			sqlite3_reset(preparedStatements->insertIntoFunctionCallParameters);
			if (rc!=SQLITE_DONE && rc!=SQLITE_OK)
			{
				RakAssert("Failed sqlite3_step to bind functionCall parameters in SQLiteServerLoggerPlugin.cpp" && 0);
			}
		}

	//	if (statement)
	//		sqlite3_finalize(statement);
	}
	else
	{

		sqlite3_stmt *pragmaTableInfo;
		RakNet::RakString pragmaQuery("PRAGMA table_info(%s)",cpuOutputNode->tableName.C_String());
		if (sqlite3_prepare_v2(
			dbHandle, 
			pragmaQuery.C_String(),
			-1,
			&pragmaTableInfo,
			0
			)!=SQLITE_OK)
		{
			RakAssert("Failed PRAGMA table_info for tableName in SQLiteServerLoggerPlugin.cpp" && 0);
			for (int i=0; i < cpuOutputNode->parameterCount; i++)
				cpuOutputNode->parameterList[i].Free();
			sqlite3_exec(dbHandle,"END TRANSACTION", 0, 0, 0);
			return sqlThreadOutput;
		}

		int rc = sqlite3_step(pragmaTableInfo);
		DataStructures::List<RakNet::RakString> existingColumnNames;
		DataStructures::List<RakNet::RakString> existingColumnTypes;
		char *errorMsg;
		while (rc==SQLITE_ROW)
		{
			/*
			int nameColumn;
			for (int j=0; j < sqlite3_column_count(statement); j++)
			{
				if (strcmp(sqlite3_column_name(statement,j),"name")==0)
				{
					nameColumn=j;
					break;
				}
			}
			int typeColumn;
			for (int j=0; j < sqlite3_column_count(statement); j++)
			{
				if (strcmp(sqlite3_column_name(statement,j),"type")==0)
				{
					typeColumn=j;
					break;
				}
			}
			*/
			const int nameColumn=1;
			const int typeColumn=2;
			RakAssert(strcmp(sqlite3_column_name(pragmaTableInfo,nameColumn),"name")==0);
			RakAssert(strcmp(sqlite3_column_name(pragmaTableInfo,typeColumn),"type")==0);
			RakNet::RakString columnName = sqlite3_column_text(pragmaTableInfo,nameColumn);
			RakNet::RakString columnType = sqlite3_column_text(pragmaTableInfo,typeColumn);
			existingColumnNames.Push(columnName, _FILE_AND_LINE_ );
			existingColumnTypes.Push(columnType, _FILE_AND_LINE_ );

			rc = sqlite3_step(pragmaTableInfo);
		}
		sqlite3_reset(pragmaTableInfo);
		sqlite3_finalize(pragmaTableInfo);
		if (rc==SQLITE_ERROR)
		{
			RakAssert("Failed sqlite3_step in SQLiteServerLoggerPlugin.cpp" && 0);
			for (int i=0; i < cpuOutputNode->parameterCount; i++)
				cpuOutputNode->parameterList[i].Free();
			sqlite3_exec(dbHandle,"END TRANSACTION", 0, 0, 0);
			return sqlThreadOutput;
		}

		int existingColumnNamesIndex,insertingColumnNamesIndex;
		if (existingColumnNames.Size()==0)
		{
			RakNet::RakString createQuery("CREATE TABLE %s (rowId_pk INTEGER PRIMARY KEY, "FILE_COLUMN" TEXT, "LINE_COLUMN" INTEGER, "TICK_COUNT_COLUMN" INTEGER, "AUTO_IP_COLUMN" TEXT, "TIMESTAMP_TEXT_COLUMN" TIMESTAMP DATE DEFAULT (datetime('now','localtime')), "TIMESTAMP_NUMERIC_COLUMN" NUMERIC",cpuOutputNode->tableName.C_String());

			for (int i=0; i < cpuOutputNode->parameterCount; i++)
			{
				createQuery+=", ";
				createQuery+=cpuOutputNode->insertingColumnNames[i];
				createQuery+=" ";
				createQuery+=GetSqlDataTypeName2(cpuOutputNode->parameterList[i].type);
			}
			createQuery+=" )";

			sqlite3_exec(dbHandle,
				createQuery.C_String(),
				0, 0, &errorMsg);
			RakAssert(errorMsg==0);
			sqlite3_free(errorMsg);
		}
		else
		{
			// Compare what is there (columnNames,columnTypes) to what we are adding. Add what is missing
			bool alreadyExists;
			for (insertingColumnNamesIndex=0; insertingColumnNamesIndex<(int) cpuOutputNode->insertingColumnNames.Size(); insertingColumnNamesIndex++)
			{
				alreadyExists=false;
				for (existingColumnNamesIndex=0; existingColumnNamesIndex<(int) existingColumnNames.Size(); existingColumnNamesIndex++)
				{
					if (existingColumnNames[existingColumnNamesIndex]==cpuOutputNode->insertingColumnNames[insertingColumnNamesIndex])
					{
						// Type mismatch? If so, abort
						if (existingColumnTypes[existingColumnNamesIndex]!=GetSqlDataTypeName2(cpuOutputNode->parameterList[insertingColumnNamesIndex].type))
						{
							printf("Error: Column type mismatch. TableName=%s. ColumnName%s. Existing=%s. New=%s\n",
								cpuOutputNode->tableName.C_String(),
								existingColumnNames[existingColumnNamesIndex].C_String(),
								existingColumnTypes[existingColumnNamesIndex].C_String(),
								GetSqlDataTypeName2(cpuOutputNode->parameterList[insertingColumnNamesIndex].type)
								);
							for (int i=0; i < cpuOutputNode->parameterCount; i++)
								cpuOutputNode->parameterList[i].Free();
							sqlite3_exec(dbHandle,"END TRANSACTION", 0, 0, 0);
							return sqlThreadOutput;
						}

						alreadyExists=true;
						break;
					}
				}

				if (alreadyExists==false)
				{
					sqlite3_exec(dbHandle,
						RakNet::RakString("ALTER TABLE %s ADD %s %s",
						cpuOutputNode->tableName.C_String(),
						cpuOutputNode->insertingColumnNames[insertingColumnNamesIndex].C_String(),
						GetSqlDataTypeName2(cpuOutputNode->parameterList[insertingColumnNamesIndex].type)
						).C_String(),
						0, 0, &errorMsg);
					RakAssert(errorMsg==0);
					sqlite3_free(errorMsg);
				}
			}
		}



		// Insert new row
		RakNet::RakString insertQuery("INSERT INTO %s (", cpuOutputNode->tableName.C_String());
		int parameterCountIndex;
		for (parameterCountIndex=0; parameterCountIndex<cpuOutputNode->parameterCount; parameterCountIndex++)
		{
			if (parameterCountIndex!=0)
				insertQuery+=", ";
			insertQuery+=cpuOutputNode->insertingColumnNames[parameterCountIndex].C_String();
		}
		// Add file and line to the end
		insertQuery+=", "FILE_COLUMN", "LINE_COLUMN", "TICK_COUNT_COLUMN", "AUTO_IP_COLUMN", "TIMESTAMP_NUMERIC_COLUMN" ) VALUES (";

		for (parameterCountIndex=0; parameterCountIndex<cpuOutputNode->parameterCount+5; parameterCountIndex++)
		{
			if (parameterCountIndex!=0)
				insertQuery+=", ?";
			else
				insertQuery+="?";
		}
		insertQuery+=")";

		sqlite3_stmt *customStatement;
		if (sqlite3_prepare_v2(
			dbHandle, 
			insertQuery.C_String(),
			-1,
			&customStatement,
			0
			)!=SQLITE_OK)
		{
			RakAssert("Failed second sqlite3_prepare_v2 in SQLiteServerLoggerPlugin.cpp" && 0);
			for (int i=0; i < cpuOutputNode->parameterCount; i++)
				cpuOutputNode->parameterList[i].Free();
			sqlite3_exec(dbHandle,"END TRANSACTION", 0, 0, 0);
			return sqlThreadOutput;
		}

		for (parameterCountIndex=0; parameterCountIndex<cpuOutputNode->parameterCount; parameterCountIndex++)
		{
			switch (cpuOutputNode->parameterList[parameterCountIndex].type)
			{
				case SQLLPDT_POINTER:
				case SQLLPDT_INTEGER:
					switch (cpuOutputNode->parameterList[parameterCountIndex].size)
					{
					case 1:
						sqlite3_bind_int(customStatement, parameterCountIndex+1, cpuOutputNode->parameterList[parameterCountIndex].data.c);
						break;
					case 2:
						sqlite3_bind_int(customStatement, parameterCountIndex+1, cpuOutputNode->parameterList[parameterCountIndex].data.s);
						break;
					case 4:
						sqlite3_bind_int(customStatement, parameterCountIndex+1, cpuOutputNode->parameterList[parameterCountIndex].data.i);
						break;
					case 8:
						sqlite3_bind_int64(customStatement, parameterCountIndex+1, cpuOutputNode->parameterList[parameterCountIndex].data.ll);
						break;
					}
					break;
				case SQLLPDT_REAL:
					if (cpuOutputNode->parameterList[parameterCountIndex].size==sizeof(float))
						sqlite3_bind_double(customStatement, parameterCountIndex+1, cpuOutputNode->parameterList[parameterCountIndex].data.f);
					else
						sqlite3_bind_double(customStatement, parameterCountIndex+1, cpuOutputNode->parameterList[parameterCountIndex].data.d);
					break;
				case SQLLPDT_TEXT:
					sqlite3_bind_text(customStatement, parameterCountIndex+1, cpuOutputNode->parameterList[parameterCountIndex].data.cptr, cpuOutputNode->parameterList[parameterCountIndex].size, DeleteBlobOrText);
					cpuOutputNode->parameterList[parameterCountIndex].DoNotFree();
					break;
				case SQLLPDT_IMAGE:
				case SQLLPDT_BLOB:
					sqlite3_bind_blob(customStatement, parameterCountIndex+1, cpuOutputNode->parameterList[parameterCountIndex].data.vptr, cpuOutputNode->parameterList[parameterCountIndex].size, DeleteBlobOrText);
					cpuOutputNode->parameterList[parameterCountIndex].DoNotFree();
					break;
			}
		}

		// Add file and line to the end
		sqlite3_bind_text(customStatement, parameterCountIndex+1, cpuOutputNode->file.C_String(), (int) cpuOutputNode->file.GetLength(), SQLITE_TRANSIENT);
		sqlite3_bind_int(customStatement, parameterCountIndex+2, cpuOutputNode->line);
		sqlite3_bind_int(customStatement, parameterCountIndex+3, cpuOutputNode->tickCount);
		sqlite3_bind_text(customStatement, parameterCountIndex+4, cpuOutputNode->ipAddressString, -1, SQLITE_TRANSIENT);
		sqlite3_bind_int(customStatement, parameterCountIndex+5, (uint32_t) (cpuOutputNode->clientSendingTime));

		rc = sqlite3_step(customStatement);
		if (rc!=SQLITE_DONE && rc!=SQLITE_OK)
		{
			RakAssert("Failed sqlite3_step to bind blobs in SQLiteServerLoggerPlugin.cpp" && 0);
			for (int i=0; i < cpuOutputNode->parameterCount; i++)
				cpuOutputNode->parameterList[i].Free();
			sqlite3_exec(dbHandle,"END TRANSACTION", 0, 0, 0);
			return sqlThreadOutput;
		}
		sqlite3_finalize(customStatement);
	}
	sqlite3_exec(dbHandle,"END TRANSACTION", 0, 0, 0);

	for (int i=0; i < cpuOutputNode->parameterCount; i++)
		cpuOutputNode->parameterList[i].Free();

	return sqlThreadOutput;
}
Example #19
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;
}