• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

FullyConnectedMesh2.cpp

Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 
00006 
00007 #include "NativeFeatureIncludes.h"
00008 #if _RAKNET_SUPPORT_FullyConnectedMesh2==1
00009 
00010 #include "FullyConnectedMesh2.h"
00011 #include "RakPeerInterface.h"
00012 #include "MessageIdentifiers.h"
00013 #include "BitStream.h"
00014 #include "RakAssert.h"
00015 #include "GetTime.h"
00016 #include "Rand.h"
00017 
00018 // #define DEBUG_FCM2
00019 
00020 FullyConnectedMesh2::FullyConnectedMesh2()
00021 {
00022         startupTime=0;
00023         totalConnectionCount=0;
00024         ourFCMGuid=0;
00025         autoParticipateConnections=true;
00026         connectOnNewRemoteConnections=true;
00027 }
00028 FullyConnectedMesh2::~FullyConnectedMesh2()
00029 {
00030         Clear();
00031 }
00032 RakNetGUID FullyConnectedMesh2::GetConnectedHost(void) const
00033 {
00034         if (ourFCMGuid==0)
00035                 return UNASSIGNED_RAKNET_GUID;
00036         return hostRakNetGuid;
00037 }
00038 SystemAddress FullyConnectedMesh2::GetConnectedHostAddr(void) const
00039 {
00040         if (ourFCMGuid==0)
00041                 return UNASSIGNED_SYSTEM_ADDRESS;
00042         return rakPeerInterface->GetSystemAddressFromGuid(hostRakNetGuid);
00043 }
00044 RakNetGUID FullyConnectedMesh2::GetHostSystem(void) const
00045 {
00046         if (ourFCMGuid==0)
00047                 return rakPeerInterface->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS);
00048 
00049         return hostRakNetGuid;
00050 }
00051 bool FullyConnectedMesh2::IsHostSystem(void) const
00052 {
00053         return GetHostSystem()==rakPeerInterface->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS);
00054 }
00055 bool FullyConnectedMesh2::IsConnectedHost(void) const
00056 {
00057         return GetConnectedHost()==rakPeerInterface->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS);
00058 }
00059 void FullyConnectedMesh2::SetAutoparticipateConnections(bool b)
00060 {
00061         autoParticipateConnections=b;
00062 }
00063 void FullyConnectedMesh2::ResetHostCalculation(void)
00064 {
00065         startupTime=RakNet::GetTimeUS();
00066         totalConnectionCount=0;
00067         ourFCMGuid=0;
00068         for (unsigned int i=0; i < participantList.Size(); i++)
00069                 SendFCMGuidRequest(participantList[i].rakNetGuid);
00070 }
00071 bool FullyConnectedMesh2::AddParticipantInternal( RakNetGUID rakNetGuid, FCM2Guid theirFCMGuid )
00072 {
00073         for (unsigned int i=0; i < participantList.Size(); i++)
00074         {
00075                 if (participantList[i].rakNetGuid==rakNetGuid)
00076                 {
00077                         if (theirFCMGuid!=0)
00078                                 participantList[i].fcm2Guid=theirFCMGuid;
00079                         return false;
00080                 }
00081         }
00082 
00083         FCM2Participant participant;
00084         participant.rakNetGuid=rakNetGuid;
00085         participant.fcm2Guid=theirFCMGuid;
00086         participantList.Push(participant,__FILE__,__LINE__);
00087 
00088         SendFCMGuidRequest(rakNetGuid);
00089 
00090         return true;
00091 }
00092 void FullyConnectedMesh2::AddParticipant( RakNetGUID rakNetGuid )
00093 {
00094         if (rakPeerInterface->IsConnected(rakPeerInterface->GetSystemAddressFromGuid(rakNetGuid),false,false)==false)
00095         {
00096 #ifdef DEBUG_FCM2
00097                 printf("AddParticipant to %s failed (not connected)\n", rakNetGuid.ToString());
00098 #endif
00099                 return;
00100         }
00101 
00102         AddParticipantInternal(rakNetGuid,0);
00103 }
00104 PluginReceiveResult FullyConnectedMesh2::OnReceive(Packet *packet)
00105 {
00106         switch (packet->data[0])
00107         {
00108         case ID_REMOTE_NEW_INCOMING_CONNECTION:
00109                 {
00110                         if (connectOnNewRemoteConnections)
00111                         {
00112                                 unsigned int count;
00113                                 RakNet::BitStream bsIn(packet->data, packet->length, false);
00114                                 bsIn.IgnoreBytes(sizeof(MessageID));
00115                                 bsIn.Read(count);
00116                                 SystemAddress remoteAddress;
00117                                 RakNetGUID remoteGuid;
00118                                 char str[64];
00119                                 for (unsigned int i=0; i < count; i++)
00120                                 {
00121                                         bsIn.Read(remoteAddress);
00122                                         bsIn.Read(remoteGuid);
00123                                         remoteAddress.ToString(false,str);
00124                                         rakPeerInterface->Connect(str,remoteAddress.port,connectionPassword.C_String(),(int) connectionPassword.GetLength());
00125                                 }
00126                         }
00127                 }
00128                 break;
00129         case ID_FCM2_REQUEST_FCMGUID:
00130                 OnRequestFCMGuid(packet);
00131                 return RR_STOP_PROCESSING_AND_DEALLOCATE;
00132         case ID_FCM2_RESPOND_CONNECTION_COUNT:
00133                 OnRespondConnectionCount(packet);
00134                 return RR_STOP_PROCESSING_AND_DEALLOCATE;
00135         case ID_FCM2_INFORM_FCMGUID:
00136                 OnInformFCMGuid(packet);
00137                 return RR_STOP_PROCESSING_AND_DEALLOCATE;
00138         }
00139         return RR_CONTINUE_PROCESSING;
00140 }
00141 void FullyConnectedMesh2::OnRakPeerStartup(void)
00142 {
00143         Clear();
00144         startupTime=RakNet::GetTimeUS();
00145 }
00146 void FullyConnectedMesh2::OnAttach(void)
00147 {
00148         Clear();
00149         // In case Startup() was called first
00150         if (rakPeerInterface->IsActive())
00151                 startupTime=RakNet::GetTimeUS();
00152 }
00153 void FullyConnectedMesh2::OnRakPeerShutdown(void)
00154 {
00155         Clear();
00156         startupTime=0;
00157 }
00158 void FullyConnectedMesh2::OnClosedConnection(SystemAddress systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
00159 {
00160         (void) lostConnectionReason;
00161         (void) systemAddress;
00162         (void) rakNetGUID;
00163 
00164         unsigned int idx;
00165         for (idx=0; idx < participantList.Size(); idx++)
00166         {
00167                 if (participantList[idx].rakNetGuid==rakNetGUID)
00168                 {
00169                         participantList[idx]=participantList[participantList.Size()-1];
00170 #ifdef DEBUG_FCM2
00171                         printf("Popping participant %s\n", participantList[participantList.Size()-1].rakNetGuid.ToString());
00172 #endif
00173 
00174                         participantList.Pop();
00175                         if (rakNetGUID==hostRakNetGuid && ourFCMGuid!=0)
00176                         {       
00177                                 if (participantList.Size()==0)
00178                                 {
00179                                         hostRakNetGuid=UNASSIGNED_RAKNET_GUID;
00180                                         hostFCM2Guid=ourFCMGuid;
00181                                 }
00182                                 else
00183                                 {
00184                                         CalculateHost(&hostRakNetGuid, &hostFCM2Guid);
00185                                 }
00186                                 PushNewHost(hostRakNetGuid);
00187                         }
00188                         return;
00189                 }
00190         }
00191 
00192 }
00193 RakNetTimeUS FullyConnectedMesh2::GetElapsedRuntime(void)
00194 {
00195         RakNetTimeUS curTime=RakNet::GetTimeUS();
00196         if (curTime>startupTime)
00197                 return curTime-startupTime;
00198         else
00199                 return 0;
00200 }
00201 void FullyConnectedMesh2::OnNewConnection(SystemAddress systemAddress, RakNetGUID rakNetGUID, bool isIncoming)
00202 {
00203         (void) isIncoming;
00204         (void) rakNetGUID;
00205         (void) systemAddress;
00206 
00207         if (autoParticipateConnections)
00208                 AddParticipant(rakNetGUID);
00209 }
00210 void FullyConnectedMesh2::Clear(void)
00211 {
00212         participantList.Clear(false, __FILE__,__LINE__);
00213 
00214         totalConnectionCount=0;
00215         ourFCMGuid=0;
00216         lastPushedHost=UNASSIGNED_RAKNET_GUID;
00217 }
00218 void FullyConnectedMesh2::PushNewHost(const RakNetGUID &guid)
00219 {
00220         Packet *p = rakPeerInterface->AllocatePacket(sizeof(MessageID));
00221         p->data[0]=ID_FCM2_NEW_HOST;
00222         p->systemAddress=rakPeerInterface->GetSystemAddressFromGuid(guid);
00223         p->systemAddress.systemIndex=(SystemIndex)-1;
00224         p->guid=guid;
00225         rakPeerInterface->PushBackPacket(p, true);
00226 
00227         lastPushedHost=guid;
00228 }
00229 void FullyConnectedMesh2::SendFCMGuidRequest(RakNetGUID rakNetGuid)
00230 {
00231         if (rakNetGuid==rakPeerInterface->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS))
00232                 return;
00233 
00234         RakNet::BitStream bsOut;
00235         bsOut.Write((MessageID)ID_FCM2_REQUEST_FCMGUID);
00236         if (ourFCMGuid==0)
00237         {
00238                 bsOut.Write(false);
00239                 bsOut.Write(GetElapsedRuntime());
00240         }
00241         else
00242         {
00243                 bsOut.Write(true);
00244                 bsOut.Write(totalConnectionCount);
00245                 bsOut.Write(ourFCMGuid);
00246         }
00247         rakPeerInterface->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,rakNetGuid,false);
00248 }
00249 void FullyConnectedMesh2::SendOurFCMGuid(SystemAddress addr)
00250 {
00251         RakNet::BitStream bsOut;
00252         bsOut.Write((MessageID)ID_FCM2_INFORM_FCMGUID);
00253         RakAssert(ourFCMGuid!=0); // Can't inform others of our FCM2Guid if it's unset!
00254         bsOut.Write(ourFCMGuid);
00255         bsOut.Write(totalConnectionCount);
00256         rakPeerInterface->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,addr,false);
00257 }
00258 void FullyConnectedMesh2::SendConnectionCountResponse(SystemAddress addr, unsigned int responseTotalConnectionCount)
00259 {
00260         RakNet::BitStream bsOut;
00261         bsOut.Write((MessageID)ID_FCM2_RESPOND_CONNECTION_COUNT);
00262         bsOut.Write(responseTotalConnectionCount);
00263         rakPeerInterface->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,addr,false);
00264 }
00265 void FullyConnectedMesh2::AssignOurFCMGuid(void)
00266 {
00267         // Only assigned once ever
00268         RakAssert(ourFCMGuid==0);
00269         unsigned int randomNumber = randomMT();
00270         randomNumber ^= (unsigned int) (RakNet::GetTimeUS() & 0xFFFFFFFF);
00271         randomNumber ^= (unsigned int) (rakPeerInterface->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS).g & 0xFFFFFFFF);
00272         ourFCMGuid |= randomNumber;
00273         uint64_t reponse64 = totalConnectionCount;
00274         ourFCMGuid |= reponse64<<32;
00275 }
00276 void FullyConnectedMesh2::CalculateHost(RakNetGUID *rakNetGuid, FCM2Guid *fcm2Guid)
00277 {
00278         // Can't calculate host without knowing our own
00279         RakAssert(ourFCMGuid!=0);
00280 
00281         // Can't calculate host without being connected to anyone else
00282         RakAssert(participantList.Size()>0);
00283 
00284         // Return the lowest value of all FCM2Guid
00285         FCM2Guid lowestFCMGuid=ourFCMGuid;
00286 //      SystemAddress associatedSystemAddress=UNASSIGNED_SYSTEM_ADDRESS;
00287         RakNetGUID associatedRakNetGuid=rakPeerInterface->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS);
00288 
00289         DataStructures::DefaultIndexType idx;
00290         for (idx=0; idx < participantList.Size(); idx++)
00291         {
00292                 if (participantList[idx].fcm2Guid!=0 && participantList[idx].fcm2Guid<lowestFCMGuid)
00293                 {
00294                         lowestFCMGuid=participantList[idx].fcm2Guid;
00295                         associatedRakNetGuid=participantList[idx].rakNetGuid;
00296                 }
00297         }
00298 
00299         *rakNetGuid=associatedRakNetGuid;
00300         *fcm2Guid=lowestFCMGuid;
00301 }
00302 void FullyConnectedMesh2::OnRequestFCMGuid(Packet *packet)
00303 {
00304         RakNet::BitStream bsIn(packet->data,packet->length,false);
00305         bsIn.IgnoreBytes(sizeof(MessageID));
00306         bool hasRemoteFCMGuid;
00307         bsIn.Read(hasRemoteFCMGuid);
00308         RakNetTimeUS senderElapsedRuntime=0;
00309         unsigned int remoteTotalConnectionCount=0;
00310         FCM2Guid theirFCMGuid=0;
00311         if (hasRemoteFCMGuid)
00312         {
00313                 bsIn.Read(remoteTotalConnectionCount);
00314                 bsIn.Read(theirFCMGuid);
00315         }
00316         else
00317         {
00318                 bsIn.Read(senderElapsedRuntime);
00319         }
00320         AddParticipantInternal(packet->guid,theirFCMGuid);
00321         if (ourFCMGuid==0)
00322         {
00323                 if (hasRemoteFCMGuid==false)
00324                 {
00325                         // Nobody has a fcmGuid
00326 
00327                         RakNetTimeUS ourElapsedRuntime = GetElapsedRuntime();
00328                         if (ourElapsedRuntime>senderElapsedRuntime)
00329                         {
00330                                 // We are probably host
00331                                 SendConnectionCountResponse(packet->systemAddress, 2);
00332                         }
00333                         else
00334                         {
00335                                 // They are probably host
00336                                 SendConnectionCountResponse(packet->systemAddress, 1);
00337                         }
00338                 }
00339                 else
00340                 {
00341                         // They have a fcmGuid, we do not
00342 
00343                         IncrementTotalConnectionCount(remoteTotalConnectionCount+1);
00344 
00345                         AssignOurFCMGuid();
00346                         DataStructures::DefaultIndexType idx;
00347                         for (idx=0; idx < participantList.Size(); idx++)
00348                                 SendOurFCMGuid(rakPeerInterface->GetSystemAddressFromGuid(participantList[idx].rakNetGuid));
00349                 }
00350         }
00351         else
00352         {
00353                 if (hasRemoteFCMGuid==false)
00354                 {
00355                         // We have a fcmGuid they do not
00356 
00357                         SendConnectionCountResponse(packet->systemAddress, totalConnectionCount+1);
00358 
00359                 }
00360                 else
00361                 {
00362                         // We both have fcmGuids
00363 
00364                         IncrementTotalConnectionCount(remoteTotalConnectionCount);
00365 
00366                         SendOurFCMGuid(packet->systemAddress);
00367                 }
00368         }
00369         CalculateAndPushHost();
00370 }
00371 void FullyConnectedMesh2::OnRespondConnectionCount(Packet *packet)
00372 {
00373         RakNet::BitStream bsIn(packet->data,packet->length,false);
00374         bsIn.IgnoreBytes(sizeof(MessageID));
00375         unsigned int responseTotalConnectionCount;
00376         bsIn.Read(responseTotalConnectionCount);
00377         IncrementTotalConnectionCount(responseTotalConnectionCount);
00378         bool wasAssigned;
00379         if (ourFCMGuid==0)
00380         {
00381                 wasAssigned=true;
00382                 AssignOurFCMGuid();
00383         }
00384         else
00385                 wasAssigned=false;
00386 
00387         // 1 is returned to give us lower priority, but the actual minimum is 2
00388         IncrementTotalConnectionCount(2);
00389 
00390         if (wasAssigned==true)
00391         {
00392                 DataStructures::DefaultIndexType idx;
00393                 for (idx=0; idx < participantList.Size(); idx++)
00394                         SendOurFCMGuid(rakPeerInterface->GetSystemAddressFromGuid(participantList[idx].rakNetGuid));
00395                 CalculateAndPushHost();
00396         }
00397 }
00398 void FullyConnectedMesh2::OnInformFCMGuid(Packet *packet)
00399 {
00400         RakNet::BitStream bsIn(packet->data,packet->length,false);
00401         bsIn.IgnoreBytes(sizeof(MessageID));
00402 
00403         FCM2Guid theirFCMGuid;
00404         unsigned int theirTotalConnectionCount;
00405         bsIn.Read(theirFCMGuid);
00406         bsIn.Read(theirTotalConnectionCount);
00407         IncrementTotalConnectionCount(theirTotalConnectionCount);
00408         AddParticipantInternal(packet->guid,theirFCMGuid);
00409 
00410         CalculateAndPushHost();
00411 }
00412 void FullyConnectedMesh2::GetParticipantCount(DataStructures::DefaultIndexType *participantListSize) const
00413 {
00414         *participantListSize=participantList.Size();
00415 }
00416 
00417 unsigned int FullyConnectedMesh2::GetParticipantCount(void) const
00418 {
00419         return participantList.Size();
00420 }
00421 void FullyConnectedMesh2::CalculateAndPushHost(void)
00422 {
00423         RakNetGUID newHostGuid;
00424         FCM2Guid newFcmGuid;
00425         if (ParticipantListComplete())
00426         {
00427                 CalculateHost(&newHostGuid, &newFcmGuid);
00428                 if (newHostGuid!=lastPushedHost)
00429                 {
00430                         hostRakNetGuid=newHostGuid;
00431                         hostFCM2Guid=newFcmGuid;
00432                         PushNewHost(hostRakNetGuid);
00433                 }
00434         }
00435 }
00436 bool FullyConnectedMesh2::ParticipantListComplete(void)
00437 {
00438         for (unsigned int i=0; i < participantList.Size(); i++)
00439         {
00440                 if (participantList[i].fcm2Guid==0)
00441                         return false;
00442         }
00443         return true;
00444 }
00445 void FullyConnectedMesh2::IncrementTotalConnectionCount(unsigned int i)
00446 {
00447         if (i>totalConnectionCount)
00448         {
00449                 totalConnectionCount=i;
00450         //      printf("totalConnectionCount=%i\n",i);
00451         }
00452 }
00453 void FullyConnectedMesh2::SetConnectOnNewRemoteConnection(bool attemptConnection, RakNet::RakString pw)
00454 {
00455         connectOnNewRemoteConnections=attemptConnection;
00456         connectionPassword=pw;
00457 }
00458 
00459 #endif // _RAKNET_SUPPORT_*

Generated on Thu Sep 30 2010 01:27:24 for RakNet by  doxygen 1.7.1