mirror of
https://github.com/celisej567/mcpe.git
synced 2025-12-31 17:49:17 +03:00
625 lines
20 KiB
C++
625 lines
20 KiB
C++
/*
|
|
* 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.
|
|
*
|
|
*/
|
|
|
|
#include "NativeFeatureIncludes.h"
|
|
#if _RAKNET_SUPPORT_NatPunchthroughServer==1
|
|
|
|
#include "NatPunchthroughServer.h"
|
|
#include "SocketLayer.h"
|
|
#include "BitStream.h"
|
|
#include "MessageIdentifiers.h"
|
|
#include "RakPeerInterface.h"
|
|
#include "MTUSize.h"
|
|
#include "GetTime.h"
|
|
#include "PacketLogger.h"
|
|
|
|
using namespace RakNet;
|
|
|
|
void NatPunchthroughServerDebugInterface_Printf::OnServerMessage(const char *msg)
|
|
{
|
|
printf("%s\n", msg);
|
|
}
|
|
#if _RAKNET_SUPPORT_PacketLogger==1
|
|
void NatPunchthroughServerDebugInterface_PacketLogger::OnServerMessage(const char *msg)
|
|
{
|
|
if (pl)
|
|
{
|
|
pl->WriteMiscellaneous("Nat", msg);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void NatPunchthroughServer::User::DeleteConnectionAttempt(NatPunchthroughServer::ConnectionAttempt *ca)
|
|
{
|
|
unsigned int index = connectionAttempts.GetIndexOf(ca);
|
|
if ((unsigned int)index!=(unsigned int)-1)
|
|
{
|
|
RakNet::OP_DELETE(ca,_FILE_AND_LINE_);
|
|
connectionAttempts.RemoveAtIndex(index);
|
|
}
|
|
}
|
|
void NatPunchthroughServer::User::DerefConnectionAttempt(NatPunchthroughServer::ConnectionAttempt *ca)
|
|
{
|
|
unsigned int index = connectionAttempts.GetIndexOf(ca);
|
|
if ((unsigned int)index!=(unsigned int)-1)
|
|
{
|
|
connectionAttempts.RemoveAtIndex(index);
|
|
}
|
|
}
|
|
bool NatPunchthroughServer::User::HasConnectionAttemptToUser(User *user)
|
|
{
|
|
unsigned int index;
|
|
for (index=0; index < connectionAttempts.Size(); index++)
|
|
{
|
|
if (connectionAttempts[index]->recipient->guid==user->guid ||
|
|
connectionAttempts[index]->sender->guid==user->guid)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
void NatPunchthroughServer::User::LogConnectionAttempts(RakNet::RakString &rs)
|
|
{
|
|
rs.Clear();
|
|
unsigned int index;
|
|
char guidStr[128], ipStr[128];
|
|
guid.ToString(guidStr);
|
|
systemAddress.ToString(true,ipStr);
|
|
rs=RakNet::RakString("User systemAddress=%s guid=%s\n", ipStr, guidStr);
|
|
rs+=RakNet::RakString("%i attempts in list:\n", connectionAttempts.Size());
|
|
for (index=0; index < connectionAttempts.Size(); index++)
|
|
{
|
|
rs+=RakNet::RakString("%i. SessionID=%i ", index+1, connectionAttempts[index]->sessionId);
|
|
if (connectionAttempts[index]->sender==this)
|
|
rs+="(We are sender) ";
|
|
else
|
|
rs+="(We are recipient) ";
|
|
if (isReady)
|
|
rs+="(READY TO START) ";
|
|
else
|
|
rs+="(NOT READY TO START) ";
|
|
if (connectionAttempts[index]->attemptPhase==NatPunchthroughServer::ConnectionAttempt::NAT_ATTEMPT_PHASE_NOT_STARTED)
|
|
rs+="(NOT_STARTED). ";
|
|
else
|
|
rs+="(GETTING_RECENT_PORTS). ";
|
|
if (connectionAttempts[index]->sender==this)
|
|
{
|
|
connectionAttempts[index]->recipient->guid.ToString(guidStr);
|
|
connectionAttempts[index]->recipient->systemAddress.ToString(true,ipStr);
|
|
}
|
|
else
|
|
{
|
|
connectionAttempts[index]->sender->guid.ToString(guidStr);
|
|
connectionAttempts[index]->sender->systemAddress.ToString(true,ipStr);
|
|
}
|
|
|
|
rs+=RakNet::RakString("Target systemAddress=%s, guid=%s.\n", ipStr, guidStr);
|
|
}
|
|
}
|
|
|
|
int RakNet::NatPunchthroughServer::NatPunchthroughUserComp( const RakNetGUID &key, User * const &data )
|
|
{
|
|
if (key < data->guid)
|
|
return -1;
|
|
if (key > data->guid)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
STATIC_FACTORY_DEFINITIONS(NatPunchthroughServer,NatPunchthroughServer);
|
|
|
|
NatPunchthroughServer::NatPunchthroughServer()
|
|
{
|
|
lastUpdate=0;
|
|
sessionId=0;
|
|
natPunchthroughServerDebugInterface=0;
|
|
for (int i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
|
|
boundAddresses[i]=UNASSIGNED_SYSTEM_ADDRESS;
|
|
boundAddressCount=0;
|
|
}
|
|
NatPunchthroughServer::~NatPunchthroughServer()
|
|
{
|
|
User *user, *otherUser;
|
|
ConnectionAttempt *connectionAttempt;
|
|
unsigned int j;
|
|
while(users.Size())
|
|
{
|
|
user = users[0];
|
|
for (j=0; j < user->connectionAttempts.Size(); j++)
|
|
{
|
|
connectionAttempt=user->connectionAttempts[j];
|
|
if (connectionAttempt->sender==user)
|
|
otherUser=connectionAttempt->recipient;
|
|
else
|
|
otherUser=connectionAttempt->sender;
|
|
otherUser->DeleteConnectionAttempt(connectionAttempt);
|
|
}
|
|
RakNet::OP_DELETE(user,_FILE_AND_LINE_);
|
|
users[0]=users[users.Size()-1];
|
|
users.RemoveAtIndex(users.Size()-1);
|
|
}
|
|
}
|
|
void NatPunchthroughServer::SetDebugInterface(NatPunchthroughServerDebugInterface *i)
|
|
{
|
|
natPunchthroughServerDebugInterface=i;
|
|
}
|
|
void NatPunchthroughServer::Update(void)
|
|
{
|
|
ConnectionAttempt *connectionAttempt;
|
|
User *user, *recipient;
|
|
unsigned int i,j;
|
|
RakNet::Time time = RakNet::GetTime();
|
|
if (time > lastUpdate+250)
|
|
{
|
|
lastUpdate=time;
|
|
|
|
for (i=0; i < users.Size(); i++)
|
|
{
|
|
user=users[i];
|
|
for (j=0; j < user->connectionAttempts.Size(); j++)
|
|
{
|
|
connectionAttempt=user->connectionAttempts[j];
|
|
if (connectionAttempt->sender==user)
|
|
{
|
|
if (connectionAttempt->attemptPhase!=ConnectionAttempt::NAT_ATTEMPT_PHASE_NOT_STARTED &&
|
|
time > connectionAttempt->startTime &&
|
|
time > 10000 + connectionAttempt->startTime ) // Formerly 5000, but sometimes false positives
|
|
{
|
|
RakNet::BitStream outgoingBs;
|
|
|
|
// that other system might not be running the plugin
|
|
outgoingBs.Write((MessageID)ID_NAT_TARGET_UNRESPONSIVE);
|
|
outgoingBs.Write(connectionAttempt->recipient->guid);
|
|
outgoingBs.Write(connectionAttempt->sessionId);
|
|
rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,connectionAttempt->sender->systemAddress,false);
|
|
|
|
// 05/28/09 Previously only told sender about ID_NAT_CONNECTION_TO_TARGET_LOST
|
|
// However, recipient may be expecting it due to external code
|
|
// In that case, recipient would never get any response if the sender dropped
|
|
outgoingBs.Reset();
|
|
outgoingBs.Write((MessageID)ID_NAT_TARGET_UNRESPONSIVE);
|
|
outgoingBs.Write(connectionAttempt->sender->guid);
|
|
outgoingBs.Write(connectionAttempt->sessionId);
|
|
rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,connectionAttempt->recipient->systemAddress,false);
|
|
|
|
connectionAttempt->sender->isReady=true;
|
|
connectionAttempt->recipient->isReady=true;
|
|
recipient=connectionAttempt->recipient;
|
|
|
|
|
|
if (natPunchthroughServerDebugInterface)
|
|
{
|
|
char str[1024];
|
|
char addr1[128], addr2[128];
|
|
// 8/01/09 Fixed bug where this was after DeleteConnectionAttempt()
|
|
connectionAttempt->sender->systemAddress.ToString(true,addr1);
|
|
connectionAttempt->recipient->systemAddress.ToString(true,addr2);
|
|
sprintf(str, "Sending ID_NAT_TARGET_UNRESPONSIVE to sender %s and recipient %s.", addr1, addr2);
|
|
natPunchthroughServerDebugInterface->OnServerMessage(str);
|
|
RakNet::RakString log;
|
|
connectionAttempt->sender->LogConnectionAttempts(log);
|
|
connectionAttempt->recipient->LogConnectionAttempts(log);
|
|
}
|
|
|
|
|
|
connectionAttempt->sender->DerefConnectionAttempt(connectionAttempt);
|
|
connectionAttempt->recipient->DeleteConnectionAttempt(connectionAttempt);
|
|
|
|
StartPunchthroughForUser(user);
|
|
StartPunchthroughForUser(recipient);
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
PluginReceiveResult NatPunchthroughServer::OnReceive(Packet *packet)
|
|
{
|
|
switch (packet->data[0])
|
|
{
|
|
case ID_NAT_PUNCHTHROUGH_REQUEST:
|
|
OnNATPunchthroughRequest(packet);
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
case ID_NAT_GET_MOST_RECENT_PORT:
|
|
OnGetMostRecentPort(packet);
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
case ID_NAT_CLIENT_READY:
|
|
OnClientReady(packet);
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
case ID_NAT_REQUEST_BOUND_ADDRESSES:
|
|
{
|
|
RakNet::BitStream outgoingBs;
|
|
outgoingBs.Write((MessageID)ID_NAT_RESPOND_BOUND_ADDRESSES);
|
|
|
|
if (boundAddresses[0]==UNASSIGNED_SYSTEM_ADDRESS)
|
|
{
|
|
DataStructures::List<RakNetSocket2* > sockets;
|
|
rakPeerInterface->GetSockets(sockets);
|
|
for (int i=0; i < sockets.Size() && i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
|
|
{
|
|
boundAddresses[i]=sockets[i]->GetBoundAddress();
|
|
boundAddressCount++;
|
|
}
|
|
}
|
|
|
|
outgoingBs.Write(boundAddressCount);
|
|
for (int i=0; i < boundAddressCount; i++)
|
|
{
|
|
outgoingBs.Write(boundAddresses[i]);
|
|
}
|
|
|
|
rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false);
|
|
}
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
case ID_NAT_PING:
|
|
{
|
|
}
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
case ID_OUT_OF_BAND_INTERNAL:
|
|
if (packet->length>=2 && packet->data[1]==ID_NAT_PING)
|
|
{
|
|
RakNet::BitStream bs(packet->data,packet->length,false);
|
|
bs.IgnoreBytes(sizeof(MessageID)*2);
|
|
uint16_t externalPort;
|
|
bs.Read(externalPort);
|
|
|
|
RakNet::BitStream outgoingBs;
|
|
outgoingBs.Write((MessageID)ID_NAT_PONG);
|
|
outgoingBs.Write(externalPort);
|
|
uint16_t externalPort2 = packet->systemAddress.GetPort();
|
|
outgoingBs.Write(externalPort2);
|
|
rakPeerInterface->SendOutOfBand((const char*) packet->systemAddress.ToString(false),packet->systemAddress.GetPort(),(const char*) outgoingBs.GetData(),outgoingBs.GetNumberOfBytesUsed());
|
|
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
}
|
|
}
|
|
return RR_CONTINUE_PROCESSING;
|
|
}
|
|
void NatPunchthroughServer::OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
|
|
{
|
|
(void) lostConnectionReason;
|
|
(void) systemAddress;
|
|
|
|
unsigned int i=0;
|
|
bool objectExists;
|
|
i = users.GetIndexFromKey(rakNetGUID, &objectExists);
|
|
if (objectExists)
|
|
{
|
|
RakNet::BitStream outgoingBs;
|
|
DataStructures::List<User *> freedUpInProgressUsers;
|
|
User *user = users[i];
|
|
User *otherUser;
|
|
unsigned int connectionAttemptIndex;
|
|
ConnectionAttempt *connectionAttempt;
|
|
for (connectionAttemptIndex=0; connectionAttemptIndex < user->connectionAttempts.Size(); connectionAttemptIndex++)
|
|
{
|
|
connectionAttempt=user->connectionAttempts[connectionAttemptIndex];
|
|
outgoingBs.Reset();
|
|
if (connectionAttempt->recipient==user)
|
|
{
|
|
otherUser=connectionAttempt->sender;
|
|
}
|
|
else
|
|
{
|
|
otherUser=connectionAttempt->recipient;
|
|
}
|
|
|
|
// 05/28/09 Previously only told sender about ID_NAT_CONNECTION_TO_TARGET_LOST
|
|
// However, recipient may be expecting it due to external code
|
|
// In that case, recipient would never get any response if the sender dropped
|
|
outgoingBs.Write((MessageID)ID_NAT_CONNECTION_TO_TARGET_LOST);
|
|
outgoingBs.Write(rakNetGUID);
|
|
outgoingBs.Write(connectionAttempt->sessionId);
|
|
rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,otherUser->systemAddress,false);
|
|
|
|
// 4/22/09 - Bug: was checking inProgress, legacy variable not used elsewhere
|
|
if (connectionAttempt->attemptPhase==ConnectionAttempt::NAT_ATTEMPT_PHASE_GETTING_RECENT_PORTS)
|
|
{
|
|
otherUser->isReady=true;
|
|
freedUpInProgressUsers.Insert(otherUser, _FILE_AND_LINE_ );
|
|
}
|
|
|
|
otherUser->DeleteConnectionAttempt(connectionAttempt);
|
|
}
|
|
|
|
RakNet::OP_DELETE(users[i], _FILE_AND_LINE_);
|
|
users.RemoveAtIndex(i);
|
|
|
|
for (i=0; i < freedUpInProgressUsers.Size(); i++)
|
|
{
|
|
StartPunchthroughForUser(freedUpInProgressUsers[i]);
|
|
}
|
|
}
|
|
|
|
/*
|
|
// Also remove from groupPunchthroughRequests
|
|
for (i=0; i < users.Size(); i++)
|
|
{
|
|
bool objectExists;
|
|
unsigned int gprIndex;
|
|
gprIndex = users[i]->groupPunchthroughRequests.GetIndexFromKey(rakNetGUID, &objectExists);
|
|
if (objectExists)
|
|
{
|
|
// printf("DEBUG %i\n", __LINE__);
|
|
|
|
RakNet::BitStream outgoingBs;
|
|
outgoingBs.Write((MessageID)ID_NAT_TARGET_NOT_CONNECTED);
|
|
outgoingBs.Write(rakNetGUID);
|
|
rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,users[i]->systemAddress,false);
|
|
|
|
users[i]->groupPunchthroughRequests.RemoveAtIndex(gprIndex);
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
void NatPunchthroughServer::OnNewConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, bool isIncoming)
|
|
{
|
|
(void) systemAddress;
|
|
(void) isIncoming;
|
|
|
|
User *user = RakNet::OP_NEW<User>(_FILE_AND_LINE_);
|
|
user->guid=rakNetGUID;
|
|
user->mostRecentPort=0;
|
|
user->systemAddress=systemAddress;
|
|
user->isReady=true;
|
|
users.Insert(rakNetGUID, user, true, _FILE_AND_LINE_);
|
|
|
|
// printf("Adding to users %s\n", rakNetGUID.ToString());
|
|
// printf("DEBUG users[0] guid=%s\n", users[0]->guid.ToString());
|
|
}
|
|
void NatPunchthroughServer::OnNATPunchthroughRequest(Packet *packet)
|
|
{
|
|
RakNet::BitStream outgoingBs;
|
|
RakNet::BitStream incomingBs(packet->data, packet->length, false);
|
|
incomingBs.IgnoreBytes(sizeof(MessageID));
|
|
RakNetGUID recipientGuid, senderGuid;
|
|
incomingBs.Read(recipientGuid);
|
|
senderGuid=packet->guid;
|
|
unsigned int i;
|
|
bool objectExists;
|
|
i = users.GetIndexFromKey(senderGuid, &objectExists);
|
|
RakAssert(objectExists);
|
|
|
|
ConnectionAttempt *ca = RakNet::OP_NEW<ConnectionAttempt>(_FILE_AND_LINE_);
|
|
ca->sender=users[i];
|
|
ca->sessionId=sessionId++;
|
|
i = users.GetIndexFromKey(recipientGuid, &objectExists);
|
|
if (objectExists==false || ca->sender == ca->recipient)
|
|
{
|
|
// printf("DEBUG %i\n", __LINE__);
|
|
// printf("DEBUG recipientGuid=%s\n", recipientGuid.ToString());
|
|
// printf("DEBUG users[0] guid=%s\n", users[0]->guid.ToString());
|
|
|
|
outgoingBs.Write((MessageID)ID_NAT_TARGET_NOT_CONNECTED);
|
|
outgoingBs.Write(recipientGuid);
|
|
rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false);
|
|
RakNet::OP_DELETE(ca,_FILE_AND_LINE_);
|
|
return;
|
|
}
|
|
ca->recipient=users[i];
|
|
if (ca->recipient->HasConnectionAttemptToUser(ca->sender))
|
|
{
|
|
outgoingBs.Write((MessageID)ID_NAT_ALREADY_IN_PROGRESS);
|
|
outgoingBs.Write(recipientGuid);
|
|
rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false);
|
|
RakNet::OP_DELETE(ca,_FILE_AND_LINE_);
|
|
return;
|
|
}
|
|
|
|
ca->sender->connectionAttempts.Insert(ca, _FILE_AND_LINE_ );
|
|
ca->recipient->connectionAttempts.Insert(ca, _FILE_AND_LINE_ );
|
|
|
|
StartPunchthroughForUser(ca->sender);
|
|
}
|
|
void NatPunchthroughServer::OnClientReady(Packet *packet)
|
|
{
|
|
unsigned int i;
|
|
bool objectExists;
|
|
i = users.GetIndexFromKey(packet->guid, &objectExists);
|
|
if (objectExists)
|
|
{
|
|
users[i]->isReady=true;
|
|
StartPunchthroughForUser(users[i]);
|
|
}
|
|
}
|
|
void NatPunchthroughServer::OnGetMostRecentPort(Packet *packet)
|
|
{
|
|
RakNet::BitStream bsIn(packet->data, packet->length, false);
|
|
bsIn.IgnoreBytes(sizeof(MessageID));
|
|
uint16_t sessionId;
|
|
unsigned short mostRecentPort;
|
|
bsIn.Read(sessionId);
|
|
bsIn.Read(mostRecentPort);
|
|
|
|
unsigned int i,j;
|
|
User *user;
|
|
ConnectionAttempt *connectionAttempt;
|
|
bool objectExists;
|
|
i = users.GetIndexFromKey(packet->guid, &objectExists);
|
|
|
|
if (natPunchthroughServerDebugInterface)
|
|
{
|
|
RakNet::RakString log;
|
|
char addr1[128], addr2[128];
|
|
packet->systemAddress.ToString(true,addr1);
|
|
packet->guid.ToString(addr2);
|
|
log=RakNet::RakString("Got ID_NAT_GET_MOST_RECENT_PORT from systemAddress %s guid %s. port=%i. sessionId=%i. userFound=%i.", addr1, addr2, mostRecentPort, sessionId, objectExists);
|
|
natPunchthroughServerDebugInterface->OnServerMessage(log.C_String());
|
|
}
|
|
|
|
if (objectExists)
|
|
{
|
|
user=users[i];
|
|
user->mostRecentPort=mostRecentPort;
|
|
RakNet::Time time = RakNet::GetTime();
|
|
|
|
for (j=0; j < user->connectionAttempts.Size(); j++)
|
|
{
|
|
connectionAttempt=user->connectionAttempts[j];
|
|
if (connectionAttempt->attemptPhase==ConnectionAttempt::NAT_ATTEMPT_PHASE_GETTING_RECENT_PORTS &&
|
|
connectionAttempt->sender->mostRecentPort!=0 &&
|
|
connectionAttempt->recipient->mostRecentPort!=0 &&
|
|
// 04/29/08 add sessionId to prevent processing for other systems
|
|
connectionAttempt->sessionId==sessionId)
|
|
{
|
|
SystemAddress senderSystemAddress = connectionAttempt->sender->systemAddress;
|
|
SystemAddress recipientSystemAddress = connectionAttempt->recipient->systemAddress;
|
|
SystemAddress recipientTargetAddress = recipientSystemAddress;
|
|
SystemAddress senderTargetAddress = senderSystemAddress;
|
|
recipientTargetAddress.SetPortHostOrder(connectionAttempt->recipient->mostRecentPort);
|
|
senderTargetAddress.SetPortHostOrder(connectionAttempt->sender->mostRecentPort);
|
|
|
|
// Pick a time far enough in the future that both systems will have gotten the message
|
|
int targetPing = rakPeerInterface->GetAveragePing(recipientTargetAddress);
|
|
int senderPing = rakPeerInterface->GetAveragePing(senderSystemAddress);
|
|
RakNet::Time simultaneousAttemptTime;
|
|
if (targetPing==-1 || senderPing==-1)
|
|
simultaneousAttemptTime = time + 1500;
|
|
else
|
|
{
|
|
int largerPing = targetPing > senderPing ? targetPing : senderPing;
|
|
if (largerPing * 4 < 100)
|
|
simultaneousAttemptTime = time + 100;
|
|
else
|
|
simultaneousAttemptTime = time + (largerPing * 4);
|
|
}
|
|
|
|
if (natPunchthroughServerDebugInterface)
|
|
{
|
|
RakNet::RakString log;
|
|
char addr1[128], addr2[128];
|
|
recipientSystemAddress.ToString(true,addr1);
|
|
connectionAttempt->recipient->guid.ToString(addr2);
|
|
log=RakNet::RakString("Sending ID_NAT_CONNECT_AT_TIME to recipient systemAddress %s guid %s", addr1, addr2);
|
|
natPunchthroughServerDebugInterface->OnServerMessage(log.C_String());
|
|
}
|
|
|
|
// Send to recipient timestamped message to connect at time
|
|
RakNet::BitStream bsOut;
|
|
bsOut.Write((MessageID)ID_TIMESTAMP);
|
|
bsOut.Write(simultaneousAttemptTime);
|
|
bsOut.Write((MessageID)ID_NAT_CONNECT_AT_TIME);
|
|
bsOut.Write(connectionAttempt->sessionId);
|
|
bsOut.Write(senderTargetAddress); // Public IP, using most recent port
|
|
for (j=0; j < MAXIMUM_NUMBER_OF_INTERNAL_IDS; j++) // Internal IP
|
|
bsOut.Write(rakPeerInterface->GetInternalID(senderSystemAddress,j));
|
|
bsOut.Write(connectionAttempt->sender->guid);
|
|
bsOut.Write(false);
|
|
rakPeerInterface->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,recipientSystemAddress,false);
|
|
|
|
|
|
if (natPunchthroughServerDebugInterface)
|
|
{
|
|
RakNet::RakString log;
|
|
char addr1[128], addr2[128];
|
|
senderSystemAddress.ToString(true,addr1);
|
|
connectionAttempt->sender->guid.ToString(addr2);
|
|
log=RakNet::RakString("Sending ID_NAT_CONNECT_AT_TIME to sender systemAddress %s guid %s", addr1, addr2);
|
|
natPunchthroughServerDebugInterface->OnServerMessage(log.C_String());
|
|
}
|
|
|
|
|
|
// Same for sender
|
|
bsOut.Reset();
|
|
bsOut.Write((MessageID)ID_TIMESTAMP);
|
|
bsOut.Write(simultaneousAttemptTime);
|
|
bsOut.Write((MessageID)ID_NAT_CONNECT_AT_TIME);
|
|
bsOut.Write(connectionAttempt->sessionId);
|
|
bsOut.Write(recipientTargetAddress); // Public IP, using most recent port
|
|
for (j=0; j < MAXIMUM_NUMBER_OF_INTERNAL_IDS; j++) // Internal IP
|
|
bsOut.Write(rakPeerInterface->GetInternalID(recipientSystemAddress,j));
|
|
bsOut.Write(connectionAttempt->recipient->guid);
|
|
bsOut.Write(true);
|
|
rakPeerInterface->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,senderSystemAddress,false);
|
|
|
|
connectionAttempt->recipient->DerefConnectionAttempt(connectionAttempt);
|
|
connectionAttempt->sender->DeleteConnectionAttempt(connectionAttempt);
|
|
|
|
// 04/29/08 missing return
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
if (natPunchthroughServerDebugInterface)
|
|
{
|
|
RakNet::RakString log;
|
|
char addr1[128], addr2[128];
|
|
packet->systemAddress.ToString(true,addr1);
|
|
packet->guid.ToString(addr2);
|
|
log=RakNet::RakString("Ignoring ID_NAT_GET_MOST_RECENT_PORT from systemAddress %s guid %s", addr1, addr2);
|
|
natPunchthroughServerDebugInterface->OnServerMessage(log.C_String());
|
|
}
|
|
|
|
}
|
|
}
|
|
void NatPunchthroughServer::StartPunchthroughForUser(User *user)
|
|
{
|
|
if (user->isReady==false)
|
|
return;
|
|
|
|
ConnectionAttempt *connectionAttempt;
|
|
User *sender,*recipient,*otherUser;
|
|
unsigned int i;
|
|
for (i=0; i < user->connectionAttempts.Size(); i++)
|
|
{
|
|
connectionAttempt=user->connectionAttempts[i];
|
|
if (connectionAttempt->sender==user)
|
|
{
|
|
otherUser=connectionAttempt->recipient;
|
|
sender=user;
|
|
recipient=otherUser;
|
|
}
|
|
else
|
|
{
|
|
otherUser=connectionAttempt->sender;
|
|
recipient=user;
|
|
sender=otherUser;
|
|
}
|
|
|
|
if (otherUser->isReady)
|
|
{
|
|
if (natPunchthroughServerDebugInterface)
|
|
{
|
|
char str[1024];
|
|
char addr1[128], addr2[128];
|
|
sender->systemAddress.ToString(true,addr1);
|
|
recipient->systemAddress.ToString(true,addr2);
|
|
sprintf(str, "Sending NAT_ATTEMPT_PHASE_GETTING_RECENT_PORTS to sender %s and recipient %s.", addr1, addr2);
|
|
natPunchthroughServerDebugInterface->OnServerMessage(str);
|
|
}
|
|
|
|
sender->isReady=false;
|
|
recipient->isReady=false;
|
|
connectionAttempt->attemptPhase=ConnectionAttempt::NAT_ATTEMPT_PHASE_GETTING_RECENT_PORTS;
|
|
connectionAttempt->startTime=RakNet::GetTime();
|
|
|
|
sender->mostRecentPort=0;
|
|
recipient->mostRecentPort=0;
|
|
|
|
RakNet::BitStream outgoingBs;
|
|
outgoingBs.Write((MessageID)ID_NAT_GET_MOST_RECENT_PORT);
|
|
// 4/29/09 Write sessionID so we don't use returned port for a system we don't want
|
|
outgoingBs.Write(connectionAttempt->sessionId);
|
|
rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,sender->systemAddress,false);
|
|
rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,recipient->systemAddress,false);
|
|
|
|
// 4/22/09 - BUG: missing break statement here
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif // _RAKNET_SUPPORT_*
|