mirror of
https://github.com/celisej567/mcpe.git
synced 2026-01-03 05:49:04 +03:00
310 lines
8.5 KiB
C++
310 lines
8.5 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_ConnectionGraph2==1
|
|
|
|
#include "ConnectionGraph2.h"
|
|
#include "RakPeerInterface.h"
|
|
#include "MessageIdentifiers.h"
|
|
#include "BitStream.h"
|
|
|
|
using namespace RakNet;
|
|
|
|
STATIC_FACTORY_DEFINITIONS(ConnectionGraph2,ConnectionGraph2)
|
|
|
|
int RakNet::ConnectionGraph2::RemoteSystemComp( const RakNetGUID &key, RemoteSystem * const &data )
|
|
{
|
|
if (key < data->guid)
|
|
return -1;
|
|
if (key > data->guid)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
int RakNet::ConnectionGraph2::SystemAddressAndGuidComp( const SystemAddressAndGuid &key, const SystemAddressAndGuid &data )
|
|
{
|
|
if (key.guid<data.guid)
|
|
return -1;
|
|
if (key.guid>data.guid)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
ConnectionGraph2::ConnectionGraph2()
|
|
{
|
|
autoProcessNewConnections=true;
|
|
}
|
|
ConnectionGraph2::~ConnectionGraph2()
|
|
{
|
|
|
|
}
|
|
bool ConnectionGraph2::GetConnectionListForRemoteSystem(RakNetGUID remoteSystemGuid, SystemAddress *saOut, RakNetGUID *guidOut, unsigned int *outLength)
|
|
{
|
|
if ((saOut==0 && guidOut==0) || outLength==0 || *outLength==0 || remoteSystemGuid==UNASSIGNED_RAKNET_GUID)
|
|
{
|
|
*outLength=0;
|
|
return false;
|
|
}
|
|
|
|
bool objectExists;
|
|
unsigned int idx = remoteSystems.GetIndexFromKey(remoteSystemGuid, &objectExists);
|
|
if (objectExists==false)
|
|
{
|
|
*outLength=0;
|
|
return false;
|
|
}
|
|
|
|
unsigned int idx2;
|
|
if (remoteSystems[idx]->remoteConnections.Size() < *outLength)
|
|
*outLength=remoteSystems[idx]->remoteConnections.Size();
|
|
for (idx2=0; idx2 < *outLength; idx2++)
|
|
{
|
|
if (guidOut)
|
|
guidOut[idx2]=remoteSystems[idx]->remoteConnections[idx2].guid;
|
|
if (saOut)
|
|
saOut[idx2]=remoteSystems[idx]->remoteConnections[idx2].systemAddress;
|
|
}
|
|
return true;
|
|
}
|
|
bool ConnectionGraph2::ConnectionExists(RakNetGUID g1, RakNetGUID g2)
|
|
{
|
|
if (g1==g2)
|
|
return false;
|
|
|
|
bool objectExists;
|
|
unsigned int idx = remoteSystems.GetIndexFromKey(g1, &objectExists);
|
|
if (objectExists==false)
|
|
{
|
|
return false;
|
|
}
|
|
SystemAddressAndGuid sag;
|
|
sag.guid=g2;
|
|
return remoteSystems[idx]->remoteConnections.HasData(sag);
|
|
}
|
|
uint16_t ConnectionGraph2::GetPingBetweenSystems(RakNetGUID g1, RakNetGUID g2) const
|
|
{
|
|
if (g1==g2)
|
|
return 0;
|
|
|
|
if (g1==rakPeerInterface->GetMyGUID())
|
|
return (uint16_t) rakPeerInterface->GetAveragePing(g2);
|
|
if (g2==rakPeerInterface->GetMyGUID())
|
|
return (uint16_t) rakPeerInterface->GetAveragePing(g1);
|
|
|
|
bool objectExists;
|
|
unsigned int idx = remoteSystems.GetIndexFromKey(g1, &objectExists);
|
|
if (objectExists==false)
|
|
{
|
|
return (uint16_t) -1;
|
|
}
|
|
|
|
SystemAddressAndGuid sag;
|
|
sag.guid=g2;
|
|
unsigned int idx2 = remoteSystems[idx]->remoteConnections.GetIndexFromKey(sag, &objectExists);
|
|
if (objectExists==false)
|
|
{
|
|
return (uint16_t) -1;
|
|
}
|
|
return remoteSystems[idx]->remoteConnections[idx2].sendersPingToThatSystem;
|
|
}
|
|
|
|
/// Returns the system with the lowest total ping among all its connections. This can be used as the 'best host' for a peer to peer session
|
|
RakNetGUID ConnectionGraph2::GetLowestAveragePingSystem(void) const
|
|
{
|
|
float lowestPing=-1.0;
|
|
unsigned int lowestPingIdx=(unsigned int) -1;
|
|
float thisAvePing=0.0f;
|
|
unsigned int idx, idx2;
|
|
int ap, count=0;
|
|
|
|
for (idx=0; idx<remoteSystems.Size(); idx++)
|
|
{
|
|
thisAvePing=0.0f;
|
|
|
|
ap = rakPeerInterface->GetAveragePing(remoteSystems[idx]->guid);
|
|
if (ap!=-1)
|
|
{
|
|
thisAvePing+=(float) ap;
|
|
count++;
|
|
}
|
|
}
|
|
|
|
if (count>0)
|
|
{
|
|
lowestPing=thisAvePing/count;
|
|
}
|
|
|
|
for (idx=0; idx<remoteSystems.Size(); idx++)
|
|
{
|
|
thisAvePing=0.0f;
|
|
count=0;
|
|
|
|
RemoteSystem *remoteSystem = remoteSystems[idx];
|
|
for (idx2=0; idx2 < remoteSystem->remoteConnections.Size(); idx2++)
|
|
{
|
|
ap=remoteSystem->remoteConnections[idx2].sendersPingToThatSystem;
|
|
if (ap!=-1)
|
|
{
|
|
thisAvePing+=(float) ap;
|
|
count++;
|
|
}
|
|
}
|
|
|
|
if (count>0 && (lowestPing==-1.0f || thisAvePing/count < lowestPing))
|
|
{
|
|
lowestPing=thisAvePing/count;
|
|
lowestPingIdx=idx;
|
|
}
|
|
}
|
|
|
|
if (lowestPingIdx==(unsigned int) -1)
|
|
return rakPeerInterface->GetMyGUID();
|
|
return remoteSystems[lowestPingIdx]->guid;
|
|
}
|
|
|
|
void ConnectionGraph2::OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
|
|
{
|
|
// Send notice to all existing connections
|
|
RakNet::BitStream bs;
|
|
if (lostConnectionReason==LCR_CONNECTION_LOST)
|
|
bs.Write((MessageID)ID_REMOTE_CONNECTION_LOST);
|
|
else
|
|
bs.Write((MessageID)ID_REMOTE_DISCONNECTION_NOTIFICATION);
|
|
bs.Write(systemAddress);
|
|
bs.Write(rakNetGUID);
|
|
SendUnified(&bs,HIGH_PRIORITY,RELIABLE_ORDERED,0,systemAddress,true);
|
|
|
|
bool objectExists;
|
|
unsigned int idx = remoteSystems.GetIndexFromKey(rakNetGUID, &objectExists);
|
|
if (objectExists)
|
|
{
|
|
RakNet::OP_DELETE(remoteSystems[idx],_FILE_AND_LINE_);
|
|
remoteSystems.RemoveAtIndex(idx);
|
|
}
|
|
}
|
|
void ConnectionGraph2::SetAutoProcessNewConnections(bool b)
|
|
{
|
|
autoProcessNewConnections=b;
|
|
}
|
|
bool ConnectionGraph2::GetAutoProcessNewConnections(void) const
|
|
{
|
|
return autoProcessNewConnections;
|
|
}
|
|
void ConnectionGraph2::AddParticipant(const SystemAddress &systemAddress, RakNetGUID rakNetGUID)
|
|
{
|
|
// Relay the new connection to other systems.
|
|
RakNet::BitStream bs;
|
|
bs.Write((MessageID)ID_REMOTE_NEW_INCOMING_CONNECTION);
|
|
bs.Write((uint32_t)1);
|
|
bs.Write(systemAddress);
|
|
bs.Write(rakNetGUID);
|
|
bs.WriteCasted<uint16_t>(rakPeerInterface->GetAveragePing(rakNetGUID));
|
|
SendUnified(&bs,HIGH_PRIORITY,RELIABLE_ORDERED,0,systemAddress,true);
|
|
|
|
// Send everyone to the new guy
|
|
DataStructures::List<SystemAddress> addresses;
|
|
DataStructures::List<RakNetGUID> guids;
|
|
rakPeerInterface->GetSystemList(addresses, guids);
|
|
bs.Reset();
|
|
bs.Write((MessageID)ID_REMOTE_NEW_INCOMING_CONNECTION);
|
|
BitSize_t writeOffset = bs.GetWriteOffset();
|
|
bs.Write((uint32_t) addresses.Size());
|
|
|
|
unsigned int i;
|
|
uint32_t count=0;
|
|
for (i=0; i < addresses.Size(); i++)
|
|
{
|
|
if (addresses[i]==systemAddress)
|
|
continue;
|
|
|
|
bs.Write(addresses[i]);
|
|
bs.Write(guids[i]);
|
|
bs.WriteCasted<uint16_t>(rakPeerInterface->GetAveragePing(guids[i]));
|
|
count++;
|
|
}
|
|
|
|
if (count>0)
|
|
{
|
|
BitSize_t writeOffset2 = bs.GetWriteOffset();
|
|
bs.SetWriteOffset(writeOffset);
|
|
bs.Write(count);
|
|
bs.SetWriteOffset(writeOffset2);
|
|
SendUnified(&bs,HIGH_PRIORITY,RELIABLE_ORDERED,0,systemAddress,false);
|
|
}
|
|
|
|
bool objectExists;
|
|
unsigned int ii = remoteSystems.GetIndexFromKey(rakNetGUID, &objectExists);
|
|
if (objectExists==false)
|
|
{
|
|
RemoteSystem* remoteSystem = RakNet::OP_NEW<RemoteSystem>(_FILE_AND_LINE_);
|
|
remoteSystem->guid=rakNetGUID;
|
|
remoteSystems.InsertAtIndex(remoteSystem,ii,_FILE_AND_LINE_);
|
|
}
|
|
}
|
|
void ConnectionGraph2::GetParticipantList(DataStructures::OrderedList<RakNetGUID, RakNetGUID> &participantList)
|
|
{
|
|
participantList.Clear(true, _FILE_AND_LINE_);
|
|
unsigned int i;
|
|
for (i=0; i < remoteSystems.Size(); i++)
|
|
participantList.InsertAtEnd(remoteSystems[i]->guid, _FILE_AND_LINE_);
|
|
}
|
|
void ConnectionGraph2::OnNewConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, bool isIncoming)
|
|
{
|
|
(void) isIncoming;
|
|
if (autoProcessNewConnections)
|
|
AddParticipant(systemAddress, rakNetGUID);
|
|
}
|
|
PluginReceiveResult ConnectionGraph2::OnReceive(Packet *packet)
|
|
{
|
|
if (packet->data[0]==ID_REMOTE_CONNECTION_LOST || packet->data[0]==ID_REMOTE_DISCONNECTION_NOTIFICATION)
|
|
{
|
|
bool objectExists;
|
|
unsigned idx = remoteSystems.GetIndexFromKey(packet->guid, &objectExists);
|
|
if (objectExists)
|
|
{
|
|
RakNet::BitStream bs(packet->data,packet->length,false);
|
|
bs.IgnoreBytes(1);
|
|
SystemAddressAndGuid saag;
|
|
bs.Read(saag.systemAddress);
|
|
bs.Read(saag.guid);
|
|
unsigned long idx2 = remoteSystems[idx]->remoteConnections.GetIndexFromKey(saag, &objectExists);
|
|
if (objectExists)
|
|
remoteSystems[idx]->remoteConnections.RemoveAtIndex(idx2);
|
|
}
|
|
}
|
|
else if (packet->data[0]==ID_REMOTE_NEW_INCOMING_CONNECTION)
|
|
{
|
|
bool objectExists;
|
|
unsigned idx = remoteSystems.GetIndexFromKey(packet->guid, &objectExists);
|
|
if (objectExists)
|
|
{
|
|
uint32_t numAddresses;
|
|
RakNet::BitStream bs(packet->data,packet->length,false);
|
|
bs.IgnoreBytes(1);
|
|
bs.Read(numAddresses);
|
|
for (unsigned int idx2=0; idx2 < numAddresses; idx2++)
|
|
{
|
|
SystemAddressAndGuid saag;
|
|
bs.Read(saag.systemAddress);
|
|
bs.Read(saag.guid);
|
|
bs.Read(saag.sendersPingToThatSystem);
|
|
bool objectExists;
|
|
unsigned int ii = remoteSystems[idx]->remoteConnections.GetIndexFromKey(saag, &objectExists);
|
|
if (objectExists==false)
|
|
remoteSystems[idx]->remoteConnections.InsertAtIndex(saag,ii,_FILE_AND_LINE_);
|
|
}
|
|
}
|
|
}
|
|
|
|
return RR_CONTINUE_PROCESSING;
|
|
}
|
|
|
|
#endif // _RAKNET_SUPPORT_*
|