PluginReceiveResult NatPunchthrough::OnConnectionRequestAccepted(Packet *packet) { unsigned i; i=0; while (i < connectionRequestList.Size()) { DataStructures::List<SystemAddress> fallbackAddresses; connectionRequestList[i]->GetAddressList(rakPeer, fallbackAddresses, connectionRequestList[i]->receiverPublic, connectionRequestList[i]->receiverPrivate, false); if (fallbackAddresses.GetIndexOf(packet->systemAddress)!=(unsigned) -1) { rakFree(connectionRequestList[i]->passwordData); delete connectionRequestList[i]; connectionRequestList.RemoveAtIndex(i); return RR_CONTINUE_PROCESSING; } i++; } // return to user return RR_CONTINUE_PROCESSING; }
bool CloudClient::Get(CloudQuery *keyQuery, DataStructures::List<CloudQueryRow*> &specificSystems, RakNetGUID systemIdentifier) { RakNet::BitStream bsOut; bsOut.Write((MessageID)ID_CLOUD_GET_REQUEST); keyQuery->Serialize(true, &bsOut); bsOut.WriteCasted<uint16_t>(specificSystems.Size()); RakAssert(specificSystems.Size() < (uint16_t)-1 ); for (uint16_t i=0; i < specificSystems.Size(); i++) { if (specificSystems[i]->clientGUID!=UNASSIGNED_RAKNET_GUID) { bsOut.Write(true); bsOut.Write(specificSystems[i]->clientGUID); } else { bsOut.Write(false); bsOut.Write(specificSystems[i]->clientSystemAddress); } } SendUnified(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, systemIdentifier, false); return true; }
void PHPDirectoryServer2::PushColumnsAndValues(DataStructures::List<RakNet::RakString> &columns, DataStructures::List<RakNet::RakString> &values) { DataStructures::Table::Row *row=0; unsigned int i; for (i=0; i < columns.Size() && i < values.Size(); i++) { if (columns[i].IsEmpty()==false) { unsigned col = lastDownloadedTable.ColumnIndex(columns[i]); if(col == (unsigned)-1) { col = lastDownloadedTable.AddColumn(columns[i], DataStructures::Table::STRING); } if (row==0) { row = lastDownloadedTable.AddRow(lastDownloadedTable.GetAvailableRowId()); } row->UpdateCell(col,values[i].C_String()); } } }
void TableSerializer::SerializeRow(DataStructures::Table::Row *in, unsigned keyIn, DataStructures::List<DataStructures::Table::ColumnDescriptor> &columns, RakNet::BitStream *out, DataStructures::List<int> &skipColumnIndices) { unsigned cellIndex; out->Write(keyIn); unsigned int numEntries=0; for (cellIndex=0; cellIndex<columns.Size(); cellIndex++) { if (skipColumnIndices.GetIndexOf(cellIndex)==(unsigned)-1) { numEntries++; } } out->Write(numEntries); for (cellIndex=0; cellIndex<columns.Size(); cellIndex++) { if (skipColumnIndices.GetIndexOf(cellIndex)==(unsigned)-1) { out->Write(cellIndex); SerializeCell(out, in->cells[cellIndex], columns[cellIndex].columnType); } } }
unsigned ReplicaManager::GetCommandListReplicaIndex(const DataStructures::List<ReplicaManager::CommandStruct> &commandList, Replica *replica, bool *objectExists) const { unsigned i; for (i=0; i < commandList.Size(); i++) { if (commandList[i].replica==replica) { *objectExists=true; return i; } } *objectExists=false; return 0; }
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_); } }
void ServerState::enter() { // console setup GG.console->clear(); GG.gui.attach(GG.console); // raknet mServer = RakNetworkFactory::GetRakPeerInterface(); mServer->SetIncomingPassword("Rumpelstiltskin", (int)strlen("Rumpelstiltskin")); mSocketDesc = SocketDescriptorPtr(new SocketDescriptor(SERVER_PORT, 0)); bool b = mServer->Startup(4, 30, mSocketDesc.get(), 1); mServer->SetMaximumIncomingConnections(4); mServer->SetOccasionalPing(true); mServer->SetUnreliableTimeout(1000); GuiConsoleOutput cout = GG.console->output(); cout << "Wargame server" << endl; cout << "local IP: " << mServer->GetLocalIP(0) << endl; cout << "GUID: " << mServer->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS).ToString() << endl; DataStructures::List<RakNetSmartPtr<RakNetSocket> > sockets; mServer->GetSockets(sockets); cout << "Ports used by RakNet:\n"; for (unsigned int i=0; i < sockets.Size(); i++) { cout << i+1 << " " << sockets[i]->boundAddress.port << endl; } cout.flush(); // console callback invoked on text input GG.console->slot("textInput", GuiCallbackPtr(new ServerConsoleInput(GG, *this))); // network classes mGameClient = WargameClientPtr(new WargameClient()); mGameServer = WargameServerPtr(new WargameServer()); }
void MessageFilter::DeleteFilterSet(int filterSetID) { FilterSet *filterSet; bool objectExists; unsigned i,index; index = filterList.GetIndexFromKey(filterSetID, &objectExists); if (objectExists) { filterSet=filterList[index]; DeallocateFilterSet(filterSet); filterList.RemoveAtIndex(index); DataStructures::List< FilteredSystem > itemList; DataStructures::List< AddressOrGUID > keyList; systemList.GetAsList(itemList, keyList, _FILE_AND_LINE_); for (i=0; i < itemList.Size(); i++) { if (itemList[i].filter==filterSet) { systemList.Remove(keyList[i], _FILE_AND_LINE_); } } /* // Don't reference this pointer any longer i=0; while (i < systemList.Size()) { if (systemList[i].filter==filterSet) systemList.RemoveAtIndex(i); else ++i; } */ } }
bool NatPunchthroughClient::OpenNATGroup(DataStructures::List<RakNetGUID> destinationSystems, const SystemAddress &facilitator) { ConnectionState cs = rakPeerInterface->GetConnectionState(facilitator); if (cs!=IS_CONNECTED) return false; unsigned long i; for (i=0; i < destinationSystems.Size(); i++) { SendPunchthrough(destinationSystems[i], facilitator); } GroupPunchRequest *gpr = RakNet::OP_NEW<GroupPunchRequest>(_FILE_AND_LINE_); gpr->facilitator=facilitator; gpr->pendingList=destinationSystems; groupPunchRequests.Push(gpr, _FILE_AND_LINE_); return true; }
PluginReceiveResult FullyConnectedMesh2::OnVerifiedJoinCapable(Packet *packet) { VerifiedJoinInProgress vjip; DecomposeJoinCapable(packet, &vjip); // If this assert hits, AddParticipant() was called on this system, or another system, which it should not have been. RakAssert(HasParticipant(packet->guid)==false); DataStructures::List<RakNetGUID> participatingMembersOnClientSucceeded; DataStructures::List<RakNetGUID> participatingMembersOnClientFailed; DataStructures::List<RakNetGUID> participatingMembersNotOnClient; DataStructures::List<RakNetGUID> clientMembersNotParticipatingSucceeded; DataStructures::List<RakNetGUID> clientMembersNotParticipatingFailed; CategorizeVJIP(&vjip, participatingMembersOnClientSucceeded, participatingMembersOnClientFailed, participatingMembersNotOnClient, clientMembersNotParticipatingSucceeded, clientMembersNotParticipatingFailed); if (participatingMembersOnClientFailed.Size()>0) { // Send ID_FCM2_VERIFIED_JOIN_FAILED with GUIDs to disconnect BitStream bsOut; bsOut.Write((MessageID) ID_FCM2_VERIFIED_JOIN_FAILED); SendUnified(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->guid, false); return RR_STOP_PROCESSING_AND_DEALLOCATE; } if (participatingMembersNotOnClient.Size()>0) { BitStream bsOut; bsOut.Write((MessageID) ID_FCM2_VERIFIED_JOIN_START); bsOut.WriteCasted<unsigned short>(participatingMembersNotOnClient.Size()); unsigned int i; for (i=0; i < participatingMembersNotOnClient.Size(); i++) { bsOut.Write(participatingMembersNotOnClient[i]); bsOut.Write(rakPeerInterface->GetSystemAddressFromGuid(participatingMembersNotOnClient[i])); } SendUnified(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->guid, false); return RR_STOP_PROCESSING_AND_DEALLOCATE; } // Let server decide if to accept or reject via RespondOnVerifiedJoinCapable return RR_CONTINUE_PROCESSING; }
void CloudClient::Unsubscribe(DataStructures::List<CloudKey> &keys, DataStructures::List<RakNetGUID> &specificSystems, RakNetGUID systemIdentifier) { SLNet::BitStream bsOut; bsOut.Write((MessageID)ID_CLOUD_UNSUBSCRIBE_REQUEST); RakAssert(keys.Size() < (uint16_t)-1 ); bsOut.WriteCasted<uint16_t>(keys.Size()); for (uint16_t i=0; i < keys.Size(); i++) { keys[i].Serialize(true,&bsOut); } bsOut.WriteCasted<uint16_t>(specificSystems.Size()); RakAssert(specificSystems.Size() < (uint16_t)-1 ); for (uint16_t i=0; i < specificSystems.Size(); i++) { bsOut.Write(specificSystems[i]); } SendUnified(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, systemIdentifier, false); }
/* What is being done here is having 8 peers all connect to eachother over the max defined connection. It runs the connect, wait 20 seconds then see the current connections. Success conditions: All extra connections Refused. Failure conditions: There are more connected than allowed. The connect function fails, the test is not even done. GetMaximumIncomingConnections returns wrong value. RakPeerInterface Functions used, tested indirectly by its use: Startup Connect SetMaximumIncomingConnections Receive DeallocatePacket GetSystemList RakPeerInterface Functions Explicitly Tested: SetMaximumIncomingConnections GetMaximumIncomingConnections */ int MaximumConnectTest::RunTest(DataStructures::List<RakString> params,bool isVerbose,bool noPauses) { const int peerNum= 8; const int maxConnections=4;//Max allowed connections for test RakPeerInterface *peerList[peerNum];//A list of 8 peers Packet *packet; destroyList.Clear(false,_FILE_AND_LINE_); int connReturn; //Initializations of the arrays for (int i=0;i<peerNum;i++) { peerList[i]=RakPeerInterface::GetInstance(); destroyList.Push(peerList[i],_FILE_AND_LINE_); peerList[i]->Startup(maxConnections, &SocketDescriptor(60000+i,0), 1); peerList[i]->SetMaximumIncomingConnections(maxConnections); connReturn=peerList[i]->GetMaximumIncomingConnections(); if (connReturn!=maxConnections) { if (isVerbose) { printf("Getmaxconnections wrong for peer %i, %i should be the value but the value is %i.Fail\n",i,maxConnections,connReturn); DebugTools::ShowError("",!noPauses && isVerbose,__LINE__,__FILE__); } } } //Connect all the peers together for (int i=0;i<peerNum;i++) { for (int j=i+1;j<peerNum;j++)//Start at i+1 so don't connect two of the same together. { if (peerList[i]->Connect("127.0.0.1", 60000+j, 0,0)!=CONNECTION_ATTEMPT_STARTED) { if (isVerbose) DebugTools::ShowError("Problem while calling connect.\n",!noPauses && isVerbose,__LINE__,__FILE__); return 1;//This fails the test, don't bother going on. } } } TimeMS entryTime=GetTimeMS();//Loop entry time while(GetTimeMS()-entryTime<20000)//Run for 20 Secoonds { for (int i=0;i<peerNum;i++)//Receive for all peers { packet=peerList[i]->Receive(); if (isVerbose&&packet) printf("For peer %i\n",i); while(packet) { switch (packet->data[0]) { case ID_REMOTE_DISCONNECTION_NOTIFICATION: if (isVerbose) printf("Another client has disconnected.\n"); break; case ID_REMOTE_CONNECTION_LOST: if (isVerbose) printf("Another client has lost the connection.\n"); break; case ID_REMOTE_NEW_INCOMING_CONNECTION: if (isVerbose) printf("Another client has connected.\n"); break; case ID_CONNECTION_REQUEST_ACCEPTED: if (isVerbose) printf("Our connection request has been accepted.\n"); break; case ID_CONNECTION_ATTEMPT_FAILED: if (isVerbose) printf("A connection has failed.\n");//Should happen in this test break; case ID_NEW_INCOMING_CONNECTION: if (isVerbose) printf("A connection is incoming.\n"); break; case ID_NO_FREE_INCOMING_CONNECTIONS: if (isVerbose) printf("The server is full.\n"); break; case ID_ALREADY_CONNECTED: if (isVerbose) printf("Already connected\n");//Shouldn't happen break; case ID_DISCONNECTION_NOTIFICATION: if (isVerbose) printf("We have been disconnected.\n"); break; case ID_CONNECTION_LOST: if (isVerbose) printf("Connection lost.\n"); break; default: break; } peerList[i]->DeallocatePacket(packet); // Stay in the loop as long as there are more packets. packet = peerList[i]->Receive(); } } RakSleep(0);//If needed for testing } DataStructures::List< SystemAddress > systemList; DataStructures::List< RakNetGUID > guidList; for (int i=0;i<peerNum;i++) { peerList[i]->GetSystemList(systemList,guidList); int connNum=guidList.Size();//Get the number of connections for the current peer if (connNum>maxConnections)//Did we connect to more? { if (isVerbose) { printf("More connections were allowed to peer %i, %i total.Fail\n",i,connNum); DebugTools::ShowError("",!noPauses && isVerbose,__LINE__,__FILE__); } return 2; } } if (isVerbose) printf("Pass\n"); return 0; }
_CONSOLE_2_SetSystemProcessParams #endif int main(void) { // Pointers to the interfaces of our server and client. // Note we can easily have both in the same program RakPeerInterface *server=RakNetworkFactory::GetRakPeerInterface(); RakNetStatistics *rss; server->SetIncomingPassword("Rumpelstiltskin", (int)strlen("Rumpelstiltskin")); server->SetTimeoutTime(30000,UNASSIGNED_SYSTEM_ADDRESS); // PacketLogger packetLogger; // server->AttachPlugin(&packetLogger); // Holds packets Packet* p; // GetPacketIdentifier returns this unsigned char packetIdentifier; // Record the first client that connects to us so we can pass it to the ping function SystemAddress clientID=UNASSIGNED_SYSTEM_ADDRESS; // Holds user data char portstring[30]; printf("This is a sample implementation of a text based chat server.\n"); printf("Connect to the project 'Chat Example Client'.\n"); printf("Difficulty: Beginner\n\n"); // A server puts("Enter the server port to listen on"); gets(portstring); if (portstring[0]==0) strcpy(portstring, "1234"); puts("Starting server."); // Starting the server is very simple. 2 players allowed. // 0 means we don't care about a connectionValidationInteger, and false // for low priority threads SocketDescriptor socketDescriptor(atoi(portstring),0); bool b = server->Startup(4, 30, &socketDescriptor, 1 ); server->SetMaximumIncomingConnections(4); if (b) puts("Server started, waiting for connections."); else { puts("Server failed to start. Terminating."); exit(1); } server->SetOccasionalPing(true); server->SetUnreliableTimeout(1000); DataStructures::List<RakNetSmartPtr<RakNetSocket> > sockets; server->GetSockets(sockets); printf("Ports used by RakNet:\n"); for (unsigned int i=0; i < sockets.Size(); i++) { printf("%i. %i\n", i+1, sockets[i]->boundAddress.port); } printf("My IP is %s\n", server->GetLocalIP(0)); printf("My GUID is %s\n", server->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS).ToString()); puts("'quit' to quit. 'stat' to show stats. 'ping' to ping.\n'ban' to ban an IP from connecting.\n'kick to kick the first connected player.\nType to talk."); char message[2048]; // Loop for input while (1) { // This sleep keeps RakNet responsive RakSleep(30); #ifdef _WIN32 if (kbhit()) { // Notice what is not here: something to keep our network running. It's // fine to block on gets or anything we want // Because the network engine was painstakingly written using threads. gets(message); if (strcmp(message, "quit")==0) { puts("Quitting."); break; } if (strcmp(message, "stat")==0) { rss=server->GetStatistics(server->GetSystemAddressFromIndex(0)); StatisticsToString(rss, message, 2); printf("%s", message); printf("Ping %i\n", server->GetAveragePing(server->GetSystemAddressFromIndex(0))); continue; } if (strcmp(message, "ping")==0) { server->Ping(clientID); continue; } if (strcmp(message, "kick")==0) { server->CloseConnection(clientID, true, 0); continue; } if (strcmp(message, "getconnectionlist")==0) { SystemAddress systems[10]; unsigned short numConnections=10; server->GetConnectionList((SystemAddress*) &systems, &numConnections); for (int i=0; i < numConnections; i++) { printf("%i. %s\n", i+1, systems[i].ToString(true)); } continue; } if (strcmp(message, "ban")==0) { printf("Enter IP to ban. You can use * as a wildcard\n"); gets(message); server->AddToBanList(message); printf("IP %s added to ban list.\n", message); continue; } // Message now holds what we want to broadcast char message2[2048]; // Append Server: to the message so clients know that it ORIGINATED from the server // All messages to all clients come from the server either directly or by being // relayed from other clients message2[0]=0; strcpy(message2, "Server: "); strcat(message2, message); // message2 is the data to send // strlen(message2)+1 is to send the null terminator // HIGH_PRIORITY doesn't actually matter here because we don't use any other priority // RELIABLE_ORDERED means make sure the message arrives in the right order // We arbitrarily pick 0 for the ordering stream // UNASSIGNED_SYSTEM_ADDRESS means don't exclude anyone from the broadcast // true means broadcast the message to everyone connected server->Send(message2, (const int) strlen(message2)+1, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true); } #endif // Get a packet from either the server or the client for (p=server->Receive(); p; server->DeallocatePacket(p), p=server->Receive()) { // We got a packet, get the identifier with our handy function packetIdentifier = GetPacketIdentifier(p); // Check if this is a network message packet switch (packetIdentifier) { case ID_DISCONNECTION_NOTIFICATION: // Connection lost normally printf("ID_DISCONNECTION_NOTIFICATION from %s\n", p->systemAddress.ToString(true));; break; case ID_NEW_INCOMING_CONNECTION: // Somebody connected. We have their IP now printf("ID_NEW_INCOMING_CONNECTION from %s with GUID %s\n", p->systemAddress.ToString(true), p->guid.ToString()); clientID=p->systemAddress; // Record the player ID of the client break; case ID_INCOMPATIBLE_PROTOCOL_VERSION: printf("ID_INCOMPATIBLE_PROTOCOL_VERSION\n"); break; case ID_MODIFIED_PACKET: // Cheater! printf("ID_MODIFIED_PACKET\n"); break; case ID_CONNECTION_LOST: // Couldn't deliver a reliable packet - i.e. the other system was abnormally // terminated printf("ID_CONNECTION_LOST from %s\n", p->systemAddress.ToString(true));; break; default: // The server knows the static data of all clients, so we can prefix the message // With the name data printf("%s\n", p->data); // Relay the message. We prefix the name for other clients. This demonstrates // That messages can be changed on the server before being broadcast // Sending is the same as before sprintf(message, "%s", p->data); server->Send(message, (const int) strlen(message)+1, HIGH_PRIORITY, RELIABLE_ORDERED, 0, p->systemAddress, true); break; } } } server->Shutdown(300); // We're done with the network RakNetworkFactory::DestroyRakPeerInterface(server); return 0; }
void Table::QueryRow(DataStructures::List<unsigned> &inclusionFilterColumnIndices, DataStructures::List<unsigned> &columnIndicesToReturn, unsigned key, Table::Row* row, FilterQuery *inclusionFilters, Table *result) { bool pass=false; unsigned columnIndex; unsigned j; // If no inclusion filters, just add the row if (inclusionFilterColumnIndices.Size()==0) { result->AddRowColumns(key, row, columnIndicesToReturn); } else { // Go through all inclusion filters. Only add this row if all filters pass. for (j=0; j<inclusionFilterColumnIndices.Size(); j++) { columnIndex=inclusionFilterColumnIndices[j]; if (columnIndex!=(unsigned)-1 && row->cells[columnIndex]->isEmpty==false ) { if (columns[inclusionFilterColumnIndices[j]].columnType==STRING && row->cells[columnIndex]->c==0 || inclusionFilters[j].cellValue->c==0 ) continue; switch (inclusionFilters[j].operation) { case QF_EQUAL: switch(columns[inclusionFilterColumnIndices[j]].columnType) { case NUMERIC: pass=row->cells[columnIndex]->i==inclusionFilters[j].cellValue->i; break; case STRING: pass=strcmp(row->cells[columnIndex]->c,inclusionFilters[j].cellValue->c)==0; break; case BINARY: pass=row->cells[columnIndex]->i==inclusionFilters[j].cellValue->i && memcmp(row->cells[columnIndex]->c,inclusionFilters[j].cellValue->c, row->cells[columnIndex]->i)==0; break; case POINTER: pass=row->cells[columnIndex]->ptr==inclusionFilters[j].cellValue->ptr; break; } break; case QF_NOT_EQUAL: switch(columns[inclusionFilterColumnIndices[j]].columnType) { case NUMERIC: pass=row->cells[columnIndex]->i!=inclusionFilters[j].cellValue->i; break; case STRING: pass=strcmp(row->cells[columnIndex]->c,inclusionFilters[j].cellValue->c)!=0; break; case BINARY: pass=row->cells[columnIndex]->i==inclusionFilters[j].cellValue->i && memcmp(row->cells[columnIndex]->c,inclusionFilters[j].cellValue->c, row->cells[columnIndex]->i)==0; break; case POINTER: pass=row->cells[columnIndex]->ptr!=inclusionFilters[j].cellValue->ptr; break; } break; case QF_GREATER_THAN: switch(columns[inclusionFilterColumnIndices[j]].columnType) { case NUMERIC: pass=row->cells[columnIndex]->i>inclusionFilters[j].cellValue->i; break; case STRING: pass=strcmp(row->cells[columnIndex]->c,inclusionFilters[j].cellValue->c)>0; break; case BINARY: break; case POINTER: pass=row->cells[columnIndex]->ptr>inclusionFilters[j].cellValue->ptr; break; } break; case QF_GREATER_THAN_EQ: switch(columns[inclusionFilterColumnIndices[j]].columnType) { case NUMERIC: pass=row->cells[columnIndex]->i>=inclusionFilters[j].cellValue->i; break; case STRING: pass=strcmp(row->cells[columnIndex]->c,inclusionFilters[j].cellValue->c)>=0; break; case BINARY: break; case POINTER: pass=row->cells[columnIndex]->ptr>=inclusionFilters[j].cellValue->ptr; break; } break; case QF_LESS_THAN: switch(columns[inclusionFilterColumnIndices[j]].columnType) { case NUMERIC: pass=row->cells[columnIndex]->i<inclusionFilters[j].cellValue->i; break; case STRING: pass=strcmp(row->cells[columnIndex]->c,inclusionFilters[j].cellValue->c)<0; break; case BINARY: break; case POINTER: pass=row->cells[columnIndex]->ptr<inclusionFilters[j].cellValue->ptr; break; } break; case QF_LESS_THAN_EQ: switch(columns[inclusionFilterColumnIndices[j]].columnType) { case NUMERIC: pass=row->cells[columnIndex]->i<=inclusionFilters[j].cellValue->i; break; case STRING: pass=strcmp(row->cells[columnIndex]->c,inclusionFilters[j].cellValue->c)<=0; break; case BINARY: break; case POINTER: pass=row->cells[columnIndex]->ptr<=inclusionFilters[j].cellValue->ptr; break; } break; case QF_IS_EMPTY: pass=false; break; case QF_NOT_EMPTY: pass=true; break; default: pass=false; RakAssert(0); break; } } else { if (inclusionFilters[j].operation==QF_IS_EMPTY) pass=true; else pass=false; // No value for this cell } if (pass==false) break; } if (pass) { result->AddRowColumns(key, row, columnIndicesToReturn); } } }
void Table::QueryTable(unsigned *columnIndicesSubset, unsigned numColumnSubset, FilterQuery *inclusionFilters, unsigned numInclusionFilters, unsigned *rowIds, unsigned numRowIDs, Table *result) { unsigned i; DataStructures::List<unsigned> columnIndicesToReturn; // Clear the result table. result->Clear(); if (columnIndicesSubset && numColumnSubset>0) { for (i=0; i < numColumnSubset; i++) { if (columnIndicesSubset[i]>=0 && columnIndicesSubset[i]<columns.Size()) columnIndicesToReturn.Insert(columnIndicesSubset[i]); } } else { for (i=0; i < columns.Size(); i++) columnIndicesToReturn.Insert(i); } if (columnIndicesToReturn.Size()==0) return; // No valid columns specified for (i=0; i < columnIndicesToReturn.Size(); i++) { result->AddColumn(columns[columnIndicesToReturn[i]].columnName,columns[columnIndicesToReturn[i]].columnType); } // Get the column indices of the filter queries. DataStructures::List<unsigned> inclusionFilterColumnIndices; if (inclusionFilters && numInclusionFilters>0) { for (i=0; i < numInclusionFilters; i++) { if (inclusionFilters[i].columnName[0]) inclusionFilters[i].columnIndex=ColumnIndex(inclusionFilters[i].columnName); if (inclusionFilters[i].columnIndex>=0 && inclusionFilters[i].columnIndex<columns.Size()) inclusionFilterColumnIndices.Insert(inclusionFilters[i].columnIndex); else inclusionFilterColumnIndices.Insert((unsigned)-1); } } if (rowIds==0 || numRowIDs==0) { // All rows DataStructures::Page<unsigned, Row*, _TABLE_BPLUS_TREE_ORDER> *cur = rows.GetListHead(); while (cur) { for (i=0; i < (unsigned)cur->size; i++) { QueryRow(inclusionFilterColumnIndices, columnIndicesToReturn, cur->keys[i], cur->data[i], inclusionFilters, result); } cur=cur->next; } } else { // Specific rows Row *row; for (i=0; i < numRowIDs; i++) { if (rows.Get(rowIds[i], row)) { QueryRow(inclusionFilterColumnIndices, columnIndicesToReturn, rowIds[i], row, inclusionFilters, result); } } } }
PluginReceiveResult NatPunchthroughServer::OnReceive(Packet *packet) { switch (packet->data[0]) { case ID_NAT_PUNCHTHROUGH_REQUEST: OnNATPunchthroughRequest(packet); return RR_STOP_PROCESSING_AND_DEALLOCATE; case ID_NAT_GET_MOST_RECENT_PORT: OnGetMostRecentPort(packet); return RR_STOP_PROCESSING_AND_DEALLOCATE; case ID_NAT_CLIENT_READY: OnClientReady(packet); return RR_STOP_PROCESSING_AND_DEALLOCATE; case ID_NAT_REQUEST_BOUND_ADDRESSES: { RakNet::BitStream outgoingBs; outgoingBs.Write((MessageID)ID_NAT_RESPOND_BOUND_ADDRESSES); if (boundAddresses[0]==UNASSIGNED_SYSTEM_ADDRESS) { DataStructures::List<RakNetSocket2* > sockets; rakPeerInterface->GetSockets(sockets); for (int i=0; i < sockets.Size() && i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++) { boundAddresses[i]=sockets[i]->GetBoundAddress(); boundAddressCount++; } } outgoingBs.Write(boundAddressCount); for (int i=0; i < boundAddressCount; i++) { outgoingBs.Write(boundAddresses[i]); } rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false); } return RR_STOP_PROCESSING_AND_DEALLOCATE; case ID_NAT_PING: { } return RR_STOP_PROCESSING_AND_DEALLOCATE; case ID_OUT_OF_BAND_INTERNAL: if (packet->length>=2 && packet->data[1]==ID_NAT_PING) { RakNet::BitStream bs(packet->data,packet->length,false); bs.IgnoreBytes(sizeof(MessageID)*2); uint16_t externalPort; bs.Read(externalPort); RakNet::BitStream outgoingBs; outgoingBs.Write((MessageID)ID_NAT_PONG); outgoingBs.Write(externalPort); uint16_t externalPort2 = packet->systemAddress.GetPort(); outgoingBs.Write(externalPort2); rakPeerInterface->SendOutOfBand((const char*) packet->systemAddress.ToString(false),packet->systemAddress.GetPort(),(const char*) outgoingBs.GetData(),outgoingBs.GetNumberOfBytesUsed()); return RR_STOP_PROCESSING_AND_DEALLOCATE; } } return RR_CONTINUE_PROCESSING; }
void StatisticsHistoryPlugin::Update(void) { DataStructures::List<SystemAddress> addresses; DataStructures::List<RakNetGUID> guids; DataStructures::List<RakNetStatistics> stats; rakPeerInterface->GetStatisticsList(addresses, guids, stats); Time curTime = GetTime(); for (unsigned int idx = 0; idx < guids.Size(); idx++) { unsigned int objectIndex = statistics.GetObjectIndex(guids[idx].g); if (objectIndex!=(unsigned int)-1) { statistics.AddValueByIndex(objectIndex, "RN_ACTUAL_BYTES_SENT", (SHValueType) stats[idx].valueOverLastSecond[ACTUAL_BYTES_SENT], curTime, false); statistics.AddValueByIndex(objectIndex, "RN_USER_MESSAGE_BYTES_RESENT", (SHValueType) stats[idx].valueOverLastSecond[USER_MESSAGE_BYTES_RESENT], curTime, false); statistics.AddValueByIndex(objectIndex, "RN_ACTUAL_BYTES_RECEIVED", (SHValueType) stats[idx].valueOverLastSecond[ACTUAL_BYTES_RECEIVED], curTime, false); statistics.AddValueByIndex(objectIndex, "RN_USER_MESSAGE_BYTES_PUSHED", (SHValueType) stats[idx].valueOverLastSecond[USER_MESSAGE_BYTES_PUSHED], curTime, false); statistics.AddValueByIndex(objectIndex, "RN_USER_MESSAGE_BYTES_RECEIVED_PROCESSED", (SHValueType) stats[idx].valueOverLastSecond[USER_MESSAGE_BYTES_RECEIVED_PROCESSED], curTime, false); statistics.AddValueByIndex(objectIndex, "RN_lastPing", (SHValueType) rakPeerInterface->GetLastPing(guids[idx]), curTime, false); statistics.AddValueByIndex(objectIndex, "RN_bytesInResendBuffer", (SHValueType) stats[idx].bytesInResendBuffer, curTime, false); statistics.AddValueByIndex(objectIndex, "RN_packetlossLastSecond", (SHValueType) stats[idx].packetlossLastSecond, curTime, false); } } /* RakNetStatistics rns; DataStructures::List<SystemAddress> addresses; DataStructures::List<RakNetGUID> guids; rakPeerInterface->GetSystemList(addresses, guids); for (unsigned int idx = 0; idx < guids.Size(); idx++) { rakPeerInterface->GetStatistics(remoteSystems[idx], &rns); statistics.AddValue(); bool AddValue(uint64_t objectId, RakString key, SHValueType val, Time curTime); } */ }
/* What is being done here is having 256 clients connect to one server, disconnect, connect again. Do this for about 10 seconds. Then allow them all to connect for one last time. This one has a nonblocking recieve so doesn't wait for connects or anything. Just rapid connecting disconnecting. Good ideas for changes: After the last check run a eightpeers like test an add the conditions of that test as well. Make sure that if we initiate the connection we get a proper message and if not we get a proper message. Add proper conditions. Randomize sending the disconnect notes Success conditions: All connected normally. Failure conditions: Doesn't reconnect normally. During the very first connect loop any connect returns false. Connect function returns false and peer is not connected to anything. */ int ManyClientsOneServerNonBlockingTest::RunTest(DataStructures::List<RakString> params,bool isVerbose,bool noPauses) { const int clientNum= 256; RakPeerInterface *clientList[clientNum];//A list of clients RakPeerInterface *server;//The server SystemAddress currentSystem; //SystemAddress currentSystem; Packet *packet; destroyList.Clear(false,_FILE_AND_LINE_); //Initializations of the arrays for (int i=0;i<clientNum;i++) { clientList[i]=RakPeerInterface::GetInstance(); destroyList.Push(clientList[i],_FILE_AND_LINE_); clientList[i]->Startup(1,&SocketDescriptor(), 1); } server=RakPeerInterface::GetInstance(); destroyList.Push(server,_FILE_AND_LINE_); server->Startup(clientNum, &SocketDescriptor(60000,0), 1); server->SetMaximumIncomingConnections(clientNum); //Connect all the clients to the server for (int i=0;i<clientNum;i++) { if (clientList[i]->Connect("127.0.0.1", 60000, 0,0)!=CONNECTION_ATTEMPT_STARTED) { if (isVerbose) DebugTools::ShowError("Problem while calling connect.\n",!noPauses && isVerbose,__LINE__,__FILE__); return 1;//This fails the test, don't bother going on. } } TimeMS entryTime=GetTimeMS();//Loop entry time DataStructures::List< SystemAddress > systemList; DataStructures::List< RakNetGUID > guidList; if (isVerbose) printf("Entering disconnect loop \n"); while(GetTimeMS()-entryTime<10000)//Run for 10 Secoonds { //Disconnect all clients IF connected to any from client side for (int i=0;i<clientNum;i++) { clientList[i]->GetSystemList(systemList,guidList);//Get connectionlist int len=systemList.Size(); for (int j=0;j<len;j++)//Disconnect them all { clientList[i]->CloseConnection (systemList[j],true,0,LOW_PRIORITY); } } //RakSleep(100); //Connect for (int i=0;i<clientNum;i++) { currentSystem.SetBinaryAddress("127.0.0.1"); currentSystem.port=60000; if(!CommonFunctions::ConnectionStateMatchesOptions (clientList[i],currentSystem,true,true,true,true) )//Are we connected or is there a pending operation ? { if (clientList[i]->Connect("127.0.0.1", 60000, 0,0)!=CONNECTION_ATTEMPT_STARTED) { if (isVerbose) DebugTools::ShowError("Problem while calling connect. \n",!noPauses && isVerbose,__LINE__,__FILE__); return 1;//This fails the test, don't bother going on. } } } //Server receive packet=server->Receive(); if (isVerbose&&packet) printf("For server\n"); while(packet) { switch (packet->data[0]) { case ID_REMOTE_DISCONNECTION_NOTIFICATION: if (isVerbose) printf("Another client has disconnected.\n"); break; case ID_REMOTE_CONNECTION_LOST: if (isVerbose) printf("Another client has lost the connection.\n"); break; case ID_REMOTE_NEW_INCOMING_CONNECTION: if (isVerbose) printf("Another client has connected.\n"); break; case ID_CONNECTION_REQUEST_ACCEPTED: if (isVerbose) printf("Our connection request has been accepted.\n"); break; case ID_CONNECTION_ATTEMPT_FAILED: if (isVerbose) printf("A connection has failed.\n"); break; case ID_NEW_INCOMING_CONNECTION: if (isVerbose) printf("A connection is incoming.\n"); break; case ID_NO_FREE_INCOMING_CONNECTIONS: if (isVerbose) printf("The server is full.\n"); break; case ID_ALREADY_CONNECTED: if (isVerbose) printf("Already connected\n"); break; case ID_DISCONNECTION_NOTIFICATION: if (isVerbose) printf("We have been disconnected.\n"); break; case ID_CONNECTION_LOST: if (isVerbose) printf("Connection lost.\n"); break; default: break; } server->DeallocatePacket(packet); // Stay in the loop as long as there are more packets. packet = server->Receive(); } for (int i=0;i<clientNum;i++)//Receive for all peers { packet=clientList[i]->Receive(); if (isVerbose&&packet) printf("For peer %i\n",i); while(packet) { switch (packet->data[0]) { case ID_REMOTE_DISCONNECTION_NOTIFICATION: if (isVerbose) printf("Another client has disconnected.\n"); break; case ID_REMOTE_CONNECTION_LOST: if (isVerbose) printf("Another client has lost the connection.\n"); break; case ID_REMOTE_NEW_INCOMING_CONNECTION: if (isVerbose) printf("Another client has connected.\n"); break; case ID_CONNECTION_REQUEST_ACCEPTED: if (isVerbose) printf("Our connection request has been accepted.\n"); break; case ID_CONNECTION_ATTEMPT_FAILED: if (isVerbose) printf("A connection has failed.\n"); break; case ID_NEW_INCOMING_CONNECTION: if (isVerbose) printf("A connection is incoming.\n"); break; case ID_NO_FREE_INCOMING_CONNECTIONS: if (isVerbose) printf("The server is full.\n"); break; case ID_ALREADY_CONNECTED: if (isVerbose) printf("Already connected\n"); break; case ID_DISCONNECTION_NOTIFICATION: if (isVerbose) printf("We have been disconnected.\n"); break; case ID_CONNECTION_LOST: if (isVerbose) printf("Connection lost.\n"); break; default: break; } clientList[i]->DeallocatePacket(packet); // Stay in the loop as long as there are more packets. packet = clientList[i]->Receive(); } } RakSleep(0);//If needed for testing } entryTime=GetTimeMS(); while(GetTimeMS()-entryTime<2000)//Run for 2 Secoonds to process incoming disconnects { //Server receive packet=server->Receive(); if (isVerbose&&packet) printf("For server\n"); while(packet) { switch (packet->data[0]) { case ID_REMOTE_DISCONNECTION_NOTIFICATION: if (isVerbose) printf("Another client has disconnected.\n"); break; case ID_REMOTE_CONNECTION_LOST: if (isVerbose) printf("Another client has lost the connection.\n"); break; case ID_REMOTE_NEW_INCOMING_CONNECTION: if (isVerbose) printf("Another client has connected.\n"); break; case ID_CONNECTION_REQUEST_ACCEPTED: if (isVerbose) printf("Our connection request has been accepted.\n"); break; case ID_CONNECTION_ATTEMPT_FAILED: if (isVerbose) printf("A connection has failed.\n"); break; case ID_NEW_INCOMING_CONNECTION: if (isVerbose) printf("A connection is incoming.\n"); break; case ID_NO_FREE_INCOMING_CONNECTIONS: if (isVerbose) printf("The server is full.\n"); break; case ID_ALREADY_CONNECTED: if (isVerbose) printf("Already connected\n"); break; case ID_DISCONNECTION_NOTIFICATION: if (isVerbose) printf("We have been disconnected.\n"); break; case ID_CONNECTION_LOST: if (isVerbose) printf("Connection lost.\n"); break; default: break; } server->DeallocatePacket(packet); // Stay in the loop as long as there are more packets. packet = server->Receive(); } for (int i=0;i<clientNum;i++)//Receive for all peers { packet=clientList[i]->Receive(); if (isVerbose&&packet) printf("For peer %i\n",i); while(packet) { switch (packet->data[0]) { case ID_REMOTE_DISCONNECTION_NOTIFICATION: if (isVerbose) printf("Another client has disconnected.\n"); break; case ID_REMOTE_CONNECTION_LOST: if (isVerbose) printf("Another client has lost the connection.\n"); break; case ID_REMOTE_NEW_INCOMING_CONNECTION: if (isVerbose) printf("Another client has connected.\n"); break; case ID_CONNECTION_REQUEST_ACCEPTED: if (isVerbose) printf("Our connection request has been accepted.\n"); break; case ID_CONNECTION_ATTEMPT_FAILED: if (isVerbose) printf("A connection has failed.\n"); break; case ID_NEW_INCOMING_CONNECTION: if (isVerbose) printf("A connection is incoming.\n"); break; case ID_NO_FREE_INCOMING_CONNECTIONS: if (isVerbose) printf("The server is full.\n"); break; case ID_ALREADY_CONNECTED: if (isVerbose) printf("Already connected\n"); break; case ID_DISCONNECTION_NOTIFICATION: if (isVerbose) printf("We have been disconnected.\n"); break; case ID_CONNECTION_LOST: if (isVerbose) printf("Connection lost.\n"); break; default: break; } clientList[i]->DeallocatePacket(packet); // Stay in the loop as long as there are more packets. packet = clientList[i]->Receive(); } } RakSleep(0);//If needed for testing } //Connect for (int i=0;i<clientNum;i++) { currentSystem.SetBinaryAddress("127.0.0.1"); currentSystem.port=60000; if(!CommonFunctions::ConnectionStateMatchesOptions (clientList[i],currentSystem,true,true,true,true) )//Are we connected or is there a pending operation ? { if (clientList[i]->Connect("127.0.0.1", 60000, 0,0)!=CONNECTION_ATTEMPT_STARTED) { clientList[i]->GetSystemList(systemList,guidList);//Get connectionlist int len=systemList.Size(); if (isVerbose) DebugTools::ShowError("Problem while calling connect. \n",!noPauses && isVerbose,__LINE__,__FILE__); return 1;//This fails the test, don't bother going on. } } } entryTime=GetTimeMS(); while(GetTimeMS()-entryTime<5000)//Run for 5 Secoonds { //Server receive packet=server->Receive(); if (isVerbose&&packet) printf("For server\n"); while(packet) { switch (packet->data[0]) { case ID_REMOTE_DISCONNECTION_NOTIFICATION: if (isVerbose) printf("Another client has disconnected.\n"); break; case ID_REMOTE_CONNECTION_LOST: if (isVerbose) printf("Another client has lost the connection.\n"); break; case ID_REMOTE_NEW_INCOMING_CONNECTION: if (isVerbose) printf("Another client has connected.\n"); break; case ID_CONNECTION_REQUEST_ACCEPTED: if (isVerbose) printf("Our connection request has been accepted.\n"); break; case ID_CONNECTION_ATTEMPT_FAILED: if (isVerbose) printf("A connection has failed.\n"); break; case ID_NEW_INCOMING_CONNECTION: if (isVerbose) printf("A connection is incoming.\n"); break; case ID_NO_FREE_INCOMING_CONNECTIONS: if (isVerbose) printf("The server is full.\n"); break; case ID_ALREADY_CONNECTED: if (isVerbose) printf("Already connected\n"); break; case ID_DISCONNECTION_NOTIFICATION: if (isVerbose) printf("We have been disconnected.\n"); break; case ID_CONNECTION_LOST: if (isVerbose) printf("Connection lost.\n"); break; default: break; } server->DeallocatePacket(packet); // Stay in the loop as long as there are more packets. packet = server->Receive(); } for (int i=0;i<clientNum;i++)//Receive for all clients { packet=clientList[i]->Receive(); if (isVerbose&&packet) printf("For peer %i\n",i); while(packet) { switch (packet->data[0]) { case ID_REMOTE_DISCONNECTION_NOTIFICATION: if (isVerbose) printf("Another client has disconnected.\n"); break; case ID_REMOTE_CONNECTION_LOST: if (isVerbose) printf("Another client has lost the connection.\n"); break; case ID_REMOTE_NEW_INCOMING_CONNECTION: if (isVerbose) printf("Another client has connected.\n"); break; case ID_CONNECTION_REQUEST_ACCEPTED: if (isVerbose) printf("Our connection request has been accepted.\n"); break; case ID_CONNECTION_ATTEMPT_FAILED: if (isVerbose) printf("A connection has failed.\n"); break; case ID_NEW_INCOMING_CONNECTION: if (isVerbose) printf("A connection is incoming.\n"); break; case ID_NO_FREE_INCOMING_CONNECTIONS: if (isVerbose) printf("The server is full.\n"); break; case ID_ALREADY_CONNECTED: if (isVerbose) printf("Already connected\n"); break; case ID_DISCONNECTION_NOTIFICATION: if (isVerbose) printf("We have been disconnected.\n"); break; case ID_CONNECTION_LOST: if (isVerbose) printf("Connection lost.\n"); break; default: break; } clientList[i]->DeallocatePacket(packet); // Stay in the loop as long as there are more packets. packet = clientList[i]->Receive(); } } RakSleep(0);//If needed for testing } for (int i=0;i<clientNum;i++) { clientList[i]->GetSystemList(systemList,guidList); int connNum=guidList.Size();//Get the number of connections for the current peer if (connNum!=1)//Did we connect to all? { if (isVerbose) printf("Not all clients reconnected normally.\nFailed on clients number %i\n",i); if (isVerbose) DebugTools::ShowError("",!noPauses && isVerbose,__LINE__,__FILE__); return 2; } } if (isVerbose) printf("Pass\n"); return 0; }
_CONSOLE_2_SetSystemProcessParams #endif int main(void) { // Pointers to the interfaces of our server and client. // Note we can easily have both in the same program RakNet::RakPeerInterface *server=RakNet::RakPeerInterface::GetInstance(); RakNet::RakNetStatistics *rss; server->SetIncomingPassword("Rumpelstiltskin", (int)strlen("Rumpelstiltskin")); server->SetTimeoutTime(30000,RakNet::UNASSIGNED_SYSTEM_ADDRESS); // RakNet::PacketLogger packetLogger; // server->AttachPlugin(&packetLogger); #if LIBCAT_SECURITY==1 cat::EasyHandshake handshake; char public_key[cat::EasyHandshake::PUBLIC_KEY_BYTES]; char private_key[cat::EasyHandshake::PRIVATE_KEY_BYTES]; handshake.GenerateServerKey(public_key, private_key); server->InitializeSecurity(public_key, private_key, false); FILE *fp = fopen("publicKey.dat","wb"); fwrite(public_key,sizeof(public_key),1,fp); fclose(fp); #endif // Holds packets RakNet::Packet* p; // GetPacketIdentifier returns this unsigned char packetIdentifier; // Record the first client that connects to us so we can pass it to the ping function RakNet::SystemAddress clientID=RakNet::UNASSIGNED_SYSTEM_ADDRESS; // Holds user data char portstring[30]; printf("This is a sample implementation of a text based chat server.\n"); printf("Connect to the project 'Chat Example Client'.\n"); printf("Difficulty: Beginner\n\n"); // A server puts("Enter the server port to listen on"); Gets(portstring,sizeof(portstring)); if (portstring[0]==0) strcpy(portstring, "1234"); puts("Starting server."); // Starting the server is very simple. 2 players allowed. // 0 means we don't care about a connectionValidationInteger, and false // for low priority threads // I am creating two socketDesciptors, to create two sockets. One using IPV6 and the other IPV4 RakNet::SocketDescriptor socketDescriptors[2]; socketDescriptors[0].port=atoi(portstring); socketDescriptors[0].socketFamily=AF_INET; // Test out IPV4 socketDescriptors[1].port=atoi(portstring); socketDescriptors[1].socketFamily=AF_INET6; // Test out IPV6 bool b = server->Startup(4, socketDescriptors, 2 )==RakNet::RAKNET_STARTED; server->SetMaximumIncomingConnections(4); if (!b) { printf("Failed to start dual IPV4 and IPV6 ports. Trying IPV4 only.\n"); // Try again, but leave out IPV6 b = server->Startup(4, socketDescriptors, 1 )==RakNet::RAKNET_STARTED; if (!b) { puts("Server failed to start. Terminating."); exit(1); } } server->SetOccasionalPing(true); server->SetUnreliableTimeout(1000); DataStructures::List< RakNet::RakNetSocket2* > sockets; server->GetSockets(sockets); printf("Socket addresses used by RakNet:\n"); for (unsigned int i=0; i < sockets.Size(); i++) { printf("%i. %s\n", i+1, sockets[i]->GetBoundAddress().ToString(true)); } printf("\nMy IP addresses:\n"); for (unsigned int i=0; i < server->GetNumberOfAddresses(); i++) { RakNet::SystemAddress sa = server->GetInternalID(RakNet::UNASSIGNED_SYSTEM_ADDRESS, i); printf("%i. %s (LAN=%i)\n", i+1, sa.ToString(false), sa.IsLANAddress()); } printf("\nMy GUID is %s\n", server->GetGuidFromSystemAddress(RakNet::UNASSIGNED_SYSTEM_ADDRESS).ToString()); puts("'quit' to quit. 'stat' to show stats. 'ping' to ping.\n'pingip' to ping an ip address\n'ban' to ban an IP from connecting.\n'kick to kick the first connected player.\nType to talk."); char message[2048]; // Loop for input while (1) { // This sleep keeps RakNet responsive RakSleep(30); if (kbhit()) { // Notice what is not here: something to keep our network running. It's // fine to block on gets or anything we want // Because the network engine was painstakingly written using threads. Gets(message,sizeof(message)); if (strcmp(message, "quit")==0) { puts("Quitting."); break; } if (strcmp(message, "stat")==0) { rss=server->GetStatistics(server->GetSystemAddressFromIndex(0)); StatisticsToString(rss, message, 2); printf("%s", message); printf("Ping %i\n", server->GetAveragePing(server->GetSystemAddressFromIndex(0))); continue; } if (strcmp(message, "ping")==0) { server->Ping(clientID); continue; } if (strcmp(message, "pingip")==0) { printf("Enter IP: "); Gets(message,sizeof(message)); printf("Enter port: "); Gets(portstring,sizeof(portstring)); if (portstring[0]==0) strcpy(portstring, "1234"); server->Ping(message, atoi(portstring), false); continue; } if (strcmp(message, "kick")==0) { server->CloseConnection(clientID, true, 0); continue; } if (strcmp(message, "getconnectionlist")==0) { RakNet::SystemAddress systems[10]; unsigned short numConnections=10; server->GetConnectionList((RakNet::SystemAddress*) &systems, &numConnections); for (int i=0; i < numConnections; i++) { printf("%i. %s\n", i+1, systems[i].ToString(true)); } continue; } if (strcmp(message, "ban")==0) { printf("Enter IP to ban. You can use * as a wildcard\n"); Gets(message,sizeof(message)); server->AddToBanList(message); printf("IP %s added to ban list.\n", message); continue; } // Message now holds what we want to broadcast char message2[2048]; // Append Server: to the message so clients know that it ORIGINATED from the server // All messages to all clients come from the server either directly or by being // relayed from other clients message2[0]=0; strcpy(message2, "Server: "); strcat(message2, message); // message2 is the data to send // strlen(message2)+1 is to send the null terminator // HIGH_PRIORITY doesn't actually matter here because we don't use any other priority // RELIABLE_ORDERED means make sure the message arrives in the right order // We arbitrarily pick 0 for the ordering stream // RakNet::UNASSIGNED_SYSTEM_ADDRESS means don't exclude anyone from the broadcast // true means broadcast the message to everyone connected server->Send(message2, (const int) strlen(message2)+1, HIGH_PRIORITY, RELIABLE_ORDERED, 0, RakNet::UNASSIGNED_SYSTEM_ADDRESS, true); } // Get a packet from either the server or the client for (p=server->Receive(); p; server->DeallocatePacket(p), p=server->Receive()) { // We got a packet, get the identifier with our handy function packetIdentifier = GetPacketIdentifier(p); // Check if this is a network message packet switch (packetIdentifier) { case ID_DISCONNECTION_NOTIFICATION: // Connection lost normally printf("ID_DISCONNECTION_NOTIFICATION from %s\n", p->systemAddress.ToString(true));; break; case ID_NEW_INCOMING_CONNECTION: // Somebody connected. We have their IP now printf("ID_NEW_INCOMING_CONNECTION from %s with GUID %s\n", p->systemAddress.ToString(true), p->guid.ToString()); clientID=p->systemAddress; // Record the player ID of the client printf("Remote internal IDs:\n"); for (int index=0; index < MAXIMUM_NUMBER_OF_INTERNAL_IDS; index++) { RakNet::SystemAddress internalId = server->GetInternalID(p->systemAddress, index); if (internalId!=RakNet::UNASSIGNED_SYSTEM_ADDRESS) { printf("%i. %s\n", index+1, internalId.ToString(true)); } } break; case ID_INCOMPATIBLE_PROTOCOL_VERSION: printf("ID_INCOMPATIBLE_PROTOCOL_VERSION\n"); break; case ID_CONNECTED_PING: case ID_UNCONNECTED_PING: printf("Ping from %s\n", p->systemAddress.ToString(true)); break; case ID_CONNECTION_LOST: // Couldn't deliver a reliable packet - i.e. the other system was abnormally // terminated printf("ID_CONNECTION_LOST from %s\n", p->systemAddress.ToString(true));; break; default: // The server knows the static data of all clients, so we can prefix the message // With the name data printf("%s\n", p->data); // Relay the message. We prefix the name for other clients. This demonstrates // That messages can be changed on the server before being broadcast // Sending is the same as before sprintf(message, "%s", p->data); server->Send(message, (const int) strlen(message)+1, HIGH_PRIORITY, RELIABLE_ORDERED, 0, p->systemAddress, true); break; } } } server->Shutdown(300); // We're done with the network RakNet::RakPeerInterface::DestroyInstance(server); return 0; }
bool TetrisServer::Init() { m_interface = RakNet::RakPeerInterface::GetInstance(); RakNet::RakNetStatistics *rss; m_interface->SetIncomingPassword("Rumpelstiltskin", (int)strlen("Rumpelstiltskin")); m_interface->SetTimeoutTime(30000, RakNet::UNASSIGNED_SYSTEM_ADDRESS); // Record the first client that connects to us so we can pass it to the ping function m_clientID = RakNet::UNASSIGNED_SYSTEM_ADDRESS; // Holds user data char* portstring = "1234"; printf("This is a sample implementation of a text based chat server.\n"); printf("Connect to the project 'Chat Example Client'.\n"); printf("Difficulty: Beginner\n\n"); printf("Starting server.\n"); // Starting the server is very simple. 2 players allowed. // 0 means we don't care about a connectionValidationInteger, and false // for low priority threads // I am creating two socketDesciptors, to create two sockets. One using IPV6 and the other IPV4 RakNet::SocketDescriptor socketDescriptors[2]; socketDescriptors[0].port = atoi(portstring); socketDescriptors[0].socketFamily = AF_INET; // Test out IPV4 socketDescriptors[1].port = atoi(portstring); socketDescriptors[1].socketFamily = AF_INET6; // Test out IPV6 bool b = m_interface->Startup(4, socketDescriptors, 2) == RakNet::RAKNET_STARTED; m_interface->SetMaximumIncomingConnections(4); if (!b) { printf("Failed to start dual IPV4 and IPV6 ports. Trying IPV4 only.\n"); // Try again, but leave out IPV6 b = m_interface->Startup(4, socketDescriptors, 1) == RakNet::RAKNET_STARTED; if (!b) { printf("Server failed to start. Terminating.\n"); return false; } } m_interface->SetOccasionalPing(true); m_interface->SetUnreliableTimeout(1000); DataStructures::List< RakNet::RakNetSocket2* > sockets; m_interface->GetSockets(sockets); printf("Socket addresses used by RakNet:\n"); for (unsigned int i = 0; i < sockets.Size(); i++) { printf("%i. %s\n", i + 1, sockets[i]->GetBoundAddress().ToString(true)); } printf("\nMy IP addresses:\n"); for (unsigned int i = 0; i < m_interface->GetNumberOfAddresses(); i++) { RakNet::SystemAddress sa = m_interface->GetInternalID(RakNet::UNASSIGNED_SYSTEM_ADDRESS, i); printf("%i. %s (LAN=%i)\n", i + 1, sa.ToString(false), sa.IsLANAddress()); } printf("\nMy GUID is %s\n", m_interface->GetGuidFromSystemAddress(RakNet::UNASSIGNED_SYSTEM_ADDRESS).ToString()); return true; }
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; }
int main(void) { printf("Demonstrates networking elements for a P2P game on the PC, self-released,\nwith player hosted game servers\n"); printf("Difficulty: Advanced\n\n"); // --------------------------------------------------------------------------------------------------------------------- // Allocate plugins. See declaration in this file for description of each // --------------------------------------------------------------------------------------------------------------------- rakPeer=RakNet::RakPeerInterface::GetInstance(); teamManager=TeamManager::GetInstance(); fullyConnectedMesh2=FullyConnectedMesh2::GetInstance(); networkIDManager = NetworkIDManager::GetInstance(); cloudClient = CloudClient::GetInstance(); natPunchthroughClient = NatPunchthroughClient::GetInstance(); #ifdef NAT_TYPE_DETECTION_SERVER natTypeDetectionClient = NatTypeDetectionClient::GetInstance(); #endif rpc4 = RPC4::GetInstance(); readyEvent = ReadyEvent::GetInstance(); replicaManager3=new SampleRM3; // --------------------------------------------------------------------------------------------------------------------- // Attach plugins // --------------------------------------------------------------------------------------------------------------------- rakPeer->AttachPlugin(fullyConnectedMesh2); rakPeer->AttachPlugin(teamManager); rakPeer->AttachPlugin(cloudClient); rakPeer->AttachPlugin(natPunchthroughClient); #ifdef NAT_TYPE_DETECTION_SERVER rakPeer->AttachPlugin(natTypeDetectionClient); #endif rakPeer->AttachPlugin(rpc4); rakPeer->AttachPlugin(readyEvent); rakPeer->AttachPlugin(replicaManager3); // --------------------------------------------------------------------------------------------------------------------- // Setup plugins: Disable automatically adding new connections. Allocate initial objects and register for replication // --------------------------------------------------------------------------------------------------------------------- // Allocate a world instance to be used for team operations teamManager->AddWorld(0); // Do not automatically count new connections teamManager->SetAutoManageConnections(false); // New connections do not count until after login. fullyConnectedMesh2->SetAutoparticipateConnections(false); // Tell ReplicaManager3 which networkIDManager to use for object lookup, used for automatic serialization replicaManager3->SetNetworkIDManager(networkIDManager); // Do not automatically count new connections, but do drop lost connections automatically replicaManager3->SetAutoManageConnections(false,true); // Reference static game objects that always exist game = new Game; game->SetNetworkIDManager(networkIDManager); game->SetNetworkID(0); replicaManager3->Reference(game); // Setup my own user User *user = new User; user->SetNetworkIDManager(networkIDManager); user->userName = rakPeer->GetMyGUID().ToString(); // Inform TeamManager of my user's team member info teamManager->GetWorldAtIndex(0)->ReferenceTeamMember(&user->tmTeamMember,user->GetNetworkID()); // --------------------------------------------------------------------------------------------------------------------- // Startup RakNet on first available port // --------------------------------------------------------------------------------------------------------------------- RakNet::SocketDescriptor sd; sd.socketFamily=AF_INET; // Only IPV4 supports broadcast on 255.255.255.255 sd.port=0; StartupResult sr = rakPeer->Startup(8,&sd,1); RakAssert(sr==RAKNET_STARTED); rakPeer->SetMaximumIncomingConnections(8); rakPeer->SetTimeoutTime(30000,RakNet::UNASSIGNED_SYSTEM_ADDRESS); printf("Our guid is %s\n", rakPeer->GetGuidFromSystemAddress(RakNet::UNASSIGNED_SYSTEM_ADDRESS).ToString()); printf("Started on %s\n", rakPeer->GetMyBoundAddress().ToString(true)); // Connect to master server game->EnterPhase(Game::CONNECTING_TO_SERVER); // --------------------------------------------------------------------------------------------------------------------- // Read packets loop // --------------------------------------------------------------------------------------------------------------------- char ch; Packet *packet; while (game->phase!=Game::EXIT_SAMPLE) { for (packet = rakPeer->Receive(); packet; rakPeer->DeallocatePacket(packet), packet = rakPeer->Receive()) { switch (packet->data[0]) { case ID_NEW_INCOMING_CONNECTION: { printf("ID_NEW_INCOMING_CONNECTION from %s. guid=%s.\n", packet->systemAddress.ToString(true), packet->guid.ToString()); } break; case ID_CONNECTION_REQUEST_ACCEPTED: { printf("ID_CONNECTION_REQUEST_ACCEPTED from %s,guid=%s\n", packet->systemAddress.ToString(true), packet->guid.ToString()); if (game->phase==Game::CONNECTING_TO_SERVER) { game->masterServerAddress=packet->systemAddress; game->masterServerGuid=packet->guid; // --------------------------------------------------------------------------------------------------------------------- // PC self-hosted servers only: Use master server to determine NAT type. Attempt to open router if needed. // --------------------------------------------------------------------------------------------------------------------- if (NAT_TYPE_DETECTION_SERVER) { game->EnterPhase(Game::DETERMINE_NAT_TYPE); } else { OpenUPNP(); game->EnterPhase(Game::SEARCH_FOR_GAMES); } } else if (game->phase==Game::CONNECTING_TO_GAME_HOST) { printf("Asking host to join session...\n"); // So time in single player does not count towards which system has been running multiplayer the longest fullyConnectedMesh2->ResetHostCalculation(); // Custom message to ask to join the game // We first connect to the game host, and the game host is responsible for calling StartVerifiedJoin() for us to join the session BitStream bsOut; bsOut.Write((MessageID)ID_USER_PACKET_ENUM); rakPeer->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->guid,false); } } break; case ID_CONNECTION_LOST: case ID_DISCONNECTION_NOTIFICATION: if (game->phase==Game::DETERMINE_NAT_TYPE) { printf("Lost connection during NAT type detection. Reason %s. Retrying...\n", PacketLogger::BaseIDTOString(packet->data[0])); game->EnterPhase(Game::CONNECTING_TO_SERVER); } else if (game->phase==Game::NAT_PUNCH_TO_GAME_HOST) { printf("Lost connection during NAT punch to game host. Reason %s.\n", PacketLogger::BaseIDTOString(packet->data[0])); game->EnterPhase(Game::SEARCH_FOR_GAMES); } else { if (packet->guid==game->masterServerGuid) { printf("Server connection lost. Reason %s.\nGame session is no longer searchable.\n", PacketLogger::BaseIDTOString(packet->data[0])); } else { printf("Peer connection lost. Reason %s.\n", PacketLogger::BaseIDTOString(packet->data[0])); } } break; case ID_ALREADY_CONNECTED: printf("ID_ALREADY_CONNECTED with guid %"PRINTF_64_BIT_MODIFIER"u\n", packet->guid); break; case ID_INVALID_PASSWORD: case ID_NO_FREE_INCOMING_CONNECTIONS: case ID_CONNECTION_ATTEMPT_FAILED: case ID_CONNECTION_BANNED: case ID_IP_RECENTLY_CONNECTED: case ID_INCOMPATIBLE_PROTOCOL_VERSION: // Note: Failing to connect to another system does not automatically mean we cannot join a session, since that system may be disconnecting from the host simultaneously // FullyConnectedMesh2::StartVerifiedJoin() internally handles success or failure and notifies the client through ID_FCM2_VERIFIED_JOIN_FAILED if needed. printf("Failed to connect to %s. Reason %s\n", packet->systemAddress.ToString(true), PacketLogger::BaseIDTOString(packet->data[0])); if (game->phase==Game::CONNECTING_TO_SERVER) game->EnterPhase(Game::EXIT_SAMPLE); break; case ID_FCM2_NEW_HOST: { RakNet::BitStream bs(packet->data,packet->length,false); bs.IgnoreBytes(1); RakNetGUID oldHost; bs.Read(oldHost); if (packet->guid==rakPeer->GetMyGUID()) { if (oldHost!=UNASSIGNED_RAKNET_GUID) { PostRoomToCloud(); printf("ID_FCM2_NEW_HOST: Taking over as host from the old host.\nNew options:\n"); } else { // Room not hosted if we become host the first time since this was done in CreateRoom() already printf("ID_FCM2_NEW_HOST: We have become host for the first time. New options:\n"); } printf("(L)ock and unlock game\n"); } else { if (oldHost!=UNASSIGNED_RAKNET_GUID) printf("ID_FCM2_NEW_HOST: A new system %s has become host, GUID=%s\n", packet->systemAddress.ToString(true), packet->guid.ToString()); else printf("ID_FCM2_NEW_HOST: System %s is host, GUID=%s\n", packet->systemAddress.ToString(true), packet->guid.ToString()); } if (oldHost==UNASSIGNED_RAKNET_GUID) { // First time calculated host. Add existing connections to ReplicaManager3 DataStructures::List<RakNetGUID> participantList; fullyConnectedMesh2->GetParticipantList(participantList); for (unsigned int i=0; i < participantList.Size(); i++) RegisterGameParticipant(participantList[i]); // Reference previously created replicated objects, which cannot be serialized until host is known the first time if (packet->guid==rakPeer->GetMyGUID()) { // As host, reference the teams we created for (unsigned int i=0; i < game->teams.Size(); i++) replicaManager3->Reference(game->teams[i]); } // Reference the user we created (host or not) for (unsigned int i=0; i < game->users.Size(); i++) replicaManager3->Reference(game->users[i]); } } break; case ID_TEAM_BALANCER_TEAM_ASSIGNED: { printf("ID_TEAM_BALANCER_TEAM_ASSIGNED for "); TM_World *world; TM_TeamMember *teamMember; teamManager->DecodeTeamAssigned(packet, &world, &teamMember); printf("worldId=%i teamMember=%s", world->GetWorldId(), ((User*)teamMember->GetOwner())->userName.C_String()); if (teamMember->GetCurrentTeam()==0) printf(" not on team\n"); else printf(" on team %s\n", ((Team*)(teamMember->GetCurrentTeam()->GetOwner()))->teamName.C_String()); } break; case ID_TEAM_BALANCER_REQUESTED_TEAM_FULL: { printf("ID_TEAM_BALANCER_REQUESTED_TEAM_FULL\n"); } break; case ID_TEAM_BALANCER_REQUESTED_TEAM_LOCKED: { printf("ID_TEAM_BALANCER_REQUESTED_TEAM_LOCKED\n"); } break; case ID_TEAM_BALANCER_TEAM_REQUESTED_CANCELLED: { printf("ID_TEAM_BALANCER_TEAM_REQUESTED_CANCELLED\n"); } break; case ID_NAT_TARGET_NOT_CONNECTED: case ID_NAT_TARGET_UNRESPONSIVE: case ID_NAT_CONNECTION_TO_TARGET_LOST: case ID_NAT_PUNCHTHROUGH_FAILED: { // As with connection failed, this does not automatically mean we cannot join the session // We only fail on ID_FCM2_VERIFIED_JOIN_FAILED printf("NAT punch to %s failed. Reason %s\n", packet->guid.ToString(), PacketLogger::BaseIDTOString(packet->data[0])); if (game->phase==Game::NAT_PUNCH_TO_GAME_HOST) game->EnterPhase(Game::SEARCH_FOR_GAMES); } case ID_NAT_ALREADY_IN_PROGRESS: // Can ignore this break; case ID_NAT_PUNCHTHROUGH_SUCCEEDED: { if (game->phase==Game::NAT_PUNCH_TO_GAME_HOST || game->phase==Game::VERIFIED_JOIN) { // Connect to the session host ConnectionAttemptResult car = rakPeer->Connect(packet->systemAddress.ToString(false), packet->systemAddress.GetPort(), 0, 0); if (car!=RakNet::CONNECTION_ATTEMPT_STARTED) { printf("Failed connect call to %s. Code=%i\n", packet->systemAddress.ToString(false), car); game->EnterPhase(Game::SEARCH_FOR_GAMES); } else { if (game->phase==Game::NAT_PUNCH_TO_GAME_HOST) { printf("NAT punch completed. Connecting to %s (game host)...\n", packet->systemAddress.ToString(true)); game->EnterPhase(Game::CONNECTING_TO_GAME_HOST); } else { printf("NAT punch completed. Connecting to %s (game client)...\n", packet->systemAddress.ToString(true)); } } } } break; case ID_CLOUD_GET_RESPONSE: { cloudClient->DeallocateWithDefaultAllocator(&cloudQueryResult); cloudClient->OnGetReponse(&cloudQueryResult, packet); unsigned int rowIndex; for (rowIndex=0; rowIndex < cloudQueryResult.rowsReturned.Size(); rowIndex++) { RakNet::CloudQueryRow *row = cloudQueryResult.rowsReturned[rowIndex]; printf("%i. ", rowIndex); PrintRow(row); } printf("(J)oin room\n"); printf("(C)reate room\n"); printf("(S)earch rooms\n"); } break; case ID_NAT_TYPE_DETECTION_RESULT: { game->myNatType = (RakNet::NATTypeDetectionResult) packet->data[1]; printf("NAT Type is %s (%s)\n", NATTypeDetectionResultToString(game->myNatType), NATTypeDetectionResultToStringFriendly(game->myNatType)); if (game->myNatType!=RakNet::NAT_TYPE_NONE) { OpenUPNP(); } if (game->myNatType==RakNet::NAT_TYPE_PORT_RESTRICTED || game->myNatType==RakNet::NAT_TYPE_SYMMETRIC) { printf("Note: Your router must support UPNP or have the user manually forward ports.\n"); printf("Otherwise NATPunchthrough may not always succeed.\n"); } game->EnterPhase(Game::SEARCH_FOR_GAMES); } break; case ID_READY_EVENT_ALL_SET: printf("Got ID_READY_EVENT_ALL_SET from %s\n", packet->systemAddress.ToString(true)); printf("All users ready.\n"); if (fullyConnectedMesh2->IsConnectedHost()) printf("New options:\n(B)egin gameplay\n"); break; case ID_READY_EVENT_SET: printf("Got ID_READY_EVENT_SET from %s\n", packet->systemAddress.ToString(true)); break; case ID_READY_EVENT_UNSET: printf("Got ID_READY_EVENT_UNSET from %s\n", packet->systemAddress.ToString(true)); break; // ID_USER_PACKET_ENUM is used by this sample as a custom message to ask to join a game case ID_USER_PACKET_ENUM: if (game->phase > Game::SEARCH_FOR_GAMES) { printf("Got request from client to join session.\nExecuting StartVerifiedJoin()\n"); fullyConnectedMesh2->StartVerifiedJoin(packet->guid); } else { BitStream bsOut; bsOut.Write((MessageID)(ID_USER_PACKET_ENUM+1)); rakPeer->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->guid,false); } break; // ID_USER_PACKET_ENUM+1 is used by this sample as a custom message to reject a join game request // Requests may also be later rejected through FullyConnectedMesh2::RespondOnVerifiedJoinCapable() to send ID_FCM2_VERIFIED_JOIN_REJECTED case (ID_USER_PACKET_ENUM+1): printf("Join request denied\n"); game->EnterPhase(Game::SEARCH_FOR_GAMES); break; case ID_FCM2_VERIFIED_JOIN_START: { game->EnterPhase(Game::VERIFIED_JOIN); // This message means the session host sent us a list of systems in the session // Once we connect to, or fail to connect to, each of these systems we will get ID_FCM2_VERIFIED_JOIN_FAILED, ID_FCM2_VERIFIED_JOIN_ACCEPTED, or ID_FCM2_VERIFIED_JOIN_REJECTED printf("Host sent us system list. Doing NAT punch to each system...\n"); DataStructures::List<SystemAddress> addresses; DataStructures::List<RakNetGUID> guids; fullyConnectedMesh2->GetVerifiedJoinRequiredProcessingList(packet->guid, addresses, guids); for (unsigned int i=0; i < guids.Size(); i++) natPunchthroughClient->OpenNAT(guids[i], game->masterServerAddress); } break; case ID_FCM2_VERIFIED_JOIN_CAPABLE: printf("Client is capable of joining FullyConnectedMesh2.\n"); if (game->lockGame) { RakNet::BitStream bsOut; bsOut.Write("Game is locked"); fullyConnectedMesh2->RespondOnVerifiedJoinCapable(packet, false, &bsOut); } else fullyConnectedMesh2->RespondOnVerifiedJoinCapable(packet, true, 0); break; case ID_FCM2_VERIFIED_JOIN_ACCEPTED: { DataStructures::List<RakNetGUID> systemsAccepted; bool thisSystemAccepted; fullyConnectedMesh2->GetVerifiedJoinAcceptedAdditionalData(packet, &thisSystemAccepted, systemsAccepted, 0); if (thisSystemAccepted) printf("Game join request accepted\n"); else printf("System %s joined the mesh\n", systemsAccepted[0].ToString()); // Add the new participant to the game if we already know who the host is. Otherwise do this // once ID_FCM2_NEW_HOST arrives if (fullyConnectedMesh2->GetConnectedHost()!=UNASSIGNED_RAKNET_GUID) { // FullyConnectedMesh2 already called AddParticipant() for each accepted system // Still need to add those systems to the other plugins though for (unsigned int i=0; i < systemsAccepted.Size(); i++) RegisterGameParticipant(systemsAccepted[i]); if (thisSystemAccepted) game->EnterPhase(Game::IN_LOBBY_WITH_HOST); } else { if (thisSystemAccepted) game->EnterPhase(Game::IN_LOBBY_WAITING_FOR_HOST); } printf("(E)xit room\n"); } break; case ID_FCM2_VERIFIED_JOIN_REJECTED: { BitStream additionalData; fullyConnectedMesh2->GetVerifiedJoinRejectedAdditionalData(packet, &additionalData); RakString reason; additionalData.Read(reason); printf("Join rejected. Reason=%s\n", reason.C_String()); rakPeer->CloseConnection(packet->guid, true); game->EnterPhase(Game::SEARCH_FOR_GAMES); break; } case ID_REPLICA_MANAGER_DOWNLOAD_COMPLETE: { if (replicaManager3->GetAllConnectionDownloadsCompleted()==true) { printf("Completed all remote downloads\n"); if (game->gameInLobby) game->EnterPhase(Game::IN_LOBBY_WITH_HOST); else game->EnterPhase(Game::IN_GAME); } break; } } } if (kbhit()) { ch=getch(); if (game->phase==Game::SEARCH_FOR_GAMES) { if (ch=='c' || ch=='C') { CreateRoom(); } if (ch=='s' || ch=='S') { game->SearchForGames(); } else if (ch=='j' || ch=='J') { // Join room if (cloudQueryResult.rowsReturned.Size()==0) { printf("No rooms to join.\n"); } else { int index; if (cloudQueryResult.rowsReturned.Size()>1) { printf("Enter index of room to join.\n"); char indexstr[64]; Gets(indexstr,64); index = atoi(indexstr); } else { index = 0; } if (index < 0 || (unsigned int) index >= cloudQueryResult.rowsReturned.Size()) { printf("Index out of range.\n"); } else { CloudQueryRow *row = cloudQueryResult.rowsReturned[index]; // Connect to the session host using NATPunchthrough natPunchthroughClient->OpenNAT(row->clientGUID, game->masterServerAddress); game->EnterPhase(Game::NAT_PUNCH_TO_GAME_HOST); } } } } else { if (game->phase==Game::IN_GAME) { if (ch=='c' || ch=='C') { DataStructures::List<RakNetGUID> participantList; fullyConnectedMesh2->GetParticipantList(participantList); if (participantList.Size()>0) { printf("Enter in-game chat message: "); char str[256]; Gets(str, 256); RakString rs; // Don't use RakString constructor to assign str, or will process % escape characters rs=str; BitStream bsOut; bsOut.Write(rs); for (unsigned int i=0; i < participantList.Size(); i++) rpc4->Signal("InGameChat", &bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, participantList[i], false, false); } } } if (ch=='1') { user->tmTeamMember.RequestTeamSwitch(&game->teams[0]->tmTeam, 0); } else if (ch=='2') { user->tmTeamMember.RequestTeamSwitch(&game->teams[1]->tmTeam, 0); } else if (ch=='r' || ch=='R') { if (readyEvent->SetEvent(0, true)) printf("We are ready to start.\n"); } else if (ch=='u' || ch=='U') { if (readyEvent->SetEvent(0, false)) printf("We are no longer ready to start.\n"); } else if (ch=='l' || ch=='L') { if (fullyConnectedMesh2->IsConnectedHost()) { if (game->lockGame) { printf("Game is no longer locked\n"); game->lockGame=false; } else { printf("Game is now locked\n"); game->lockGame=true; } } } else if (ch=='b' || ch=='B') { if (fullyConnectedMesh2->IsConnectedHost()) { if (game->gameInLobby) { readyEvent->ForceCompletion(0); game->gameInLobby=false; game->EnterPhase(Game::IN_GAME); } else { readyEvent->DeleteEvent(0); printf("Game ended, and now in lobby\n"); game->gameInLobby=true; game->EnterPhase(Game::IN_LOBBY_WITH_HOST); } } } else if (ch=='e' || ch=='E') { // Disconnect from FullyConnectedMesh2 participants DataStructures::List<RakNetGUID> participantList; fullyConnectedMesh2->GetParticipantList(participantList); for (unsigned int i=0; i < participantList.Size(); i++) rakPeer->CloseConnection(participantList[i], true); // User instances are deleted automatically from ReplicaManager3. // However, teams are not deleted since the Team class can migrate between systems. So delete Team instances manually while (game->teams.Size()) delete game->teams[game->teams.Size()-1]; // If we were the host, no longer list this session // The new host will call PostRoomToCloud to reupload under a new IP address on ID_FCM2_NEW_HOST ReleaseRoomFromCloud(); // Clear out state data from plugins fullyConnectedMesh2->Clear(); readyEvent->DeleteEvent(0); replicaManager3->Clear(false); replicaManager3->Reference(game); game->Reset(); game->EnterPhase(Game::SEARCH_FOR_GAMES); } else if (ch=='q' || ch=='Q') { printf("Quitting.\n"); // Disconnecting from the master server automatically releases from cloud game->EnterPhase(Game::EXIT_SAMPLE); } } } RakSleep(30); } rakPeer->Shutdown(100); while (game->teams.Size()) delete game->teams[game->teams.Size()-1]; while (game->users.Size()) delete game->users[game->users.Size()-1]; delete game; cloudClient->DeallocateWithDefaultAllocator(&cloudQueryResult); RakPeerInterface::DestroyInstance(rakPeer); TeamManager::DestroyInstance(teamManager); FullyConnectedMesh2::DestroyInstance(fullyConnectedMesh2); cloudClient->DeallocateWithDefaultAllocator(&cloudQueryResult); CloudClient::DestroyInstance(cloudClient); NatPunchthroughClient::DestroyInstance(natPunchthroughClient); NatTypeDetectionClient::DestroyInstance(natTypeDetectionClient); RPC4::DestroyInstance(rpc4); ReadyEvent::DestroyInstance(readyEvent); delete replicaManager3; NetworkIDManager::DestroyInstance(networkIDManager); return 1; }
bool AutopatcherMySQLRepository::UpdateApplicationFiles(const char *applicationName, const char *applicationDirectory, const char *userName, FileListProgress *cb) { MYSQL_STMT *stmt; MYSQL_BIND bind[3]; char query[512]; FileList filesOnHarddrive; filesOnHarddrive.SetCallback(cb); int prepareResult; my_bool falseVar=false; RakNet::RakString escapedApplicationName = GetEscapedString(applicationName); filesOnHarddrive.AddFilesFromDirectory(applicationDirectory,"", true, true, true, FileListNodeContext(0,0)); if (filesOnHarddrive.fileList.Size()==0) { sprintf(lastError,"ERROR: Can't find files at %s in UpdateApplicationFiles\n",applicationDirectory); return false; } sprintf(query, "SELECT applicationID FROM Applications WHERE applicationName='%s';", escapedApplicationName.C_String()); int applicationID; if (!ExecuteQueryReadInt(query, &applicationID)) { sprintf(lastError,"ERROR: %s not found in UpdateApplicationFiles\n",escapedApplicationName.C_String()); return false; } if (!ExecuteBlockingCommand("BEGIN;")) { return false; } sprintf(query, "UPDATE Applications SET changeSetId = changeSetId + 1 where applicationID=%i;", applicationID); if (!ExecuteBlockingCommand(query)) { Rollback (); return false; } int changeSetId = 0; sprintf(query, "SELECT changeSetId FROM Applications WHERE applicationID=%i;", applicationID); if (!ExecuteQueryReadInt(query, &changeSetId)) { Rollback (); return false; } // +1 was added in the update changeSetId--; // Gets all newest files sprintf(query, "SELECT filename, contentHash, createFile FROM FileVersionHistory " "JOIN (SELECT max(fileId) maxId FROM FileVersionHistory WHERE applicationId=%i GROUP BY fileName) MaxId " "ON FileVersionHistory.fileId = MaxId.maxId " "ORDER BY filename DESC;", applicationID); MYSQL_RES *result = 0; if (!ExecuteBlockingCommand(query, &result)) { Rollback(); return false; } DataStructures::List <FileInfo> newestFiles; MYSQL_ROW row; while ((row = mysql_fetch_row (result)) != 0) { FileInfo fi; fi.filename = row [0]; fi.createFile = (atoi (row [2]) != 0); if (fi.createFile) { RakAssert(mysql_fetch_lengths (result) [1] == HASH_LENGTH); // check the data is sensible memcpy (fi.contentHash, row [1], HASH_LENGTH); } newestFiles.Insert (fi); } mysql_free_result(result); FileList newFiles; // Loop through files on filesOnHarddrive // If the file in filesOnHarddrive does not exist in the query result, or if it does but the hash is different or non-existent, add this file to the create list for (unsigned fileListIndex=0; fileListIndex < filesOnHarddrive.fileList.Size(); fileListIndex++) { bool addFile=true; if (fileListIndex%10==0) printf("Hashing files %i/%i\n", fileListIndex+1, filesOnHarddrive.fileList.Size()); const char * hardDriveFilename=filesOnHarddrive.fileList[fileListIndex].filename; const char * hardDriveHash=filesOnHarddrive.fileList[fileListIndex].data; for (unsigned i = 0; i != newestFiles.Size (); ++i) { const FileInfo & fi = newestFiles [i]; if (_stricmp(hardDriveFilename, fi.filename)==0) { if (fi.createFile && memcmp(fi.contentHash, hardDriveHash, HASH_LENGTH)==0) { // File exists in database and is the same addFile=false; } break; } } // Unless set to false, file does not exist in query result or is different. if (addFile) { newFiles.AddFile(hardDriveFilename,hardDriveFilename, filesOnHarddrive.fileList[fileListIndex].data, filesOnHarddrive.fileList[fileListIndex].dataLengthBytes, filesOnHarddrive.fileList[fileListIndex].fileLengthBytes, FileListNodeContext(0,0), false); } } // Go through query results that are marked as create // If a file that is currently in the database is not on the harddrive, add it to the delete list FileList deletedFiles; for (unsigned i = 0; i != newestFiles.Size (); ++i) { const FileInfo & fi = newestFiles [i]; if (!fi.createFile) continue; // If already false don't mark false again. bool fileOnHarddrive=false; for (unsigned fileListIndex=0; fileListIndex < filesOnHarddrive.fileList.Size(); fileListIndex++) { const char * hardDriveFilename=filesOnHarddrive.fileList[fileListIndex].filename; //hardDriveHash=filesOnHarddrive.fileList[fileListIndex].data; if (_stricmp(hardDriveFilename, fi.filename)==0) { fileOnHarddrive=true; break; } } if (!fileOnHarddrive) deletedFiles.AddFile(fi.filename,fi.filename,0,0,0,FileListNodeContext(0,0), false); } // files on harddrive no longer needed. Free this memory since generating all the patches is memory intensive. filesOnHarddrive.Clear(); // For each file in the delete list add a row indicating file deletion for (unsigned fileListIndex=0; fileListIndex < deletedFiles.fileList.Size(); fileListIndex++) { if (fileListIndex%10==0) printf("Tagging deleted files %i/%i\n", fileListIndex+1, deletedFiles.fileList.Size()); sprintf(query, "INSERT INTO FileVersionHistory(applicationID, filename, createFile, changeSetID, userName) VALUES (%i, '%s', FALSE,%i,'%s');", applicationID, GetEscapedString(deletedFiles.fileList[fileListIndex].filename).C_String(), changeSetId, GetEscapedString(userName).C_String()); if (!ExecuteBlockingCommand (query)) { Rollback(); deletedFiles.Clear(); newFiles.Clear(); return false; } } // Clear the delete list as it is no longer needed. deletedFiles.Clear(); // For each file in the create list for (unsigned fileListIndex=0; fileListIndex < newFiles.fileList.Size(); fileListIndex++) { if (fileListIndex%10==0) printf("Adding file %i/%i\n", fileListIndex+1, newFiles.fileList.Size()); const char * hardDriveFilename=newFiles.fileList[fileListIndex].filename; const char * hardDriveData=newFiles.fileList[fileListIndex].data+HASH_LENGTH; const char * hardDriveHash=newFiles.fileList[fileListIndex].data; unsigned hardDriveDataLength=newFiles.fileList[fileListIndex].fileLengthBytes; sprintf( query, "SELECT fileID from FileVersionHistory WHERE applicationID=%i AND filename='%s' AND createFile=TRUE;", applicationID, GetEscapedString(hardDriveFilename).C_String() ); MYSQL_RES * res = 0; if (!ExecuteBlockingCommand (query, &res)) { Rollback(); newFiles.Clear(); return false; } // Create new patches for every create version MYSQL_ROW row; while ((row = mysql_fetch_row (res)) != 0) { const char * fileID = row [0]; // The last query handled all the relevant comparisons sprintf(query, "SELECT content from FileVersionHistory WHERE fileID=%s", fileID ); MYSQL_RES * queryResult = 0; if (!ExecuteBlockingCommand (query, &queryResult)) { Rollback(); newFiles.Clear(); mysql_free_result(res); return false; } MYSQL_ROW queryRow = mysql_fetch_row (queryResult); const unsigned contentLength=mysql_fetch_lengths (queryResult) [0]; const char * content=queryRow [0]; char *patch; unsigned patchLength; if (!CreatePatch(content, contentLength, (char *) hardDriveData, hardDriveDataLength, &patch, &patchLength)) { strcpy(lastError,"CreatePatch failed."); Rollback(); newFiles.Clear(); mysql_free_result(res); mysql_free_result(queryResult); return false; } char buf[512]; stmt = mysql_stmt_init(mySqlConnection); sprintf (buf, "UPDATE FileVersionHistory SET patch=? where fileID=%s;", fileID); if ((prepareResult=mysql_stmt_prepare(stmt, buf, (unsigned long) strlen(buf)))!=0) { strcpy (lastError, mysql_stmt_error (stmt)); mysql_stmt_close(stmt); Rollback(); return false; } memset(bind, 0, sizeof(bind)); unsigned long l1; l1=patchLength; bind[0].buffer_type= MYSQL_TYPE_LONG_BLOB; bind[0].buffer= patch; bind[0].buffer_length= patchLength; bind[0].is_null= &falseVar; bind[0].length=&l1; if (mysql_stmt_bind_param(stmt, bind)) { strcpy (lastError, mysql_stmt_error (stmt)); mysql_stmt_close(stmt); Rollback(); return false; } if (mysql_stmt_execute(stmt)) { strcpy (lastError, mysql_stmt_error (stmt)); mysql_stmt_close(stmt); Rollback(); newFiles.Clear(); mysql_free_result(res); mysql_free_result(queryResult); delete [] patch; return false; } mysql_stmt_close(stmt); delete [] patch; mysql_free_result(queryResult); } mysql_free_result(res); stmt = mysql_stmt_init(mySqlConnection); sprintf(query, "INSERT INTO FileVersionHistory (applicationID, filename, fileLength, content, contentHash, createFile, changeSetID, userName) " "VALUES (%i, ?, %i,?,?, TRUE, %i, '%s' );", applicationID, hardDriveDataLength, changeSetId, GetEscapedString(userName).C_String()); if ((prepareResult=mysql_stmt_prepare(stmt, query, (unsigned long) strlen(query)))!=0) { strcpy (lastError, mysql_stmt_error (stmt)); mysql_stmt_close(stmt); Rollback(); return false; } memset(bind, 0, sizeof(bind)); unsigned long l2,l3,l4; l2=(unsigned long) strlen(hardDriveFilename); l3=hardDriveDataLength; l4=HASH_LENGTH; bind[0].buffer_type= MYSQL_TYPE_STRING; bind[0].buffer= (void*) hardDriveFilename; bind[0].buffer_length= (unsigned long) strlen(hardDriveFilename); bind[0].is_null= &falseVar; bind[0].length=&l2; bind[1].buffer_type= MYSQL_TYPE_LONG_BLOB; bind[1].buffer= (void*) hardDriveData; bind[1].buffer_length= hardDriveDataLength; bind[1].is_null= &falseVar; bind[1].length=&l3; bind[2].buffer_type= MYSQL_TYPE_TINY_BLOB; bind[2].buffer= (void*) hardDriveHash; bind[2].buffer_length= HASH_LENGTH; bind[2].is_null= &falseVar; bind[2].length=&l4; if (mysql_stmt_bind_param(stmt, bind)) { strcpy (lastError, mysql_stmt_error (stmt)); mysql_stmt_close(stmt); Rollback(); return false; } if (mysql_stmt_execute(stmt)) { strcpy (lastError, mysql_stmt_error (stmt)); mysql_stmt_close(stmt); Rollback(); return false; } mysql_stmt_close(stmt); } if (!ExecuteBlockingCommand("COMMIT;")) { Rollback (); return false; } return true; }
void NatPunchthrough::ConnectionRequest::GetAddressList(RakPeerInterface *rakPeer, DataStructures::List<SystemAddress> &fallbackAddresses, SystemAddress publicAddress, SystemAddress privateAddress, bool excludeConnected) { SystemAddress fallback; fallbackAddresses.Clear(true); fallback.binaryAddress=publicAddress.binaryAddress; fallback.port=publicAddress.port; if (excludeConnected==false || rakPeer->IsConnected(fallback,true)==false) fallbackAddresses.Insert(fallback); if (privateAddress!=publicAddress && privateAddress!=UNASSIGNED_SYSTEM_ADDRESS && (excludeConnected==false ||rakPeer->IsConnected(privateAddress,true)==false)) fallbackAddresses.Insert(privateAddress); fallback.port=publicAddress.port+1; if (excludeConnected==false || rakPeer->IsConnected(fallback,true)==false) fallbackAddresses.Insert(fallback); fallback.port=publicAddress.port+2; if (excludeConnected==false || rakPeer->IsConnected(fallback,true)==false) fallbackAddresses.Insert(fallback); fallback.port=rakPeer->GetInternalID().port; if (fallbackAddresses.GetIndexOf(fallback)==(unsigned) -1 && (excludeConnected==false || rakPeer->IsConnected(fallback,true)==false)) fallbackAddresses.Insert(fallback); fallback.port=rakPeer->GetInternalID().port+1; if (fallbackAddresses.GetIndexOf(fallback)==(unsigned) -1 && (excludeConnected==false || rakPeer->IsConnected(fallback,true)==false)) fallbackAddresses.Insert(fallback); fallback.port=rakPeer->GetInternalID().port+2; if (fallbackAddresses.GetIndexOf(fallback)==(unsigned) -1 && (excludeConnected==false || rakPeer->IsConnected(fallback,true)==false)) fallbackAddresses.Insert(fallback); // Try to keep down the number of fallbacks or the router may run out of mappings /* fallback.port=publicAddress.port+3; if (excludeConnected==false || rakPeer->IsConnected(fallback,true)==false) fallbackAddresses.Insert(fallback); fallback.port=publicAddress.port+4; if (excludeConnected==false || rakPeer->IsConnected(fallback,true)==false) fallbackAddresses.Insert(fallback); fallback.port=rakPeer->GetInternalID().port+3; if (fallbackAddresses.GetIndexOf(fallback)==(unsigned) -1 && (excludeConnected==false || rakPeer->IsConnected(fallback,true)==false)) fallbackAddresses.Insert(fallback); fallback.port=rakPeer->GetInternalID().port+4; if (fallbackAddresses.GetIndexOf(fallback)==(unsigned) -1 && (excludeConnected==false || rakPeer->IsConnected(fallback,true)==false)) fallbackAddresses.Insert(fallback); */ }
/* What is being done here is having 8 peers all connect to eachother, disconnect, connect again. Do this for about 10 seconds. Then allow them all to connect for one last time. This test also tests the cancelpendingconnections. Also tests nonblocking connects, the simpler one PeerConnectDisconnect tests without it Good ideas for changes: After the last check run a eightpeers like test an add the conditions of that test as well. Make sure that if we initiate the connection we get a proper message and if not we get a proper message. Add proper conditions. Randomize sending the disconnect notes Success conditions: All connected normally and pending requests get canceled normally. Failure conditions: Doesn't reconnect normally. During the very first connect loop any connect returns false. Connect function returns false and peer is not connected to anything. Pending request is not canceled. */ int PeerConnectDisconnectWithCancelPendingTest::RunTest(DataStructures::List<RakString> params,bool isVerbose,bool noPauses) { const int peerNum= 8; const int maxConnections=peerNum*3;//Max allowed connections for test set to times 3 to eliminate problem variables RakPeerInterface *peerList[peerNum];//A list of 8 peers SystemAddress currentSystem; Packet *packet; destroyList.Clear(false,_FILE_AND_LINE_); //Initializations of the arrays for (int i=0;i<peerNum;i++) { peerList[i]=RakPeerInterface::GetInstance(); destroyList.Push(peerList[i],_FILE_AND_LINE_); peerList[i]->Startup(maxConnections, &SocketDescriptor(60000+i,0), 1); peerList[i]->SetMaximumIncomingConnections(maxConnections); } //Connect all the peers together for (int i=0;i<peerNum;i++) { for (int j=i+1;j<peerNum;j++)//Start at i+1 so don't connect two of the same together. { if (peerList[i]->Connect("127.0.0.1", 60000+j, 0,0)!=CONNECTION_ATTEMPT_STARTED) { if (isVerbose) DebugTools::ShowError("Problem while calling connect.",!noPauses && isVerbose,__LINE__,__FILE__); return 1;//This fails the test, don't bother going on. } } } TimeMS entryTime=GetTimeMS();//Loop entry time DataStructures::List< SystemAddress > systemList; DataStructures::List< RakNetGUID > guidList; printf("Entering disconnect loop \n"); bool printedYet; while(GetTimeMS()-entryTime<10000)//Run for 10 Secoonds { //Disconnect all peers IF connected to any for (int i=0;i<peerNum;i++) { peerList[i]->GetSystemList(systemList,guidList);//Get connectionlist int len=systemList.Size(); for (int j=0;j<len;j++)//Disconnect them all { peerList[i]->CloseConnection (systemList[j],true,0,LOW_PRIORITY); } } RakSleep(100); //Clear pending if not finished for (int i=0;i<peerNum;i++) { for (int j=i+1;j<peerNum;j++)//Start at i+1 so don't connect two of the same together. { currentSystem.SetBinaryAddress("127.0.0.1"); currentSystem.port=60000+j; peerList[i]->CancelConnectionAttempt(currentSystem); //Make sure a connection is not pending before trying to connect. } } RakSleep(100); //Connect for (int i=0;i<peerNum;i++) { for (int j=i+1;j<peerNum;j++)//Start at i+1 so don't connect two of the same together. { if (peerList[i]->Connect("127.0.0.1", 60000+j, 0,0)!=CONNECTION_ATTEMPT_STARTED) { currentSystem.SetBinaryAddress("127.0.0.1"); currentSystem.port=60000+j; peerList[i]->GetSystemList(systemList,guidList);//Get connectionlist int len=systemList.Size(); if(CommonFunctions::ConnectionStateMatchesOptions (peerList[i],currentSystem,false,true,true))//Did we drop the pending connection? { if (isVerbose) DebugTools::ShowError("Did not cancel the pending request \n",!noPauses && isVerbose,__LINE__,__FILE__); return 3; } if (!CommonFunctions::ConnectionStateMatchesOptions (peerList[i],currentSystem,true,true,true,true)) { if (isVerbose) DebugTools::ShowError("Problem while calling connect. \n",!noPauses && isVerbose,__LINE__,__FILE__); return 1;//This fails the test, don't bother going on. } } } } for (int i=0;i<peerNum;i++)//Receive for all peers { printedYet=false; packet=peerList[i]->Receive(); while(packet) { if (isVerbose&&!printedYet) { printf("For peer %i\n",i); printedYet=true; } switch (packet->data[0]) { case ID_REMOTE_DISCONNECTION_NOTIFICATION: if (isVerbose) printf("Another client has disconnected.\n"); break; case ID_REMOTE_CONNECTION_LOST: if (isVerbose) printf("Another client has lost the connection.\n"); break; case ID_REMOTE_NEW_INCOMING_CONNECTION: if (isVerbose) printf("Another client has connected.\n"); break; case ID_CONNECTION_REQUEST_ACCEPTED: if (isVerbose) printf("Our connection request has been accepted.\n"); break; case ID_CONNECTION_ATTEMPT_FAILED: if (isVerbose) printf("A connection has failed.\n"); break; case ID_NEW_INCOMING_CONNECTION: if (isVerbose) printf("A connection is incoming.\n"); break; case ID_NO_FREE_INCOMING_CONNECTIONS: if (isVerbose) printf("The server is full.\n"); break; case ID_ALREADY_CONNECTED: if (isVerbose) printf("Already connected\n"); break; case ID_DISCONNECTION_NOTIFICATION: if (isVerbose) printf("We have been disconnected.\n"); break; case ID_CONNECTION_LOST: if (isVerbose) printf("Connection lost.\n"); break; default: break; } peerList[i]->DeallocatePacket(packet); // Stay in the loop as long as there are more packets. packet = peerList[i]->Receive(); } } RakSleep(0);//If needed for testing } while(GetTimeMS()-entryTime<2000)//Run for 2 Secoonds to process incoming disconnects { for (int i=0;i<peerNum;i++)//Receive for all peers { printedYet=false; packet=peerList[i]->Receive(); while(packet) { if (isVerbose&&!printedYet) { printf("For peer %i\n",i); printedYet=true; } switch (packet->data[0]) { case ID_REMOTE_DISCONNECTION_NOTIFICATION: if (isVerbose) printf("Another client has disconnected.\n"); break; case ID_REMOTE_CONNECTION_LOST: if (isVerbose) printf("Another client has lost the connection.\n"); break; case ID_REMOTE_NEW_INCOMING_CONNECTION: if (isVerbose) printf("Another client has connected.\n"); break; case ID_CONNECTION_REQUEST_ACCEPTED: if (isVerbose) printf("Our connection request has been accepted.\n"); break; case ID_CONNECTION_ATTEMPT_FAILED: if (isVerbose) printf("A connection has failed.\n"); break; case ID_NEW_INCOMING_CONNECTION: if (isVerbose) printf("A connection is incoming.\n"); break; case ID_NO_FREE_INCOMING_CONNECTIONS: if (isVerbose) printf("The server is full.\n"); break; case ID_ALREADY_CONNECTED: if (isVerbose) printf("Already connected\n"); break; case ID_DISCONNECTION_NOTIFICATION: if (isVerbose) printf("We have been disconnected.\n"); break; case ID_CONNECTION_LOST: if (isVerbose) printf("Connection lost.\n"); break; default: break; } peerList[i]->DeallocatePacket(packet); // Stay in the loop as long as there are more packets. packet = peerList[i]->Receive(); } } RakSleep(0);//If needed for testing } //Connect for (int i=0;i<peerNum;i++) { for (int j=i+1;j<peerNum;j++)//Start at i+1 so don't connect two of the same together. { currentSystem.SetBinaryAddress("127.0.0.1"); currentSystem.port=60000+j; peerList[i]->CancelConnectionAttempt(currentSystem); //Make sure a connection is not pending before trying to connect. if (peerList[i]->Connect("127.0.0.1", 60000+j, 0,0)!=CONNECTION_ATTEMPT_STARTED) { peerList[i]->GetSystemList(systemList,guidList);//Get connectionlist int len=systemList.Size(); if (len==0)//No connections, should not fail. { if (isVerbose) DebugTools::ShowError("Problem while calling connect \n",!noPauses && isVerbose,__LINE__,__FILE__); return 1;//This fails the test, don't bother going on. } } } } entryTime=GetTimeMS(); while(GetTimeMS()-entryTime<5000)//Run for 5 Secoonds { for (int i=0;i<peerNum;i++)//Receive for all peers { printedYet=false; packet=peerList[i]->Receive(); while(packet) { if (isVerbose&&!printedYet) { printf("For peer %i\n",i); printedYet=true; } switch (packet->data[0]) { case ID_REMOTE_DISCONNECTION_NOTIFICATION: if (isVerbose) printf("Another client has disconnected.\n"); break; case ID_REMOTE_CONNECTION_LOST: if (isVerbose) printf("Another client has lost the connection.\n"); break; case ID_REMOTE_NEW_INCOMING_CONNECTION: if (isVerbose) printf("Another client has connected.\n"); break; case ID_CONNECTION_REQUEST_ACCEPTED: if (isVerbose) printf("Our connection request has been accepted.\n"); break; case ID_CONNECTION_ATTEMPT_FAILED: if (isVerbose) printf("A connection has failed.\n"); break; case ID_NEW_INCOMING_CONNECTION: if (isVerbose) printf("A connection is incoming.\n"); break; case ID_NO_FREE_INCOMING_CONNECTIONS: if (isVerbose) printf("The server is full.\n"); break; case ID_ALREADY_CONNECTED: if (isVerbose) printf("Already connected\n"); break; case ID_DISCONNECTION_NOTIFICATION: if (isVerbose) printf("We have been disconnected.\n"); break; case ID_CONNECTION_LOST: if (isVerbose) printf("Connection lost.\n"); break; default: break; } peerList[i]->DeallocatePacket(packet); // Stay in the loop as long as there are more packets. packet = peerList[i]->Receive(); } } RakSleep(0);//If needed for testing } for (int i=0;i<peerNum;i++) { peerList[i]->GetSystemList(systemList,guidList); int connNum=guidList.Size();//Get the number of connections for the current peer if (connNum!=peerNum-1)//Did we connect to all? { if (isVerbose) DebugTools::ShowError("Not all peers reconnected normally.\n ",!noPauses && isVerbose,__LINE__,__FILE__); return 2; } } if (isVerbose) printf("Pass\n"); return 0; }
void LightweightDatabaseServer::Update(RakPeerInterface *peer) { RakNetTime time=0; DatabaseTable *databaseTable; DataStructures::Page<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> *cur; unsigned i,j; DataStructures::Table::Row* row; DataStructures::List<unsigned> removeList; PlayerID playerId; // periodic ping if removing system that do not respond to pings. for (i=0; i < database.Size(); i++) { databaseTable=database[i]; if (databaseTable->removeRowOnPingFailure) { // Reading the time is slow - only do it once if necessary. if (time==0) time = RakNet::GetTime(); if (databaseTable->nextRowPingCheck < time) { databaseTable->nextRowPingCheck=time+1000+(randomMT()%1000); DataStructures::BPlusTree<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> &rows = databaseTable->table.GetRows(); cur = rows.GetListHead(); while (cur) { // Mark dropped entities for (j=0; j < (unsigned)cur->size; j++) { row = cur->data[j]; if (time - row->cells[databaseTable->lastPingResponseColumnIndex]->i > DROP_SERVER_INTERVAL) removeList.Insert(cur->keys[j]); } cur=cur->next; } // Remove dropped entities for (j=0; j < removeList.Size(); j++) databaseTable->table.RemoveRow(removeList[i]); removeList.Clear(true); cur = rows.GetListHead(); // Ping remaining entities if they are not connected. If they are connected just increase the ping interval. while (cur) { for (j=0; j < (unsigned)cur->size; j++) { row = cur->data[j]; if (row->cells[databaseTable->nextPingSendColumnIndex]->i < (int) time) { row->cells[databaseTable->systemIdColumnIndex]->Get((char*)&playerId, 0); if (peer->GetIndexFromPlayerID(playerId)==-1) { peer->Ping(playerId.ToString(false), playerId.port, false); } else { // Consider the fact that they are connected to be a ping response row->cells[databaseTable->lastPingResponseColumnIndex]->i=time; } row->cells[databaseTable->nextPingSendColumnIndex]->i=time+SEND_PING_INTERVAL+(randomMT()%1000); } } cur=cur->next; } } } } }
int main() { FullyConnectedMesh2 fcm2; ConnectionGraph2 cg2; rakPeer=RakNet::RakPeerInterface::GetInstance(); rakPeer->AttachPlugin(&fcm2); rakPeer->AttachPlugin(&cg2); fcm2.SetAutoparticipateConnections(true); RakNet::SocketDescriptor sd; sd.socketFamily=AF_INET; // Only IPV4 supports broadcast on 255.255.255.255 sd.port=60000; while (IRNS2_Berkley::IsPortInUse(sd.port, sd.hostAddress, sd.socketFamily, SOCK_DGRAM)==true) sd.port++; StartupResult sr = rakPeer->Startup(8,&sd,1); RakAssert(sr==RAKNET_STARTED); rakPeer->SetMaximumIncomingConnections(8); rakPeer->SetTimeoutTime(1000,RakNet::UNASSIGNED_SYSTEM_ADDRESS); printf("Our guid is %s\n", rakPeer->GetGuidFromSystemAddress(RakNet::UNASSIGNED_SYSTEM_ADDRESS).ToString()); printf("Started on %s\n", rakPeer->GetMyBoundAddress().ToString(true)); BitStream contextBs; contextBs.Write(RakString("Our guid is %s\n", rakPeer->GetGuidFromSystemAddress(RakNet::UNASSIGNED_SYSTEM_ADDRESS).ToString())); fcm2.SetMyContext(&contextBs); // PacketLogger packetLogger; // rakPeer->AttachPlugin(&packetLogger); // packetLogger.SetLogDirectMessages(false); bool quit=false; RakNet::Packet *packet; char ch; while (!quit) { for (packet = rakPeer->Receive(); packet; rakPeer->DeallocatePacket(packet), packet = rakPeer->Receive()) { switch (packet->data[0]) { case ID_DISCONNECTION_NOTIFICATION: // Connection lost normally printf("ID_DISCONNECTION_NOTIFICATION\n"); break; case ID_NEW_INCOMING_CONNECTION: // Somebody connected. We have their IP now printf("ID_NEW_INCOMING_CONNECTION from %s. guid=%s.\n", packet->systemAddress.ToString(true), packet->guid.ToString()); break; case ID_CONNECTION_REQUEST_ACCEPTED: // Somebody connected. We have their IP now printf("ID_CONNECTION_REQUEST_ACCEPTED from %s. guid=%s.\n", packet->systemAddress.ToString(true), packet->guid.ToString()); break; case ID_CONNECTION_LOST: // Couldn't deliver a reliable packet - i.e. the other system was abnormally // terminated printf("ID_CONNECTION_LOST\n"); break; case ID_ADVERTISE_SYSTEM: if (packet->guid!=rakPeer->GetMyGUID()) rakPeer->Connect(packet->systemAddress.ToString(false), packet->systemAddress.GetPort(),0,0); break; case ID_FCM2_NEW_HOST: { if (packet->guid==rakPeer->GetMyGUID()) printf("Got new host (ourselves)"); else printf("Got new host %s, GUID=%s", packet->systemAddress.ToString(true), packet->guid.ToString()); RakNet::BitStream bs(packet->data,packet->length,false); bs.IgnoreBytes(1); RakNetGUID oldHost; bs.Read(oldHost); // If oldHost is different then the current host, then we lost connection to the host if (oldHost!=UNASSIGNED_RAKNET_GUID) printf(". Oldhost Guid=%s\n", oldHost.ToString()); else printf(". (First reported host)\n"); } break; // case ID_REMOTE_NEW_INCOMING_CONNECTION: // { // uint32_t count; // RakNet::BitStream bsIn(packet->data, packet->length,false); // bsIn.IgnoreBytes(1); // bsIn.Read(count); // SystemAddress sa; // RakNetGUID guid; // printf("ID_REMOTE_NEW_INCOMING_CONNECTION from %s\n", packet->systemAddress.ToString(true)); // for (uint32_t i=0; i < count; i++) // { // bsIn.Read(sa); // bsIn.Read(guid); // // printf("%s ", sa.ToString(true)); // } // printf("\n"); // } } } if (kbhit()) { ch=getch(); if (ch==' ') { DataStructures::List<RakNetGUID> participantList; fcm2.GetParticipantList(participantList); printf("%i participants\n", participantList.Size()); for (int i=0; i < participantList.Size(); i++) { BitStream userContext; fcm2.GetParticipantContext(participantList[i], &userContext); RakString str; userContext.Read(str); printf("%i. %s: %s", i+1, participantList[i].ToString(), str.C_String()); } } if (ch=='q' || ch=='Q') { printf("Quitting.\n"); quit=true; } } RakSleep(30); for (int i=0; i < 32; i++) { if (rakPeer->GetInternalID(RakNet::UNASSIGNED_SYSTEM_ADDRESS,0).GetPort()!=60000+i) rakPeer->AdvertiseSystem("255.255.255.255", 60000+i, 0,0,0); } } RakNet::RakPeerInterface::DestroyInstance(rakPeer); return 0; }
PGresult * PostgreSQLInterface::QueryVariadic( const char * input, ... ) { RakNet::RakString query; PGresult *result; DataStructures::List<VariadicSQLParser::IndexAndType> indices; if ( input==0 || input[0]==0 ) return 0; // Lookup this query in the stored query table. If it doesn't exist, prepare it. RakNet::RakString inputStr; inputStr=input; unsigned int preparedQueryIndex; for (preparedQueryIndex=0; preparedQueryIndex < preparedQueries.Size(); preparedQueryIndex++) { if (preparedQueries[preparedQueryIndex].StrICmp(inputStr)==0) break; } // Find out how many params there are // Find out the type of each param (%f, %s) indices.Clear(false, _FILE_AND_LINE_); GetTypeMappingIndices( input, indices ); if (preparedQueryIndex==preparedQueries.Size()) { // if (indices.Size()>0) // query += " ("; RakNet::RakString formatCopy; RakNet::RakString insertion; formatCopy=input; unsigned int i; unsigned int indexOffset=0; for (i=0; i < indices.Size(); i++) { // if (i!=0) // query += ","; // query+=typeMappings[indices[i].typeMappingIndex].type; formatCopy.SetChar(indices[i].strIndex+indexOffset, '$'); // if (i < 9) // formatCopy.SetChar(indices[i].strIndex+1, i+1+'0'); // else insertion=RakNet::RakString("%i::%s", i+1, VariadicSQLParser::GetTypeMappingAtIndex(indices[i].typeMappingIndex)); formatCopy.SetChar(indices[i].strIndex+1+indexOffset, insertion); indexOffset+=(unsigned int) insertion.GetLength()-1; } // if (indices.Size()>0) // query += ")"; // query += " AS "; query += formatCopy; // query += ";\n"; formatCopy+= ";\n"; result = PQprepare(pgConn, RakNet::RakString("PGSQL_ExecuteVariadic_%i", preparedQueries.Size()), formatCopy.C_String(), indices.Size(), NULL); if (IsResultSuccessful(result, false)) { PQclear(result); preparedQueries.Insert(inputStr, _FILE_AND_LINE_); } else { printf(formatCopy.C_String()); printf("\n"); printf(lastError); RakAssert(0); PQclear(result); return 0; } } // char *paramData[512]; // int paramLength[512]; // int paramFormat[512]; va_list argptr; va_start(argptr, input); char **paramData; int *paramLength; int *paramFormat; ExtractArguments(argptr, indices, ¶mData, ¶mLength); paramFormat=RakNet::OP_NEW_ARRAY<int>(indices.Size(),_FILE_AND_LINE_); for (unsigned int i=0; i < indices.Size(); i++) paramFormat[i]=PQEXECPARAM_FORMAT_BINARY; result = PQexecPrepared(pgConn, RakNet::RakString("PGSQL_ExecuteVariadic_%i", preparedQueryIndex), indices.Size(), paramData, paramLength, paramFormat, PQEXECPARAM_FORMAT_BINARY ); VariadicSQLParser::FreeArguments(indices, paramData, paramLength); RakNet::OP_DELETE_ARRAY(paramFormat,_FILE_AND_LINE_); va_end(argptr); if (IsResultSuccessful(result, false)==false) { printf(lastError); PQclear(result); return 0; } return result; }
void NatPunchthroughServer::OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason ) { (void) lostConnectionReason; (void) systemAddress; unsigned int i=0; bool objectExists; i = users.GetIndexFromKey(rakNetGUID, &objectExists); if (objectExists) { RakNet::BitStream outgoingBs; DataStructures::List<User *> freedUpInProgressUsers; User *user = users[i]; User *otherUser; unsigned int connectionAttemptIndex; ConnectionAttempt *connectionAttempt; for (connectionAttemptIndex=0; connectionAttemptIndex < user->connectionAttempts.Size(); connectionAttemptIndex++) { connectionAttempt=user->connectionAttempts[connectionAttemptIndex]; outgoingBs.Reset(); if (connectionAttempt->recipient==user) { otherUser=connectionAttempt->sender; } else { otherUser=connectionAttempt->recipient; } // 05/28/09 Previously only told sender about ID_NAT_CONNECTION_TO_TARGET_LOST // However, recipient may be expecting it due to external code // In that case, recipient would never get any response if the sender dropped outgoingBs.Write((MessageID)ID_NAT_CONNECTION_TO_TARGET_LOST); outgoingBs.Write(rakNetGUID); outgoingBs.Write(connectionAttempt->sessionId); rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,otherUser->systemAddress,false); // 4/22/09 - Bug: was checking inProgress, legacy variable not used elsewhere if (connectionAttempt->attemptPhase==ConnectionAttempt::NAT_ATTEMPT_PHASE_GETTING_RECENT_PORTS) { otherUser->isReady=true; freedUpInProgressUsers.Insert(otherUser, _FILE_AND_LINE_ ); } otherUser->DeleteConnectionAttempt(connectionAttempt); } RakNet::OP_DELETE(users[i], _FILE_AND_LINE_); users.RemoveAtIndex(i); for (i=0; i < freedUpInProgressUsers.Size(); i++) { StartPunchthroughForUser(freedUpInProgressUsers[i]); } } /* // Also remove from groupPunchthroughRequests for (i=0; i < users.Size(); i++) { bool objectExists; unsigned int gprIndex; gprIndex = users[i]->groupPunchthroughRequests.GetIndexFromKey(rakNetGUID, &objectExists); if (objectExists) { // printf("DEBUG %i\n", __LINE__); RakNet::BitStream outgoingBs; outgoingBs.Write((MessageID)ID_NAT_TARGET_NOT_CONNECTED); outgoingBs.Write(rakNetGUID); rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,users[i]->systemAddress,false); users[i]->groupPunchthroughRequests.RemoveAtIndex(gprIndex); } } */ }
/** * _findfirst - equivalent */ long _findfirst(const char *name, _finddata_t *f) { // char* nameCopy = new char[sizeof(name)]; // memset(nameCopy, '\0', sizeof(nameCopy)); // // strcpy(nameCopy, name); // // char* filter = new char[sizeof(nameCopy)]; // memset(filter, '\0', sizeof(filter)); int length = strlen(name)+1; char* nameCopy = new char[length]; memset(nameCopy, '\0', length); strcpy(nameCopy, name); char* filter = new char[length]; memset(filter, '\0', length); char* lastSep = strrchr(nameCopy,'/'); if(!lastSep) { strcpy(filter, nameCopy); strcpy(nameCopy, "."); } else { strcpy(filter, lastSep+1); *lastSep = 0; } DIR* dir = opendir(nameCopy); if(!dir) { return -1; } _findinfo_t* fi = new _findinfo_t; strcpy(fi->filter,filter); fi->openedDir = dir; while(true) { dirent* entry = readdir(dir); if(entry == 0) break; if(fnmatch(fi->filter,entry->d_name, 200) == 0) { strcpy(f->name, entry->d_name); break; } } fileInfo.Insert(fi); return fileInfo.Size()-1; // return 0; }