00001 #include "NativeFeatureIncludes.h"
00002 #if _RAKNET_SUPPORT_LightweightDatabaseServer==1
00003
00004 #include "LightweightDatabaseServer.h"
00005 #include "MessageIdentifiers.h"
00006 #include "BitStream.h"
00007 #include "StringCompressor.h"
00008 #include "RakPeerInterface.h"
00009 #include "TableSerializer.h"
00010 #include "RakAssert.h"
00011 #include "GetTime.h"
00012 #include "Rand.h"
00013
00014 static const int SEND_PING_INTERVAL=15000;
00015 static const int DROP_SERVER_INTERVAL=75000;
00016
00017 #ifdef _MSC_VER
00018 #pragma warning( push )
00019 #endif
00020
00021 int LightweightDatabaseServer::DatabaseTableComp( const char* const &key1, const char* const &key2 )
00022 {
00023 return strcmp(key1, key2);
00024 }
00025
00026 LightweightDatabaseServer::LightweightDatabaseServer()
00027 {
00028
00029 }
00030 LightweightDatabaseServer::~LightweightDatabaseServer()
00031 {
00032 Clear();
00033 }
00034 DataStructures::Table *LightweightDatabaseServer::GetTable(const char *tableName)
00035 {
00036 if (tableName==0)
00037 {
00038 if (database.Size()>0)
00039 return &(database[0]->table);
00040 return 0;
00041 }
00042 if (database.Has(tableName))
00043 return &(database.Get(tableName)->table);
00044 return 0;
00045 }
00046 DataStructures::Page<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> *LightweightDatabaseServer::GetTableRows(const char *tableName)
00047 {
00048 if (database.Has(tableName))
00049 database.Get(tableName)->table.GetRows().GetListHead();
00050 return 0;
00051 }
00052 DataStructures::Table* LightweightDatabaseServer::AddTable(const char *tableName,
00053 bool allowRemoteQuery,
00054 bool allowRemoteUpdate,
00055 bool allowRemoteRemove,
00056 const char *queryPassword,
00057 const char *updatePassword,
00058 const char *removePassword,
00059 bool oneRowPerSystemAddress,
00060 bool onlyUpdateOwnRows,
00061 bool removeRowOnPingFailure,
00062 bool removeRowOnDisconnect,
00063 bool autogenerateRowIDs)
00064 {
00065 if (tableName==0 || tableName[0]==0)
00066 return 0;
00067 if (database.Has(tableName))
00068 return 0;
00069 DatabaseTable *databaseTable = RakNet::OP_NEW<DatabaseTable>( __FILE__, __LINE__ );
00070
00071 strncpy(databaseTable->tableName, tableName, _SIMPLE_DATABASE_TABLE_NAME_LENGTH-1);
00072 databaseTable->tableName[_SIMPLE_DATABASE_TABLE_NAME_LENGTH-1]=0;
00073
00074 if (allowRemoteUpdate)
00075 {
00076 strncpy(databaseTable->updatePassword, updatePassword, _SIMPLE_DATABASE_PASSWORD_LENGTH-1);
00077 databaseTable->updatePassword[_SIMPLE_DATABASE_PASSWORD_LENGTH-1]=0;
00078 }
00079 else
00080 databaseTable->updatePassword[0]=0;
00081
00082 if (allowRemoteQuery)
00083 {
00084 strncpy(databaseTable->queryPassword, queryPassword, _SIMPLE_DATABASE_PASSWORD_LENGTH-1);
00085 databaseTable->queryPassword[_SIMPLE_DATABASE_PASSWORD_LENGTH-1]=0;
00086 }
00087 else
00088 databaseTable->queryPassword[0]=0;
00089
00090 if (allowRemoteRemove)
00091 {
00092 strncpy(databaseTable->removePassword, removePassword, _SIMPLE_DATABASE_PASSWORD_LENGTH-1);
00093 databaseTable->removePassword[_SIMPLE_DATABASE_PASSWORD_LENGTH-1]=0;
00094 }
00095 else
00096 databaseTable->removePassword[0]=0;
00097
00098 if (allowRemoteUpdate)
00099 {
00100 databaseTable->allowRemoteUpdate=true;
00101 databaseTable->oneRowPerSystemAddress=oneRowPerSystemAddress;
00102 databaseTable->onlyUpdateOwnRows=onlyUpdateOwnRows;
00103 databaseTable->removeRowOnPingFailure=removeRowOnPingFailure;
00104 databaseTable->removeRowOnDisconnect=removeRowOnDisconnect;
00105 }
00106 else
00107 {
00108
00109 databaseTable->allowRemoteUpdate=true;
00110 databaseTable->oneRowPerSystemAddress=false;
00111 databaseTable->onlyUpdateOwnRows=false;
00112 databaseTable->removeRowOnPingFailure=false;
00113 databaseTable->removeRowOnDisconnect=false;
00114 }
00115
00116 databaseTable->nextRowId=0;
00117 databaseTable->nextRowPingCheck=0;
00118
00119 databaseTable->autogenerateRowIDs=autogenerateRowIDs;
00120 databaseTable->allowRemoteRemove=allowRemoteRemove;
00121 databaseTable->allowRemoteQuery=allowRemoteQuery;
00122
00123 database.SetNew(databaseTable->tableName, databaseTable);
00124
00125 if ( oneRowPerSystemAddress || onlyUpdateOwnRows || removeRowOnPingFailure || removeRowOnDisconnect)
00126 {
00127 databaseTable->SystemAddressColumnIndex=databaseTable->table.AddColumn(SYSTEM_ID_COLUMN_NAME, DataStructures::Table::BINARY);
00128 databaseTable->SystemGuidColumnIndex=databaseTable->table.AddColumn(SYSTEM_GUID_COLUMN_NAME, DataStructures::Table::BINARY);
00129 }
00130 else
00131 {
00132 databaseTable->SystemAddressColumnIndex=(unsigned) -1;
00133 databaseTable->SystemGuidColumnIndex=(unsigned) -1;
00134 }
00135 if (databaseTable->removeRowOnPingFailure)
00136 {
00137 databaseTable->lastPingResponseColumnIndex=databaseTable->table.AddColumn(LAST_PING_RESPONSE_COLUMN_NAME, DataStructures::Table::NUMERIC);
00138 databaseTable->nextPingSendColumnIndex=databaseTable->table.AddColumn(NEXT_PING_SEND_COLUMN_NAME, DataStructures::Table::NUMERIC);
00139 }
00140 else
00141 {
00142 databaseTable->lastPingResponseColumnIndex=(unsigned) -1;
00143 databaseTable->nextPingSendColumnIndex=(unsigned) -1;
00144 }
00145
00146 return &(databaseTable->table);
00147 }
00148 bool LightweightDatabaseServer::RemoveTable(const char *tableName)
00149 {
00150 LightweightDatabaseServer::DatabaseTable *databaseTable;
00151 databaseTable = database.Get(tableName);
00152 if (databaseTable==0)
00153 return false;
00154
00155 database.Delete(tableName);
00156 databaseTable->table.Clear();
00157 RakNet::OP_DELETE(databaseTable, __FILE__, __LINE__);
00158 return true;
00159 }
00160 void LightweightDatabaseServer::Clear(void)
00161 {
00162 unsigned i;
00163
00164 for (i=0; i < database.Size(); i++)
00165 {
00166 database[i]->table.Clear();
00167 RakNet::OP_DELETE(database[i], __FILE__, __LINE__);
00168 }
00169
00170 database.Clear();
00171 }
00172 unsigned LightweightDatabaseServer::GetAndIncrementRowID(const char *tableName)
00173 {
00174 LightweightDatabaseServer::DatabaseTable *databaseTable;
00175 databaseTable = database.Get(tableName);
00176 RakAssert(databaseTable);
00177 RakAssert(databaseTable->autogenerateRowIDs==true);
00178 return ++(databaseTable->nextRowId) - 1;
00179 }
00180
00181 void LightweightDatabaseServer::Update(void)
00182 {
00183 RakNetTime time=0;
00184 DatabaseTable *databaseTable;
00185 DataStructures::Page<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> *cur;
00186 unsigned i,j;
00187 DataStructures::Table::Row* row;
00188 DataStructures::List<unsigned> removeList;
00189 SystemAddress systemAddress;
00190
00191
00192 for (i=0; i < database.Size(); i++)
00193 {
00194 databaseTable=database[i];
00195
00196 if (databaseTable->removeRowOnPingFailure)
00197 {
00198
00199 if (time==0)
00200 time = RakNet::GetTime();
00201
00202 if (databaseTable->nextRowPingCheck < time)
00203 {
00204 databaseTable->nextRowPingCheck=time+1000+(randomMT()%1000);
00205 const DataStructures::BPlusTree<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> &rows = databaseTable->table.GetRows();
00206 cur = rows.GetListHead();
00207 while (cur)
00208 {
00209
00210 for (j=0; j < (unsigned)cur->size; j++)
00211 {
00212 row = cur->data[j];
00213 row->cells[databaseTable->SystemAddressColumnIndex]->Get((char*)&systemAddress, 0);
00214 if (rakPeerInterface->IsConnected(systemAddress)==false)
00215 {
00216 if (time > time - (unsigned int) row->cells[databaseTable->lastPingResponseColumnIndex]->i &&
00217 time - (unsigned int) row->cells[databaseTable->lastPingResponseColumnIndex]->i > (unsigned int) DROP_SERVER_INTERVAL)
00218 {
00219 removeList.Insert(cur->keys[j], __FILE__, __LINE__);
00220 }
00221 else
00222 {
00223 if (row->cells[databaseTable->nextPingSendColumnIndex]->i < (int) time)
00224 {
00225 char str1[64];
00226 systemAddress.ToString(false, str1);
00227 rakPeerInterface->Ping(str1, systemAddress.port, false);
00228 row->cells[databaseTable->nextPingSendColumnIndex]->i=(double)(time+SEND_PING_INTERVAL+(randomMT()%1000));
00229 }
00230 }
00231 }
00232 }
00233 cur=cur->next;
00234 }
00235
00236
00237 for (j=0; j < removeList.Size(); j++)
00238 databaseTable->table.RemoveRow(removeList[i]);
00239 removeList.Clear(true, __FILE__,__LINE__);
00240
00241 }
00242 }
00243 }
00244 }
00245 PluginReceiveResult LightweightDatabaseServer::OnReceive(Packet *packet)
00246 {
00247 switch (packet->data[0])
00248 {
00249 case ID_DATABASE_QUERY_REQUEST:
00250 OnQueryRequest(packet);
00251 return RR_STOP_PROCESSING_AND_DEALLOCATE;
00252 case ID_DATABASE_UPDATE_ROW:
00253 OnUpdateRow(packet);
00254 return RR_STOP_PROCESSING_AND_DEALLOCATE;
00255 case ID_DATABASE_REMOVE_ROW:
00256 OnRemoveRow(packet);
00257 return RR_STOP_PROCESSING_AND_DEALLOCATE;
00258 case ID_PONG:
00259 OnPong(packet);
00260 return RR_CONTINUE_PROCESSING;
00261 }
00262 return RR_CONTINUE_PROCESSING;
00263 }
00264 void LightweightDatabaseServer::OnClosedConnection(SystemAddress systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
00265 {
00266 (void) rakNetGUID;
00267 (void) lostConnectionReason;
00268
00269 RemoveRowsFromIP(systemAddress);
00270 }
00271 void LightweightDatabaseServer::OnQueryRequest(Packet *packet)
00272 {
00273 RakNet::BitStream inBitstream(packet->data, packet->length, false);
00274 LightweightDatabaseServer::DatabaseTable *databaseTable = DeserializeClientHeader(&inBitstream, rakPeerInterface, packet, 0);
00275 if (databaseTable==0)
00276 return;
00277 if (databaseTable->allowRemoteQuery==false)
00278 return;
00279 unsigned char numColumnSubset;
00280 RakNet::BitStream outBitstream;
00281 unsigned i;
00282 if (inBitstream.Read(numColumnSubset)==false)
00283 return;
00284 unsigned char columnName[256];
00285 unsigned columnIndicesSubset[256];
00286 unsigned columnIndicesCount;
00287 for (i=0,columnIndicesCount=0; i < numColumnSubset; i++)
00288 {
00289 stringCompressor->DecodeString((char*)columnName, 256, &inBitstream);
00290 unsigned colIndex = databaseTable->table.ColumnIndex((char*)columnName);
00291 if (colIndex!=(unsigned)-1)
00292 columnIndicesSubset[columnIndicesCount++]=colIndex;
00293 }
00294 unsigned char numNetworkedFilters;
00295 if (inBitstream.Read(numNetworkedFilters)==false)
00296 return;
00297 DatabaseFilter networkedFilters[256];
00298 for (i=0; i < numNetworkedFilters; i++)
00299 {
00300 if (networkedFilters[i].Deserialize(&inBitstream)==false)
00301 return;
00302 }
00303
00304 unsigned rowIds[256];
00305 unsigned char numRowIDs;
00306 if (inBitstream.Read(numRowIDs)==false)
00307 return;
00308 for (i=0; i < numRowIDs; i++)
00309 inBitstream.Read(rowIds[i]);
00310
00311
00312 DataStructures::Table::FilterQuery tableFilters[256];
00313 unsigned numTableFilters=0;
00314 for (i=0; i < numNetworkedFilters; i++)
00315 {
00316 tableFilters[numTableFilters].columnIndex=databaseTable->table.ColumnIndex(networkedFilters[i].columnName);
00317 if (tableFilters[numTableFilters].columnIndex==(unsigned)-1)
00318 continue;
00319 if (networkedFilters[i].columnType!=databaseTable->table.GetColumns()[tableFilters[numTableFilters].columnIndex].columnType)
00320 continue;
00321 tableFilters[numTableFilters].operation=networkedFilters[i].operation;
00322
00323 tableFilters[numTableFilters++].cellValue=&(networkedFilters[i].cellValue);
00324 }
00325
00326 DataStructures::Table queryResult;
00327 databaseTable->table.QueryTable(columnIndicesSubset, columnIndicesCount, tableFilters, numTableFilters, rowIds, numRowIDs, &queryResult);
00328 outBitstream.Write((MessageID)ID_DATABASE_QUERY_REPLY);
00329 TableSerializer::SerializeTable(&queryResult, &outBitstream);
00330 SendUnified(&outBitstream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->systemAddress, false);
00331 }
00332 void LightweightDatabaseServer::OnUpdateRow(Packet *packet)
00333 {
00334 RakNet::BitStream inBitstream(packet->data, packet->length, false);
00335 LightweightDatabaseServer::DatabaseTable *databaseTable = DeserializeClientHeader(&inBitstream, rakPeerInterface, packet, 1);
00336 if (databaseTable==0)
00337 {
00338 printf("ERROR: LightweightDatabaseServer::OnUpdateRow databaseTable==0\n");
00339 return;
00340 }
00341 if (databaseTable->allowRemoteUpdate==false)
00342 {
00343 printf("Warning: LightweightDatabaseServer::OnUpdateRow databaseTable->allowRemoteUpdate==false\n");
00344 return;
00345 }
00346 unsigned char updateMode;
00347 bool hasRowId=false;
00348 unsigned rowId;
00349 unsigned i;
00350 DataStructures::Table::Row *row;
00351 inBitstream.Read(updateMode);
00352 inBitstream.Read(hasRowId);
00353 if (hasRowId)
00354 inBitstream.Read(rowId);
00355 else
00356 rowId=(unsigned) -1;
00357 unsigned char numCellUpdates;
00358 if (inBitstream.Read(numCellUpdates)==false)
00359 return;
00360
00361 DatabaseCellUpdate cellUpdates[256];
00362 for (i=0; i < numCellUpdates; i++)
00363 {
00364 if (cellUpdates[i].Deserialize(&inBitstream)==false)
00365 {
00366 printf("ERROR: LightweightDatabaseServer::OnUpdateRow cellUpdates deserialize failed i=%i numCellUpdates=%i\n",i,numCellUpdates);
00367 return;
00368 }
00369 }
00370
00371 if ((RowUpdateMode)updateMode==RUM_UPDATE_EXISTING_ROW)
00372 {
00373 if (hasRowId==false)
00374 {
00375 unsigned rowKey;
00376 row = GetRowFromIP(databaseTable, packet->systemAddress, &rowKey);
00377 if (row==0)
00378 printf("ERROR: LightweightDatabaseServer::OnUpdateRow updateMode==RUM_UPDATE_EXISTING_ROW hasRowId==false");
00379 }
00380 else
00381 {
00382
00383 row = databaseTable->table.GetRowByID(rowId);
00384 if (row==0 || (databaseTable->onlyUpdateOwnRows && RowHasIP(row, packet->systemAddress, databaseTable->SystemAddressColumnIndex)==false))
00385 {
00386 if (row==0)
00387 printf("ERROR: LightweightDatabaseServer::OnUpdateRow row = databaseTable->table.GetRowByID(rowId); row==0\n");
00388 else
00389 printf("ERROR: LightweightDatabaseServer::OnUpdateRow row = databaseTable->table.GetRowByID(rowId); databaseTable->onlyUpdateOwnRows && RowHasIP\n");
00390
00391 return;
00392 }
00393 }
00394 }
00395 else if ((RowUpdateMode)updateMode==RUM_UPDATE_OR_ADD_ROW)
00396 {
00397 if (hasRowId)
00398 row = databaseTable->table.GetRowByID(rowId);
00399 else
00400 {
00401 unsigned rowKey;
00402 row = GetRowFromIP(databaseTable, packet->systemAddress, &rowKey);
00403 }
00404
00405 if (row==0)
00406 {
00407 row=AddRow(databaseTable, packet->systemAddress, packet->guid, hasRowId, rowId);
00408 if (row==0)
00409 {
00410 printf("ERROR: LightweightDatabaseServer::OnUpdateRow updateMode==RUM_UPDATE_OR_ADD_ROW; row=AddRow; row==0\n");
00411 return;
00412 }
00413 }
00414 else
00415 {
00416
00417 if (databaseTable->onlyUpdateOwnRows && RowHasIP(row, packet->systemAddress, databaseTable->SystemAddressColumnIndex)==false)
00418 {
00419 SystemAddress sysAddr;
00420 memcpy(&sysAddr, row->cells[databaseTable->SystemAddressColumnIndex]->c, SystemAddress::size());
00421
00422 char str1[64], str2[64];
00423 packet->systemAddress.ToString(true, str1);
00424 sysAddr.ToString(true, str2);
00425 printf("ERROR: LightweightDatabaseServer::OnUpdateRow updateMode==RUM_UPDATE_OR_ADD_ROW; databaseTable->onlyUpdateOwnRows && RowHasIP. packet->systemAddress=%s sysAddr=%s\n",
00426 str1, str2);
00427
00428 return;
00429 }
00430 }
00431 }
00432 else
00433 {
00434 RakAssert((RowUpdateMode)updateMode==RUM_ADD_NEW_ROW);
00435
00436 row=AddRow(databaseTable, packet->systemAddress, packet->guid, hasRowId, rowId);
00437 if (row==0)
00438 {
00439 printf("ERROR: LightweightDatabaseServer::OnUpdateRow updateMode==RUM_ADD_NEW_ROW; row==0\n");
00440 return;
00441 }
00442 }
00443
00444 unsigned columnIndex;
00445 for (i=0; i < numCellUpdates; i++)
00446 {
00447 columnIndex=databaseTable->table.ColumnIndex(cellUpdates[i].columnName);
00448 RakAssert(columnIndex!=(unsigned)-1);
00449 if (columnIndex!=(unsigned)-1 &&
00450 (databaseTable->onlyUpdateOwnRows==false ||
00451 (columnIndex!=databaseTable->lastPingResponseColumnIndex &&
00452 columnIndex!=databaseTable->nextPingSendColumnIndex &&
00453 columnIndex!=databaseTable->SystemAddressColumnIndex &&
00454 columnIndex!=databaseTable->SystemGuidColumnIndex)))
00455 {
00456 if (cellUpdates[i].cellValue.isEmpty)
00457 row->cells[columnIndex]->Clear();
00458 else if (cellUpdates[i].columnType==databaseTable->table.GetColumnType(columnIndex))
00459 {
00460 if (cellUpdates[i].columnType==DataStructures::Table::NUMERIC)
00461 {
00462 row->UpdateCell(columnIndex, cellUpdates[i].cellValue.i);
00463 }
00464 else if (cellUpdates[i].columnType==DataStructures::Table::BINARY)
00465 {
00466 row->UpdateCell(columnIndex, (int) cellUpdates[i].cellValue.i, cellUpdates[i].cellValue.c);
00467 }
00468 else
00469 {
00470 RakAssert(cellUpdates[i].columnType==DataStructures::Table::STRING);
00471 row->UpdateCell(columnIndex, cellUpdates[i].cellValue.c);
00472 }
00473 }
00474 }
00475 }
00476 }
00477 void LightweightDatabaseServer::OnRemoveRow(Packet *packet)
00478 {
00479 RakNet::BitStream inBitstream(packet->data, packet->length, false);
00480 LightweightDatabaseServer::DatabaseTable *databaseTable = DeserializeClientHeader(&inBitstream, rakPeerInterface, packet, 0);
00481 if (databaseTable==0)
00482 return;
00483 if (databaseTable->allowRemoteRemove==false)
00484 return;
00485 unsigned rowId;
00486 inBitstream.Read(rowId);
00487 databaseTable->table.RemoveRow(rowId);
00488 }
00489 void LightweightDatabaseServer::OnPong(Packet *packet)
00490 {
00491 unsigned databaseIndex;
00492 DatabaseTable *databaseTable;
00493 unsigned curIndex;
00494 SystemAddress systemAddress;
00495 RakNetTime time=0;
00496 for (databaseIndex=0; databaseIndex < database.Size(); databaseIndex++)
00497 {
00498 databaseTable=database[databaseIndex];
00499 if (databaseTable->removeRowOnPingFailure)
00500 {
00501 if ((unsigned int) databaseTable->SystemAddressColumnIndex==(unsigned int)-1)
00502 continue;
00503 if (time==0)
00504 time=RakNet::GetTime();
00505
00506 const DataStructures::BPlusTree<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> &rows = databaseTable->table.GetRows();
00507 DataStructures::Page<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> *cur = rows.GetListHead();
00508
00509 while (cur)
00510 {
00511 for (curIndex=0; curIndex < (unsigned) cur->size; curIndex++)
00512 {
00513 cur->data[curIndex]->cells[databaseTable->SystemAddressColumnIndex]->Get((char*)&systemAddress,0);
00514 if (systemAddress==packet->systemAddress)
00515 {
00516 cur->data[curIndex]->cells[databaseTable->lastPingResponseColumnIndex]->i=(int)time;
00517 }
00518 }
00519 cur=cur->next;
00520 }
00521 }
00522 }
00523 }
00524
00525 LightweightDatabaseServer::DatabaseTable * LightweightDatabaseServer::DeserializeClientHeader(RakNet::BitStream *inBitstream, RakPeerInterface *peer, Packet *packet, int mode)
00526 {
00527 RakNet::BitStream outBitstream;
00528 bool hasPassword=false;
00529 char password[_SIMPLE_DATABASE_PASSWORD_LENGTH];
00530 inBitstream->IgnoreBits(8);
00531 char tableName[_SIMPLE_DATABASE_TABLE_NAME_LENGTH];
00532 stringCompressor->DecodeString(tableName, _SIMPLE_DATABASE_TABLE_NAME_LENGTH, inBitstream);
00533 DatabaseTable *databaseTable = database.Get(tableName);
00534 if (databaseTable==0)
00535 {
00536 outBitstream.Write((MessageID)ID_DATABASE_UNKNOWN_TABLE);
00537 peer->Send(&outBitstream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->systemAddress, false);
00538 return 0;
00539 }
00540 const char *dbPass;
00541 if (mode==0)
00542 dbPass=databaseTable->queryPassword;
00543 else if (mode==1)
00544 dbPass=databaseTable->updatePassword;
00545 else
00546 dbPass=databaseTable->removePassword;
00547
00548 inBitstream->Read(hasPassword);
00549 if (hasPassword)
00550 {
00551 if (stringCompressor->DecodeString(password, _SIMPLE_DATABASE_PASSWORD_LENGTH, inBitstream)==false)
00552 return 0;
00553 if (databaseTable->queryPassword[0] && strcmp(password, dbPass)!=0)
00554 {
00555 outBitstream.Write((MessageID)ID_DATABASE_INCORRECT_PASSWORD);
00556 peer->Send(&outBitstream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->systemAddress, false);
00557
00558 char str1[64];
00559 packet->systemAddress.ToString(false, str1);
00560 peer->AddToBanList(str1, 1000);
00561
00562 peer->CloseConnection(packet->systemAddress, false, 0);
00563 return 0;
00564 }
00565 }
00566 else if (dbPass[0])
00567 {
00568 outBitstream.Write((MessageID)ID_DATABASE_INCORRECT_PASSWORD);
00569 peer->Send(&outBitstream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->systemAddress, false);
00570 return 0;
00571 }
00572
00573 return databaseTable;
00574 }
00575
00576 DataStructures::Table::Row * LightweightDatabaseServer::GetRowFromIP(DatabaseTable *databaseTable, SystemAddress systemAddress, unsigned *rowKey)
00577 {
00578 const DataStructures::BPlusTree<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> &rows = databaseTable->table.GetRows();
00579 DataStructures::Page<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> *cur = rows.GetListHead();
00580 DataStructures::Table::Row* row;
00581 unsigned i;
00582 if ((unsigned int) databaseTable->SystemAddressColumnIndex==(unsigned int)-1)
00583 return 0;
00584 while (cur)
00585 {
00586 for (i=0; i < (unsigned)cur->size; i++)
00587 {
00588 row = cur->data[i];
00589 if (RowHasIP(row, systemAddress, databaseTable->SystemAddressColumnIndex ))
00590 {
00591 if (rowKey)
00592 *rowKey=cur->keys[i];
00593 return row;
00594 }
00595 }
00596 cur=cur->next;
00597 }
00598 return 0;
00599 }
00600 bool LightweightDatabaseServer::RowHasIP(DataStructures::Table::Row *row, SystemAddress systemAddress, unsigned SystemAddressColumnIndex)
00601 {
00602 if ((unsigned int) SystemAddressColumnIndex==(unsigned int)-1)
00603 return false;
00604
00605 SystemAddress sysAddr;
00606 memcpy(&sysAddr, row->cells[SystemAddressColumnIndex]->c, SystemAddress::size());
00607 return sysAddr==systemAddress;
00608
00609
00610
00611
00612
00613
00614 }
00615 DataStructures::Table::Row * LightweightDatabaseServer::AddRow(LightweightDatabaseServer::DatabaseTable *databaseTable, SystemAddress systemAddress, RakNetGUID guid, bool hasRowId, unsigned rowId)
00616 {
00617 DataStructures::Table::Row *row;
00618 if (databaseTable->oneRowPerSystemAddress && GetRowFromIP(databaseTable, systemAddress, 0))
00619 return 0;
00620
00621 if (databaseTable->autogenerateRowIDs==false)
00622 {
00623
00624
00625
00626
00627 if (hasRowId==false || databaseTable->table.GetRowByID(rowId))
00628 return 0;
00629 }
00630 else
00631 rowId=databaseTable->nextRowId++;
00632
00633
00634 row = databaseTable->table.AddRow(rowId);
00635
00636
00637 if ( databaseTable->oneRowPerSystemAddress || databaseTable->onlyUpdateOwnRows || databaseTable->removeRowOnPingFailure || databaseTable->removeRowOnDisconnect)
00638 {
00639 row->cells[databaseTable->SystemAddressColumnIndex]->Set((char*)&systemAddress, (int) SystemAddress::size());
00640 row->cells[databaseTable->SystemGuidColumnIndex]->Set((char*)&guid, sizeof(guid));
00641 }
00642 if (databaseTable->removeRowOnPingFailure)
00643 {
00644 RakNetTime time = RakNet::GetTime();
00645 row->cells[databaseTable->lastPingResponseColumnIndex]->Set((int) time);
00646 row->cells[databaseTable->nextPingSendColumnIndex]->Set((int) time+SEND_PING_INTERVAL);
00647 }
00648
00649 return row;
00650 }
00651 void LightweightDatabaseServer::RemoveRowsFromIP(SystemAddress systemAddress)
00652 {
00653
00654 DatabaseTable *databaseTable;
00655 DataStructures::List<unsigned> removeList;
00656 DataStructures::Table::Row* row;
00657 DataStructures::Page<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> *cur;
00658 unsigned i,j;
00659 for (i=0; i < database.Size(); i++)
00660 {
00661 databaseTable=database[i];
00662 if ((unsigned int) databaseTable->SystemAddressColumnIndex!=(unsigned int)-1)
00663 {
00664 const DataStructures::BPlusTree<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> &rows = databaseTable->table.GetRows();
00665 cur = rows.GetListHead();
00666 while (cur)
00667 {
00668
00669 for (j=0; j < (unsigned)cur->size; j++)
00670 {
00671 if (RowHasIP(cur->data[j], systemAddress, databaseTable->SystemAddressColumnIndex))
00672 {
00673 if (databaseTable->removeRowOnDisconnect)
00674 {
00675 removeList.Insert(cur->keys[j], __FILE__, __LINE__);
00676 }
00677 else if (databaseTable->removeRowOnPingFailure)
00678 {
00679 row = cur->data[j];
00680 row->cells[databaseTable->nextPingSendColumnIndex]->i=(double)(RakNet::GetTime()+SEND_PING_INTERVAL+(randomMT()%1000));
00681 }
00682 }
00683 }
00684 cur=cur->next;
00685 }
00686 }
00687
00688 for (j=0; j < removeList.Size(); j++)
00689 databaseTable->table.RemoveRow(removeList[j]);
00690 removeList.Clear(true, __FILE__,__LINE__);
00691 }
00692 }
00693 #ifdef _MSC_VER
00694 #pragma warning( pop )
00695 #endif
00696
00697 #endif // _RAKNET_SUPPORT_*