void ConnectionGraph::OnConnectionGraphRequest(Packet *packet) { char password[256]; RakNet::BitStream inBitstream(packet->data, packet->length, false); inBitstream.IgnoreBits(8); stringCompressor->DecodeString(password,256,&inBitstream); if (pw && pw[0] && strcmp(pw, password)!=0) return; #ifdef _CONNECTION_GRAPH_DEBUG_PRINT RAKNET_DEBUG_PRINTF("ID_CONNECTION_GRAPH_REPLY "); #endif RakNet::BitStream outBitstream; outBitstream.Write((MessageID)ID_CONNECTION_GRAPH_REPLY); stringCompressor->EncodeString(pw,256,&outBitstream); SerializeWeightedGraph(&outBitstream, graph); SendUnified(&outBitstream, LOW_PRIORITY, RELIABLE_ORDERED, connectionGraphChannel, packet->systemAddress, false); #ifdef _CONNECTION_GRAPH_DEBUG_PRINT RAKNET_DEBUG_PRINTF("from %i to %i\n", peer->GetInternalID().port, packet->systemAddress.port); #endif // Add packet->systemAddress to the participant list if it is not already there AddParticipant(packet->systemAddress); }
void LightweightDatabaseServer::OnQueryRequest(RakPeerInterface *peer, Packet *packet) { RakNet::BitStream inBitstream(packet->data, packet->length, false); LightweightDatabaseServer::DatabaseTable *databaseTable = DeserializeClientHeader(&inBitstream, peer, packet, 0); if (databaseTable==0) return; if (databaseTable->allowRemoteQuery==false) return; unsigned char numColumnSubset; RakNet::BitStream outBitstream; unsigned i; if (inBitstream.Read(numColumnSubset)==false) return; unsigned columnSubset[256]; for (i=0; i < numColumnSubset; i++) inBitstream.Read(columnSubset[i]); unsigned char numNetworkedFilters; if (inBitstream.Read(numNetworkedFilters)==false) return; DatabaseFilter networkedFilters[256]; for (i=0; i < numNetworkedFilters; i++) { if (networkedFilters[i].Deserialize(&inBitstream)==false) return; } unsigned rowIds[256]; unsigned char numRowIDs; if (inBitstream.Read(numRowIDs)==false) return; for (i=0; i < numRowIDs; i++) inBitstream.Read(rowIds[i]); // Convert the safer and more robust networked database filter to the more efficient form the table actually uses. DataStructures::Table::FilterQuery tableFilters[256]; unsigned numTableFilters=0; for (i=0; i < numNetworkedFilters; i++) { tableFilters[numTableFilters].columnIndex=databaseTable->table.ColumnIndex(networkedFilters[i].columnName); if (tableFilters[numTableFilters].columnIndex==(unsigned)-1) continue; if (networkedFilters[i].columnType!=databaseTable->table.GetColumns()[tableFilters[numTableFilters].columnIndex].columnType) continue; tableFilters[numTableFilters].operation=networkedFilters[i].operation; // It's important that I store a pointer to the class here or the destructor of the class will deallocate the cell twice tableFilters[numTableFilters++].cellValue=&(networkedFilters[i].cellValue); } DataStructures::Table queryResult; databaseTable->table.QueryTable(columnSubset, numColumnSubset, tableFilters, numTableFilters, rowIds, numRowIDs, &queryResult); outBitstream.Write((unsigned char)ID_DATABASE_QUERY_REPLY); TableSerializer::SerializeTable(&queryResult, &outBitstream); peer->Send(&outBitstream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->playerId, false); }
void LightweightDatabaseServer::OnRemoveRow(RakPeerInterface *peer, Packet *packet) { RakNet::BitStream inBitstream(packet->data, packet->length, false); LightweightDatabaseServer::DatabaseTable *databaseTable = DeserializeClientHeader(&inBitstream, peer, packet, 0); if (databaseTable==0) return; if (databaseTable->allowRemoteRemove==false) return; unsigned rowId; inBitstream.Read(rowId); databaseTable->table.RemoveRow(rowId); }
bool ConnectionGraph::OnConnectionLostInternal(Packet *packet, unsigned char packetId) { // Only accept from participants if (participantList.HasData(packet->systemAddress)==false) return false; SystemAddress node1, node2; RakNet::BitStream inBitstream(packet->data, packet->length, false); inBitstream.IgnoreBits(8); // This is correct - group IDs are not written for removal, only addition. inBitstream.Read(node1); if (inBitstream.Read(node2)==false) return false; DataStructures::OrderedList<SystemAddress,SystemAddress> ignoreList; DeserializeIgnoreList(ignoreList, &inBitstream); ignoreList.Insert(packet->systemAddress, packet->systemAddress, false, __FILE__, __LINE__); return RemoveAndRelayConnection(ignoreList, packetId, node1, node2, rakPeerInterface); }
void ConnectionGraph::OnConnectionGraphUpdate(Packet *packet) { // Only accept from participants if (participantList.HasData(packet->systemAddress)==false) return; RakNet::BitStream inBitstream(packet->data, packet->length, false); inBitstream.IgnoreBits(8); if (DeserializeWeightedGraph(&inBitstream, rakPeerInterface)==false) return; DataStructures::OrderedList<SystemAddress,SystemAddress> ignoreList; DeserializeIgnoreList(ignoreList, &inBitstream); // Forward the updated graph to all participants. ignoreList.Insert(packet->systemAddress,packet->systemAddress, false, __FILE__, __LINE__); BroadcastGraphUpdate(ignoreList, rakPeerInterface); }
void ConnectionGraph::OnConnectionGraphReply(Packet *packet) { unsigned char password[256]; RakNet::BitStream inBitstream(packet->data, packet->length, false); inBitstream.IgnoreBits(8); stringCompressor->DecodeString((char*)password,256,&inBitstream); if (pw && pw[0] && strcmp(pw, (const char*)password)!=0) return; // Serialize the weighted graph and send it to them RakNet::BitStream outBitstream; outBitstream.Write((MessageID)ID_CONNECTION_GRAPH_UPDATE); #ifdef _CONNECTION_GRAPH_DEBUG_PRINT RAKNET_DEBUG_PRINTF("ID_CONNECTION_GRAPH_UPDATE "); #endif // Send our current graph to the sender SerializeWeightedGraph(&outBitstream, graph); // Write the systems that have processed this graph so we don't resend to these systems outBitstream.Write((unsigned short) 1); outBitstream.Write(rakPeerInterface->GetExternalID(packet->systemAddress)); #ifdef _CONNECTION_GRAPH_DEBUG_PRINT RAKNET_DEBUG_PRINTF("from %i to %i\n", peer->GetInternalID().port, packet->systemAddress.port); #endif SendUnified(&outBitstream, LOW_PRIORITY, RELIABLE_ORDERED, connectionGraphChannel, packet->systemAddress, false); // Add packet->systemAddress to the participant list if it is not already there AddParticipant(packet->systemAddress); if (DeserializeWeightedGraph(&inBitstream, rakPeerInterface)==false) return; // Forward the updated graph to all current participants DataStructures::OrderedList<SystemAddress,SystemAddress> ignoreList; ignoreList.Insert(packet->systemAddress,packet->systemAddress, true, __FILE__, __LINE__); BroadcastGraphUpdate(ignoreList, rakPeerInterface); }
void ConnectionGraph::OnNewConnectionInternal(Packet *packet) { // Only accept from participants if (participantList.HasData(packet->systemAddress)==false) return; SystemAddressAndGroupId node1, node2; unsigned short ping; RakNet::BitStream inBitstream(packet->data, packet->length, false); inBitstream.IgnoreBits(8); inBitstream.Read(node1.systemAddress); inBitstream.Read(node1.groupId); inBitstream.Read(node1.guid); inBitstream.Read(node2.systemAddress); inBitstream.Read(node2.groupId); inBitstream.Read(node2.guid); if (inBitstream.Read(ping)==false) return; DataStructures::OrderedList<SystemAddress,SystemAddress> ignoreList; DeserializeIgnoreList(ignoreList, &inBitstream); ignoreList.Insert(packet->systemAddress,packet->systemAddress, false, __FILE__, __LINE__); AddAndRelayConnection(ignoreList, node1, node2, ping, rakPeerInterface); }
PluginReceiveResult ReplicaManager::OnReceive(RakPeerInterface *peer, Packet *packet) { unsigned char packetIdentifier; if ( ( unsigned char ) packet->data[ 0 ] == ID_TIMESTAMP ) { if ( packet->length > sizeof( unsigned char ) + sizeof( unsigned int ) ) packetIdentifier = ( unsigned char ) packet->data[ sizeof( unsigned char ) + sizeof( unsigned int ) ]; else return RR_STOP_PROCESSING_AND_DEALLOCATE; } else packetIdentifier = ( unsigned char ) packet->data[ 0 ]; switch (packetIdentifier) { case ID_NEW_INCOMING_CONNECTION: case ID_CONNECTION_REQUEST_ACCEPTED: if (autoParticipateNewConnections) AddParticipant(packet->playerId); return RR_CONTINUE_PROCESSING; case ID_DISCONNECTION_NOTIFICATION: case ID_CONNECTION_LOST: OnCloseConnection(peer, packet->playerId); return RR_CONTINUE_PROCESSING; case ID_REPLICA_MANAGER_DOWNLOAD_COMPLETE: if (_receiveDownloadCompleteCB==0) { return RR_STOP_PROCESSING_AND_DEALLOCATE; } case ID_REPLICA_MANAGER_CONSTRUCTION: case ID_REPLICA_MANAGER_DESTRUCTION: case ID_REPLICA_MANAGER_SCOPE_CHANGE: case ID_REPLICA_MANAGER_SERIALIZE: { ParticipantStruct *participantStruct; bool hasNetworkId; ReceivedCommand receivedCommand; bool b=true; RakNet::BitStream inBitstream(packet->data, packet->length, false); // SetWriteOffset is used here to get around a design flaw, where I should have had the bitstream constructor take bits, rather than bytes // It sets the actual number of bits in the packet inBitstream.SetWriteOffset(packet->bitSize); receivedCommand.playerId=packet->playerId; receivedCommand.command=packetIdentifier; if ( ( unsigned char ) packet->data[ 0 ] == ID_TIMESTAMP ) { inBitstream.IgnoreBits(8); b=inBitstream.Read(receivedCommand.u1); } else receivedCommand.u1=0; inBitstream.IgnoreBits(8); // Ignore the packet id receivedCommand.networkID=UNASSIGNED_NETWORK_ID; if (packetIdentifier==ID_REPLICA_MANAGER_CONSTRUCTION) // ID_REPLICA_MANAGER_CONSTRUCTION has an optional networkID { b=inBitstream.Read(hasNetworkId); if (hasNetworkId) b=inBitstream.Read(receivedCommand.networkID); } else if (packetIdentifier!=ID_REPLICA_MANAGER_DOWNLOAD_COMPLETE) { b=inBitstream.Read(receivedCommand.networkID); // Other packets always have an networkID } if (b==false) { // Invalid packet #ifdef _DEBUG assert(0); #endif return RR_STOP_PROCESSING_AND_DEALLOCATE; } receivedCommand.userData=&inBitstream; participantStruct=GetParticipantByPlayerID(receivedCommand.playerId); if (participantStruct) { // .Size()>0 is because commands are always processed in order. If a command is delayed, no further commands are processed. // ProcessReceivedCommand(...)==false means that the use signaled to delay a command if (participantStruct->pendingCommands.Size()>0 || ProcessReceivedCommand(participantStruct, &receivedCommand)==REPLICA_PROCESS_LATER) { // Copy the data and add this to a queue that will call ProcessReceivedCommand again in Update. // Allocate and copy structure ReceivedCommand *rc = new ReceivedCommand; memcpy(rc, &receivedCommand, sizeof(ReceivedCommand)); // Allocate and copy inBitstream remaining data rc->userData = new RakNet::BitStream; rc->userData->Write(&inBitstream, inBitstream.GetNumberOfBitsUsed()); participantStruct->pendingCommands.Push(rc); } } return RR_STOP_PROCESSING_AND_DEALLOCATE; } } return RR_CONTINUE_PROCESSING; }
void LightweightDatabaseServer::OnUpdateRow(RakPeerInterface *peer, Packet *packet) { RakNet::BitStream inBitstream(packet->data, packet->length, false); LightweightDatabaseServer::DatabaseTable *databaseTable = DeserializeClientHeader(&inBitstream, peer, packet, 1); if (databaseTable==0) return; if (databaseTable->allowRemoteUpdate==false) return; unsigned char updateMode; bool hasRowId; 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) return; } if ((RowUpdateMode)updateMode==RUM_UPDATE_EXISTING_ROW) { if (hasRowId==false) return; row = databaseTable->table.GetRowByID(rowId); if (row==0 || databaseTable->onlyUpdateOwnRows && RowHasIP(row, packet->playerId, databaseTable->systemIdColumnIndex)==false) 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 row=0; if (row==0) { row=AddRow(databaseTable, packet->playerId, hasRowId, rowId); if (row==0) return; } else { // Existing row if (databaseTable->onlyUpdateOwnRows && RowHasIP(row, packet->playerId, databaseTable->systemIdColumnIndex)==false) return; // You can't update some other system's row } } else { RakAssert((RowUpdateMode)updateMode==RUM_ADD_NEW_ROW); row=AddRow(databaseTable, packet->playerId, hasRowId, rowId); if (row==0) return; } unsigned columnIndex; for (i=0; i < numCellUpdates; i++) { columnIndex=databaseTable->table.ColumnIndex(cellUpdates[i].columnName); if (columnIndex!=(unsigned)-1 && columnIndex!=databaseTable->lastPingResponseColumnIndex && columnIndex!=databaseTable->nextPingSendColumnIndex && columnIndex!=databaseTable->systemIdColumnIndex) { 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, cellUpdates[i].cellValue.i, cellUpdates[i].cellValue.c); } else { RakAssert(cellUpdates[i].columnType==DataStructures::Table::STRING); row->UpdateCell(columnIndex, cellUpdates[i].cellValue.c); } } } } }
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); } } } } }