/* * 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 Forwards UDP datagrams. Independent of RakNet's protocol. /// #include "NativeFeatureIncludes.h" #if _RAKNET_SUPPORT_UDPForwarder==1 #ifndef __UDP_FORWARDER_H #define __UDP_FORWARDER_H #include "Export.h" #include "RakNetTypes.h" #include "SocketIncludes.h" #include "UDPProxyCommon.h" #include "SimpleMutex.h" #include "RakString.h" #include "RakThread.h" #include "DS_Queue.h" #include "DS_OrderedList.h" #include "LocklessTypes.h" #include "DS_ThreadsafeAllocatingQueue.h" namespace RakNet { enum UDPForwarderResult { UDPFORWARDER_FORWARDING_ALREADY_EXISTS, UDPFORWARDER_NO_SOCKETS, UDPFORWARDER_BIND_FAILED, UDPFORWARDER_INVALID_PARAMETERS, UDPFORWARDER_NOT_RUNNING, UDPFORWARDER_SUCCESS, UDPFORWARDER_RESULT_COUNT }; /// \brief Forwards UDP datagrams. Independent of RakNet's protocol. /// \ingroup NAT_PUNCHTHROUGH_GROUP class RAK_DLL_EXPORT UDPForwarder { public: UDPForwarder(); virtual ~UDPForwarder(); /// Starts the system. /// Required to call before StartForwarding void Startup(void); /// Stops the system, and frees all sockets void Shutdown(void); /// Sets the maximum number of forwarding entries allowed /// Set according to your available bandwidth and the estimated average bandwidth per forwarded address. /// \param[in] maxEntries The maximum number of simultaneous forwarding entries. Defaults to 64 (32 connections) void SetMaxForwardEntries(unsigned short maxEntries); /// \return The \a maxEntries parameter passed to SetMaxForwardEntries(), or the default if it was never called int GetMaxForwardEntries(void) const; /// \return How many entries have been used int GetUsedForwardEntries(void) const; /// Forwards datagrams from source to destination, and vice-versa /// Does nothing if this forward entry already exists via a previous call /// \pre Call Startup() /// \note RakNet's protocol will ensure a message is sent at least every 15 seconds, so if routing RakNet messages, it is a reasonable value for timeoutOnNoDataMS, plus an some extra seconds for latency /// \param[in] source The source IP and port /// \param[in] destination Where to forward to (and vice-versa) /// \param[in] timeoutOnNoDataMS If no messages are forwarded for this many MS, then automatically remove this entry. /// \param[in] forceHostAddress Force binding on a particular address. 0 to use any. /// \param[in] socketFamily IP version: For IPV4, use AF_INET (default). For IPV6, use AF_INET6. To autoselect, use AF_UNSPEC. /// \param[out] forwardingPort New opened port for forwarding /// \param[out] forwardingSocket New opened socket for forwarding /// \return UDPForwarderResult UDPForwarderResult StartForwarding( SystemAddress source, SystemAddress destination, RakNet::TimeMS timeoutOnNoDataMS, const char *forceHostAddress, unsigned short socketFamily, unsigned short *forwardingPort, __UDPSOCKET__ *forwardingSocket); /// No longer forward datagrams from source to destination /// \param[in] source The source IP and port /// \param[in] destination Where to forward to void StopForwarding(SystemAddress source, SystemAddress destination); struct ForwardEntry { ForwardEntry(); ~ForwardEntry(); SystemAddress addr1Unconfirmed, addr2Unconfirmed, addr1Confirmed, addr2Confirmed; RakNet::TimeMS timeLastDatagramForwarded; __UDPSOCKET__ socket; RakNet::TimeMS timeoutOnNoDataMS; short socketFamily; }; protected: friend RAK_THREAD_DECLARATION(UpdateUDPForwarderGlobal); void UpdateUDPForwarder(void); void RecvFrom(RakNet::TimeMS curTime, ForwardEntry *forwardEntry); struct StartForwardingInputStruct { SystemAddress source; SystemAddress destination; RakNet::TimeMS timeoutOnNoDataMS; RakString forceHostAddress; unsigned short socketFamily; unsigned int inputId; }; DataStructures::ThreadsafeAllocatingQueue startForwardingInput; struct StartForwardingOutputStruct { unsigned short forwardingPort; __UDPSOCKET__ forwardingSocket; UDPForwarderResult result; unsigned int inputId; }; DataStructures::Queue startForwardingOutput; SimpleMutex startForwardingOutputMutex; struct StopForwardingStruct { SystemAddress source; SystemAddress destination; }; DataStructures::ThreadsafeAllocatingQueue stopForwardingCommands; unsigned int nextInputId; // New entries are added to forwardListNotUpdated DataStructures::List forwardListNotUpdated; // SimpleMutex forwardListNotUpdatedMutex; unsigned short maxForwardEntries; RakNet::LocklessUint32_t isRunning, threadRunning; }; } // End namespace #endif #endif // #if _RAKNET_SUPPORT_UDPForwarder==1