DataStructures::Table::Row * LightweightDatabaseServer::AddRow(LightweightDatabaseServer::DatabaseTable *databaseTable, PlayerID playerId, bool hasRowId, unsigned rowId)
{
	DataStructures::Table::Row *row;
	if (databaseTable->oneRowPerSystemId && GetRowFromIP(databaseTable, playerId, 0))
		return 0; // This system already has a row.

	if (databaseTable->autogenerateRowIDs==false)
	{
		// For a new row:
		// rowID required but not specified OR
		// rowId specified but already in the table
		// Then exit
		if (hasRowId==false || databaseTable->table.GetRowByID(rowId))
			return 0; 
	}
	else
		rowId=databaseTable->nextRowId++;

	// Add new row
	row = databaseTable->table.AddRow(rowId);

	// Set IP and last update time
	if ( databaseTable->oneRowPerSystemId || databaseTable->onlyUpdateOwnRows || databaseTable->removeRowOnPingFailure || databaseTable->removeRowOnDisconnect)
		row->cells[databaseTable->systemIdColumnIndex]->Set((char*)&playerId, sizeof(PlayerID));
	if (databaseTable->removeRowOnPingFailure)
	{
		RakNetTime time = RakNet::GetTime();
		row->cells[databaseTable->lastPingResponseColumnIndex]->Set(time);
		row->cells[databaseTable->nextPingSendColumnIndex]->Set(time+SEND_PING_INTERVAL);
	}

	return row;
}
Exemplo n.º 2
0
void LightweightDatabaseServer::OnUpdateRow(Packet *packet)
	{
	RakNet::BitStream inBitstream(packet->data, packet->length, false);
	LightweightDatabaseServer::DatabaseTable *databaseTable = DeserializeClientHeader(&inBitstream, rakPeerInterface, packet, 1);
	if (databaseTable==0)
		{
		printf("ERROR: LightweightDatabaseServer::OnUpdateRow databaseTable==0\n");
		return;
		}
	if (databaseTable->allowRemoteUpdate==false)
		{
		printf("Warning: LightweightDatabaseServer::OnUpdateRow databaseTable->allowRemoteUpdate==false\n");
		return;
		}
	unsigned char updateMode;
	bool hasRowId=false;
	unsigned rowId;
	unsigned i;
	DataStructures::Table::Row *row;
	inBitstream.Read(updateMode);
	inBitstream.Read(hasRowId);
	if (hasRowId)
		inBitstream.Read(rowId);
	else
		rowId=(unsigned) -1; // Not used here but remove the debugging check
	unsigned char numCellUpdates;
	if (inBitstream.Read(numCellUpdates)==false)
		return;
	// Read the updates for the row
	DatabaseCellUpdate cellUpdates[256];
	for (i=0; i < numCellUpdates; i++)
		{
		if (cellUpdates[i].Deserialize(&inBitstream)==false)
			{
			printf("ERROR: LightweightDatabaseServer::OnUpdateRow cellUpdates deserialize failed i=%i numCellUpdates=%i\n",i,numCellUpdates);
			return;
			}
		}

	if ((RowUpdateMode)updateMode==RUM_UPDATE_EXISTING_ROW)
	{
		if (hasRowId==false)
		{
			unsigned rowKey;
			row = GetRowFromIP(databaseTable, packet->systemAddress, &rowKey);
			if (row==0)
				printf("ERROR: LightweightDatabaseServer::OnUpdateRow updateMode==RUM_UPDATE_EXISTING_ROW hasRowId==false");
		}
		else
		{

			row = databaseTable->table.GetRowByID(rowId);
			if (row==0 || (databaseTable->onlyUpdateOwnRows && RowHasIP(row, packet->systemAddress, databaseTable->SystemAddressColumnIndex)==false))
			{
				if (row==0)
					printf("ERROR: LightweightDatabaseServer::OnUpdateRow row = databaseTable->table.GetRowByID(rowId); row==0\n");
				else
					printf("ERROR: LightweightDatabaseServer::OnUpdateRow row = databaseTable->table.GetRowByID(rowId); databaseTable->onlyUpdateOwnRows && RowHasIP\n");

				return; // You can't update some other system's row
			}
		}
	}
	else if ((RowUpdateMode)updateMode==RUM_UPDATE_OR_ADD_ROW)
		{
		if (hasRowId)
			row = databaseTable->table.GetRowByID(rowId);
		else
			{
			unsigned rowKey;
			row = GetRowFromIP(databaseTable, packet->systemAddress, &rowKey);
			}

		if (row==0)
			{
			row=AddRow(databaseTable, packet->systemAddress, packet->guid, hasRowId, rowId);
			if (row==0)
				{
				printf("ERROR: LightweightDatabaseServer::OnUpdateRow updateMode==RUM_UPDATE_OR_ADD_ROW; row=AddRow; row==0\n");
				return;
				}
			}
		else
			{
			// Existing row
			if (databaseTable->onlyUpdateOwnRows && RowHasIP(row, packet->systemAddress, databaseTable->SystemAddressColumnIndex)==false)
				{
				SystemAddress sysAddr;
				memcpy(&sysAddr, row->cells[databaseTable->SystemAddressColumnIndex]->c, SystemAddress::size());

				char str1[64], str2[64];
				packet->systemAddress.ToString(true, str1);
				sysAddr.ToString(true, str2);
				printf("ERROR: LightweightDatabaseServer::OnUpdateRow updateMode==RUM_UPDATE_OR_ADD_ROW; databaseTable->onlyUpdateOwnRows && RowHasIP. packet->systemAddress=%s sysAddr=%s\n",
					str1, str2);

				return; // You can't update some other system's row
				}
			}
		}
	else
		{
		RakAssert((RowUpdateMode)updateMode==RUM_ADD_NEW_ROW);

		row=AddRow(databaseTable, packet->systemAddress, packet->guid, hasRowId, rowId);
		if (row==0)
			{
			printf("ERROR: LightweightDatabaseServer::OnUpdateRow updateMode==RUM_ADD_NEW_ROW; row==0\n");
			return;
			}
		}

	unsigned columnIndex;
	for (i=0; i < numCellUpdates; i++)
		{
		columnIndex=databaseTable->table.ColumnIndex(cellUpdates[i].columnName);
		RakAssert(columnIndex!=(unsigned)-1); // Unknown column name
		if (columnIndex!=(unsigned)-1 &&
			(databaseTable->onlyUpdateOwnRows==false ||
			(columnIndex!=databaseTable->lastPingResponseColumnIndex &&
			columnIndex!=databaseTable->nextPingSendColumnIndex &&
			columnIndex!=databaseTable->SystemAddressColumnIndex &&
			columnIndex!=databaseTable->SystemGuidColumnIndex)))
			{
			if (cellUpdates[i].cellValue.isEmpty)
				row->cells[columnIndex]->Clear();
			else if (cellUpdates[i].columnType==databaseTable->table.GetColumnType(columnIndex))
				{
				if (cellUpdates[i].columnType==DataStructures::Table::NUMERIC)
					{
					row->UpdateCell(columnIndex, cellUpdates[i].cellValue.i);
					}
				else if (cellUpdates[i].columnType==DataStructures::Table::BINARY)
					{
					row->UpdateCell(columnIndex, (int) cellUpdates[i].cellValue.i, cellUpdates[i].cellValue.c);
					}
				else
					{
					RakAssert(cellUpdates[i].columnType==DataStructures::Table::STRING);
					row->UpdateCell(columnIndex, cellUpdates[i].cellValue.c);
					}
				}
			}
		}
	}