bool NetworkManager::start(bool isServer, Ogre::ushort serverPort, Ogre::String serverIP) { mServer = isServer; RakNet::Time waitTime = 10000; RakNet::Time prevTime = 0; if(isServer) { Ogre::LogManager::getSingletonPtr() ->logMessage(RealToys::logMessagePrefix + "Starting network as " + "server on port " + Ogre::StringConverter::toString(serverPort) ); } else { Ogre::LogManager::getSingletonPtr() ->logMessage(RealToys::logMessagePrefix + "Starting network as " + "client to server " + serverIP + " on port " + Ogre::StringConverter::toString(serverPort) ); } mAirplaneManager = AirplaneManager::getSingletonPtr(); upAndRunning = false; mConnectAtemp = false; mWaitForPong = false; RakNet::SocketDescriptor sd; mRakPeer = RakNet::RakPeerInterface::GetInstance(); if(isServer) { sd.port = serverPort; mReplicaManager = RT_ReplicaManager(mSceneMgr, mWorld); } else { sd.port = 0; mReplicaManager = RT_ReplicaManager(mSceneMgr); } mReplicaManager.SetDefaultPacketReliability(UNRELIABLE_SEQUENCED); mReplicaManager.SetDefaultPacketPriority(HIGH_PRIORITY); // The network ID authority is the system that creates the common numerical identifier used to lookup pointers (the server here). //mNetworkIdManager.SetIsNetworkIDAuthority(isServer); // ObjectMemberRPC, AutoRPC for objects, and ReplicaManager3 require that you call SetNetworkIDManager() mReplicaManager.SetNetworkIDManager(&mNetworkIdManager); // Setup RPC3 system and classes //mRPCIdManager.SetIsNetworkIDAuthority(true); mRPC3Inst.SetNetworkIDManager(&mRPCIdManager); this->SetNetworkIDManager(&mRPCIdManager); RakNet::NetworkID id0 = 0; this->SetNetworkID(id0); RPC3_REGISTER_FUNCTION(&mRPC3Inst, &NetworkManager::createAirplane); RPC3_REGISTER_FUNCTION(&mRPC3Inst, &NetworkManager::processAirplaneInput); // Start RakNet, up to 32 connections if the server if(!doStartup(isServer, sd)) { return false; } mRakPeer->AttachPlugin(&mReplicaManager); mRakPeer->AttachPlugin(&mRPC3Inst); mNetworkID = mRakPeer->GetGuidFromSystemAddress(RakNet::UNASSIGNED_SYSTEM_ADDRESS); // The server should allow systems to connect. Clients do not need to unless we want to transmit messages directly between systems or to use RakVoice if (isServer) { // mRakPeer->SetMaximumIncomingConnections(RealToys::maxClients-1); mRakPeer->SetMaximumIncomingConnections(0); //will not accept connections until setCurrentMap is called //mNetworkID = RealToys::serverPlayerID; } else { if(serverIP == "255.255.255.255") { if(mRakPeer->Ping( serverIP.c_str(), serverPort, true, 0 ) ) { Ogre::LogManager::getSingletonPtr() ->logMessage(RealToys::logMessagePrefix + "Client will try to search for servers on LAN"); mWaitForPong = true; } else { Ogre::LogManager::getSingletonPtr() ->logMessage(RealToys::logMessagePrefix + "Client PING failed"); return false; } } else { if(!doConnect(serverIP, serverPort)) { return false; } } } mIsStarted = true; if(isServer) { upAndRunning = true; } else { Ogre::LogManager::getSingletonPtr() ->logMessage(RealToys::logMessagePrefix + "Trying to connect to server" ); //"update" until receives a package saying if it was a successful connection or not prevTime = RakNet::GetTime(); while(!upAndRunning && (mConnectAtemp || mWaitForPong) && waitTime > 0) { update(); waitTime-=(RakNet::GetTime()-prevTime); prevTime = RakNet::GetTime(); } } if(upAndRunning) { mAirplaneManager->setPlayerID(mNetworkID); ScoresManager::getSingletonPtr()->setLocalSysAddress(mNetworkID); Ogre::String addrs( mNetworkID.ToString() ); if(mServer) addrs += " (server)"; Ogre::LogManager::getSingletonPtr() ->logMessage(RealToys::logMessagePrefix + "Network started " + addrs); } else { Ogre::LogManager::getSingletonPtr() ->logMessage(RealToys::logMessagePrefix + "Network failed to start" ); } return upAndRunning; }
int main(int argc, char *argv[]) { std::cout << "Performance test for the RPC314 plugin." << std::endl; bool isServer = false; bool testAll = false; bool testSignal = false; bool testCallC = false; bool testCallCpp = false; bool useBoost = false; unsigned int clientCount = 1; unsigned int callCount = 1; int opt; while (1) { static struct option long_options[] = { {"use-boost", no_argument, 0, 'b'}, {"test", required_argument, 0, 't'}, {"client-count", required_argument, 0, 'c'}, {"call-count", required_argument, 0, 'r'}, {0, 0, 0, 0} }; // getopt_long stores the option index here. int option_index = 0; opt = getopt_long(argc, argv, "bc:t:", long_options, &option_index); // Detect the end of the options. if (opt == -1) { break; } switch (opt) { case 0: break; case 'b': useBoost = true; break; case 'c': clientCount = atoi(optarg); break; case 'r': callCount = atoi(optarg); break; case 't': { if (optarg == "all") { testAll = true; } else if (optarg == "signal") { testSignal = true; } else if (optarg == "c") { testCallC = true; } else if (optarg == "cpp") { testCallCpp = true; } else { testAll = true; } } break; case '?': return 1; default: testAll = true; break; } } TestValues testValues; testValues.allReady = false; uint64_t programStartTime = RakNet::GetTimeUS(); std::unique_ptr<std::recursive_mutex> mutex_(new std::recursive_mutex()); unsigned int peerCount = clientCount + 1; std::vector<RakNet::RakPeerInterface *> rakPeers; //rakPeers.assign(peerCount, RakNet::RakPeerInterface::GetInstance()); std::vector<RakNet::RPC3 *> rpcPlugins; //rpcPlugins.assign(peerCount, new RakNet::RPC3()); std::vector<RakNet::NetworkIDManager> networkIdManagers; networkIdManagers.assign(peerCount, RakNet::NetworkIDManager()); std::vector<BaseClassA> a; a.assign(peerCount, BaseClassA()); std::vector<BaseClassB> b; b.assign(peerCount, BaseClassB()); std::vector<ClassC> c; c.assign(peerCount, ClassC()); std::vector<ClassD> d; d.assign(peerCount, ClassD()); for (std::size_t i = 0; i < peerCount; i++) { rakPeers.push_back(RakNet::RakPeerInterface::GetInstance()); rpcPlugins.push_back(new RakNet::RPC3()); if (i == 0) { RakNet::SocketDescriptor socketDescriptorServer(60000, 0); // Only IPV4 supports broadcast on 255.255.255.255 socketDescriptorServer.socketFamily = AF_INET; rakPeers[i]->Startup(clientCount, &socketDescriptorServer, 1); rakPeers[i]->SetMaximumIncomingConnections(clientCount); std::cout << "Server started." << std::endl; } else { RakNet::SocketDescriptor socketDescriptorClient(60000 + i, 0); // Only IPV4 supports broadcast on 255.255.255.255 socketDescriptorClient.socketFamily = AF_INET; rakPeers[i]->Startup(1, &socketDescriptorClient, 1); // Send out a LAN broadcast to find the server on the same computer. rakPeers[i]->Ping("255.255.255.255", 60000, true, 0); std::cout << "Client #" << i << " started." << std::endl; } rakPeers[i]->AttachPlugin(rpcPlugins[i]); rpcPlugins[i]->SetNetworkIDManager(&networkIdManagers[i]); c[i].SetNetworkIDManager(&networkIdManagers[i]); d[i].SetNetworkIDManager(&networkIdManagers[i]); c[i].SetNetworkID(0); d[i].SetNetworkID(1); // Register a regular C function. RPC3_REGISTER_FUNCTION(rpcPlugins[i], CFuncTest); // Register C++ class member functions. RPC3_REGISTER_FUNCTION(rpcPlugins[i], &ClassC::ClassMemberFuncTest); // All equivalent local and remote slots are called when a signal is sent. rpcPlugins[i]->RegisterSlot( "TestSlotTest", &ClassC::TestSlotTest, c[i].GetNetworkID(), 0); rpcPlugins[i]->RegisterSlot( "TestSlotTest", &ClassD::TestSlotTest, d[i].GetNetworkID(), 0); } std::cout << "Clients will automatically connect to running server." << std::endl; std::cout << "Running " << callCount << " rounds." << std::endl; RakNet::Packet *packet; std::thread serverT; bool allready = true; while (!testValues.allReady) { for (std::size_t i = 0; i < peerCount; i++) { for (packet=rakPeers[i]->Receive(); packet; rakPeers[i]->DeallocatePacket(packet), packet=rakPeers[i]->Receive()) { switch (packet->data[0]) { case ID_DISCONNECTION_NOTIFICATION: std::cout << "ID_DISCONNECTION_NOTIFICATION peer index:" << i << std::endl; break; case ID_ALREADY_CONNECTED: std::cout << "ID_ALREADY_CONNECTED peer index:" << i << std::endl; break; case ID_CONNECTION_ATTEMPT_FAILED: std::cout << "Connection attempt failed peer index:" << i << std::endl; break; case ID_NO_FREE_INCOMING_CONNECTIONS: std::cout << "ID_NO_FREE_INCOMING_CONNECTIONS peer index:" << i << std::endl; break; case ID_UNCONNECTED_PONG: // Found the server rakPeers[i]->Connect( packet->systemAddress.ToString(false), packet->systemAddress.GetPort(), 0, 0, 0 ); break; case ID_CONNECTION_REQUEST_ACCEPTED: // This tells the client they have connected std::cout << "ID_CONNECTION_REQUEST_ACCEPTED peer index:" << i << std::endl; break; case ID_NEW_INCOMING_CONNECTION: { clientCount--; std::cout << "ID_NEW_INCOMING_CONNECTION peer index:" << i << " clients to wait:" << clientCount << std::endl; if (!clientCount) { // If all clients are connected. serverT = std::thread( serverThread, mutex_.get(), &testValues, &a[0], &c[0], &d[0], rpcPlugins[0], peerCount, callCount ); serverT.detach(); } break; } case ID_RPC_REMOTE_ERROR: { // Recipient system returned an error switch (packet->data[1]) { case RakNet::RPC_ERROR_NETWORK_ID_MANAGER_UNAVAILABLE: std::cout << "RPC_ERROR_NETWORK_ID_MANAGER_UNAVAILABLE" << " peer index:" << i << std::endl; break; case RakNet::RPC_ERROR_OBJECT_DOES_NOT_EXIST: std::cout << "RPC_ERROR_OBJECT_DOES_NOT_EXIST peer index:" << i << std::endl; break; case RakNet::RPC_ERROR_FUNCTION_INDEX_OUT_OF_RANGE: std::cout << "RPC_ERROR_FUNCTION_INDEX_OUT_OF_RANGE " << " peer index:" << i << std::endl; break; case RakNet::RPC_ERROR_FUNCTION_NOT_REGISTERED: std::cout << "RPC_ERROR_FUNCTION_NOT_REGISTERED" << " peer index:" << i << std::endl; break; case RakNet::RPC_ERROR_FUNCTION_NO_LONGER_REGISTERED: std::cout << "RPC_ERROR_FUNCTION_NO_LONGER_REGISTERED" << " peer index:" << i << std::endl; break; case RakNet::RPC_ERROR_CALLING_CPP_AS_C: std::cout << "RPC_ERROR_CALLING_CPP_AS_C peer index:" << i << std::endl; break; case RakNet::RPC_ERROR_CALLING_C_AS_CPP: std::cout << "RPC_ERROR_CALLING_C_AS_CPP peer index:" << i << std::endl; break; } std::cout << "Function: " << packet->data + 2 << " peer index:" << i << std::endl; break; } default: //std::cout << "Unknown id received: " // << packet->data[0] << std::endl; break; } } //std::cout << "before" << std::endl; uint64_t allCount = (peerCount-1) * callCount; if (c[i].testCalls.size() < allCount || c[i].testSlots.size() < allCount || d[i].testSlots.size() < allCount || cFuncTestCalls.size() < allCount) { /*std::cout << "in " << "\n\tc[" << i << "].testCalls.size(): " << c[i].testCalls.size() << "\n\tc[" << i << "].testSlots.size(): " << c[i].testSlots.size() << "\n\td[" << i << "].testSlots.size(): " << d[i].testSlots.size() << "\n\tcFuncTestCalls.size(): " << cFuncTestCalls.size() << "\n\tallCount: " << allCount << std::endl;*/ allready = false; } } RakSleep(0); if (allready) { mutex_->lock(); testValues.allReady = true; mutex_->unlock(); } allready = true; } testValues.programRunTime = RakNet::GetTimeUS() - programStartTime; testValues.AppendCFuncValues(cFuncTestCalls); for (size_t i = 1; i < peerCount; i++) { testValues.AppendCClassValues(c[i].testCalls); testValues.AppendCClassSlotValues(c[i].testSlots); testValues.AppendCClassSlotValues(d[i].testSlots); } testValues.PrintTestSummary(); for (std::size_t i = 0; i < peerCount; i++) { delete rpcPlugins[i]; rakPeers[i]->Shutdown(0, 0); RakNet::RakPeerInterface::DestroyInstance(rakPeers[i]); } rpcPlugins.clear(); return 1; }