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
NatTypeDetectionClient.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_NatTypeDetectionClient==1
18
19 #include "slikenet/NatTypeDetectionClient.h"
20 #include "slikenet/smartptr.h"
21 #include "slikenet/BitStream.h"
22 #include "slikenet/SocketIncludes.h"
23 #include "slikenet/string.h"
24 #include "slikenet/peerinterface.h"
25 #include "slikenet/MessageIdentifiers.h"
26 #include "slikenet/SocketLayer.h"
27 #include "slikenet/SocketDefines.h"
28
29 using namespace SLNet;
30
31 STATIC_FACTORY_DEFINITIONS(NatTypeDetectionClient,NatTypeDetectionClient);
32
33 NatTypeDetectionClient::NatTypeDetectionClient()
34 {
35 c2=0;
36 }
37 NatTypeDetectionClient::~NatTypeDetectionClient()
38 {
39 if (c2!=0)
40 {
41 SLNet::OP_DELETE(c2,_FILE_AND_LINE_);
42 }
43 }
44 void NatTypeDetectionClient::DetectNATType(SystemAddress _serverAddress)
45 {
46 if (IsInProgress())
47 return;
48
49 if (c2==0)
50 {
51 DataStructures::List<RakNetSocket2* > sockets;
52 rakPeerInterface->GetSockets(sockets);
53 //SystemAddress sockAddr;
54 //SocketLayer::GetSystemAddress(sockets[0], &sockAddr);
55 char str[64];
56 //sockAddr.ToString(false,str);
57 sockets[0]->GetBoundAddress().ToString(false,str,static_cast<size_t>(64));
58 c2=CreateNonblockingBoundSocket(str
59 #ifdef __native_client__
60 , sockets[0]->chromeInstance
61 #endif
62 ,this
63 );
64 //c2Port=SocketLayer::GetLocalPort(c2);
65 }
66
67 #if !defined(__native_client__) && !defined(WINDOWS_STORE_RT)
68 if (c2->IsBerkleySocket())
69 ((RNS2_Berkley*) c2)->CreateRecvPollingThread(0);
70 #endif
71
72 serverAddress=_serverAddress;
73
74 SLNet::BitStream bs;
75 bs.Write((unsigned char)ID_NAT_TYPE_DETECTION_REQUEST);
76 bs.Write(true); // IsRequest
77 bs.Write(c2->GetBoundAddress().GetPort());
78 rakPeerInterface->Send(&bs,MEDIUM_PRIORITY,RELIABLE,0,serverAddress,false);
79 }
80 void NatTypeDetectionClient::OnCompletion(NATTypeDetectionResult result)
81 {
82 Packet *p = AllocatePacketUnified(sizeof(MessageID)+sizeof(unsigned char)*2);
83 //printf("Returning nat detection result to the user\n");
84 p->data[0]=ID_NAT_TYPE_DETECTION_RESULT;
85 p->systemAddress=serverAddress;
86 p->systemAddress.systemIndex=(SystemIndex)-1;
87 p->guid=rakPeerInterface->GetGuidFromSystemAddress(serverAddress);
88 p->data[1]=(unsigned char) result;
89 p->wasGeneratedLocally=true;
90 rakPeerInterface->PushBackPacket(p, true);
91
92 // Symmetric and port restricted are determined by server, so no need to notify server we are done
93 if (result!=NAT_TYPE_PORT_RESTRICTED && result!=NAT_TYPE_SYMMETRIC)
94 {
95 // Otherwise tell the server we got this message, so it stops sending tests to us
96 SLNet::BitStream bs;
97 bs.Write((unsigned char)ID_NAT_TYPE_DETECTION_REQUEST);
98 bs.Write(false); // Done
99 rakPeerInterface->Send(&bs,HIGH_PRIORITY,RELIABLE,0,serverAddress,false);
100 }
101
102 Shutdown();
103 }
104 bool NatTypeDetectionClient::IsInProgress(void) const
105 {
106 return serverAddress!=UNASSIGNED_SYSTEM_ADDRESS;
107 }
108 void NatTypeDetectionClient::Update(void)
109 {
110 if (IsInProgress())
111 {
112 RNS2RecvStruct *recvStruct;
113 bufferedPacketsMutex.Lock();
114 if (bufferedPackets.Size()>0)
115 recvStruct=bufferedPackets.Pop();
116 else
117 recvStruct=0;
118 bufferedPacketsMutex.Unlock();
119 while (recvStruct)
120 {
121 if (recvStruct->bytesRead==1 && recvStruct->data[0]==NAT_TYPE_NONE)
122 {
123 OnCompletion(NAT_TYPE_NONE);
124 RakAssert(IsInProgress()==false);
125 }
126 DeallocRNS2RecvStruct(recvStruct, _FILE_AND_LINE_);
127
128 bufferedPacketsMutex.Lock();
129 if (bufferedPackets.Size()>0)
130 recvStruct=bufferedPackets.Pop();
131 else
132 recvStruct=0;
133 bufferedPacketsMutex.Unlock();
134 }
135 }
136 }
137 PluginReceiveResult NatTypeDetectionClient::OnReceive(Packet *packet)
138 {
139 if (IsInProgress())
140 {
141 switch (packet->data[0])
142 {
143 case ID_OUT_OF_BAND_INTERNAL:
144 {
145 if (packet->length>=3 && packet->data[1]==ID_NAT_TYPE_DETECT)
146 {
147 OnCompletion((NATTypeDetectionResult)packet->data[2]);
148 return RR_STOP_PROCESSING_AND_DEALLOCATE;
149 }
150 }
151 break;
152 case ID_NAT_TYPE_DETECTION_RESULT:
153 if (packet->wasGeneratedLocally==false)
154 {
155 OnCompletion((NATTypeDetectionResult)packet->data[1]);
156 return RR_STOP_PROCESSING_AND_DEALLOCATE;
157 }
158 else
159 break;
160 case ID_NAT_TYPE_DETECTION_REQUEST:
161 OnTestPortRestricted(packet);
162 return RR_STOP_PROCESSING_AND_DEALLOCATE;
163 }
164 }
165
166 return RR_CONTINUE_PROCESSING;
167 }
168 void NatTypeDetectionClient::OnClosedConnection(const SystemAddress &systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
169 {
170 (void) lostConnectionReason;
171 (void) rakNetGUID;
172
173 if (IsInProgress() && systemAddress==serverAddress)
174 Shutdown();
175 }
176 void NatTypeDetectionClient::OnRakPeerShutdown(void)
177 {
178 Shutdown();
179 }
180 void NatTypeDetectionClient::OnDetach(void)
181 {
182 Shutdown();
183 }
184 void NatTypeDetectionClient::OnTestPortRestricted(Packet *packet)
185 {
186 SLNet::BitStream bsIn(packet->data,packet->length,false);
187 bsIn.IgnoreBytes(sizeof(MessageID));
188 SLNet::RakString s3p4StrAddress;
189 bsIn.Read(s3p4StrAddress);
190 unsigned short s3p4Port;
191 bsIn.Read(s3p4Port);
192
193 DataStructures::List<RakNetSocket2* > sockets;
194 rakPeerInterface->GetSockets(sockets);
195 SystemAddress s3p4Addr = sockets[0]->GetBoundAddress();
196 s3p4Addr.FromStringExplicitPort(s3p4StrAddress.C_String(), s3p4Port);
197
198 // Send off the RakNet socket to the specified address, message is unformatted
199 // Server does this twice, so don't have to unduly worry about packetloss
200 SLNet::BitStream bsOut;
201 bsOut.Write((MessageID) NAT_TYPE_PORT_RESTRICTED);
202 bsOut.Write(rakPeerInterface->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS));
203 // SocketLayer::SendTo_PC( sockets[0], (const char*) bsOut.GetData(), bsOut.GetNumberOfBytesUsed(), s3p4Addr, __FILE__, __LINE__ );
204
205 RNS2_SendParameters bsp;
206 bsp.data = (char*) bsOut.GetData();
207 bsp.length = bsOut.GetNumberOfBytesUsed();
208 bsp.systemAddress=s3p4Addr;
209 sockets[0]->Send(&bsp, _FILE_AND_LINE_);
210
211 }
212 void NatTypeDetectionClient::Shutdown(void)
213 {
214 serverAddress=UNASSIGNED_SYSTEM_ADDRESS;
215 if (c2!=0)
216 {
217 #if !defined(__native_client__) && !defined(WINDOWS_STORE_RT)
218 if (c2->IsBerkleySocket())
219 ((RNS2_Berkley *)c2)->BlockOnStopRecvPollingThread();
220 #endif
221
222 SLNet::OP_DELETE(c2, _FILE_AND_LINE_);
223 c2=0;
224 }
225
226 bufferedPacketsMutex.Lock();
227 while (bufferedPackets.Size())
228 SLNet::OP_DELETE(bufferedPackets.Pop(), _FILE_AND_LINE_);
229 bufferedPacketsMutex.Unlock();
230 }
231
232 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
233 void NatTypeDetectionClient::DeallocRNS2RecvStruct(RNS2RecvStruct *s, const char *file, unsigned int line)
234 {
235 SLNet::OP_DELETE(s, file, line);
236 }
237 // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
238 RNS2RecvStruct *NatTypeDetectionClient::AllocRNS2RecvStruct(const char *file, unsigned int line)
239 {
240 return SLNet::OP_NEW<RNS2RecvStruct>(file,line);
241 }
242 void NatTypeDetectionClient::OnRNS2Recv(RNS2RecvStruct *recvStruct)
243 {
244 bufferedPacketsMutex.Lock();
245 bufferedPackets.Push(recvStruct,_FILE_AND_LINE_);
246 bufferedPacketsMutex.Unlock();
247 }
248
249 #endif // _RAKNET_SUPPORT_*