/* * Copyright (c) 2014, Oculus VR, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * */ /// \file /// \brief Contains the NAT-punchthrough plugin for the server. /// #include "NativeFeatureIncludes.hpp" #if _RAKNET_SUPPORT_NatPunchthroughServer==1 #ifndef __NAT_PUNCHTHROUGH_SERVER_H #define __NAT_PUNCHTHROUGH_SERVER_H #include "RakNetTypes.hpp" #include "Export.hpp" #include "PluginInterface2.hpp" #include "PacketPriority.hpp" #include "SocketIncludes.hpp" #include "DS_OrderedList.hpp" #include "RakString.hpp" namespace RakNet { /// Forward declarations class RakPeerInterface; struct Packet; #if _RAKNET_SUPPORT_PacketLogger==1 class PacketLogger; #endif /// \defgroup NAT_PUNCHTHROUGH_GROUP NatPunchthrough /// \brief Connect systems despite both systems being behind a router /// \details /// \ingroup PLUGINS_GROUP /// \ingroup NAT_PUNCHTHROUGH_GROUP struct RAK_DLL_EXPORT NatPunchthroughServerDebugInterface { NatPunchthroughServerDebugInterface() {} virtual ~NatPunchthroughServerDebugInterface() {} virtual void OnServerMessage(const char *msg)=0; }; /// \ingroup NAT_PUNCHTHROUGH_GROUP struct RAK_DLL_EXPORT NatPunchthroughServerDebugInterface_Printf : public NatPunchthroughServerDebugInterface { virtual void OnServerMessage(const char *msg); }; #if _RAKNET_SUPPORT_PacketLogger==1 /// \ingroup NAT_PUNCHTHROUGH_GROUP struct RAK_DLL_EXPORT NatPunchthroughServerDebugInterface_PacketLogger : public NatPunchthroughServerDebugInterface { // Set to non-zero to write to the packetlogger! PacketLogger *pl; NatPunchthroughServerDebugInterface_PacketLogger() {pl=0;} ~NatPunchthroughServerDebugInterface_PacketLogger() {} virtual void OnServerMessage(const char *msg); }; #endif /// \brief Server code for NATPunchthrough /// \details Maintain connection to NatPunchthroughServer to process incoming connection attempts through NatPunchthroughClient
/// Server maintains two sockets clients can connect to so as to estimate the next port choice
/// Server tells other client about port estimate, current public port to the server, and a time to start connection attempts /// \sa NatTypeDetectionClient /// See also http://www.jenkinssoftware.com/raknet/manual/natpunchthrough.html /// \ingroup NAT_PUNCHTHROUGH_GROUP class RAK_DLL_EXPORT NatPunchthroughServer : public PluginInterface2 { public: STATIC_FACTORY_DECLARATIONS(NatPunchthroughServer) // Constructor NatPunchthroughServer(); // Destructor virtual ~NatPunchthroughServer(); /// Sets a callback to be called with debug messages /// \param[in] i Pointer to an interface. The pointer is stored, so don't delete it while in progress. Pass 0 to clear. void SetDebugInterface(NatPunchthroughServerDebugInterface *i); /// \internal For plugin handling virtual void Update(void); /// \internal For plugin handling virtual PluginReceiveResult OnReceive(Packet *packet); /// \internal For plugin handling virtual void OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason ); virtual void OnNewConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, bool isIncoming); // Each connected user has a ready state. Ready means ready for nat punchthrough. struct User; struct ConnectionAttempt { ConnectionAttempt() {sender=0; recipient=0; startTime=0; attemptPhase=NAT_ATTEMPT_PHASE_NOT_STARTED;} User *sender, *recipient; uint16_t sessionId; RakNet::Time startTime; enum { NAT_ATTEMPT_PHASE_NOT_STARTED, NAT_ATTEMPT_PHASE_GETTING_RECENT_PORTS, } attemptPhase; }; struct User { RakNetGUID guid; SystemAddress systemAddress; unsigned short mostRecentPort; bool isReady; DataStructures::OrderedList groupPunchthroughRequests; DataStructures::List connectionAttempts; bool HasConnectionAttemptToUser(User *user); void DerefConnectionAttempt(ConnectionAttempt *ca); void DeleteConnectionAttempt(ConnectionAttempt *ca); void LogConnectionAttempts(RakNet::RakString &rs); }; RakNet::Time lastUpdate; static int NatPunchthroughUserComp( const RakNetGUID &key, User * const &data ); protected: void OnNATPunchthroughRequest(Packet *packet); DataStructures::OrderedList users; void OnGetMostRecentPort(Packet *packet); void OnClientReady(Packet *packet); void SendTimestamps(void); void StartPendingPunchthrough(void); void StartPunchthroughForUser(User*user); uint16_t sessionId; NatPunchthroughServerDebugInterface *natPunchthroughServerDebugInterface; SystemAddress boundAddresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS]; unsigned char boundAddressCount; }; } // namespace RakNet #endif #endif // _RAKNET_SUPPORT_*