NatPunchthrough Class Reference
[NatPunchthrough]

The NatPunchthrough class implements the NAT punch through technique, allowing two systems to connect to each other that are both behind NATs. More...

#include <NatPunchthrough.h>

Inheritance diagram for NatPunchthrough:

PluginInterface

List of all members.

Public Member Functions

 NatPunchthrough ()
 Constructor.
virtual ~NatPunchthrough ()
 Destructor.
void FacilitateConnections (bool allow)
bool Connect (const char *destination, unsigned short remotePort, const char *passwordData, int passwordDataLength, SystemAddress facilitator)
bool Connect (SystemAddress destination, const char *passwordData, int passwordDataLength, SystemAddress facilitator)
void Clear (void)
 Free internal memory.
void SetLogger (NatPunchthroughLogger *l)
 Sets the log output to print messages to.
unsigned short GetLastPortUsedToConnect (void) const
virtual void OnAttach (RakPeerInterface *peer)
virtual void Update (RakPeerInterface *peer)
virtual PluginReceiveResult OnReceive (RakPeerInterface *peer, Packet *packet)
virtual void OnShutdown (RakPeerInterface *peer)
virtual void OnCloseConnection (RakPeerInterface *peer, SystemAddress systemAddress)


Detailed Description

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

Rebinding instances of RakPeer: If after connecting two instances of RakPeer, you want to use the now open ports on the router with another instance of RakPeer, follow these steps A. Connect the two systems by NAT punchthrough. Store the IP address of the system you connected to. You can get this with SystemAddress::ToString(false) B. Once you get ID_CONNECTION_REQUEST_ACCEPTED or ID_NEW_INCOMING_CONNECTION, call RakPeer::Shutdown(0). This will stop RakNet without telling the other system. C. Wait about double the ping time to make sure the other system had the opportunity to call RakPeer::Shutdown(0). D. Recreate on the receiver the instance of RakPeer, in the new application. If you originally used port 1234, call Startup() again with that port. If you used port 0, you will need to know what port the socket was bound on. Use GetInternalID(UNASSIGNED_SYSTEM_ADDRESS).port anytime after calling Startup() E. Recreate on the sender the instance of RakPeer in the new application, using the same port as originally used in the last instance of RakPeer on the sender. F. Connect the sender to the receiver, using the port returned by NatPunchthrough::GetLastPortUsedToConnect()

Note:
Timing is important with this plugin. You need to call RakPeer::Receive frequently.

Member Function Documentation

bool NatPunchthrough::Connect ( SystemAddress  destination,
const char *  passwordData,
int  passwordDataLength,
SystemAddress  facilitator 
)

Same as above, but takes a SystemAddress for a host

Parameters:
[in] destination The address of the host to connect to.
[in] remotePort Which port to connect to of the system you ultimately want to connect to.
[in] passwordData A data block that must match the data block on the host. This can be just a password, or can be a stream of data
[in] passwordDataLength The length in bytes of passwordData
Returns:
If you are not connected to the facilitator this function returns false. Otherwise it returns true.

bool NatPunchthrough::Connect ( const char *  destination,
unsigned short  remotePort,
const char *  passwordData,
int  passwordDataLength,
SystemAddress  facilitator 
)

Call this to start to connect to the specified host (ip or domain name) and server port using 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.

Precondition:
Requires that you first call Initialize

Both host and this system must already be connected to the system at the address facilitator and facilitator must be running NatPunchthrough with FacilitateConnections(true) previously called.

Parameters:
[in] destination Either a dotted IP address or a domain name of the system you ultimately want to connect to.
[in] remotePort Which port to connect to of the system you ultimately want to connect to.
[in] passwordData A data block that must match the data block on the host. This can be just a password, or can be a stream of data
[in] passwordDataLength The length in bytes of passwordData
Returns:
If you are not connected to the facilitator this function returns false. Otherwise it returns true.

void NatPunchthrough::FacilitateConnections ( bool  allow  ) 

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

Parameters:
[in] allow True to allow, false to disallow.

unsigned short NatPunchthrough::GetLastPortUsedToConnect ( void   )  const

Returns the last port we tried to connect on. If at some point we get ID_CONNECTION_REQUEST_ACCEPTED, the remote router should be open on this port, and should forward messages send on this port to the remotely bound port. Returns 0 if none.

void NatPunchthrough::OnAttach ( RakPeerInterface peer  )  [virtual]

Called when the interface is attached

Parameters:
[in] peer the instance of RakPeer that is calling Receive

Reimplemented from PluginInterface.

void NatPunchthrough::OnCloseConnection ( RakPeerInterface peer,
SystemAddress  systemAddress 
) [virtual]

Called when a connection is dropped because the user called RakPeer::CloseConnection() for a particular system

Parameters:
[in] peer the instance of RakPeer that is calling Receive
[in] systemAddress The system whose connection was closed

Reimplemented from PluginInterface.

PluginReceiveResult NatPunchthrough::OnReceive ( RakPeerInterface peer,
Packet packet 
) [virtual]

OnReceive is called for every packet.

Parameters:
[in] peer the instance of RakPeer that is calling Receive
[in] packet the packet that is being returned to the user
Returns:
True to allow the game and other plugins to get this message, false to absorb it

Reimplemented from PluginInterface.

void NatPunchthrough::OnShutdown ( RakPeerInterface peer  )  [virtual]

Called when RakPeer is shutdown

Parameters:
[in] peer the instance of RakPeer that is calling Receive

Reimplemented from PluginInterface.

void NatPunchthrough::Update ( RakPeerInterface peer  )  [virtual]

Update is called every time a packet is checked for .

Parameters:
[in] peer - the instance of RakPeer that is calling Receive

Reimplemented from PluginInterface.


The documentation for this class was generated from the following files:

Generated on Tue Feb 10 08:44:07 2009 for RakNet by  doxygen 1.5.7.1