SLikeNet  0.1.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ConnectionGraph2.cpp
Go to the documentation of this file.
1 /*
2  * Original work: Copyright (c) 2014, Oculus VR, Inc.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * RakNet License.txt file in the licenses directory of this source tree. An additional grant
7  * of patent rights can be found in the RakNet Patents.txt file in the same directory.
8  *
9  *
10  * Modified work: Copyright (c) 2016-2017, SLikeSoft UG (haftungsbeschränkt)
11  *
12  * This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
13  * license found in the license.txt file in the root directory of this source tree.
14  */
15 
17 #if _RAKNET_SUPPORT_ConnectionGraph2==1
18 
20 #include "slikenet/peerinterface.h"
22 #include "slikenet/BitStream.h"
23 
24 using namespace SLNet;
25 
27 
28 int SLNet::ConnectionGraph2::RemoteSystemComp( const RakNetGUID &key, RemoteSystem * const &data )
29 {
30  if (key < data->guid)
31  return -1;
32  if (key > data->guid)
33  return 1;
34  return 0;
35 }
36 
37 int SLNet::ConnectionGraph2::SystemAddressAndGuidComp( const SystemAddressAndGuid &key, const SystemAddressAndGuid &data )
38 {
39  if (key.guid<data.guid)
40  return -1;
41  if (key.guid>data.guid)
42  return 1;
43  return 0;
44 }
46 {
48 }
50 {
51 
52 }
53 bool ConnectionGraph2::GetConnectionListForRemoteSystem(RakNetGUID remoteSystemGuid, SystemAddress *saOut, RakNetGUID *guidOut, unsigned int *outLength)
54 {
55  if ((saOut==0 && guidOut==0) || outLength==0 || *outLength==0 || remoteSystemGuid==UNASSIGNED_RAKNET_GUID)
56  {
57  *outLength=0;
58  return false;
59  }
60 
61  bool objectExists;
62  unsigned int idx = remoteSystems.GetIndexFromKey(remoteSystemGuid, &objectExists);
63  if (objectExists==false)
64  {
65  *outLength=0;
66  return false;
67  }
68 
69  unsigned int idx2;
70  if (remoteSystems[idx]->remoteConnections.Size() < *outLength)
71  *outLength=remoteSystems[idx]->remoteConnections.Size();
72  for (idx2=0; idx2 < *outLength; idx2++)
73  {
74  if (guidOut)
75  guidOut[idx2]=remoteSystems[idx]->remoteConnections[idx2].guid;
76  if (saOut)
77  saOut[idx2]=remoteSystems[idx]->remoteConnections[idx2].systemAddress;
78  }
79  return true;
80 }
82 {
83  if (g1==g2)
84  return false;
85 
86  bool objectExists;
87  unsigned int idx = remoteSystems.GetIndexFromKey(g1, &objectExists);
88  if (objectExists==false)
89  {
90  return false;
91  }
92  SystemAddressAndGuid sag;
93  sag.guid=g2;
94  return remoteSystems[idx]->remoteConnections.HasData(sag);
95 }
97 {
98  if (g1==g2)
99  return 0;
100 
101  if (g1==rakPeerInterface->GetMyGUID())
103  if (g2==rakPeerInterface->GetMyGUID())
105 
106  bool objectExists;
107  unsigned int idx = remoteSystems.GetIndexFromKey(g1, &objectExists);
108  if (objectExists==false)
109  {
110  return (uint16_t) -1;
111  }
112 
113  SystemAddressAndGuid sag;
114  sag.guid=g2;
115  unsigned int idx2 = remoteSystems[idx]->remoteConnections.GetIndexFromKey(sag, &objectExists);
116  if (objectExists==false)
117  {
118  return (uint16_t) -1;
119  }
120  return remoteSystems[idx]->remoteConnections[idx2].sendersPingToThatSystem;
121 }
122 
125 {
126  float lowestPing=-1.0;
127  unsigned int lowestPingIdx=(unsigned int) -1;
128  float thisAvePing=0.0f;
129  unsigned int idx, idx2;
130  int ap, count=0;
131 
132  for (idx=0; idx<remoteSystems.Size(); idx++)
133  {
134  thisAvePing=0.0f;
135 
137  if (ap!=-1)
138  {
139  thisAvePing+=(float) ap;
140  count++;
141  }
142  }
143 
144  if (count>0)
145  {
146  lowestPing=thisAvePing/count;
147  }
148 
149  for (idx=0; idx<remoteSystems.Size(); idx++)
150  {
151  thisAvePing=0.0f;
152  count=0;
153 
154  RemoteSystem *remoteSystem = remoteSystems[idx];
155  for (idx2=0; idx2 < remoteSystem->remoteConnections.Size(); idx2++)
156  {
157  ap=remoteSystem->remoteConnections[idx2].sendersPingToThatSystem;
158  if (ap!=-1)
159  {
160  thisAvePing+=(float) ap;
161  count++;
162  }
163  }
164 
165  if (count>0 && (lowestPing==-1.0f || thisAvePing/count < lowestPing))
166  {
167  lowestPing=thisAvePing/count;
168  lowestPingIdx=idx;
169  }
170  }
171 
172  if (lowestPingIdx==(unsigned int) -1)
173  return rakPeerInterface->GetMyGUID();
174  return remoteSystems[lowestPingIdx]->guid;
175 }
176 
177 void ConnectionGraph2::OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
178 {
179  // Send notice to all existing connections
180  SLNet::BitStream bs;
181  if (lostConnectionReason==LCR_CONNECTION_LOST)
183  else
185  bs.Write(systemAddress);
186  bs.Write(rakNetGUID);
187  SendUnified(&bs,HIGH_PRIORITY,RELIABLE_ORDERED,0,systemAddress,true);
188 
189  bool objectExists;
190  unsigned int idx = remoteSystems.GetIndexFromKey(rakNetGUID, &objectExists);
191  if (objectExists)
192  {
195  }
196 }
198 {
200 }
202 {
204 }
205 void ConnectionGraph2::AddParticipant(const SystemAddress &systemAddress, RakNetGUID rakNetGUID)
206 {
207  // Relay the new connection to other systems.
208  SLNet::BitStream bs;
210  bs.Write((uint32_t)1);
211  bs.Write(systemAddress);
212  bs.Write(rakNetGUID);
214  SendUnified(&bs,HIGH_PRIORITY,RELIABLE_ORDERED,0,systemAddress,true);
215 
216  // Send everyone to the new guy
219  rakPeerInterface->GetSystemList(addresses, guids);
220  bs.Reset();
221  bs.Write((MessageID)ID_REMOTE_NEW_INCOMING_CONNECTION);
222  BitSize_t writeOffset = bs.GetWriteOffset();
223  bs.Write((uint32_t) addresses.Size());
224 
225  unsigned int i;
226  uint32_t count=0;
227  for (i=0; i < addresses.Size(); i++)
228  {
229  if (addresses[i]==systemAddress)
230  continue;
231 
232  bs.Write(addresses[i]);
233  bs.Write(guids[i]);
235  count++;
236  }
237 
238  if (count>0)
239  {
240  BitSize_t writeOffset2 = bs.GetWriteOffset();
241  bs.SetWriteOffset(writeOffset);
242  bs.Write(count);
243  bs.SetWriteOffset(writeOffset2);
244  SendUnified(&bs,HIGH_PRIORITY,RELIABLE_ORDERED,0,systemAddress,false);
245  }
246 
247  bool objectExists;
248  unsigned int ii = remoteSystems.GetIndexFromKey(rakNetGUID, &objectExists);
249  if (objectExists==false)
250  {
251  RemoteSystem* remoteSystem = SLNet::OP_NEW<RemoteSystem>(_FILE_AND_LINE_);
252  remoteSystem->guid=rakNetGUID;
254  }
255 }
257 {
258  participantList.Clear(true, _FILE_AND_LINE_);
259  unsigned int i;
260  for (i=0; i < remoteSystems.Size(); i++)
261  participantList.InsertAtEnd(remoteSystems[i]->guid, _FILE_AND_LINE_);
262 }
263 void ConnectionGraph2::OnNewConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, bool isIncoming)
264 {
265  (void) isIncoming;
267  AddParticipant(systemAddress, rakNetGUID);
268 }
270 {
271  if (packet->data[0]==ID_REMOTE_CONNECTION_LOST || packet->data[0]==ID_REMOTE_DISCONNECTION_NOTIFICATION)
272  {
273  bool objectExists;
274  unsigned idx = remoteSystems.GetIndexFromKey(packet->guid, &objectExists);
275  if (objectExists)
276  {
277  SLNet::BitStream bs(packet->data,packet->length,false);
278  bs.IgnoreBytes(1);
279  SystemAddressAndGuid saag;
280  bs.Read(saag.systemAddress);
281  bs.Read(saag.guid);
282  unsigned long idx2 = remoteSystems[idx]->remoteConnections.GetIndexFromKey(saag, &objectExists);
283  if (objectExists)
284  remoteSystems[idx]->remoteConnections.RemoveAtIndex(idx2);
285  }
286  }
287  else if (packet->data[0]==ID_REMOTE_NEW_INCOMING_CONNECTION)
288  {
289  bool objectExists;
290  unsigned idx = remoteSystems.GetIndexFromKey(packet->guid, &objectExists);
291  if (objectExists)
292  {
293  uint32_t numAddresses;
294  SLNet::BitStream bs(packet->data,packet->length,false);
295  bs.IgnoreBytes(1);
296  bs.Read(numAddresses);
297  for (unsigned int idx2=0; idx2 < numAddresses; idx2++)
298  {
299  SystemAddressAndGuid saag;
300  bs.Read(saag.systemAddress);
301  bs.Read(saag.guid);
302  bs.Read(saag.sendersPingToThatSystem);
303  unsigned int ii = remoteSystems[idx]->remoteConnections.GetIndexFromKey(saag, &objectExists);
304  if (objectExists==false)
305  remoteSystems[idx]->remoteConnections.InsertAtIndex(saag,ii,_FILE_AND_LINE_);
306  }
307  }
308  }
309 
310  return RR_CONTINUE_PROCESSING;
311 }
312 
313 #endif // _RAKNET_SUPPORT_*