mirror of
https://github.com/celisej567/mcpe.git
synced 2026-01-04 14:09:47 +03:00
1424 lines
42 KiB
C++
1424 lines
42 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.
|
|
*
|
|
*/
|
|
|
|
/// \file
|
|
///
|
|
|
|
|
|
#include "NativeFeatureIncludes.h"
|
|
#if _RAKNET_SUPPORT_FullyConnectedMesh2==1
|
|
|
|
#include "FullyConnectedMesh2.h"
|
|
#include "RakPeerInterface.h"
|
|
#include "MessageIdentifiers.h"
|
|
#include "RakAssert.h"
|
|
#include "GetTime.h"
|
|
#include "Rand.h"
|
|
#include "DS_OrderedList.h"
|
|
|
|
using namespace RakNet;
|
|
|
|
int FCM2ParticipantComp( FullyConnectedMesh2::FCM2Participant * const &key, FullyConnectedMesh2::FCM2Participant * const &data )
|
|
{
|
|
if (key->fcm2Guid < data->fcm2Guid)
|
|
return -1;
|
|
if (key->fcm2Guid > data->fcm2Guid)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
STATIC_FACTORY_DEFINITIONS(FullyConnectedMesh2,FullyConnectedMesh2);
|
|
|
|
FullyConnectedMesh2::FullyConnectedMesh2()
|
|
{
|
|
startupTime=0;
|
|
totalConnectionCount=0;
|
|
ourFCMGuid=0;
|
|
autoParticipateConnections=true;
|
|
|
|
|
|
|
|
|
|
connectOnNewRemoteConnections=true;
|
|
|
|
hostRakNetGuid=UNASSIGNED_RAKNET_GUID;
|
|
}
|
|
FullyConnectedMesh2::~FullyConnectedMesh2()
|
|
{
|
|
Clear();
|
|
}
|
|
RakNetGUID FullyConnectedMesh2::GetConnectedHost(void) const
|
|
{
|
|
if (ourFCMGuid==0)
|
|
return UNASSIGNED_RAKNET_GUID;
|
|
return hostRakNetGuid;
|
|
}
|
|
SystemAddress FullyConnectedMesh2::GetConnectedHostAddr(void) const
|
|
{
|
|
if (ourFCMGuid==0)
|
|
return UNASSIGNED_SYSTEM_ADDRESS;
|
|
return rakPeerInterface->GetSystemAddressFromGuid(hostRakNetGuid);
|
|
}
|
|
RakNetGUID FullyConnectedMesh2::GetHostSystem(void) const
|
|
{
|
|
if (ourFCMGuid==0)
|
|
return rakPeerInterface->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS);
|
|
|
|
return hostRakNetGuid;
|
|
}
|
|
bool FullyConnectedMesh2::IsHostSystem(void) const
|
|
{
|
|
return GetHostSystem()==rakPeerInterface->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS);
|
|
}
|
|
void FullyConnectedMesh2::GetHostOrder(DataStructures::List<RakNetGUID> &hostList)
|
|
{
|
|
hostList.Clear(true, _FILE_AND_LINE_);
|
|
|
|
if (ourFCMGuid==0 || fcm2ParticipantList.Size()==0)
|
|
{
|
|
hostList.Push(rakPeerInterface->GetMyGUID(), _FILE_AND_LINE_);
|
|
return;
|
|
}
|
|
|
|
FCM2Participant fcm2;
|
|
fcm2.fcm2Guid=ourFCMGuid;
|
|
fcm2.rakNetGuid=rakPeerInterface->GetMyGUID();
|
|
|
|
DataStructures::OrderedList<FCM2Participant*, FCM2Participant*, FCM2ParticipantComp> olist;
|
|
olist.Insert(&fcm2, &fcm2, true, _FILE_AND_LINE_);
|
|
for (unsigned int i=0; i < fcm2ParticipantList.Size(); i++)
|
|
olist.Insert(fcm2ParticipantList[i], fcm2ParticipantList[i], true, _FILE_AND_LINE_);
|
|
|
|
for (unsigned int i=0; i < olist.Size(); i++)
|
|
{
|
|
hostList.Push(olist[i]->rakNetGuid, _FILE_AND_LINE_);
|
|
}
|
|
}
|
|
bool FullyConnectedMesh2::IsConnectedHost(void) const
|
|
{
|
|
return GetConnectedHost()==rakPeerInterface->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS);
|
|
}
|
|
void FullyConnectedMesh2::SetAutoparticipateConnections(bool b)
|
|
{
|
|
autoParticipateConnections=b;
|
|
}
|
|
void FullyConnectedMesh2::ResetHostCalculation(void)
|
|
{
|
|
hostRakNetGuid=UNASSIGNED_RAKNET_GUID;
|
|
startupTime=RakNet::GetTimeUS();
|
|
totalConnectionCount=0;
|
|
ourFCMGuid=0;
|
|
for (unsigned int i=0; i < fcm2ParticipantList.Size(); i++)
|
|
SendFCMGuidRequest(fcm2ParticipantList[i]->rakNetGuid);
|
|
}
|
|
// bool FullyConnectedMesh2::AddParticipantInternal( RakNetGUID rakNetGuid, FCM2Guid theirFCMGuid, BitStream *userContext )
|
|
bool FullyConnectedMesh2::AddParticipantInternal( RakNetGUID rakNetGuid, FCM2Guid theirFCMGuid )
|
|
{
|
|
for (unsigned int i=0; i < fcm2ParticipantList.Size(); i++)
|
|
{
|
|
if (fcm2ParticipantList[i]->rakNetGuid==rakNetGuid)
|
|
{
|
|
if (theirFCMGuid!=0)
|
|
fcm2ParticipantList[i]->fcm2Guid=theirFCMGuid;
|
|
/*
|
|
fcm2ParticipantList[i]->userContext.Reset();
|
|
if (userContext)
|
|
{
|
|
userContext->ResetReadPointer();
|
|
fcm2ParticipantList[i]->userContext.Write(userContext);
|
|
}
|
|
*/
|
|
return false;
|
|
}
|
|
}
|
|
|
|
FCM2Participant *participant = RakNet::OP_NEW<FCM2Participant>(_FILE_AND_LINE_);
|
|
participant->rakNetGuid=rakNetGuid;
|
|
participant->fcm2Guid=theirFCMGuid;
|
|
/*
|
|
if (userContext)
|
|
{
|
|
userContext->ResetReadPointer();
|
|
participant->userContext.Write(userContext);
|
|
}
|
|
*/
|
|
fcm2ParticipantList.Push(participant,_FILE_AND_LINE_);
|
|
|
|
SendFCMGuidRequest(rakNetGuid);
|
|
|
|
return true;
|
|
}
|
|
void FullyConnectedMesh2::AddParticipant( RakNetGUID rakNetGuid )
|
|
{
|
|
if (rakPeerInterface->GetConnectionState(rakPeerInterface->GetSystemAddressFromGuid(rakNetGuid))!=IS_CONNECTED)
|
|
{
|
|
#ifdef DEBUG_FCM2
|
|
printf("AddParticipant to %s failed (not connected)\n", rakNetGuid.ToString());
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
// Need to query other system for userdata before calling AddParticipantInternal
|
|
// But maybe I can call with no data, and piggyback on ID_FCM2_REQUEST_FCMGUID
|
|
//AddParticipantInternal(rakNetGuid,0,0);
|
|
AddParticipantInternal(rakNetGuid,0);
|
|
}
|
|
void FullyConnectedMesh2::GetParticipantList(DataStructures::List<RakNetGUID> &participantList)
|
|
{
|
|
participantList.Clear(true, _FILE_AND_LINE_);
|
|
unsigned int i;
|
|
for (i=0; i < fcm2ParticipantList.Size(); i++)
|
|
participantList.Push(fcm2ParticipantList[i]->rakNetGuid, _FILE_AND_LINE_);
|
|
}
|
|
bool FullyConnectedMesh2::HasParticipant(RakNetGUID participantGuid)
|
|
{
|
|
unsigned int i;
|
|
for (i=0; i < fcm2ParticipantList.Size(); i++)
|
|
{
|
|
if (fcm2ParticipantList[i]->rakNetGuid==participantGuid)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
/*
|
|
bool FullyConnectedMesh2::GetParticipantContext(RakNetGUID participantGuid, BitStream *userContext)
|
|
{
|
|
unsigned int i;
|
|
for (i=0; i < fcm2ParticipantList.Size(); i++)
|
|
{
|
|
if (fcm2ParticipantList[i]->rakNetGuid==participantGuid)
|
|
{
|
|
if (fcm2ParticipantList[i]->userContext.GetNumberOfBitsUsed() > 0)
|
|
{
|
|
userContext->Write(fcm2ParticipantList[i]->userContext);
|
|
fcm2ParticipantList[i]->userContext.ResetReadPointer();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
void FullyConnectedMesh2::SetMyContext(BitStream *userContext)
|
|
{
|
|
if (userContext==0)
|
|
{
|
|
if (myContext.GetNumberOfBitsUsed()==0)
|
|
return;
|
|
myContext.Reset();
|
|
}
|
|
else
|
|
{
|
|
myContext.Write(userContext);
|
|
userContext->ResetReadPointer();
|
|
}
|
|
|
|
RakNet::BitStream bsOut;
|
|
bsOut.Write((MessageID)ID_FCM2_UPDATE_USER_CONTEXT);
|
|
bsOut.Write(myContext);
|
|
myContext.ResetReadPointer();
|
|
|
|
unsigned int idx;
|
|
for (idx=0; idx < fcm2ParticipantList.Size(); idx++)
|
|
{
|
|
rakPeerInterface->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,fcm2ParticipantList[idx]->rakNetGuid,false);
|
|
}
|
|
}
|
|
*/
|
|
PluginReceiveResult FullyConnectedMesh2::OnReceive(Packet *packet)
|
|
{
|
|
switch (packet->data[0])
|
|
{
|
|
case ID_REMOTE_NEW_INCOMING_CONNECTION:
|
|
{
|
|
if (connectOnNewRemoteConnections)
|
|
ConnectToRemoteNewIncomingConnections(packet);
|
|
}
|
|
break;
|
|
case ID_FCM2_REQUEST_FCMGUID:
|
|
OnRequestFCMGuid(packet);
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
//case ID_FCM2_UPDATE_USER_CONTEXT:
|
|
// OnUpdateUserContext(packet);
|
|
// return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
case ID_FCM2_RESPOND_CONNECTION_COUNT:
|
|
OnRespondConnectionCount(packet);
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
case ID_FCM2_INFORM_FCMGUID:
|
|
OnInformFCMGuid(packet);
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
case ID_FCM2_UPDATE_MIN_TOTAL_CONNECTION_COUNT:
|
|
OnUpdateMinTotalConnectionCount(packet);
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
case ID_FCM2_NEW_HOST:
|
|
if (packet->wasGeneratedLocally==false)
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
break;
|
|
case ID_FCM2_VERIFIED_JOIN_START:
|
|
return OnVerifiedJoinStart(packet);
|
|
case ID_FCM2_VERIFIED_JOIN_CAPABLE:
|
|
return OnVerifiedJoinCapable(packet);
|
|
case ID_FCM2_VERIFIED_JOIN_FAILED:
|
|
OnVerifiedJoinFailed(packet->guid, true);
|
|
return RR_CONTINUE_PROCESSING;
|
|
case ID_FCM2_VERIFIED_JOIN_ACCEPTED:
|
|
if (packet->wasGeneratedLocally==false)
|
|
OnVerifiedJoinAccepted(packet);
|
|
return RR_CONTINUE_PROCESSING;
|
|
case ID_FCM2_VERIFIED_JOIN_REJECTED:
|
|
OnVerifiedJoinRejected(packet);
|
|
return RR_CONTINUE_PROCESSING;
|
|
|
|
case ID_NAT_TARGET_UNRESPONSIVE:
|
|
case ID_NAT_TARGET_NOT_CONNECTED:
|
|
case ID_NAT_CONNECTION_TO_TARGET_LOST:
|
|
{
|
|
RakNet::RakNetGUID g;
|
|
RakNet::BitStream b(packet->data, packet->length, false);
|
|
b.IgnoreBits(8); // Ignore the ID_...
|
|
b.Read(g);
|
|
UpdateVerifiedJoinInProgressMember(g, UNASSIGNED_RAKNET_GUID, JIPS_FAILED);
|
|
return RR_CONTINUE_PROCESSING;
|
|
}
|
|
case ID_NAT_PUNCHTHROUGH_FAILED:
|
|
UpdateVerifiedJoinInProgressMember(packet->guid, UNASSIGNED_RAKNET_GUID, JIPS_FAILED);
|
|
return RR_CONTINUE_PROCESSING;
|
|
}
|
|
|
|
return RR_CONTINUE_PROCESSING;
|
|
}
|
|
void FullyConnectedMesh2::OnRakPeerStartup(void)
|
|
{
|
|
Clear();
|
|
startupTime=RakNet::GetTimeUS();
|
|
}
|
|
void FullyConnectedMesh2::OnAttach(void)
|
|
{
|
|
Clear();
|
|
// In case Startup() was called first
|
|
if (rakPeerInterface->IsActive())
|
|
startupTime=RakNet::GetTimeUS();
|
|
}
|
|
void FullyConnectedMesh2::OnRakPeerShutdown(void)
|
|
{
|
|
Clear();
|
|
startupTime=0;
|
|
}
|
|
void FullyConnectedMesh2::OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
|
|
{
|
|
(void) lostConnectionReason;
|
|
(void) systemAddress;
|
|
(void) rakNetGUID;
|
|
|
|
unsigned int idx;
|
|
idx=0;
|
|
while (idx < joinsInProgress.Size())
|
|
{
|
|
if (joinsInProgress[idx]->requester==rakNetGUID)
|
|
{
|
|
Packet *p = AllocatePacketUnified(sizeof(MessageID)+sizeof(unsigned char));
|
|
p->data[0]=ID_FCM2_VERIFIED_JOIN_FAILED;
|
|
p->systemAddress=systemAddress;
|
|
p->systemAddress.systemIndex=(SystemIndex)-1;
|
|
p->guid=rakNetGUID;
|
|
p->wasGeneratedLocally=true;
|
|
rakPeerInterface->PushBackPacket(p, true);
|
|
|
|
for (unsigned int j=0; j < joinsInProgress[idx]->vjipMembers.Size(); j++)
|
|
{
|
|
if ( joinsInProgress[idx]->vjipMembers[j].userData != 0)
|
|
{
|
|
RakNet::OP_DELETE(joinsInProgress[idx]->vjipMembers[j].userData, _FILE_AND_LINE_);
|
|
}
|
|
}
|
|
|
|
RakNet::OP_DELETE(joinsInProgress[idx], _FILE_AND_LINE_);
|
|
joinsInProgress.RemoveAtIndex(idx);
|
|
}
|
|
else
|
|
{
|
|
idx++;
|
|
}
|
|
}
|
|
|
|
UpdateVerifiedJoinInProgressMember(rakNetGUID, UNASSIGNED_RAKNET_GUID, JIPS_FAILED);
|
|
|
|
for (idx=0; idx < fcm2ParticipantList.Size(); idx++)
|
|
{
|
|
if (fcm2ParticipantList[idx]->rakNetGuid==rakNetGUID)
|
|
{
|
|
fcm2ParticipantList[idx]=fcm2ParticipantList[fcm2ParticipantList.Size()-1];
|
|
#ifdef DEBUG_FCM2
|
|
printf("Popping participant %s\n", fcm2ParticipantList[fcm2ParticipantList.Size()-1].rakNetGuid.ToString());
|
|
#endif
|
|
|
|
fcm2ParticipantList.Pop();
|
|
if (rakNetGUID==hostRakNetGuid && ourFCMGuid!=0)
|
|
{
|
|
if (fcm2ParticipantList.Size()==0)
|
|
{
|
|
hostRakNetGuid=rakPeerInterface->GetMyGUID();
|
|
hostFCM2Guid=ourFCMGuid;
|
|
}
|
|
else
|
|
{
|
|
CalculateHost(&hostRakNetGuid, &hostFCM2Guid);
|
|
}
|
|
PushNewHost(hostRakNetGuid, rakNetGUID);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
}
|
|
RakNet::TimeUS FullyConnectedMesh2::GetElapsedRuntime(void)
|
|
{
|
|
RakNet::TimeUS curTime=RakNet::GetTimeUS();
|
|
if (curTime>startupTime)
|
|
return curTime-startupTime;
|
|
else
|
|
return 0;
|
|
}
|
|
void FullyConnectedMesh2::OnNewConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, bool isIncoming)
|
|
{
|
|
(void) isIncoming;
|
|
(void) rakNetGUID;
|
|
(void) systemAddress;
|
|
|
|
UpdateVerifiedJoinInProgressMember(rakNetGUID, rakNetGUID, JIPS_CONNECTED);
|
|
|
|
if (autoParticipateConnections)
|
|
AddParticipant(rakNetGUID);
|
|
}
|
|
void FullyConnectedMesh2::OnFailedConnectionAttempt(Packet *packet, PI2_FailedConnectionAttemptReason failedConnectionAttemptReason)
|
|
{
|
|
if (failedConnectionAttemptReason==FCAR_ALREADY_CONNECTED)
|
|
{
|
|
UpdateVerifiedJoinInProgressMember(packet->guid, packet->guid, JIPS_CONNECTED);
|
|
}
|
|
else
|
|
{
|
|
UpdateVerifiedJoinInProgressMember(packet->systemAddress, UNASSIGNED_RAKNET_GUID, JIPS_FAILED);
|
|
}
|
|
}
|
|
void FullyConnectedMesh2::Clear(void)
|
|
{
|
|
for (unsigned int i=0; i < fcm2ParticipantList.Size(); i++)
|
|
{
|
|
delete fcm2ParticipantList[i];
|
|
}
|
|
fcm2ParticipantList.Clear(false, _FILE_AND_LINE_);
|
|
|
|
for (unsigned int i=0; i < joinsInProgress.Size(); i++)
|
|
{
|
|
for (unsigned int j=0; j < joinsInProgress[i]->vjipMembers.Size(); j++)
|
|
{
|
|
if ( joinsInProgress[i]->vjipMembers[j].userData != 0)
|
|
{
|
|
RakNet::OP_DELETE(joinsInProgress[i]->vjipMembers[j].userData, _FILE_AND_LINE_);
|
|
}
|
|
}
|
|
|
|
RakNet::OP_DELETE(joinsInProgress[i], _FILE_AND_LINE_);
|
|
}
|
|
joinsInProgress.Clear(true, _FILE_AND_LINE_);
|
|
|
|
totalConnectionCount=0;
|
|
ourFCMGuid=0;
|
|
lastPushedHost=UNASSIGNED_RAKNET_GUID;
|
|
}
|
|
void FullyConnectedMesh2::PushNewHost(const RakNetGUID &guid, RakNetGUID oldHost)
|
|
{
|
|
Packet *p = AllocatePacketUnified(sizeof(MessageID)+sizeof(oldHost));
|
|
RakNet::BitStream bs(p->data,p->length,false);
|
|
bs.SetWriteOffset(0);
|
|
bs.Write((MessageID)ID_FCM2_NEW_HOST);
|
|
bs.Write(oldHost);
|
|
p->systemAddress=rakPeerInterface->GetSystemAddressFromGuid(guid);
|
|
p->systemAddress.systemIndex=(SystemIndex)-1;
|
|
p->guid=guid;
|
|
p->wasGeneratedLocally=true;
|
|
rakPeerInterface->PushBackPacket(p, true);
|
|
|
|
lastPushedHost=guid;
|
|
}
|
|
void FullyConnectedMesh2::SendFCMGuidRequest(RakNetGUID rakNetGuid)
|
|
{
|
|
if (rakNetGuid==rakPeerInterface->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS))
|
|
return;
|
|
|
|
RakNet::BitStream bsOut;
|
|
bsOut.Write((MessageID)ID_FCM2_REQUEST_FCMGUID);
|
|
if (ourFCMGuid==0)
|
|
{
|
|
bsOut.Write(false);
|
|
bsOut.Write(GetElapsedRuntime());
|
|
}
|
|
else
|
|
{
|
|
bsOut.Write(true);
|
|
bsOut.Write(totalConnectionCount);
|
|
bsOut.Write(ourFCMGuid);
|
|
}
|
|
bsOut.Write(myContext);
|
|
myContext.ResetReadPointer();
|
|
rakPeerInterface->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,rakNetGuid,false);
|
|
}
|
|
void FullyConnectedMesh2::SendOurFCMGuid(SystemAddress addr)
|
|
{
|
|
RakNet::BitStream bsOut;
|
|
bsOut.Write((MessageID)ID_FCM2_INFORM_FCMGUID);
|
|
RakAssert(ourFCMGuid!=0); // Can't inform others of our FCM2Guid if it's unset!
|
|
bsOut.Write(ourFCMGuid);
|
|
bsOut.Write(totalConnectionCount);
|
|
bsOut.Write(myContext);
|
|
myContext.ResetReadPointer();
|
|
rakPeerInterface->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,addr,false);
|
|
}
|
|
void FullyConnectedMesh2::SendConnectionCountResponse(SystemAddress addr, unsigned int responseTotalConnectionCount)
|
|
{
|
|
RakNet::BitStream bsOut;
|
|
bsOut.Write((MessageID)ID_FCM2_RESPOND_CONNECTION_COUNT);
|
|
bsOut.Write(responseTotalConnectionCount);
|
|
//bsOut.Write(myContext);
|
|
//myContext.ResetReadPointer();
|
|
rakPeerInterface->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,addr,false);
|
|
}
|
|
void FullyConnectedMesh2::AssignOurFCMGuid(void)
|
|
{
|
|
// Only assigned once ever
|
|
RakAssert(ourFCMGuid==0);
|
|
unsigned int randomNumber = randomMT();
|
|
randomNumber ^= (unsigned int) (RakNet::GetTimeUS() & 0xFFFFFFFF);
|
|
randomNumber ^= (unsigned int) (rakPeerInterface->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS).g & 0xFFFFFFFF);
|
|
ourFCMGuid |= randomNumber;
|
|
uint64_t reponse64 = totalConnectionCount;
|
|
ourFCMGuid |= reponse64<<32;
|
|
}
|
|
void FullyConnectedMesh2::CalculateHost(RakNetGUID *rakNetGuid, FCM2Guid *fcm2Guid)
|
|
{
|
|
// Can't calculate host without knowing our own
|
|
RakAssert(ourFCMGuid!=0);
|
|
|
|
// Can't calculate host without being connected to anyone else
|
|
RakAssert(fcm2ParticipantList.Size()>0);
|
|
|
|
// Return the lowest value of all FCM2Guid
|
|
FCM2Guid lowestFCMGuid=ourFCMGuid;
|
|
// SystemAddress associatedSystemAddress=UNASSIGNED_SYSTEM_ADDRESS;
|
|
RakNetGUID associatedRakNetGuid=rakPeerInterface->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS);
|
|
|
|
unsigned int idx;
|
|
for (idx=0; idx < fcm2ParticipantList.Size(); idx++)
|
|
{
|
|
if (fcm2ParticipantList[idx]->fcm2Guid!=0 && fcm2ParticipantList[idx]->fcm2Guid<lowestFCMGuid)
|
|
{
|
|
lowestFCMGuid=fcm2ParticipantList[idx]->fcm2Guid;
|
|
associatedRakNetGuid=fcm2ParticipantList[idx]->rakNetGuid;
|
|
}
|
|
}
|
|
|
|
*rakNetGuid=associatedRakNetGuid;
|
|
*fcm2Guid=lowestFCMGuid;
|
|
}
|
|
void FullyConnectedMesh2::OnRequestFCMGuid(Packet *packet)
|
|
{
|
|
RakNet::BitStream bsIn(packet->data,packet->length,false);
|
|
bsIn.IgnoreBytes(sizeof(MessageID));
|
|
bool hasRemoteFCMGuid=false;
|
|
bsIn.Read(hasRemoteFCMGuid);
|
|
RakNet::TimeUS senderElapsedRuntime=0;
|
|
unsigned int remoteTotalConnectionCount=0;
|
|
FCM2Guid theirFCMGuid=0;
|
|
if (hasRemoteFCMGuid)
|
|
{
|
|
bsIn.Read(remoteTotalConnectionCount);
|
|
bsIn.Read(theirFCMGuid);
|
|
}
|
|
else
|
|
{
|
|
bsIn.Read(senderElapsedRuntime);
|
|
}
|
|
/*
|
|
BitStream remoteContext;
|
|
bsIn.Read(remoteContext);
|
|
AddParticipantInternal(packet->guid,theirFCMGuid, &remoteContext);
|
|
*/
|
|
AddParticipantInternal(packet->guid,theirFCMGuid);
|
|
if (ourFCMGuid==0)
|
|
{
|
|
if (hasRemoteFCMGuid==false)
|
|
{
|
|
// Nobody has a fcmGuid
|
|
|
|
RakNet::TimeUS ourElapsedRuntime = GetElapsedRuntime();
|
|
if (ourElapsedRuntime>senderElapsedRuntime)
|
|
{
|
|
// We are probably host
|
|
SendConnectionCountResponse(packet->systemAddress, 2);
|
|
}
|
|
else
|
|
{
|
|
// They are probably host
|
|
SendConnectionCountResponse(packet->systemAddress, 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// They have a fcmGuid, we do not
|
|
IncrementTotalConnectionCount(remoteTotalConnectionCount+1);
|
|
|
|
AssignOurFCMGuid();
|
|
unsigned int idx;
|
|
for (idx=0; idx < fcm2ParticipantList.Size(); idx++)
|
|
SendOurFCMGuid(rakPeerInterface->GetSystemAddressFromGuid(fcm2ParticipantList[idx]->rakNetGuid));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (hasRemoteFCMGuid==false)
|
|
{
|
|
// We have a fcmGuid they do not
|
|
SendConnectionCountResponse(packet->systemAddress, totalConnectionCount+1);
|
|
}
|
|
else
|
|
{
|
|
// We both have fcmGuids
|
|
IncrementTotalConnectionCount(remoteTotalConnectionCount);
|
|
|
|
SendOurFCMGuid(packet->systemAddress);
|
|
}
|
|
}
|
|
CalculateAndPushHost();
|
|
}
|
|
/*
|
|
void FullyConnectedMesh2::OnUpdateUserContext(Packet *packet)
|
|
{
|
|
RakNet::BitStream bsIn(packet->data,packet->length,false);
|
|
bsIn.IgnoreBytes(sizeof(MessageID));
|
|
BitStream remoteContext;
|
|
bsIn.Read(remoteContext);
|
|
|
|
for (unsigned int i=0; i < fcm2ParticipantList.Size(); i++)
|
|
{
|
|
if (fcm2ParticipantList[i]->rakNetGuid==packet->guid)
|
|
{
|
|
fcm2ParticipantList[i]->userContext.Reset();
|
|
remoteContext.Read(fcm2ParticipantList[i]->userContext);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
void FullyConnectedMesh2::OnRespondConnectionCount(Packet *packet)
|
|
{
|
|
RakNet::BitStream bsIn(packet->data,packet->length,false);
|
|
bsIn.IgnoreBytes(sizeof(MessageID));
|
|
unsigned int responseTotalConnectionCount;
|
|
bsIn.Read(responseTotalConnectionCount);
|
|
/*
|
|
BitStream remoteContext;
|
|
bsIn.Read(remoteContext);
|
|
|
|
for (unsigned int i=0; i < fcm2ParticipantList.Size(); i++)
|
|
{
|
|
if (fcm2ParticipantList[i]->rakNetGuid==packet->guid)
|
|
{
|
|
fcm2ParticipantList[i]->userContext.Reset();
|
|
remoteContext.Read(fcm2ParticipantList[i]->userContext);
|
|
break;
|
|
}
|
|
}
|
|
*/
|
|
|
|
IncrementTotalConnectionCount(responseTotalConnectionCount);
|
|
bool wasAssigned;
|
|
if (ourFCMGuid==0)
|
|
{
|
|
wasAssigned=true;
|
|
AssignOurFCMGuid();
|
|
}
|
|
else
|
|
wasAssigned=false;
|
|
|
|
// 1 is returned to give us lower priority, but the actual minimum is 2
|
|
IncrementTotalConnectionCount(2);
|
|
|
|
if (wasAssigned==true)
|
|
{
|
|
unsigned int idx;
|
|
for (idx=0; idx < fcm2ParticipantList.Size(); idx++)
|
|
SendOurFCMGuid(rakPeerInterface->GetSystemAddressFromGuid(fcm2ParticipantList[idx]->rakNetGuid));
|
|
CalculateAndPushHost();
|
|
}
|
|
}
|
|
void FullyConnectedMesh2::OnInformFCMGuid(Packet *packet)
|
|
{
|
|
RakNet::BitStream bsIn(packet->data,packet->length,false);
|
|
bsIn.IgnoreBytes(sizeof(MessageID));
|
|
|
|
FCM2Guid theirFCMGuid;
|
|
unsigned int theirTotalConnectionCount;
|
|
bsIn.Read(theirFCMGuid);
|
|
bsIn.Read(theirTotalConnectionCount);
|
|
|
|
BitStream remoteContext;
|
|
bsIn.Read(remoteContext);
|
|
|
|
IncrementTotalConnectionCount(theirTotalConnectionCount);
|
|
|
|
//if (AddParticipantInternal(packet->guid,theirFCMGuid, &remoteContext))
|
|
if (AddParticipantInternal(packet->guid,theirFCMGuid))
|
|
{
|
|
// 1/19/2010 - Relay increased total connection count in case new participant only connects to part of the mesh
|
|
unsigned int idx;
|
|
RakNet::BitStream bsOut;
|
|
bsOut.Write((MessageID)ID_FCM2_UPDATE_MIN_TOTAL_CONNECTION_COUNT);
|
|
bsOut.Write(totalConnectionCount);
|
|
for (idx=0; idx < fcm2ParticipantList.Size(); idx++)
|
|
{
|
|
if (packet->guid!=fcm2ParticipantList[idx]->rakNetGuid)
|
|
rakPeerInterface->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,fcm2ParticipantList[idx]->rakNetGuid,false);
|
|
}
|
|
}
|
|
|
|
if (ourFCMGuid==0)
|
|
{
|
|
AssignOurFCMGuid();
|
|
unsigned int idx;
|
|
for (idx=0; idx < fcm2ParticipantList.Size(); idx++)
|
|
SendOurFCMGuid(rakPeerInterface->GetSystemAddressFromGuid(fcm2ParticipantList[idx]->rakNetGuid));
|
|
}
|
|
|
|
CalculateAndPushHost();
|
|
}
|
|
void FullyConnectedMesh2::OnUpdateMinTotalConnectionCount(Packet *packet)
|
|
{
|
|
RakNet::BitStream bsIn(packet->data,packet->length,false);
|
|
bsIn.IgnoreBytes(sizeof(MessageID));
|
|
unsigned int newMin;
|
|
bsIn.Read(newMin);
|
|
IncrementTotalConnectionCount(newMin);
|
|
}
|
|
void FullyConnectedMesh2::GetParticipantCount(unsigned int *participantListSize) const
|
|
{
|
|
*participantListSize=fcm2ParticipantList.Size();
|
|
}
|
|
|
|
unsigned int FullyConnectedMesh2::GetParticipantCount(void) const
|
|
{
|
|
return fcm2ParticipantList.Size();
|
|
}
|
|
void FullyConnectedMesh2::CalculateAndPushHost(void)
|
|
{
|
|
RakNetGUID newHostGuid;
|
|
FCM2Guid newFcmGuid;
|
|
if (ParticipantListComplete())
|
|
{
|
|
CalculateHost(&newHostGuid, &newFcmGuid);
|
|
if (newHostGuid!=lastPushedHost)
|
|
{
|
|
hostRakNetGuid=newHostGuid;
|
|
hostFCM2Guid=newFcmGuid;
|
|
PushNewHost(hostRakNetGuid, lastPushedHost);
|
|
}
|
|
}
|
|
}
|
|
bool FullyConnectedMesh2::ParticipantListComplete(void)
|
|
{
|
|
for (unsigned int i=0; i < fcm2ParticipantList.Size(); i++)
|
|
{
|
|
if (fcm2ParticipantList[i]->fcm2Guid==0)
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
void FullyConnectedMesh2::IncrementTotalConnectionCount(unsigned int i)
|
|
{
|
|
if (i>totalConnectionCount)
|
|
{
|
|
totalConnectionCount=i;
|
|
// printf("totalConnectionCount=%i\n",i);
|
|
}
|
|
}
|
|
void FullyConnectedMesh2::SetConnectOnNewRemoteConnection(bool attemptConnection, RakNet::RakString pw)
|
|
{
|
|
connectOnNewRemoteConnections=attemptConnection;
|
|
connectionPassword=pw;
|
|
}
|
|
|
|
void FullyConnectedMesh2::ConnectToRemoteNewIncomingConnections(Packet *packet)
|
|
{
|
|
unsigned int count;
|
|
RakNet::BitStream bsIn(packet->data, packet->length, false);
|
|
bsIn.IgnoreBytes(sizeof(MessageID));
|
|
bsIn.Read(count);
|
|
SystemAddress remoteAddress;
|
|
RakNetGUID remoteGuid;
|
|
char str[64];
|
|
for (unsigned int i=0; i < count; i++)
|
|
{
|
|
bsIn.Read(remoteAddress);
|
|
bsIn.Read(remoteGuid);
|
|
remoteAddress.ToString(false,str);
|
|
rakPeerInterface->Connect(str,remoteAddress.GetPort(),connectionPassword.C_String(),(int) connectionPassword.GetLength());
|
|
}
|
|
}
|
|
unsigned int FullyConnectedMesh2::GetTotalConnectionCount(void) const
|
|
{
|
|
return totalConnectionCount;
|
|
}
|
|
void FullyConnectedMesh2::StartVerifiedJoin(RakNetGUID client)
|
|
{
|
|
// Assert is because there is no point calling StartVerifiedJoin() if this client is already a participant
|
|
RakAssert(HasParticipant(client)==false);
|
|
RakAssert(client!=rakPeerInterface->GetMyGUID());
|
|
|
|
BitStream bsOut;
|
|
bsOut.Write((MessageID) ID_FCM2_VERIFIED_JOIN_START);
|
|
bsOut.WriteCasted<unsigned short>(fcm2ParticipantList.Size());
|
|
unsigned int i;
|
|
for (i=0; i < fcm2ParticipantList.Size(); i++)
|
|
{
|
|
bsOut.Write(fcm2ParticipantList[i]->rakNetGuid);
|
|
bsOut.Write(rakPeerInterface->GetSystemAddressFromGuid(fcm2ParticipantList[i]->rakNetGuid));
|
|
|
|
BitStream vjsOut;
|
|
//WriteVJSUserData(&vjsOut, fcm2ParticipantList[i]->rakNetGuid, &fcm2ParticipantList[i]->userContext );
|
|
WriteVJSUserData(&vjsOut, fcm2ParticipantList[i]->rakNetGuid );
|
|
bsOut.Write(vjsOut.GetNumberOfBitsUsed());
|
|
bsOut.Write(&vjsOut);
|
|
bsOut.AlignWriteToByteBoundary();
|
|
}
|
|
SendUnified(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, client, false);
|
|
}
|
|
void FullyConnectedMesh2::RespondOnVerifiedJoinCapable(Packet *packet, bool accept, BitStream *additionalData)
|
|
{
|
|
VerifiedJoinInProgress vjip;
|
|
DecomposeJoinCapable(packet, &vjip);
|
|
|
|
DataStructures::List<RakNetGUID> participatingMembersOnClientSucceeded;
|
|
DataStructures::List<RakNetGUID> participatingMembersOnClientFailed;
|
|
DataStructures::List<RakNetGUID> participatingMembersNotOnClient;
|
|
DataStructures::List<RakNetGUID> clientMembersNotParticipatingSucceeded;
|
|
DataStructures::List<RakNetGUID> clientMembersNotParticipatingFailed;
|
|
CategorizeVJIP(&vjip,
|
|
participatingMembersOnClientSucceeded,
|
|
participatingMembersOnClientFailed,
|
|
participatingMembersNotOnClient,
|
|
clientMembersNotParticipatingSucceeded,
|
|
clientMembersNotParticipatingFailed);
|
|
|
|
if (participatingMembersNotOnClient.Size()>0)
|
|
{
|
|
BitStream bsOut;
|
|
bsOut.Write((MessageID) ID_FCM2_VERIFIED_JOIN_START);
|
|
bsOut.WriteCasted<unsigned short>(participatingMembersNotOnClient.Size());
|
|
unsigned int i;
|
|
for (i=0; i < participatingMembersNotOnClient.Size(); i++)
|
|
{
|
|
bsOut.Write(participatingMembersNotOnClient[i]);
|
|
bsOut.Write(rakPeerInterface->GetSystemAddressFromGuid(participatingMembersNotOnClient[i]));
|
|
|
|
bool written=false;
|
|
for (unsigned int j=0; j < fcm2ParticipantList.Size(); j++)
|
|
{
|
|
if (fcm2ParticipantList[j]->rakNetGuid == participatingMembersNotOnClient[i])
|
|
{
|
|
written=true;
|
|
|
|
BitStream vjsOut;
|
|
//WriteVJSUserData(&vjsOut, fcm2ParticipantList[j]->rakNetGuid, &fcm2ParticipantList[j]->userContext );
|
|
WriteVJSUserData(&vjsOut, fcm2ParticipantList[j]->rakNetGuid );
|
|
bsOut.Write(vjsOut.GetNumberOfBitsUsed());
|
|
bsOut.Write(&vjsOut);
|
|
bsOut.AlignWriteToByteBoundary();
|
|
break;
|
|
}
|
|
}
|
|
RakAssert(written==true);
|
|
}
|
|
SendUnified(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->guid, false);
|
|
return;
|
|
}
|
|
|
|
RakAssert(participatingMembersOnClientFailed.Size()==0);
|
|
RakAssert(participatingMembersNotOnClient.Size()==0);
|
|
|
|
RakNet::BitStream bsOut;
|
|
if (accept)
|
|
{
|
|
bsOut.Write((MessageID)ID_FCM2_VERIFIED_JOIN_ACCEPTED);
|
|
bsOut.Write(packet->guid);
|
|
|
|
// Tell client to disconnect from clientMembersNotParticipatingSucceeded
|
|
bsOut.WriteCasted<unsigned short>(clientMembersNotParticipatingSucceeded.Size());
|
|
for (unsigned int i=0; i < clientMembersNotParticipatingSucceeded.Size(); i++)
|
|
bsOut.Write(clientMembersNotParticipatingSucceeded[i]);
|
|
|
|
// Tell client to call AddParticipant() for participatingMembersOnClientSucceeded
|
|
bsOut.WriteCasted<unsigned short>(participatingMembersOnClientSucceeded.Size());
|
|
for (unsigned int i=0; i < participatingMembersOnClientSucceeded.Size(); i++)
|
|
bsOut.Write(participatingMembersOnClientSucceeded[i]);
|
|
|
|
if (additionalData)
|
|
bsOut.Write(additionalData);
|
|
|
|
for (unsigned int i=0; i < fcm2ParticipantList.Size(); i++)
|
|
SendUnified(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, fcm2ParticipantList[i]->rakNetGuid, false);
|
|
|
|
// Process immediately
|
|
// This is so if another ID_FCM2_VERIFIED_JOIN_CAPABLE is buffered, it responds with ID_FCM2_VERIFIED_JOIN_START
|
|
AddParticipant(packet->guid);
|
|
|
|
Packet *p = AllocatePacketUnified(bsOut.GetNumberOfBytesUsed());
|
|
memcpy(p->data, bsOut.GetData(), bsOut.GetNumberOfBytesUsed());
|
|
p->systemAddress=packet->systemAddress;
|
|
p->systemAddress.systemIndex=(SystemIndex)-1;
|
|
p->guid=packet->guid;
|
|
p->wasGeneratedLocally=true;
|
|
rakPeerInterface->PushBackPacket(p, true);
|
|
}
|
|
else
|
|
{
|
|
// Tell client rejected, otherwise process the same as ID_FCM2_VERIFIED_JOIN_FAILED
|
|
bsOut.Write((MessageID)ID_FCM2_VERIFIED_JOIN_REJECTED);
|
|
if (additionalData)
|
|
bsOut.Write(additionalData);
|
|
}
|
|
|
|
SendUnified(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->guid, false);
|
|
}
|
|
void FullyConnectedMesh2::GetVerifiedJoinRequiredProcessingList(RakNetGUID host, DataStructures::List<SystemAddress> &addresses, DataStructures::List<RakNetGUID> &guids, DataStructures::List<BitStream*> &userData)
|
|
{
|
|
addresses.Clear(true, _FILE_AND_LINE_);
|
|
guids.Clear(true, _FILE_AND_LINE_);
|
|
|
|
unsigned int curIndex = GetJoinsInProgressIndex(host);
|
|
if (curIndex!=(unsigned int) -1)
|
|
{
|
|
VerifiedJoinInProgress *vjip = joinsInProgress[curIndex];
|
|
unsigned int j;
|
|
for (j=0; j < vjip->vjipMembers.Size(); j++)
|
|
{
|
|
if (vjip->vjipMembers[j].joinInProgressState==JIPS_PROCESSING)
|
|
{
|
|
addresses.Push(vjip->vjipMembers[j].systemAddress, _FILE_AND_LINE_);
|
|
guids.Push(vjip->vjipMembers[j].guid, _FILE_AND_LINE_);
|
|
userData.Push(vjip->vjipMembers[j].userData, _FILE_AND_LINE_);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
void FullyConnectedMesh2::GetVerifiedJoinAcceptedAdditionalData(Packet *packet, bool *thisSystemAccepted, DataStructures::List<RakNetGUID> &systemsAccepted, BitStream *additionalData)
|
|
{
|
|
systemsAccepted.Clear(true, _FILE_AND_LINE_);
|
|
|
|
RakNet::BitStream bsIn(packet->data, packet->length, false);
|
|
bsIn.IgnoreBytes(sizeof(MessageID));
|
|
RakNetGUID systemToAddGuid;
|
|
bsIn.Read(systemToAddGuid);
|
|
*thisSystemAccepted = systemToAddGuid == rakPeerInterface->GetMyGUID();
|
|
unsigned short listSize;
|
|
bsIn.Read(listSize);
|
|
bsIn.IgnoreBytes(listSize*RakNetGUID::size());
|
|
bsIn.Read(listSize);
|
|
if (systemToAddGuid==rakPeerInterface->GetMyGUID())
|
|
{
|
|
for (unsigned short i=0; i < listSize; i++)
|
|
{
|
|
bsIn.Read(systemToAddGuid);
|
|
systemsAccepted.Push(systemToAddGuid, _FILE_AND_LINE_);
|
|
}
|
|
systemsAccepted.Push(packet->guid, _FILE_AND_LINE_);
|
|
}
|
|
else
|
|
{
|
|
systemsAccepted.Push(systemToAddGuid, _FILE_AND_LINE_);
|
|
bsIn.IgnoreBytes(listSize*RakNetGUID::size());
|
|
}
|
|
if (additionalData)
|
|
{
|
|
additionalData->Reset();
|
|
additionalData->Write(bsIn);
|
|
}
|
|
}
|
|
void FullyConnectedMesh2::GetVerifiedJoinRejectedAdditionalData(Packet *packet, BitStream *additionalData)
|
|
{
|
|
RakNet::BitStream bsIn(packet->data, packet->length, false);
|
|
bsIn.IgnoreBytes(sizeof(MessageID));
|
|
if (additionalData)
|
|
{
|
|
additionalData->Reset();
|
|
additionalData->Write(bsIn);
|
|
}
|
|
}
|
|
PluginReceiveResult FullyConnectedMesh2::OnVerifiedJoinStart(Packet *packet)
|
|
{
|
|
RakNet::BitStream bsIn(packet->data,packet->length,false);
|
|
bsIn.IgnoreBytes(sizeof(MessageID));
|
|
|
|
unsigned short listSize;
|
|
bsIn.Read(listSize);
|
|
|
|
unsigned int curIndex = GetJoinsInProgressIndex(packet->guid);
|
|
if (curIndex!=(unsigned int) -1)
|
|
{
|
|
// Got update to existing list
|
|
|
|
VerifiedJoinInProgress *vjip = joinsInProgress[curIndex];
|
|
// if (vjip->sentResults==false)
|
|
// {
|
|
// // Got ID_FCM2_VERIFIED_JOIN_START twice before sending ID_FCM2_VERIFIED_JOIN_CAPABLE
|
|
// RakAssert(vjip->sentResults!=false);
|
|
// return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
// }
|
|
|
|
for (unsigned int i=0; i < vjip->vjipMembers.Size(); i++)
|
|
{
|
|
vjip->vjipMembers[i].workingFlag=false;
|
|
}
|
|
|
|
// Server has updated list of participants
|
|
for (unsigned short i=0; i < listSize; i++)
|
|
{
|
|
VerifiedJoinInProgressMember vjipm;
|
|
ReadVerifiedJoinInProgressMember(&bsIn, &vjipm);
|
|
|
|
unsigned int j;
|
|
if (vjipm.guid!=UNASSIGNED_RAKNET_GUID)
|
|
j = GetVerifiedJoinInProgressMemberIndex(vjipm.guid, vjip);
|
|
else
|
|
j = GetVerifiedJoinInProgressMemberIndex(vjipm.systemAddress, vjip);
|
|
|
|
if (j==(unsigned int)-1)
|
|
{
|
|
// New
|
|
vjipm.workingFlag=true;
|
|
|
|
// 11/13/2013 - ReadVerifiedJoinInProgressMember already sets joinInProgressState
|
|
// http://www.jenkinssoftware.com/forum/index.php?topic=5211.0
|
|
// vjipm.joinInProgressState=JIPS_PROCESSING;
|
|
vjip->vjipMembers.Push(vjipm, _FILE_AND_LINE_);
|
|
|
|
// Allow resend of ID_FCM2_VERIFIED_JOIN_CAPABLE
|
|
//vjip->sentResults=false;
|
|
}
|
|
else
|
|
{
|
|
vjip->vjipMembers[j].workingFlag=true;
|
|
}
|
|
}
|
|
|
|
for (unsigned int i=0; i < vjip->vjipMembers.Size(); i++)
|
|
{
|
|
if (vjip->vjipMembers[i].workingFlag==false)
|
|
vjip->vjipMembers[i].joinInProgressState=JIPS_UNNECESSARY;
|
|
}
|
|
|
|
if (ProcessVerifiedJoinInProgressIfCompleted(vjip))
|
|
{
|
|
// Completed
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
}
|
|
|
|
// Else tell user about new list
|
|
return RR_CONTINUE_PROCESSING;
|
|
}
|
|
|
|
VerifiedJoinInProgress *vjip = RakNet::OP_NEW<VerifiedJoinInProgress>(_FILE_AND_LINE_);
|
|
vjip->requester=packet->guid;
|
|
if (listSize==0)
|
|
{
|
|
//vjip->sentResults=true;
|
|
|
|
// Send back result
|
|
RakNet::BitStream bsOut;
|
|
bsOut.Write((MessageID)ID_FCM2_VERIFIED_JOIN_CAPABLE);
|
|
bsOut.WriteCasted<unsigned short>(0);
|
|
WriteVJCUserData(&bsOut);
|
|
SendUnified(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->guid, false);
|
|
//vjip->sentResults=true;
|
|
joinsInProgress.Push(vjip, _FILE_AND_LINE_);
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
}
|
|
|
|
//vjip->sentResults=false;
|
|
|
|
for (unsigned short i=0; i < listSize; i++)
|
|
{
|
|
VerifiedJoinInProgressMember vjipm;
|
|
ReadVerifiedJoinInProgressMember(&bsIn, &vjipm);
|
|
vjip->vjipMembers.Push(vjipm, _FILE_AND_LINE_);
|
|
}
|
|
|
|
joinsInProgress.Push(vjip, _FILE_AND_LINE_);
|
|
|
|
// 11/13/2013 - ReadVerifiedJoinInProgressMember may set JIPS_CONNECTED, so this may already be done
|
|
// http://www.jenkinssoftware.com/forum/index.php?topic=5211.0
|
|
if (ProcessVerifiedJoinInProgressIfCompleted(vjip))
|
|
{
|
|
// Completed
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
}
|
|
|
|
return RR_CONTINUE_PROCESSING;
|
|
}
|
|
void FullyConnectedMesh2::SkipToVJCUserData(RakNet::BitStream *bsIn)
|
|
{
|
|
bsIn->IgnoreBytes(sizeof(MessageID));
|
|
unsigned short listSize;
|
|
bsIn->Read(listSize);
|
|
for (unsigned short i=0; i < listSize; i++)
|
|
{
|
|
bsIn->IgnoreBytes(RakNetGUID::size());
|
|
bsIn->IgnoreBytes(SystemAddress::size());
|
|
bsIn->IgnoreBytes(sizeof(unsigned char));
|
|
}
|
|
}
|
|
void FullyConnectedMesh2::DecomposeJoinCapable(Packet *packet, VerifiedJoinInProgress *vjip)
|
|
{
|
|
RakNet::BitStream bsIn(packet->data,packet->length,false);
|
|
bsIn.IgnoreBytes(sizeof(MessageID));
|
|
|
|
unsigned short listSize;
|
|
bsIn.Read(listSize);
|
|
|
|
for (unsigned short i=0; i < listSize; i++)
|
|
{
|
|
VerifiedJoinInProgressMember member;
|
|
bsIn.Read(member.guid);
|
|
bsIn.Read(member.systemAddress);
|
|
bsIn.ReadCasted<unsigned char>(member.joinInProgressState);
|
|
member.userData = 0;
|
|
member.workingFlag=false;
|
|
vjip->vjipMembers.Push(member, _FILE_AND_LINE_);
|
|
}
|
|
}
|
|
PluginReceiveResult FullyConnectedMesh2::OnVerifiedJoinCapable(Packet *packet)
|
|
{
|
|
VerifiedJoinInProgress vjip;
|
|
DecomposeJoinCapable(packet, &vjip);
|
|
|
|
// If this assert hits, AddParticipant() was called on this system, or another system, which it should not have been.
|
|
RakAssert(HasParticipant(packet->guid)==false);
|
|
|
|
DataStructures::List<RakNetGUID> participatingMembersOnClientSucceeded;
|
|
DataStructures::List<RakNetGUID> participatingMembersOnClientFailed;
|
|
DataStructures::List<RakNetGUID> participatingMembersNotOnClient;
|
|
DataStructures::List<RakNetGUID> clientMembersNotParticipatingSucceeded;
|
|
DataStructures::List<RakNetGUID> clientMembersNotParticipatingFailed;
|
|
CategorizeVJIP(&vjip,
|
|
participatingMembersOnClientSucceeded,
|
|
participatingMembersOnClientFailed,
|
|
participatingMembersNotOnClient,
|
|
clientMembersNotParticipatingSucceeded,
|
|
clientMembersNotParticipatingFailed);
|
|
|
|
if (participatingMembersOnClientFailed.Size()>0)
|
|
{
|
|
// Send ID_FCM2_VERIFIED_JOIN_FAILED with GUIDs to disconnect
|
|
BitStream bsOut;
|
|
bsOut.Write((MessageID) ID_FCM2_VERIFIED_JOIN_FAILED);
|
|
SendUnified(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->guid, false);
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
}
|
|
|
|
if (participatingMembersNotOnClient.Size()>0)
|
|
{
|
|
BitStream bsOut;
|
|
bsOut.Write((MessageID) ID_FCM2_VERIFIED_JOIN_START);
|
|
bsOut.WriteCasted<unsigned short>(participatingMembersNotOnClient.Size());
|
|
unsigned int i;
|
|
for (i=0; i < participatingMembersNotOnClient.Size(); i++)
|
|
{
|
|
bsOut.Write(participatingMembersNotOnClient[i]);
|
|
bsOut.Write(rakPeerInterface->GetSystemAddressFromGuid(participatingMembersNotOnClient[i]));
|
|
|
|
bool written=false;
|
|
for (unsigned int j=0; j < fcm2ParticipantList.Size(); j++)
|
|
{
|
|
if (fcm2ParticipantList[j]->rakNetGuid == participatingMembersNotOnClient[i])
|
|
{
|
|
written=true;
|
|
|
|
BitStream vjsOut;
|
|
//WriteVJSUserData(&vjsOut, fcm2ParticipantList[j]->rakNetGuid, &fcm2ParticipantList[j]->userContext );
|
|
WriteVJSUserData(&vjsOut, fcm2ParticipantList[j]->rakNetGuid );
|
|
bsOut.Write(vjsOut.GetNumberOfBitsUsed());
|
|
bsOut.Write(&vjsOut);
|
|
bsOut.AlignWriteToByteBoundary();
|
|
break;
|
|
}
|
|
}
|
|
RakAssert(written);
|
|
}
|
|
SendUnified(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->guid, false);
|
|
return RR_STOP_PROCESSING_AND_DEALLOCATE;
|
|
}
|
|
|
|
// Let server decide if to accept or reject via RespondOnVerifiedJoinCapable
|
|
return RR_CONTINUE_PROCESSING;
|
|
}
|
|
void FullyConnectedMesh2::OnVerifiedJoinFailed(RakNetGUID hostGuid, bool callCloseConnection)
|
|
{
|
|
unsigned int curIndex = GetJoinsInProgressIndex(hostGuid);
|
|
if (curIndex==(unsigned int) -1)
|
|
return;
|
|
|
|
if (callCloseConnection)
|
|
{
|
|
VerifiedJoinInProgress *vjip = joinsInProgress[curIndex];
|
|
for (unsigned int j=0; j < vjip->vjipMembers.Size(); j++)
|
|
{
|
|
if (vjip->vjipMembers[j].joinInProgressState!=JIPS_FAILED)
|
|
{
|
|
rakPeerInterface->CloseConnection(vjip->vjipMembers[j].guid, true);
|
|
}
|
|
|
|
if (vjip->vjipMembers[j].userData != 0)
|
|
RakNet::OP_DELETE(vjip->vjipMembers[j].userData, _FILE_AND_LINE_);
|
|
}
|
|
}
|
|
|
|
for (unsigned int j=0; j < joinsInProgress[curIndex]->vjipMembers.Size(); j++)
|
|
{
|
|
if ( joinsInProgress[curIndex]->vjipMembers[j].userData != 0)
|
|
{
|
|
RakNet::OP_DELETE(joinsInProgress[curIndex]->vjipMembers[j].userData, _FILE_AND_LINE_);
|
|
}
|
|
}
|
|
|
|
|
|
// Clear joinsInProgress for packet->guid
|
|
RakNet::OP_DELETE(joinsInProgress[curIndex], _FILE_AND_LINE_);
|
|
joinsInProgress.RemoveAtIndex(curIndex);
|
|
}
|
|
void FullyConnectedMesh2::OnVerifiedJoinAccepted(Packet *packet)
|
|
{
|
|
RakNet::BitStream bsIn(packet->data,packet->length,false);
|
|
bsIn.IgnoreBytes(sizeof(MessageID));
|
|
|
|
RakNetGUID systemToAddGuid;
|
|
bsIn.Read(systemToAddGuid);
|
|
|
|
if (systemToAddGuid==rakPeerInterface->GetMyGUID())
|
|
{
|
|
// My own system
|
|
unsigned int curIndex = GetJoinsInProgressIndex(packet->guid);
|
|
if (curIndex==(unsigned int)-1)
|
|
return;
|
|
|
|
unsigned short listSize;
|
|
bsIn.Read(listSize);
|
|
for (unsigned short i=0; i < listSize; i++)
|
|
{
|
|
// List of clientMembersNotParticipatingSucceeded
|
|
RakNetGUID guid;
|
|
bsIn.Read(guid);
|
|
rakPeerInterface->CloseConnection(guid, true);
|
|
}
|
|
|
|
bsIn.Read(listSize);
|
|
for (unsigned short i=0; i < listSize; i++)
|
|
{
|
|
// List of participatingMembersOnClientSucceeded
|
|
RakNetGUID guid;
|
|
bsIn.Read(guid);
|
|
AddParticipant(guid);
|
|
}
|
|
AddParticipant(packet->guid);
|
|
|
|
for (unsigned int j=0; j < joinsInProgress[curIndex]->vjipMembers.Size(); j++)
|
|
{
|
|
if ( joinsInProgress[curIndex]->vjipMembers[j].userData != 0)
|
|
{
|
|
RakNet::OP_DELETE(joinsInProgress[curIndex]->vjipMembers[j].userData, _FILE_AND_LINE_);
|
|
}
|
|
}
|
|
|
|
// Clear joinsInProgress for packet->guid
|
|
RakNet::OP_DELETE(joinsInProgress[curIndex], _FILE_AND_LINE_);
|
|
joinsInProgress.RemoveAtIndex(curIndex);
|
|
}
|
|
else
|
|
{
|
|
// Another system
|
|
ConnectionState cs = rakPeerInterface->GetConnectionState(systemToAddGuid);
|
|
RakAssert(cs==IS_CONNECTED);
|
|
if (cs==IS_CONNECTED)
|
|
AddParticipant(systemToAddGuid);
|
|
}
|
|
}
|
|
void FullyConnectedMesh2::OnVerifiedJoinRejected(Packet *packet)
|
|
{
|
|
OnVerifiedJoinFailed(packet->guid, true);
|
|
}
|
|
unsigned int FullyConnectedMesh2::GetJoinsInProgressIndex(RakNetGUID requester) const
|
|
{
|
|
for (unsigned int i=0; i < joinsInProgress.Size(); i++)
|
|
{
|
|
if (joinsInProgress[i]->requester==requester)
|
|
return i;
|
|
}
|
|
return (unsigned int) -1;
|
|
}
|
|
void FullyConnectedMesh2::UpdateVerifiedJoinInProgressMember(const AddressOrGUID systemIdentifier, RakNetGUID guidToAssign, FullyConnectedMesh2::JoinInProgressState newState)
|
|
{
|
|
bool anythingChanged;
|
|
|
|
for (unsigned int i=0; i < joinsInProgress.Size(); i++)
|
|
{
|
|
VerifiedJoinInProgress *vjip = joinsInProgress[i];
|
|
//if (vjip->sentResults==true)
|
|
// continue;
|
|
anythingChanged=false;
|
|
|
|
unsigned int j;
|
|
j = GetVerifiedJoinInProgressMemberIndex(systemIdentifier, vjip);
|
|
if (j!=(unsigned int)-1)
|
|
{
|
|
if (vjip->vjipMembers[j].guid==UNASSIGNED_RAKNET_GUID && guidToAssign!=UNASSIGNED_RAKNET_GUID)
|
|
vjip->vjipMembers[j].guid = guidToAssign;
|
|
|
|
if (vjip->vjipMembers[j].joinInProgressState==JIPS_PROCESSING)
|
|
{
|
|
anythingChanged=true;
|
|
vjip->vjipMembers[j].joinInProgressState=newState;
|
|
}
|
|
}
|
|
|
|
if (anythingChanged)
|
|
{
|
|
ProcessVerifiedJoinInProgressIfCompleted(vjip);
|
|
}
|
|
}
|
|
}
|
|
bool FullyConnectedMesh2::ProcessVerifiedJoinInProgressIfCompleted(VerifiedJoinInProgress *vjip)
|
|
{
|
|
//if (vjip->sentResults)
|
|
// return true;
|
|
|
|
// If no systems in processing state, send results to server
|
|
// Return true if this was done
|
|
bool anyProcessing=false;
|
|
for (unsigned int i=0; i < vjip->vjipMembers.Size(); i++)
|
|
{
|
|
if (vjip->vjipMembers[i].joinInProgressState==JIPS_PROCESSING)
|
|
{
|
|
anyProcessing=true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (anyProcessing==true)
|
|
return false;
|
|
|
|
// Send results to server
|
|
BitStream bsOut;
|
|
WriteVerifiedJoinCapable(&bsOut, vjip);
|
|
WriteVJCUserData(&bsOut);
|
|
SendUnified(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, vjip->requester, false);
|
|
|
|
//vjip->sentResults=true;
|
|
return true;
|
|
}
|
|
void FullyConnectedMesh2::WriteVerifiedJoinCapable(RakNet::BitStream *bsOut, VerifiedJoinInProgress *vjip)
|
|
{
|
|
bsOut->Write((MessageID) ID_FCM2_VERIFIED_JOIN_CAPABLE);
|
|
bsOut->WriteCasted<unsigned short>(vjip->vjipMembers.Size());
|
|
unsigned int i;
|
|
for (i=0; i < vjip->vjipMembers.Size(); i++)
|
|
{
|
|
bsOut->Write(vjip->vjipMembers[i].guid);
|
|
bsOut->Write(vjip->vjipMembers[i].systemAddress);
|
|
bsOut->WriteCasted<unsigned char>(vjip->vjipMembers[i].joinInProgressState);
|
|
}
|
|
}
|
|
|
|
void FullyConnectedMesh2::ReadVerifiedJoinInProgressMember(RakNet::BitStream *bsIn, VerifiedJoinInProgressMember *vjipm)
|
|
{
|
|
bsIn->Read(vjipm->guid);
|
|
bsIn->Read(vjipm->systemAddress);
|
|
ConnectionState cs = rakPeerInterface->GetConnectionState(vjipm->guid);
|
|
if (cs==IS_CONNECTED)
|
|
vjipm->joinInProgressState=JIPS_CONNECTED;
|
|
else if (cs==IS_DISCONNECTING || cs==IS_SILENTLY_DISCONNECTING)
|
|
vjipm->joinInProgressState=JIPS_FAILED;
|
|
else
|
|
vjipm->joinInProgressState=JIPS_PROCESSING;
|
|
|
|
BitSize_t vjsUserDataSize;
|
|
bsIn->Read(vjsUserDataSize);
|
|
if (vjsUserDataSize > 0)
|
|
{
|
|
vjipm->userData = RakNet::OP_NEW<BitStream>(_FILE_AND_LINE_);
|
|
bsIn->Read(vjipm->userData, vjsUserDataSize);
|
|
}
|
|
else
|
|
vjipm->userData = 0;
|
|
bsIn->AlignReadToByteBoundary();
|
|
}
|
|
|
|
unsigned int FullyConnectedMesh2::GetVerifiedJoinInProgressMemberIndex(const AddressOrGUID systemIdentifier, VerifiedJoinInProgress *vjip)
|
|
{
|
|
for (unsigned int j=0; j < vjip->vjipMembers.Size(); j++)
|
|
{
|
|
if ((systemIdentifier.rakNetGuid!=UNASSIGNED_RAKNET_GUID && vjip->vjipMembers[j].guid==systemIdentifier.rakNetGuid) ||
|
|
(systemIdentifier.systemAddress!=UNASSIGNED_SYSTEM_ADDRESS && vjip->vjipMembers[j].systemAddress==systemIdentifier.systemAddress))
|
|
{
|
|
return j;
|
|
}
|
|
}
|
|
return (unsigned int) -1;
|
|
}
|
|
|
|
void FullyConnectedMesh2::CategorizeVJIP(VerifiedJoinInProgress *vjip,
|
|
DataStructures::List<RakNetGUID> &participatingMembersOnClientSucceeded,
|
|
DataStructures::List<RakNetGUID> &participatingMembersOnClientFailed,
|
|
DataStructures::List<RakNetGUID> &participatingMembersNotOnClient,
|
|
DataStructures::List<RakNetGUID> &clientMembersNotParticipatingSucceeded,
|
|
DataStructures::List<RakNetGUID> &clientMembersNotParticipatingFailed)
|
|
{
|
|
for (unsigned int i=0; i < vjip->vjipMembers.Size(); i++)
|
|
vjip->vjipMembers[i].workingFlag=false;
|
|
|
|
for (unsigned int i=0; i < fcm2ParticipantList.Size(); i++)
|
|
{
|
|
unsigned int j = GetVerifiedJoinInProgressMemberIndex(fcm2ParticipantList[i]->rakNetGuid, vjip);
|
|
if (j==(unsigned int)-1)
|
|
{
|
|
participatingMembersNotOnClient.Push(fcm2ParticipantList[i]->rakNetGuid, _FILE_AND_LINE_);
|
|
}
|
|
else
|
|
{
|
|
if (vjip->vjipMembers[j].joinInProgressState==JIPS_FAILED)
|
|
participatingMembersOnClientFailed.Push(fcm2ParticipantList[i]->rakNetGuid, _FILE_AND_LINE_);
|
|
else
|
|
participatingMembersOnClientSucceeded.Push(fcm2ParticipantList[i]->rakNetGuid, _FILE_AND_LINE_);
|
|
vjip->vjipMembers[j].workingFlag=true;
|
|
}
|
|
}
|
|
|
|
|
|
for (unsigned int j=0; j < vjip->vjipMembers.Size(); j++)
|
|
{
|
|
if (vjip->vjipMembers[j].workingFlag==false)
|
|
{
|
|
if (vjip->vjipMembers[j].joinInProgressState==JIPS_FAILED)
|
|
clientMembersNotParticipatingFailed.Push(vjip->vjipMembers[j].guid, _FILE_AND_LINE_);
|
|
else
|
|
clientMembersNotParticipatingSucceeded.Push(vjip->vjipMembers[j].guid, _FILE_AND_LINE_);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif // _RAKNET_SUPPORT_*
|