Files
mcpe/thirdparty/raknet/FullyConnectedMesh2.cpp
iProgramInCpp 9642818a88 * Initial commit.
:)
2023-07-30 22:22:02 +03:00

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_*