/* * 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 &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 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(_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 &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]->fcm2Guidfcm2Guid; 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(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 participatingMembersOnClientSucceeded; DataStructures::List participatingMembersOnClientFailed; DataStructures::List participatingMembersNotOnClient; DataStructures::List clientMembersNotParticipatingSucceeded; DataStructures::List clientMembersNotParticipatingFailed; CategorizeVJIP(&vjip, participatingMembersOnClientSucceeded, participatingMembersOnClientFailed, participatingMembersNotOnClient, clientMembersNotParticipatingSucceeded, clientMembersNotParticipatingFailed); if (participatingMembersNotOnClient.Size()>0) { BitStream bsOut; bsOut.Write((MessageID) ID_FCM2_VERIFIED_JOIN_START); bsOut.WriteCasted(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(clientMembersNotParticipatingSucceeded.Size()); for (unsigned int i=0; i < clientMembersNotParticipatingSucceeded.Size(); i++) bsOut.Write(clientMembersNotParticipatingSucceeded[i]); // Tell client to call AddParticipant() for participatingMembersOnClientSucceeded bsOut.WriteCasted(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 &addresses, DataStructures::List &guids, DataStructures::List &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 &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(_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(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(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 participatingMembersOnClientSucceeded; DataStructures::List participatingMembersOnClientFailed; DataStructures::List participatingMembersNotOnClient; DataStructures::List clientMembersNotParticipatingSucceeded; DataStructures::List 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(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(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(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(_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 &participatingMembersOnClientSucceeded, DataStructures::List &participatingMembersOnClientFailed, DataStructures::List &participatingMembersNotOnClient, DataStructures::List &clientMembersNotParticipatingSucceeded, DataStructures::List &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_*