SLikeNet 0.1.3

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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
16 #include "slikenet/NativeFeatureIncludes.h"
17 #if _RAKNET_SUPPORT_ConnectionGraph2==1
18
19 #include "slikenet/ConnectionGraph2.h"
20 #include "slikenet/peerinterface.h"
21 #include "slikenet/MessageIdentifiers.h"
22 #include "slikenet/BitStream.h"
23
24 using namespace SLNet;
25
26 STATIC_FACTORY_DEFINITIONS(ConnectionGraph2,ConnectionGraph2)
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 }
45 ConnectionGraph2::ConnectionGraph2()
46 {
47 autoProcessNewConnections=true;
48 }
49 ConnectionGraph2::~ConnectionGraph2()
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 }
81 bool ConnectionGraph2::ConnectionExists(RakNetGUID g1, RakNetGUID g2)
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 }
96 uint16_t ConnectionGraph2::GetPingBetweenSystems(RakNetGUID g1, RakNetGUID g2) const
97 {
98 if (g1==g2)
99 return 0;
100
101 if (g1==rakPeerInterface->GetMyGUID())
102 return (uint16_t) rakPeerInterface->GetAveragePing(g2);
103 if (g2==rakPeerInterface->GetMyGUID())
104 return (uint16_t) rakPeerInterface->GetAveragePing(g1);
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
124 RakNetGUID ConnectionGraph2::GetLowestAveragePingSystem(void) const
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
136 ap = rakPeerInterface->GetAveragePing(remoteSystems[idx]->guid);
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)
182 bs.Write((MessageID)ID_REMOTE_CONNECTION_LOST);
183 else
184 bs.Write((MessageID)ID_REMOTE_DISCONNECTION_NOTIFICATION);
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 {
193 SLNet::OP_DELETE(remoteSystems[idx],_FILE_AND_LINE_);
194 remoteSystems.RemoveAtIndex(idx);
195 }
196 }
197 void ConnectionGraph2::SetAutoProcessNewConnections(bool b)
198 {
199 autoProcessNewConnections=b;
200 }
201 bool ConnectionGraph2::GetAutoProcessNewConnections(void) const
202 {
203 return autoProcessNewConnections;
204 }
205 void ConnectionGraph2::AddParticipant(const SystemAddress &systemAddress, RakNetGUID rakNetGUID)
206 {
207 // Relay the new connection to other systems.
208 SLNet::BitStream bs;
209 bs.Write((MessageID)ID_REMOTE_NEW_INCOMING_CONNECTION);
210 bs.Write((uint32_t)1);
211 bs.Write(systemAddress);
212 bs.Write(rakNetGUID);
213 bs.WriteCasted<uint16_t>(rakPeerInterface->GetAveragePing(rakNetGUID));
214 SendUnified(&bs,HIGH_PRIORITY,RELIABLE_ORDERED,0,systemAddress,true);
215
216 // Send everyone to the new guy
217 DataStructures::List<SystemAddress> addresses;
218 DataStructures::List<RakNetGUID> guids;
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]);
234 bs.WriteCasted<uint16_t>(rakPeerInterface->GetAveragePing(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;
253 remoteSystems.InsertAtIndex(remoteSystem,ii,_FILE_AND_LINE_);
254 }
255 }
256 void ConnectionGraph2::GetParticipantList(DataStructures::OrderedList<RakNetGUID, RakNetGUID> &participantList)
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;
266 if (autoProcessNewConnections)
267 AddParticipant(systemAddress, rakNetGUID);
268 }
269 PluginReceiveResult ConnectionGraph2::OnReceive(Packet *packet)
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_*