mirror of
https://github.com/dashr9230/SA-MP.git
synced 2024-12-22 14:37:29 +08:00
bcdbedc0be
* Add RakNet source files to the VS project
144 lines
6.9 KiB
C++
144 lines
6.9 KiB
C++
/// \file
|
|
/// \brief Contains the NAT-punchthrough plugin
|
|
///
|
|
/// This file is part of RakNet Copyright 2003 Kevin Jenkins.
|
|
///
|
|
/// Usage of RakNet is subject to the appropriate license agreement.
|
|
/// Creative Commons Licensees are subject to the
|
|
/// license found at
|
|
/// http://creativecommons.org/licenses/by-nc/2.5/
|
|
/// Single application licensees are subject to the license found at
|
|
/// http://www.rakkarsoft.com/SingleApplicationLicense.html
|
|
/// Custom license users are subject to the terms therein.
|
|
/// GPL license users are subject to the GNU General Public
|
|
/// License as published by the Free
|
|
/// Software Foundation; either version 2 of the License, or (at your
|
|
/// option) any later version.
|
|
|
|
#ifndef __NAT_PUNCHTHROUGH_H
|
|
#define __NAT_PUNCHTHROUGH_H
|
|
|
|
#include "NetworkTypes.h"
|
|
#include "Export.h"
|
|
#include "PluginInterface.h"
|
|
#include "PacketPriority.h"
|
|
#include "DS_List.h"
|
|
|
|
class RakPeerInterface;
|
|
struct Packet;
|
|
|
|
/// \defgroup NAT_PUNCHTHROUGH_GROUP NatPunchthrough
|
|
/// \ingroup PLUGINS_GROUP
|
|
|
|
/// \brief The NatPunchthrough class implements the NAT punch through technique, allowing two systems to connect to each other that are both behind NATs.
|
|
///
|
|
/// A NAT (Network Address Translator) is a system that will makes it so your system's IP address is different from the IP address exposed to the internet.
|
|
/// This provides some security and allows multiple computers, each with a different IP address, to share one IP address as seen by the internet.
|
|
///
|
|
/// The problem is that NATs also ignore packets sent to them unless they sent a packet to the sender first.
|
|
/// If two systems are both behind NATs, then neither system can connect to each other.
|
|
/// Furthermore, some NATs will impose a temporary ban on an IP address that send unsolicited packets to them.
|
|
///
|
|
/// This can be solved by using a third system, a facilitator, that is not behind a NAT and that both systems are already connected to.
|
|
/// It will synchronize a send between both NAT systems such that the routers will both consider themselves as handling a reply to a message, when in
|
|
/// fact they are handing an initial message. As replies are allowed, both systems get their corresponding messages and the connection takes place.
|
|
/// S = system that wants to connect
|
|
/// F = facilitator
|
|
/// R = system to get the connection request.
|
|
///
|
|
/// S knows IP of R in advance.
|
|
/// 1. S->F facilitate connection request to R
|
|
/// 2. if (R is not is connected) F->S ID_NAT_TARGET_NOT_CONNECTED. Exit.
|
|
/// 3. F -> (Ping S, Ping R), every X ms Y times. Wait Max(Ping(s), Ping(r) * multiple ms more, then go to step 4.
|
|
/// 4. F picks time highest(ave of Ping R,S) * N from now and sends this time RELIABLE and timestamped to R,S.
|
|
/// 5. At time picked in (4), S attempts to connect to R. R sends offline ping to S.
|
|
/// 6. If R disconnects before or at step 4, tell this to S via ID_NAT_TARGET_CONNECTION_LOST
|
|
///
|
|
/// \note Timing is important with this plugin. You need to call RakPeer::Receive frequently.
|
|
/// \ingroup NAT_PUNCHTHROUGH_GROUP
|
|
class RAK_DLL_EXPORT NatPunchthrough : public PluginInterface
|
|
{
|
|
public:
|
|
/// Constructor
|
|
NatPunchthrough();
|
|
|
|
/// Destructor
|
|
~NatPunchthrough();
|
|
|
|
/// Call with true to allow other systems to use this system as a NAT punch through facilitator. This takes a little bandwidth but
|
|
/// otherwise there is no reason to disallow it.
|
|
/// Defaults to true
|
|
/// \param[in] allow True to allow, false to disallow.
|
|
void FacilitateConnections(bool allow);
|
|
|
|
/// Call this to start to connect to the specified host (ip or domain name) and server port using \a facilitator to punch through a NAT
|
|
/// This is a non-blocking operation
|
|
/// You know the connection is successful when you get the message ID_CONNECTION_ACCEPTED.
|
|
/// You know the connection failed when you get the message ID_CONNECTION_ATTEMPT_FAILED, ID_CONNECTION_BANNED, or ID_NAT_TARGET_NOT_CONNECTED
|
|
/// Both you and the host must be connected to the facilitator.
|
|
/// \pre Requires that you first call Initialize
|
|
/// \pre Both \a host and this system must already be connected to the system at the address \a facilitator and facilitator must be running NatPunchthrough with FacilitateConnections(true) previously called.
|
|
/// \param[in] receiver Either a dotted IP address or a domain name of the system you ultimately want to connect to.
|
|
/// \param[in] remotePort Which port to connect to of the system you ultimately want to connect to.
|
|
/// \param[in] passwordData A data block that must match the data block on the \a host. This can be just a password, or can be a stream of data
|
|
/// \param[in] passwordDataLength The length in bytes of passwordData
|
|
/// \return If you are not connected to the facilitator this function returns false. Otherwise it returns true.
|
|
bool Connect(const char* receiver, unsigned short remotePort, char* passwordData, int passwordDataLength, PlayerID facilitator);
|
|
|
|
/// Same as above, but takes a PlayerID for a host
|
|
/// \param[in] receiver The address of the host to connect to.
|
|
/// \param[in] remotePort Which port to connect to of the system you ultimately want to connect to.
|
|
/// \param[in] passwordData A data block that must match the data block on the \a host. This can be just a password, or can be a stream of data
|
|
/// \param[in] passwordDataLength The length in bytes of passwordData
|
|
/// \return If you are not connected to the facilitator this function returns false. Otherwise it returns true.
|
|
bool Connect(PlayerID receiver, char* passwordData, int passwordDataLength, PlayerID facilitator);
|
|
|
|
/// Free internal memory.
|
|
void Clear(void);
|
|
|
|
/// \internal For plugin handling
|
|
virtual void OnAttach(RakPeerInterface *peer);
|
|
/// \internal For plugin handling
|
|
virtual void Update(RakPeerInterface *peer);
|
|
/// \internal For plugin handling
|
|
virtual PluginReceiveResult OnReceive(RakPeerInterface *peer, Packet *packet);
|
|
/// \internal For plugin handling
|
|
virtual void OnDisconnect(RakPeerInterface *peer);
|
|
/// \internal For plugin handling
|
|
virtual void OnCloseConnection(RakPeerInterface *peer, PlayerID playerId);
|
|
|
|
struct ConnectionRequest
|
|
{
|
|
// Used by all
|
|
// 0 means unset. non-zero means send a connection request or offline message at that time.
|
|
// If the sender is set, then we send an offline message. If the reciever is set, we send a connection request.
|
|
RakNetTime nextActionTime;
|
|
|
|
// Used by sender and facilitator
|
|
bool facilitatingConnection;
|
|
PlayerID receiver;
|
|
// Used to remove old connection Requests
|
|
RakNetTime timeoutTime;
|
|
|
|
// Used only by sender
|
|
PlayerID facilitator;
|
|
char* passwordData;
|
|
int passwordDataLength;
|
|
|
|
// Used only by facilitator
|
|
PlayerID sender;
|
|
unsigned char pingCount;
|
|
};
|
|
protected:
|
|
void OnPunchthroughRequest(RakPeerInterface *peer, Packet *packet);
|
|
void OnConnectAtTime(RakPeerInterface *peer, Packet *packet);
|
|
void OnSendOfflineMessageAtTime(RakPeerInterface *peer, Packet *packet);
|
|
PluginReceiveResult RemoveRequestByFacilitator(PlayerID playerId);
|
|
|
|
bool allowFacilitation;
|
|
RakPeerInterface *rakPeer;
|
|
DataStructures::List<ConnectionRequest*> connectionRequestList;
|
|
};
|
|
|
|
#endif
|