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;
}
示例#2
0
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;
}