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
NatPunchthroughServer.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-2018, 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_NatPunchthroughServer==1
18
19 #include "slikenet/NatPunchthroughServer.h"
20 #include "slikenet/SocketLayer.h"
21 #include "slikenet/BitStream.h"
22 #include "slikenet/MessageIdentifiers.h"
23 #include "slikenet/peerinterface.h"
24 #include "slikenet/MTUSize.h"
25 #include "slikenet/GetTime.h"
26 #include "slikenet/PacketLogger.h"
27 #include "slikenet/linux_adapter.h"
28 #include "slikenet/osx_adapter.h"
29
30 using namespace SLNet;
31
32 void NatPunchthroughServerDebugInterface_Printf::OnServerMessage(const char *msg)
33 {
34 printf("%s\n", msg);
35 }
36 #if _RAKNET_SUPPORT_PacketLogger==1
37 void NatPunchthroughServerDebugInterface_PacketLogger::OnServerMessage(const char *msg)
38 {
39 if (pl)
40 {
41 pl->WriteMiscellaneous("Nat", msg);
42 }
43 }
44 #endif
45
46 void NatPunchthroughServer::User::DeleteConnectionAttempt(NatPunchthroughServer::ConnectionAttempt *ca)
47 {
48 unsigned int index = connectionAttempts.GetIndexOf(ca);
49 if ((unsigned int)index!=(unsigned int)-1)
50 {
51 SLNet::OP_DELETE(ca,_FILE_AND_LINE_);
52 connectionAttempts.RemoveAtIndex(index);
53 }
54 }
55 void NatPunchthroughServer::User::DerefConnectionAttempt(NatPunchthroughServer::ConnectionAttempt *ca)
56 {
57 unsigned int index = connectionAttempts.GetIndexOf(ca);
58 if ((unsigned int)index!=(unsigned int)-1)
59 {
60 connectionAttempts.RemoveAtIndex(index);
61 }
62 }
63 bool NatPunchthroughServer::User::HasConnectionAttemptToUser(User *user)
64 {
65 unsigned int index;
66 for (index=0; index < connectionAttempts.Size(); index++)
67 {
68 if (connectionAttempts[index]->recipient->guid==user->guid ||
69 connectionAttempts[index]->sender->guid==user->guid)
70 return true;
71 }
72 return false;
73 }
74 void NatPunchthroughServer::User::LogConnectionAttempts(SLNet::RakString &rs)
75 {
76 rs.Clear();
77 unsigned int index;
78 char guidStr[128], ipStr[128];
79 guid.ToString(guidStr, 128);
80 systemAddress.ToString(true,ipStr,static_cast<size_t>(128));
81 rs= SLNet::RakString("User systemAddress=%s guid=%s\n", ipStr, guidStr);
82 rs+= SLNet::RakString("%i attempts in list:\n", connectionAttempts.Size());
83 for (index=0; index < connectionAttempts.Size(); index++)
84 {
85 rs+= SLNet::RakString("%i. SessionID=%i ", index+1, connectionAttempts[index]->sessionId);
86 if (connectionAttempts[index]->sender==this)
87 rs+="(We are sender) ";
88 else
89 rs+="(We are recipient) ";
90 if (isReady)
91 rs+="(READY TO START) ";
92 else
93 rs+="(NOT READY TO START) ";
94 if (connectionAttempts[index]->attemptPhase==NatPunchthroughServer::ConnectionAttempt::NAT_ATTEMPT_PHASE_NOT_STARTED)
95 rs+="(NOT_STARTED). ";
96 else
97 rs+="(GETTING_RECENT_PORTS). ";
98 if (connectionAttempts[index]->sender==this)
99 {
100 connectionAttempts[index]->recipient->guid.ToString(guidStr, 128);
101 connectionAttempts[index]->recipient->systemAddress.ToString(true,ipStr,static_cast<size_t>(128));
102 }
103 else
104 {
105 connectionAttempts[index]->sender->guid.ToString(guidStr, 128);
106 connectionAttempts[index]->sender->systemAddress.ToString(true,ipStr,static_cast<size_t>(128));
107 }
108
109 rs+= SLNet::RakString("Target systemAddress=%s, guid=%s.\n", ipStr, guidStr);
110 }
111 }
112
113 int SLNet::NatPunchthroughServer::NatPunchthroughUserComp( const RakNetGUID &key, User * const &data )
114 {
115 if (key < data->guid)
116 return -1;
117 if (key > data->guid)
118 return 1;
119 return 0;
120 }
121
122 STATIC_FACTORY_DEFINITIONS(NatPunchthroughServer,NatPunchthroughServer);
123
124 NatPunchthroughServer::NatPunchthroughServer()
125 {
126 lastUpdate=0;
127 sessionId=0;
128 natPunchthroughServerDebugInterface=0;
129 for (int i=0; i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
130 boundAddresses[i]=UNASSIGNED_SYSTEM_ADDRESS;
131 boundAddressCount=0;
132 }
133 NatPunchthroughServer::~NatPunchthroughServer()
134 {
135 User *user, *otherUser;
136 ConnectionAttempt *connectionAttempt;
137 unsigned int j;
138 while(users.Size())
139 {
140 user = users[0];
141 for (j=0; j < user->connectionAttempts.Size(); j++)
142 {
143 connectionAttempt=user->connectionAttempts[j];
144 if (connectionAttempt->sender==user)
145 otherUser=connectionAttempt->recipient;
146 else
147 otherUser=connectionAttempt->sender;
148 otherUser->DeleteConnectionAttempt(connectionAttempt);
149 }
150 SLNet::OP_DELETE(user,_FILE_AND_LINE_);
151 users[0]=users[users.Size()-1];
152 users.RemoveAtIndex(users.Size()-1);
153 }
154 }
155 void NatPunchthroughServer::SetDebugInterface(NatPunchthroughServerDebugInterface *i)
156 {
157 natPunchthroughServerDebugInterface=i;
158 }
159 void NatPunchthroughServer::Update(void)
160 {
161 ConnectionAttempt *connectionAttempt;
162 User *user, *recipient;
163 unsigned int i,j;
164 SLNet::Time time = SLNet::GetTime();
165 if (time > lastUpdate+250)
166 {
167 lastUpdate=time;
168
169 for (i=0; i < users.Size(); i++)
170 {
171 user=users[i];
172 for (j=0; j < user->connectionAttempts.Size(); j++)
173 {
174 connectionAttempt=user->connectionAttempts[j];
175 if (connectionAttempt->sender==user)
176 {
177 if (connectionAttempt->attemptPhase!=ConnectionAttempt::NAT_ATTEMPT_PHASE_NOT_STARTED &&
178 time > connectionAttempt->startTime &&
179 time > 10000 + connectionAttempt->startTime ) // Formerly 5000, but sometimes false positives
180 {
181 SLNet::BitStream outgoingBs;
182
183 // that other system might not be running the plugin
184 outgoingBs.Write((MessageID)ID_NAT_TARGET_UNRESPONSIVE);
185 outgoingBs.Write(connectionAttempt->recipient->guid);
186 outgoingBs.Write(connectionAttempt->sessionId);
187 rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,connectionAttempt->sender->systemAddress,false);
188
189 // 05/28/09 Previously only told sender about ID_NAT_CONNECTION_TO_TARGET_LOST
190 // However, recipient may be expecting it due to external code
191 // In that case, recipient would never get any response if the sender dropped
192 outgoingBs.Reset();
193 outgoingBs.Write((MessageID)ID_NAT_TARGET_UNRESPONSIVE);
194 outgoingBs.Write(connectionAttempt->sender->guid);
195 outgoingBs.Write(connectionAttempt->sessionId);
196 rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,connectionAttempt->recipient->systemAddress,false);
197
198 connectionAttempt->sender->isReady=true;
199 connectionAttempt->recipient->isReady=true;
200 recipient=connectionAttempt->recipient;
201
202
203 if (natPunchthroughServerDebugInterface)
204 {
205 char str[1024];
206 char addr1[128], addr2[128];
207 // 8/01/09 Fixed bug where this was after DeleteConnectionAttempt()
208 connectionAttempt->sender->systemAddress.ToString(true,addr1,static_cast<size_t>(128));
209 connectionAttempt->recipient->systemAddress.ToString(true,addr2,static_cast<size_t>(128));
210 sprintf_s(str, "Sending ID_NAT_TARGET_UNRESPONSIVE to sender %s and recipient %s.", addr1, addr2);
211 natPunchthroughServerDebugInterface->OnServerMessage(str);
212 SLNet::RakString log;
213 connectionAttempt->sender->LogConnectionAttempts(log);
214 connectionAttempt->recipient->LogConnectionAttempts(log);
215 }
216
217
218 connectionAttempt->sender->DerefConnectionAttempt(connectionAttempt);
219 connectionAttempt->recipient->DeleteConnectionAttempt(connectionAttempt);
220
221 StartPunchthroughForUser(user);
222 StartPunchthroughForUser(recipient);
223
224 break;
225 }
226 }
227 }
228 }
229 }
230 }
231 PluginReceiveResult NatPunchthroughServer::OnReceive(Packet *packet)
232 {
233 switch (packet->data[0])
234 {
235 case ID_NAT_PUNCHTHROUGH_REQUEST:
236 OnNATPunchthroughRequest(packet);
237 return RR_STOP_PROCESSING_AND_DEALLOCATE;
238 case ID_NAT_GET_MOST_RECENT_PORT:
239 OnGetMostRecentPort(packet);
240 return RR_STOP_PROCESSING_AND_DEALLOCATE;
241 case ID_NAT_CLIENT_READY:
242 OnClientReady(packet);
243 return RR_STOP_PROCESSING_AND_DEALLOCATE;
244 case ID_NAT_REQUEST_BOUND_ADDRESSES:
245 {
246 SLNet::BitStream outgoingBs;
247 outgoingBs.Write((MessageID)ID_NAT_RESPOND_BOUND_ADDRESSES);
248
249 if (boundAddresses[0]==UNASSIGNED_SYSTEM_ADDRESS)
250 {
251 DataStructures::List<RakNetSocket2* > sockets;
252 rakPeerInterface->GetSockets(sockets);
253 for (unsigned i=0; i < sockets.Size() && i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
254 {
255 boundAddresses[i]=sockets[i]->GetBoundAddress();
256 boundAddressCount++;
257 }
258 }
259
260 outgoingBs.Write(boundAddressCount);
261 for (int i=0; i < boundAddressCount; i++)
262 {
263 outgoingBs.Write(boundAddresses[i]);
264 }
265
266 rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false);
267 }
268 return RR_STOP_PROCESSING_AND_DEALLOCATE;
269 case ID_NAT_PING:
270 {
271 }
272 return RR_STOP_PROCESSING_AND_DEALLOCATE;
273 case ID_OUT_OF_BAND_INTERNAL:
274 if (packet->length>=2 && packet->data[1]==ID_NAT_PING)
275 {
276 SLNet::BitStream bs(packet->data,packet->length,false);
277 bs.IgnoreBytes(sizeof(MessageID)*2);
278 uint16_t externalPort;
279 bs.Read(externalPort);
280
281 SLNet::BitStream outgoingBs;
282 outgoingBs.Write((MessageID)ID_NAT_PONG);
283 outgoingBs.Write(externalPort);
284 uint16_t externalPort2 = packet->systemAddress.GetPort();
285 outgoingBs.Write(externalPort2);
286 rakPeerInterface->SendOutOfBand((const char*) packet->systemAddress.ToString(false),packet->systemAddress.GetPort(),(const char*) outgoingBs.GetData(),outgoingBs.GetNumberOfBytesUsed());
287
288 return RR_STOP_PROCESSING_AND_DEALLOCATE;
289 }
290 }
291 return RR_CONTINUE_PROCESSING;
292 }
293 void NatPunchthroughServer::OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
294 {
295 (void) lostConnectionReason;
296 (void) systemAddress;
297
298 unsigned int i=0;
299 bool objectExists;
300 i = users.GetIndexFromKey(rakNetGUID, &objectExists);
301 if (objectExists)
302 {
303 SLNet::BitStream outgoingBs;
304 DataStructures::List<User *> freedUpInProgressUsers;
305 User *user = users[i];
306 User *otherUser;
307 unsigned int connectionAttemptIndex;
308 ConnectionAttempt *connectionAttempt;
309 for (connectionAttemptIndex=0; connectionAttemptIndex < user->connectionAttempts.Size(); connectionAttemptIndex++)
310 {
311 connectionAttempt=user->connectionAttempts[connectionAttemptIndex];
312 outgoingBs.Reset();
313 if (connectionAttempt->recipient==user)
314 {
315 otherUser=connectionAttempt->sender;
316 }
317 else
318 {
319 otherUser=connectionAttempt->recipient;
320 }
321
322 // 05/28/09 Previously only told sender about ID_NAT_CONNECTION_TO_TARGET_LOST
323 // However, recipient may be expecting it due to external code
324 // In that case, recipient would never get any response if the sender dropped
325 outgoingBs.Write((MessageID)ID_NAT_CONNECTION_TO_TARGET_LOST);
326 outgoingBs.Write(rakNetGUID);
327 outgoingBs.Write(connectionAttempt->sessionId);
328 rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,otherUser->systemAddress,false);
329
330 // 4/22/09 - Bug: was checking inProgress, legacy variable not used elsewhere
331 if (connectionAttempt->attemptPhase==ConnectionAttempt::NAT_ATTEMPT_PHASE_GETTING_RECENT_PORTS)
332 {
333 otherUser->isReady=true;
334 freedUpInProgressUsers.Insert(otherUser, _FILE_AND_LINE_ );
335 }
336
337 otherUser->DeleteConnectionAttempt(connectionAttempt);
338 }
339
340 SLNet::OP_DELETE(users[i], _FILE_AND_LINE_);
341 users.RemoveAtIndex(i);
342
343 for (i=0; i < freedUpInProgressUsers.Size(); i++)
344 {
345 StartPunchthroughForUser(freedUpInProgressUsers[i]);
346 }
347 }
348
349 /*
350 // Also remove from groupPunchthroughRequests
351 for (i=0; i < users.Size(); i++)
352 {
353 bool objectExists;
354 unsigned int gprIndex;
355 gprIndex = users[i]->groupPunchthroughRequests.GetIndexFromKey(rakNetGUID, &objectExists);
356 if (objectExists)
357 {
358 // printf("DEBUG %i\n", __LINE__);
359
360 SLNet::BitStream outgoingBs;
361 outgoingBs.Write((MessageID)ID_NAT_TARGET_NOT_CONNECTED);
362 outgoingBs.Write(rakNetGUID);
363 rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,users[i]->systemAddress,false);
364
365 users[i]->groupPunchthroughRequests.RemoveAtIndex(gprIndex);
366 }
367 }
368 */
369 }
370
371 void NatPunchthroughServer::OnNewConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, bool isIncoming)
372 {
373 (void) systemAddress;
374 (void) isIncoming;
375
376 User *user = SLNet::OP_NEW<User>(_FILE_AND_LINE_);
377 user->guid=rakNetGUID;
378 user->mostRecentPort=0;
379 user->systemAddress=systemAddress;
380 user->isReady=true;
381 users.Insert(rakNetGUID, user, true, _FILE_AND_LINE_);
382
383 // printf("Adding to users %s\n", rakNetGUID.ToString());
384 // printf("DEBUG users[0] guid=%s\n", users[0]->guid.ToString());
385 }
386 void NatPunchthroughServer::OnNATPunchthroughRequest(Packet *packet)
387 {
388 SLNet::BitStream outgoingBs;
389 SLNet::BitStream incomingBs(packet->data, packet->length, false);
390 incomingBs.IgnoreBytes(sizeof(MessageID));
391 RakNetGUID recipientGuid, senderGuid;
392 incomingBs.Read(recipientGuid);
393 senderGuid=packet->guid;
394 unsigned int i;
395 bool objectExists;
396 i = users.GetIndexFromKey(senderGuid, &objectExists);
397 RakAssert(objectExists);
398
399 ConnectionAttempt *ca = SLNet::OP_NEW<ConnectionAttempt>(_FILE_AND_LINE_);
400 ca->sender=users[i];
401 ca->sessionId=sessionId++;
402 i = users.GetIndexFromKey(recipientGuid, &objectExists);
403 if (objectExists==false || ca->sender == ca->recipient)
404 {
405 // printf("DEBUG %i\n", __LINE__);
406 // printf("DEBUG recipientGuid=%s\n", recipientGuid.ToString());
407 // printf("DEBUG users[0] guid=%s\n", users[0]->guid.ToString());
408
409 outgoingBs.Write((MessageID)ID_NAT_TARGET_NOT_CONNECTED);
410 outgoingBs.Write(recipientGuid);
411 rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false);
412 SLNet::OP_DELETE(ca,_FILE_AND_LINE_);
413 return;
414 }
415 ca->recipient=users[i];
416 if (ca->recipient->HasConnectionAttemptToUser(ca->sender))
417 {
418 outgoingBs.Write((MessageID)ID_NAT_ALREADY_IN_PROGRESS);
419 outgoingBs.Write(recipientGuid);
420 rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false);
421 SLNet::OP_DELETE(ca,_FILE_AND_LINE_);
422 return;
423 }
424
425 ca->sender->connectionAttempts.Insert(ca, _FILE_AND_LINE_ );
426 ca->recipient->connectionAttempts.Insert(ca, _FILE_AND_LINE_ );
427
428 StartPunchthroughForUser(ca->sender);
429 }
430 void NatPunchthroughServer::OnClientReady(Packet *packet)
431 {
432 unsigned int i;
433 bool objectExists;
434 i = users.GetIndexFromKey(packet->guid, &objectExists);
435 if (objectExists)
436 {
437 users[i]->isReady=true;
438 StartPunchthroughForUser(users[i]);
439 }
440 }
441 void NatPunchthroughServer::OnGetMostRecentPort(Packet *packet)
442 {
443 SLNet::BitStream bsIn(packet->data, packet->length, false);
444 bsIn.IgnoreBytes(sizeof(MessageID));
445 uint16_t curSessionId;
446 unsigned short mostRecentPort;
447 bsIn.Read(curSessionId);
448 bsIn.Read(mostRecentPort);
449
450 unsigned int i,j;
451 User *user;
452 ConnectionAttempt *connectionAttempt;
453 bool objectExists;
454 i = users.GetIndexFromKey(packet->guid, &objectExists);
455
456 if (natPunchthroughServerDebugInterface)
457 {
458 SLNet::RakString log;
459 char addr1[128], addr2[128];
460 packet->systemAddress.ToString(true,addr1,static_cast<size_t>(128));
461 packet->guid.ToString(addr2, 128);
462 log= SLNet::RakString("Got ID_NAT_GET_MOST_RECENT_PORT from systemAddress %s guid %s. port=%i. sessionId=%i. userFound=%i.", addr1, addr2, mostRecentPort, curSessionId, objectExists);
463 natPunchthroughServerDebugInterface->OnServerMessage(log.C_String());
464 }
465
466 if (objectExists)
467 {
468 user=users[i];
469 user->mostRecentPort=mostRecentPort;
470 SLNet::Time time = SLNet::GetTime();
471
472 for (j=0; j < user->connectionAttempts.Size(); j++)
473 {
474 connectionAttempt=user->connectionAttempts[j];
475 if (connectionAttempt->attemptPhase==ConnectionAttempt::NAT_ATTEMPT_PHASE_GETTING_RECENT_PORTS &&
476 connectionAttempt->sender->mostRecentPort!=0 &&
477 connectionAttempt->recipient->mostRecentPort!=0 &&
478 // 04/29/08 add sessionId to prevent processing for other systems
479 connectionAttempt->sessionId== curSessionId)
480 {
481 SystemAddress senderSystemAddress = connectionAttempt->sender->systemAddress;
482 SystemAddress recipientSystemAddress = connectionAttempt->recipient->systemAddress;
483 SystemAddress recipientTargetAddress = recipientSystemAddress;
484 SystemAddress senderTargetAddress = senderSystemAddress;
485 recipientTargetAddress.SetPortHostOrder(connectionAttempt->recipient->mostRecentPort);
486 senderTargetAddress.SetPortHostOrder(connectionAttempt->sender->mostRecentPort);
487
488 // Pick a time far enough in the future that both systems will have gotten the message
489 int targetPing = rakPeerInterface->GetAveragePing(recipientTargetAddress);
490 int senderPing = rakPeerInterface->GetAveragePing(senderSystemAddress);
491 SLNet::Time simultaneousAttemptTime;
492 if (targetPing==-1 || senderPing==-1)
493 simultaneousAttemptTime = time + 1500;
494 else
495 {
496 int largerPing = targetPing > senderPing ? targetPing : senderPing;
497 if (largerPing * 4 < 100)
498 simultaneousAttemptTime = time + 100;
499 else
500 simultaneousAttemptTime = time + (largerPing * 4);
501 }
502
503 if (natPunchthroughServerDebugInterface)
504 {
505 SLNet::RakString log;
506 char addr1[128], addr2[128];
507 recipientSystemAddress.ToString(true,addr1,static_cast<size_t>(128));
508 connectionAttempt->recipient->guid.ToString(addr2, 128);
509 log= SLNet::RakString("Sending ID_NAT_CONNECT_AT_TIME to recipient systemAddress %s guid %s", addr1, addr2);
510 natPunchthroughServerDebugInterface->OnServerMessage(log.C_String());
511 }
512
513 // Send to recipient timestamped message to connect at time
514 SLNet::BitStream bsOut;
515 bsOut.Write((MessageID)ID_TIMESTAMP);
516 bsOut.Write(simultaneousAttemptTime);
517 bsOut.Write((MessageID)ID_NAT_CONNECT_AT_TIME);
518 bsOut.Write(connectionAttempt->sessionId);
519 bsOut.Write(senderTargetAddress); // Public IP, using most recent port
520 for (j=0; j < MAXIMUM_NUMBER_OF_INTERNAL_IDS; j++) // Internal IP
521 bsOut.Write(rakPeerInterface->GetInternalID(senderSystemAddress,j));
522 bsOut.Write(connectionAttempt->sender->guid);
523 bsOut.Write(false);
524 rakPeerInterface->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,recipientSystemAddress,false);
525
526
527 if (natPunchthroughServerDebugInterface)
528 {
529 SLNet::RakString log;
530 char addr1[128], addr2[128];
531 senderSystemAddress.ToString(true,addr1,static_cast<size_t>(128));
532 connectionAttempt->sender->guid.ToString(addr2, 128);
533 log= SLNet::RakString("Sending ID_NAT_CONNECT_AT_TIME to sender systemAddress %s guid %s", addr1, addr2);
534 natPunchthroughServerDebugInterface->OnServerMessage(log.C_String());
535 }
536
537
538 // Same for sender
539 bsOut.Reset();
540 bsOut.Write((MessageID)ID_TIMESTAMP);
541 bsOut.Write(simultaneousAttemptTime);
542 bsOut.Write((MessageID)ID_NAT_CONNECT_AT_TIME);
543 bsOut.Write(connectionAttempt->sessionId);
544 bsOut.Write(recipientTargetAddress); // Public IP, using most recent port
545 for (j=0; j < MAXIMUM_NUMBER_OF_INTERNAL_IDS; j++) // Internal IP
546 bsOut.Write(rakPeerInterface->GetInternalID(recipientSystemAddress,j));
547 bsOut.Write(connectionAttempt->recipient->guid);
548 bsOut.Write(true);
549 rakPeerInterface->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,senderSystemAddress,false);
550
551 connectionAttempt->recipient->DerefConnectionAttempt(connectionAttempt);
552 connectionAttempt->sender->DeleteConnectionAttempt(connectionAttempt);
553
554 // 04/29/08 missing return
555 return;
556 }
557 }
558 }
559 else
560 {
561
562 if (natPunchthroughServerDebugInterface)
563 {
564 SLNet::RakString log;
565 char addr1[128], addr2[128];
566 packet->systemAddress.ToString(true,addr1,static_cast<size_t>(128));
567 packet->guid.ToString(addr2, 128);
568 log= SLNet::RakString("Ignoring ID_NAT_GET_MOST_RECENT_PORT from systemAddress %s guid %s", addr1, addr2);
569 natPunchthroughServerDebugInterface->OnServerMessage(log.C_String());
570 }
571
572 }
573 }
574 void NatPunchthroughServer::StartPunchthroughForUser(User *user)
575 {
576 if (user->isReady==false)
577 return;
578
579 ConnectionAttempt *connectionAttempt;
580 User *sender,*recipient,*otherUser;
581 unsigned int i;
582 for (i=0; i < user->connectionAttempts.Size(); i++)
583 {
584 connectionAttempt=user->connectionAttempts[i];
585 if (connectionAttempt->sender==user)
586 {
587 otherUser=connectionAttempt->recipient;
588 sender=user;
589 recipient=otherUser;
590 }
591 else
592 {
593 otherUser=connectionAttempt->sender;
594 recipient=user;
595 sender=otherUser;
596 }
597
598 if (otherUser->isReady)
599 {
600 if (natPunchthroughServerDebugInterface)
601 {
602 char str[1024];
603 char addr1[128], addr2[128];
604 sender->systemAddress.ToString(true,addr1,static_cast<size_t>(128));
605 recipient->systemAddress.ToString(true,addr2,static_cast<size_t>(128));
606 sprintf_s(str, "Sending NAT_ATTEMPT_PHASE_GETTING_RECENT_PORTS to sender %s and recipient %s.", addr1, addr2);
607 natPunchthroughServerDebugInterface->OnServerMessage(str);
608 }
609
610 sender->isReady=false;
611 recipient->isReady=false;
612 connectionAttempt->attemptPhase=ConnectionAttempt::NAT_ATTEMPT_PHASE_GETTING_RECENT_PORTS;
613 connectionAttempt->startTime= SLNet::GetTime();
614
615 sender->mostRecentPort=0;
616 recipient->mostRecentPort=0;
617
618 SLNet::BitStream outgoingBs;
619 outgoingBs.Write((MessageID)ID_NAT_GET_MOST_RECENT_PORT);
620 // 4/29/09 Write sessionID so we don't use returned port for a system we don't want
621 outgoingBs.Write(connectionAttempt->sessionId);
622 rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,sender->systemAddress,false);
623 rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,recipient->systemAddress,false);
624
625 // 4/22/09 - BUG: missing break statement here
626 break;
627 }
628 }
629 }
630
631 #endif // _RAKNET_SUPPORT_*