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
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
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);
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
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
00279 RakAssert(ourFCMGuid!=0);
00280
00281
00282 RakAssert(participantList.Size()>0);
00283
00284
00285 FCM2Guid lowestFCMGuid=ourFCMGuid;
00286
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
00326
00327 RakNetTimeUS ourElapsedRuntime = GetElapsedRuntime();
00328 if (ourElapsedRuntime>senderElapsedRuntime)
00329 {
00330
00331 SendConnectionCountResponse(packet->systemAddress, 2);
00332 }
00333 else
00334 {
00335
00336 SendConnectionCountResponse(packet->systemAddress, 1);
00337 }
00338 }
00339 else
00340 {
00341
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
00356
00357 SendConnectionCountResponse(packet->systemAddress, totalConnectionCount+1);
00358
00359 }
00360 else
00361 {
00362
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
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
00451 }
00452 }
00453 void FullyConnectedMesh2::SetConnectOnNewRemoteConnection(bool attemptConnection, RakNet::RakString pw)
00454 {
00455 connectOnNewRemoteConnections=attemptConnection;
00456 connectionPassword=pw;
00457 }
00458
00459 #endif // _RAKNET_SUPPORT_*