Bläddra i källkod

flows updated, disconnect functionality added

Arnis Lielturks 7 år sedan
förälder
incheckning
3bc415011f

+ 24 - 16
Source/Samples/54_P2PMultiplayer/P2PMultiplayer.cpp

@@ -132,10 +132,13 @@ void P2PMultiplayer::CreateUI()
     marginTop += 40;
     resetHostButton_ = CreateButton("Reset host", 160, IntVector2(20, marginTop));
 
-    marginTop += 100;
+    marginTop += 80;
     readyButton_ = CreateButton("Set ready", 160, IntVector2(20, marginTop));
     static_cast<Text*>(readyButton_->GetChild(0))->SetColor(Color::GREEN);
 
+    marginTop += 40;
+    disconnect_ = CreateButton("Disconnect", 160, IntVector2(20, marginTop));
+
     // No viewports or scene is defined. However, the default zone's fog color controls the fill color
     //GetSubsystem<Renderer>()->GetDefaultZone()->SetFogColor(Color(0.0f, 0.0f, 0.1f));
 }
@@ -151,6 +154,7 @@ void P2PMultiplayer::SubscribeToEvents()
     SubscribeToEvent(readyButton_, "Released", URHO3D_HANDLER(P2PMultiplayer, HandleReady));
 
     SubscribeToEvent(resetHostButton_, "Released", URHO3D_HANDLER(P2PMultiplayer, HandleResetHost));
+    SubscribeToEvent(disconnect_, "Released", URHO3D_HANDLER(P2PMultiplayer, HandleDisconnect));
 
     SubscribeToEvent(E_CLIENTCONNECTED, URHO3D_HANDLER(P2PMultiplayer, HandleClientConnected));
     SubscribeToEvent(E_CLIENTDISCONNECTED, URHO3D_HANDLER(P2PMultiplayer, HandleClientDisconnected));
@@ -211,7 +215,8 @@ void P2PMultiplayer::HandleUpdate(StringHash eventType, VariantMap& eventData)
         body_->SetLinearVelocity(Vector3(0, 0, 0));
     }
 
-    if (timer_.GetMSec(false) > 500) {
+    if (timer_.GetMSec(false) > 1000) {
+        GetSubsystem<Network>()->DisplayPingTimes();
         i++;
         timer_.Reset();
 //        URHO3D_LOGINFO(" ");
@@ -258,7 +263,6 @@ void P2PMultiplayer::Init()
     GetSubsystem<Network>()->SetMode(NetworkMode::PEER_TO_PEER);
 //    GetSubsystem<Network>()->SetNATServerInfo("frameskippers.com", 61111);
     GetSubsystem<Network>()->SetNATServerInfo("frameskippers.com", 61111);
-    GetSubsystem<Network>()->P2PConnectNAT("frameskippers.com", 61111);
 //    GetSubsystem<Network>()->BanAddress("192.168.68.*");
     GetSubsystem<Network>()->SetUpdateFps(30);
 }
@@ -458,7 +462,6 @@ void P2PMultiplayer::HandleClientConnected(StringHash eventType, VariantMap& eve
     auto* newConnection = static_cast<Connection*>(eventData[P_CONNECTION].GetPtr());
     newConnection->SetScene(scene_);
 
-    return;
     // Then create a controllable object for that client
 //    Node* newObject = CreateControllableObject();
 //    serverObjects_[newConnection] = newObject;
@@ -481,7 +484,6 @@ void P2PMultiplayer::HandleClientConnected(StringHash eventType, VariantMap& eve
     auto* body = ballNode->CreateComponent<RigidBody>();
     body->SetMass(1.0f);
     body->SetFriction(1.0f);
-    body_ = body;
     // In addition to friction, use motion damping so that the ball can not accelerate limitlessly
 //    body->SetLinearDamping(0.5f);
 //    body->SetAngularDamping(0.5f);
@@ -492,25 +494,20 @@ void P2PMultiplayer::HandleClientConnected(StringHash eventType, VariantMap& eve
     // Create a random colored point light at the ball so that can see better where is going
     auto* light = ballNode->CreateComponent<Light>();
     light->SetRange(3.0f);
-    light->SetColor(
-            Color(0.5f + ((unsigned)Rand() & 1u) * 0.5f, 0.5f + ((unsigned)Rand() & 1u) * 0.5f, 0.5f + ((unsigned)Rand() & 1u) * 0.5f));
+    light->SetColor(Color(0.5f + ((unsigned)Rand() & 1u) * 0.5f, 0.5f + ((unsigned)Rand() & 1u) * 0.5f, 0.5f + ((unsigned)Rand() & 1u) * 0.5f));
+    playerNodes_[newConnection] = ballNode;
 }
 
 void P2PMultiplayer::HandleClientDisconnected(StringHash eventType, VariantMap& eventData)
 {
-//    return;
     using namespace ClientConnected;
-    return;
 //
 //    // When a client disconnects, remove the controlled object
     auto* connection = static_cast<Connection*>(eventData[P_CONNECTION].GetPtr());
-    Node* node = scene_->GetChild(connection->GetAddress());
-    node->Remove();
-//    Node* object = serverObjects_[connection];
-//    if (object)
-//        object->Remove();
-//
-//    serverObjects_.Erase(connection);
+    if (playerNodes_[connection]) {
+        playerNodes_[connection]->Remove();
+        playerNodes_.Erase(connection);
+    }
 }
 
 void P2PMultiplayer::HandleResetHost(StringHash eventType, VariantMap& eventData)
@@ -529,4 +526,15 @@ void P2PMultiplayer::HandleAllReadyChanged(StringHash eventType, VariantMap& eve
 {
     using namespace P2PAllReadyChanged;
     _allReady = eventData[P_READY].GetBool();
+}
+
+void P2PMultiplayer::HandleDisconnect(StringHash eventType, VariantMap& eventData)
+{
+    GetSubsystem<Network>()->Disconnect(1000);
+    for (auto it = playerNodes_.Begin(); it != playerNodes_.End(); ++it) {
+        if ((*it).second_) {
+            (*it).second_->Remove();
+        }
+    }
+    playerNodes_.Clear();
 }

+ 5 - 0
Source/Samples/54_P2PMultiplayer/P2PMultiplayer.h

@@ -105,6 +105,8 @@ private:
 
     void HandleAllReadyChanged(StringHash eventType, VariantMap& eventData);
 
+    void HandleDisconnect(StringHash eventType, VariantMap& eventData);
+
     Timer timer_;
 //    /// Stop server
 //	void HandleStopServer(StringHash eventType, VariantMap& eventData);
@@ -118,6 +120,7 @@ private:
     SharedPtr<Button> joinSession_;
     SharedPtr<Button> readyButton_;
     SharedPtr<Button> resetHostButton_;
+    SharedPtr<Button> disconnect_;
     SharedPtr<LineEdit> guid_;
 //    /// Found server list
 	SharedPtr<Text> clientCount_;
@@ -125,6 +128,8 @@ private:
     SharedPtr<Text> myGuid_;
     SharedPtr<Text> hostGuid_;
     SharedPtr<RigidBody> body_;
+    HashMap<Connection*, WeakPtr<Node>> playerNodes_;
+
     SharedPtr<Node> ball_;
     bool _allReady;
 };

+ 2 - 0
Source/Samples/CMakeLists.txt

@@ -61,4 +61,6 @@ list (SORT DIRS)
 #endforeach ()
 add_sample_subdirectory (16_Chat)
 add_sample_subdirectory (17_SceneReplication)
+add_sample_subdirectory (52_NATPunchtrough)
+add_sample_subdirectory (53_LANDiscovery)
 add_sample_subdirectory (54_P2PMultiplayer)

+ 107 - 77
Source/Urho3D/Network/Network.cpp

@@ -211,7 +211,6 @@ Network::Network(Context* context) :
     scene_(nullptr),
     natPunchServerAddress_(nullptr),
     remoteGUID_(nullptr),
-    natPunchtroughAttempt_(false),
     networkMode_(SERVER_CLIENT)
 {
     rakPeer_ = SLNet::RakPeerInterface::GetInstance();
@@ -288,6 +287,16 @@ Network::Network(Context* context) :
     blacklistedRemoteEvents_.Insert(E_NETWORKUPDATE);
     blacklistedRemoteEvents_.Insert(E_NETWORKUPDATESENT);
     blacklistedRemoteEvents_.Insert(E_NETWORKSCENELOADFAILED);
+    blacklistedRemoteEvents_.Insert(E_NATMASTERCONNECTIONSUCCEEDED);
+    blacklistedRemoteEvents_.Insert(E_NATMASTERCONNECTIONFAILED);
+    blacklistedRemoteEvents_.Insert(E_NETWORKNATPUNCHTROUGHSUCCEEDED);
+    blacklistedRemoteEvents_.Insert(E_NETWORKNATPUNCHTROUGHFAILED);
+    blacklistedRemoteEvents_.Insert(E_P2PJOINREQUESTDENIED);
+    blacklistedRemoteEvents_.Insert(E_P2PALLREADYCHANGED);
+    blacklistedRemoteEvents_.Insert(E_NETWORKHOSTDISCOVERED);
+    blacklistedRemoteEvents_.Insert(E_NETWORKINVALIDPASSWORD);
+    blacklistedRemoteEvents_.Insert(E_NETWORKBANNED);
+
 }
 
 Network::~Network()
@@ -354,7 +363,7 @@ void Network::HandleMessage(const SLNet::AddressOrGUID& source, int packetID, in
 
 void Network::NewConnectionEstablished(const SLNet::AddressOrGUID& connection)
 {
-    P2PSubscribeForReadyEvents();
+    P2PReadyStatusChanged();
     if (networkMode_ == PEER_TO_PEER && clientConnections_[connection]) {
         URHO3D_LOGERROR("3");
         URHO3D_LOGWARNINGF("Client already in the client list.", connection.rakNetGuid.ToString());
@@ -399,7 +408,7 @@ void Network::ClientDisconnected(const SLNet::AddressOrGUID& connection)
         clientConnections_.Erase(i);
     }
 
-    P2PSubscribeForReadyEvents();
+    P2PReadyStatusChanged();
 }
 
 void Network::SetDiscoveryBeacon(const VariantMap& data)
@@ -434,7 +443,6 @@ bool Network::Connect(const String& address, unsigned short port, Scene* scene,
 {
     URHO3D_PROFILE(Connect);
 
-    natPunchtroughAttempt_ = false;
     if (!rakPeerClient_->IsActive())
     {
         URHO3D_LOGINFO("Initializing client connection...");
@@ -476,8 +484,9 @@ bool Network::P2PConnectNAT(const String& address, unsigned short port)
         URHO3D_LOGINFO("Initializing client connection...");
         SLNet::SocketDescriptor socket;
         // Startup local connection with max 2 incoming connections(first param) and 1 socket description (third param)
-        rakPeer_->Startup(32, &socket, 1);
-        rakPeer_->SetMaximumIncomingConnections(32);
+        rakPeer_->Startup(128, &socket, 1);
+        rakPeer_->SetMaximumIncomingConnections(128);
+        rakPeer_->AttachPlugin(natPunchthroughServerClient_);
     }
     else {
         OnServerDisconnected();
@@ -504,8 +513,15 @@ void Network::Disconnect(int waitMSec)
     if (!serverConnection_)
         return;
 
+    if (networkMode_ == PEER_TO_PEER) {
+        rakPeer_->Shutdown(1000);
+        clientConnections_.Clear();
+    }
+
     URHO3D_PROFILE(Disconnect);
     serverConnection_->Disconnect(waitMSec);
+    serverConnection_.Reset();
+
 }
 
 bool Network::StartServer(unsigned short port)
@@ -581,7 +597,6 @@ void Network::StartNATClient()
 
 void Network::AttemptNATPunchtrough(const String& guid, Scene* scene, const VariantMap& identity)
 {
-    natPunchtroughAttempt_ = true;
     scene_ = scene;
     identity_ = identity;
     if (!remoteGUID_)
@@ -856,7 +871,6 @@ void Network::HandleIncomingPacket(SLNet::Packet* packet, bool isServer)
     {
         //TODO find out who's really sending out this message
         URHO3D_LOGWARNING("ID_REMOTE_CONNECTION_LOST");
-        //ClientDisconnected(packet->guid);
         packetHandled = true;
     }
     else if (packetID == ID_ALREADY_CONNECTED)
@@ -875,7 +889,7 @@ void Network::HandleIncomingPacket(SLNet::Packet* packet, bool isServer)
         if(natPunchServerAddress_ && packet->systemAddress == *natPunchServerAddress_) {
             URHO3D_LOGINFO("Succesfully connected to NAT punchtrough server! ");
             SendEvent(E_NATMASTERCONNECTIONSUCCEEDED);
-            if (!isServer && remoteGUID_)
+            if (!isServer && remoteGUID_&& networkMode_ == SERVER_CLIENT)
             {
                 natPunchthroughClient_->OpenNAT(*remoteGUID_, *natPunchServerAddress_);
             }
@@ -885,17 +899,17 @@ void Network::HandleIncomingPacket(SLNet::Packet* packet, bool isServer)
             } else {
                 URHO3D_LOGINFOF("ID_CONNECTION_REQUEST_ACCEPTED from %s,guid=%s", packet->systemAddress.ToString(true),
                                 packet->guid.ToString());
-//            fullyConnectedMesh2_->ResetHostCalculation();
-//                SLNet::ConnectionAttemptResult car = rakPeerClient_->Connect(packet->systemAddress.ToString(false), packet->systemAddress.GetPort(), 0, 0);
-//                OnServerConnected(packet->systemAddress);
-                //TODO this works
+                // Assume that we're connecting to the P2P host
+//                serverConnection_->SetAddressOrGUID(packet->guid);
+
+                // Send out join request to the host
+//                VectorBuffer msg;
+//                msg.WriteBool(true);
+//                serverConnection_->SendMessage(MSG_P2P_JOIN_REQUEST, true, true, msg);
+
                 SLNet::BitStream bsOut;
                 bsOut.Write((unsigned char) MSG_P2P_JOIN_REQUEST);
                 rakPeer_->Send(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->guid, false);
-                //TODO this doesn't, but should. Maybe host GUID is not set correctly
-//            VectorBuffer msg;
-//            msg.WriteBool(true);
-//            serverConnection_->SendMessage(MSG_P2P_JOIN_REQUEST, true, true, msg);
             }
         }
         packetHandled = true;
@@ -905,7 +919,7 @@ void Network::HandleIncomingPacket(SLNet::Packet* packet, bool isServer)
         URHO3D_LOGERROR("Target server not connected to NAT master server!");
         packetHandled = true;
     }
-    else if (packetID == ID_CONNECTION_LOST) // We've lost connectivity with the packet source
+    else if (packetID == ID_CONNECTION_LOST || packetID == ID_DISCONNECTION_NOTIFICATION) // We've lost connectivity with the packet source
     {
         if(natPunchServerAddress_ && packet->systemAddress == *natPunchServerAddress_) {
             URHO3D_LOGERROR("Connection to NAT server lost!");
@@ -916,19 +930,11 @@ void Network::HandleIncomingPacket(SLNet::Packet* packet, bool isServer)
         }
         else
         {
-            OnServerDisconnected();
-        }
-        packetHandled = true;
-    }
-    else if (packetID == ID_DISCONNECTION_NOTIFICATION) // We've lost connection with the other side
-    {
-        if (isServer)
-        {
-            ClientDisconnected(packet->guid);
-        }
-        else
-        {
-            OnServerDisconnected();
+            if (networkMode_ == SERVER_CLIENT) {
+                OnServerDisconnected();
+            } else {
+                ClientDisconnected(packet->guid);
+            }
         }
         packetHandled = true;
     }
@@ -951,7 +957,7 @@ void Network::HandleIncomingPacket(SLNet::Packet* packet, bool isServer)
     {
         SLNet::SystemAddress remotePeer = packet->systemAddress;
         URHO3D_LOGINFO("NAT punchtrough succeeded! Remote peer: " + String(remotePeer.ToString()));
-        if (!isServer && natPunchtroughAttempt_)
+        if (!isServer && networkMode_ == SERVER_CLIENT)
         {
             using namespace NetworkNatPunchtroughSucceeded;
             VariantMap eventMap;
@@ -960,7 +966,7 @@ void Network::HandleIncomingPacket(SLNet::Packet* packet, bool isServer)
             SendEvent(E_NETWORKNATPUNCHTROUGHSUCCEEDED, eventMap);
             URHO3D_LOGINFO("Connecting to server behind NAT: " + String(remotePeer.ToString()));
             Connect(String(remotePeer.ToString(false)), remotePeer.GetPort(), scene_, identity_);
-        } else {
+        } else if (networkMode_ == PEER_TO_PEER){
             SLNet::ConnectionAttemptResult car = rakPeer_->Connect(packet->systemAddress.ToString(false), packet->systemAddress.GetPort(), 0, 0);
         }
         packetHandled = true;
@@ -1088,7 +1094,7 @@ void Network::HandleIncomingPacket(SLNet::Packet* packet, bool isServer)
             }
         }
 
-        P2PSubscribeForReadyEvents();
+        P2PReadyStatusChanged();
         URHO3D_LOGINFO("");
 
 
@@ -1162,15 +1168,15 @@ void Network::HandleIncomingPacket(SLNet::Packet* packet, bool isServer)
 //            ClientDisconnected(packet->guid);
         } else if (networkMode_ == PEER_TO_PEER && P2PIsHostSystem())
         {
-//            URHO3D_LOGINFO("P2P Host system handler " + String(packet->guid.ToString()));
+            // We are the host in the P2P server, parse the message accordingly
             HandleMessage(packet->guid, 0, packetID, (const char*)(packet->data + dataStart), packet->length - dataStart);
         }
         else if (networkMode_ == SERVER_CLIENT && isServer_) {
-//            URHO3D_LOGINFO("Server system handler " + String(packet->guid.ToString()));
+            // We are the server in the server-client connection
             HandleMessage(packet->guid, 0, packetID, (const char*)(packet->data + dataStart), packet->length - dataStart);
         }
         else {
-//            URHO3D_LOGINFO("Client system handler " + String(packet->guid.ToString()));
+            // we are client in either P2P or server-client mode
             MemoryBuffer buffer(packet->data + dataStart, packet->length - dataStart);
             bool processed = serverConnection_->ProcessMessage(packetID, buffer);
             if (!processed)
@@ -1345,57 +1351,94 @@ void Network::ConfigureNetworkSimulator()
 
 bool Network::P2PStartSession(Scene* scene, const VariantMap& identity)
 {
+    if (!natPunchServerAddress_) {
+        URHO3D_LOGERROR("Set the NAT server info first!");
+        return false;
+    }
+    P2PConnectNAT(natPunchServerAddress_->ToString(false), natPunchServerAddress_->GetPort());
     if (networkMode_ == SERVER_CLIENT) {
         URHO3D_LOGERROR("P2P sessions are not available for SERVER_CLIENT mode!");
         return false;
     }
+
+    UnsubscribeFromEvent(E_NATMASTERCONNECTIONSUCCEEDED);
+    SubscribeToEvent(E_NATMASTERCONNECTIONSUCCEEDED, URHO3D_HANDLER(Network, HandleNATStartP2PSession));
 //    SetSimulatedLatency(500);
 //    SetSimulatedPacketLoss(0.3);
+    scene_ = scene;
+    identity_ = identity;
+    return true;
+
+}
+
+void Network::HandleNATStartP2PSession(StringHash eventType, VariantMap& eventData)
+{
+    UnsubscribeFromEvent(E_NATMASTERCONNECTIONSUCCEEDED);
+    URHO3D_LOGINFO("HandleNATStartP2PSession");
     isServer_ = false;
     if (!serverConnection_) {
         serverConnection_ = new Connection(context_, false, rakPeer_->GetMyBoundAddress(), rakPeer_);
-        serverConnection_->SetScene(scene);
+        serverConnection_->SetScene(scene_);
         serverConnection_->SetSceneLoaded(true);
-        serverConnection_->SetIdentity(identity);
+        serverConnection_->SetIdentity(identity_);
         serverConnection_->SetConnectPending(true);
         serverConnection_->ConfigureNetworkSimulator(simulatedLatency_, simulatedPacketLoss_);
     }
-    rakPeer_->AttachPlugin(natPunchthroughServerClient_);
+    rakPeer_->SetOccasionalPing(true);
     fullyConnectedMesh2_->Clear();
     fullyConnectedMesh2_->ResetHostCalculation();
 
     hostGuid_ = P2PGetGUID();
     P2PSetReady(false);
-    return true;
 }
 
 void Network::P2PJoinSession(String guid, Scene* scene, const VariantMap& identity)
 {
+    if (!natPunchServerAddress_) {
+        URHO3D_LOGERROR("Set the NAT server info first!");
+        return;
+    }
+    P2PConnectNAT(natPunchServerAddress_->ToString(false), natPunchServerAddress_->GetPort());
     if (networkMode_ == SERVER_CLIENT) {
         URHO3D_LOGERROR("P2P sessions are not available for SERVER_CLIENT mode!");
         return;
     }
-    natPunchtroughAttempt_ = false;
-//    SetSimulatedLatency(500);
+
+    if (remoteGUID_) {
+        delete remoteGUID_;
+        remoteGUID_ = nullptr;
+    }
+    remoteGUID_ = new SLNet::RakNetGUID;
+    remoteGUID_->FromString(guid.CString());
+
+    scene_ = scene;
+    identity_ = identity;
+
+    UnsubscribeFromEvent(E_NATMASTERCONNECTIONSUCCEEDED);
+    SubscribeToEvent(E_NATMASTERCONNECTIONSUCCEEDED, URHO3D_HANDLER(Network, HandleNATJoinP2PSession));
+
+}
+
+void Network::HandleNATJoinP2PSession(StringHash eventType, VariantMap& eventData)
+{
+    UnsubscribeFromEvent(E_NATMASTERCONNECTIONSUCCEEDED);
+//    SetSimulatedLatency(Random(100.0f));
 //    SetSimulatedPacketLoss(0.3);
     P2PSetReady(false);
     if (!serverConnection_) {
         serverConnection_ = new Connection(context_, false, rakPeer_->GetMyBoundAddress(), rakPeer_);
-        serverConnection_->SetScene(scene);
+        serverConnection_->SetScene(scene_);
         serverConnection_->SetSceneLoaded(true);
-        serverConnection_->SetIdentity(identity);
+        serverConnection_->SetIdentity(identity_);
         serverConnection_->SetConnectPending(true);
         serverConnection_->ConfigureNetworkSimulator(simulatedLatency_, simulatedPacketLoss_);
     }
 
-    rakPeer_->AttachPlugin(natPunchthroughServerClient_);
+    rakPeer_->SetOccasionalPing(true);
     fullyConnectedMesh2_->ResetHostCalculation();
     fullyConnectedMesh2_->Clear();
-    SLNet::RakNetGUID remoteGUID;
-
-    remoteGUID.FromString(guid.CString());
-    URHO3D_LOGINFO("Attempting to Join P2P Session : " + guid);
-    natPunchthroughServerClient_->OpenNAT(remoteGUID, *natPunchServerAddress_);
+    URHO3D_LOGINFO("Attempting to Join P2P Session : " + String(remoteGUID_->ToString()));
+    natPunchthroughServerClient_->OpenNAT(*remoteGUID_, *natPunchServerAddress_);
 }
 
 int Network::GetP2PParticipantCount()
@@ -1541,32 +1584,6 @@ void Network::HandleTcpResponse()
     }
 }
 
-void Network::P2PSubscribeForReadyEvents() {
-    if (networkMode_ == SERVER_CLIENT) {
-        return;
-    }
-    URHO3D_LOGWARNING("P2PSubscribeForReadyEvents " + String(isServer_));
-    DataStructures::List<SLNet::RakNetGUID> participantList;
-    fullyConnectedMesh2_->GetParticipantList(participantList);
-    for (unsigned int i = 0; i < participantList.Size(); i++) {
-        if (participantList[i] != rakPeerClient_->GetMyGUID()) {
-            readyEvent_->AddToWaitList(0, participantList[i]);
-        }
-    }
-    P2PReadyStatusChanged();
-//    if (isServer_) {
-//    }
-//    else {
-//        DataStructures::List<SLNet::RakNetGUID> participantList;
-//        fullyConnectedMesh2_->GetParticipantList(participantList);
-//        for (unsigned int i = 0; i < participantList.Size(); i++) {
-//            if (participantList[i] != rakPeerClient_->GetMyGUID()) {
-//                readyEvent_->RemoveFromWaitList(0, participantList[i]);
-//            }
-//        }
-//    }
-}
-
 void Network::SetMode(NetworkMode mode, bool force)
 {
     if (rakPeer_->IsActive() || rakPeerClient_->IsActive()) {
@@ -1591,6 +1608,19 @@ const NetworkMode  Network::GetMode() const
     return networkMode_;
 }
 
+void Network::DisplayPingTimes()
+{
+    if (clientConnections_.Size() > 0) {
+        URHO3D_LOGINFO("-------- PING TIMES --------");
+        for (auto it = clientConnections_.Begin(); it != clientConnections_.End(); ++it) {
+            SLNet::AddressOrGUID address = (*it).second_->GetAddressOrGUID();
+            int ping = rakPeer_->GetLastPing(address);
+            URHO3D_LOGINFO((*it).second_->ToString() + " : " + String(ping));
+        }
+        URHO3D_LOGINFO("----------------------------");
+    }
+}
+
 void RegisterNetworkLibrary(Context* context)
 {
     NetworkPriority::RegisterObject(context);

+ 6 - 4
Source/Urho3D/Network/Network.h

@@ -77,8 +77,6 @@ public:
     bool P2PStartSession(Scene* scene, const VariantMap& identity = Variant::emptyVariantMap);
     /// Join existing P2P session
     void P2PJoinSession(String guid, Scene* scene, const VariantMap& identity = Variant::emptyVariantMap);
-    /// Subscribe for peer event handling
-    void P2PSubscribeForReadyEvents();
     /// Current peer count in session
     int GetP2PParticipantCount();
     /// Is host connected to the P2P session
@@ -170,11 +168,17 @@ public:
     /// Get current network mode
     const NetworkMode  GetMode() const;
 
+    void DisplayPingTimes();
+
 private:
     /// Handle begin frame event.
     void HandleBeginFrame(StringHash eventType, VariantMap& eventData);
     /// Handle render update frame event.
     void HandleRenderUpdate(StringHash eventType, VariantMap& eventData);
+    /// Start P2P session when connected to NAT master
+    void HandleNATStartP2PSession(StringHash eventType, VariantMap& eventData);
+    /// Join P2P session when connected to NAT master
+    void HandleNATJoinP2PSession(StringHash eventType, VariantMap& eventData);
     /// Handle server connection.
     void OnServerConnected(const SLNet::AddressOrGUID& address);
     /// Handle server disconnection.
@@ -229,8 +233,6 @@ private:
     SLNet::RakNetGUID* remoteGUID_;
     /// Local server GUID.
     String guid_;
-    /// Attempting NAT punchtrough
-    bool natPunchtroughAttempt_;
     /// Ready event for automated event handling in P2P connections
     SLNet::ReadyEvent *readyEvent_;
     /// P2P functionality

+ 3 - 0
Source/Urho3D/Network/NetworkEvents.h

@@ -143,16 +143,19 @@ URHO3D_EVENT(E_NATMASTERCONNECTIONSUCCEEDED, NetworkNatMasterConnectionSucceeded
     URHO3D_PARAM(P_PORT, Port);         // int
 }
 
+/// Http request returned response
 URHO3D_EVENT(E_HTTPREQUESTFINISHED, HttpRequestFinished)
 {
     URHO3D_PARAM(P_ADDRESS, Address);   // String
     URHO3D_PARAM(P_RESPONSE, Response);         // int
 }
 
+/// When P2P network declines our connection
 URHO3D_EVENT(E_P2PJOINREQUESTDENIED, P2PJoinRequestDenied)
 {
 }
 
+/// Status of all p2p connection readiness
 URHO3D_EVENT(E_P2PALLREADYCHANGED, P2PAllReadyChanged)
 {
 	URHO3D_PARAM(P_READY, Ready);   // String