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
RakNetSocket2.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) 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/socket2.h"
17 #include "slikenet/memoryoverride.h"
18 #include "slikenet/assert.h"
19 #include "slikenet/sleep.h"
20 #include "slikenet/SocketDefines.h"
21 #include "slikenet/GetTime.h"
22 #include <stdio.h>
23 #include <string.h> // memcpy
24
25 using namespace SLNet;
26
27 #ifdef _WIN32
28 #else
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <arpa/inet.h>
32 #include <errno.h> // error numbers
33 #if !defined(ANDROID)
34 #include <ifaddrs.h>
35 #endif
36 #include <netinet/in.h>
37 #include <net/if.h>
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <sys/ioctl.h>
41 #endif
42
43 #ifdef TEST_NATIVE_CLIENT_ON_WINDOWS
44 #else
45 #define RAKNET_SOCKET_2_INLINE_FUNCTIONS
46 #include "RakNetSocket2_360_720.cpp"
47 #include "RakNetSocket2_PS3_PS4.cpp"
48 #include "RakNetSocket2_PS4.cpp"
49 #include "RakNetSocket2_Windows_Linux.cpp"
50 #include "RakNetSocket2_Windows_Linux_360.cpp"
51 #include "RakNetSocket2_Vita.cpp"
52 #include "RakNetSocket2_NativeClient.cpp"
53 #include "RakNetSocket2_Berkley.cpp"
54 #include "RakNetSocket2_Berkley_NativeClient.cpp"
55 #include "RakNetSocket2_WindowsStore8.cpp"
56 #undef RAKNET_SOCKET_2_INLINE_FUNCTIONS
57
58 #endif
59
60 #ifndef INVALID_SOCKET
61 #define INVALID_SOCKET -1
62 #endif
63
64 void RakNetSocket2Allocator::DeallocRNS2(RakNetSocket2 *s) { SLNet::OP_DELETE(s,_FILE_AND_LINE_);}
65 RakNetSocket2::RakNetSocket2() {eventHandler=0;}
66 RakNetSocket2::~RakNetSocket2() {}
67 void RakNetSocket2::SetRecvEventHandler(RNS2EventHandler *_eventHandler) {eventHandler=_eventHandler;}
68 RNS2Type RakNetSocket2::GetSocketType(void) const {return socketType;}
69 void RakNetSocket2::SetSocketType(RNS2Type t) {socketType=t;}
70 bool RakNetSocket2::IsBerkleySocket(void) const {
71 return socketType!=RNS2T_CHROME && socketType!=RNS2T_WINDOWS_STORE_8;
72 }
73 SystemAddress RakNetSocket2::GetBoundAddress(void) const {return boundAddress;}
74
75 RakNetSocket2* RakNetSocket2Allocator::AllocRNS2(void)
76 {
77 RakNetSocket2* s2;
78 #if defined(WINDOWS_STORE_RT)
79 s2 = SLNet::OP_NEW<RNS2_WindowsStore8>(_FILE_AND_LINE_);
80 s2->SetSocketType(RNS2T_WINDOWS_STORE_8);
81
82
83
84
85
86
87 #elif defined(__native_client__)
88 s2 = SLNet::OP_NEW<RNS2_NativeClient>(_FILE_AND_LINE_);
89 s2->SetSocketType(RNS2T_CHROME);
90
91
92
93
94
95
96
97
98
99 #elif defined(_WIN32)
100 s2 = SLNet::OP_NEW<RNS2_Windows>(_FILE_AND_LINE_);
101 s2->SetSocketType(RNS2T_WINDOWS);
102 #else
103 s2 = SLNet::OP_NEW<RNS2_Linux>(_FILE_AND_LINE_);
104 s2->SetSocketType(RNS2T_LINUX);
105 #endif
106 return s2;
107 }
108 void RakNetSocket2::GetMyIP( SystemAddress addresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS] )
109 {
110 #if defined(WINDOWS_STORE_RT)
111 RNS2_WindowsStore8::GetMyIP( addresses );
112
113
114
115
116 #elif defined(__native_client__)
117 RNS2_NativeClient::GetMyIP( addresses );
118
119
120
121
122
123
124 #elif defined(_WIN32)
125 RNS2_Windows::GetMyIP( addresses );
126 #else
127 RNS2_Linux::GetMyIP( addresses );
128 #endif
129 }
130
131 unsigned int RakNetSocket2::GetUserConnectionSocketIndex(void) const {return userConnectionSocketIndex;}
132 void RakNetSocket2::SetUserConnectionSocketIndex(unsigned int i) {userConnectionSocketIndex=i;}
133 RNS2EventHandler * RakNetSocket2::GetEventHandler(void) const {return eventHandler;}
134
135 void RakNetSocket2::DomainNameToIP( const char *domainName, char ip[65] ) {
136 #if defined(WINDOWS_STORE_RT)
137 return RNS2_WindowsStore8::DomainNameToIP( domainName, ip );
138 #elif defined(__native_client__)
139 return DomainNameToIP_Berkley( domainName, ip );
140
141
142
143
144
145
146
147
148
149
150 #elif defined(_WIN32)
151 return DomainNameToIP_Berkley( domainName, ip );
152 #else
153 return DomainNameToIP_Berkley( domainName, ip );
154 #endif
155 }
156
157 #if defined(WINDOWS_STORE_RT)
158 #elif defined(__native_client__)
159 RNS2_NativeClient::RNS2_NativeClient() {bindState = BS_UNBOUND; sendInProgress=false;}
160 RNS2_NativeClient::~RNS2_NativeClient()
161 {
162 bufferedSendsMutex.Lock();
163 while (bufferedSends.Size())
164 SLNet::OP_DELETE(bufferedSends.Pop(), _FILE_AND_LINE_);
165 bufferedSendsMutex.Unlock();
166 }
167 void RNS2_NativeClient::onSocketBound(void* pData, int32_t dataSize)
168 {
169 RAKNET_DEBUG_PRINTF("onSocketBound ==> %d\n", dataSize);
170 RNS2_NativeClient *csc = (RNS2_NativeClient *)pData;
171
172 //any error codes will be given to us in the dataSize value
173 if(dataSize < 0)
174 {
175 csc->bindState=BS_FAILED;
176 fprintf(stderr,"onSocketBound exiting, dataSize = %d\n", dataSize);
177 return;
178 }
179
180 csc->bindState=BS_BOUND;
181
182 csc->ProcessBufferedSend();
183 csc->IssueReceiveCall();
184 }
185 void RNS2_NativeClient::ProcessBufferedSend(void)
186 {
187 // Don't send until bound
188 if (bindState!=BS_BOUND)
189 return;
190 // Fast non-threadsafe check
191 if (bufferedSends.IsEmpty()==true)
192 return;
193
194 sendInProgressMutex.Lock();
195 if (sendInProgress==true) {sendInProgressMutex.Unlock(); return;}
196 else {sendInProgress=true;}
197 sendInProgressMutex.Unlock();
198
199 RNS2_SendParameters_NativeClient *sp;
200 bufferedSendsMutex.Lock();
201 if (bufferedSends.IsEmpty()==false)
202 sp=bufferedSends.Pop();
203 else
204 sp=0;
205 bufferedSendsMutex.Unlock();
206 if (sp==0)
207 {
208 sendInProgressMutex.Lock();
209 sendInProgress=false;
210 sendInProgressMutex.Unlock();
211 return; // Nothing to send after all
212 }
213
214 SendImmediate(sp);
215 // sp remains in memory until the callback completes
216 // DeallocSP(sp);
217 }
218 void RNS2_NativeClient::DeallocSP(RNS2_SendParameters_NativeClient *sp)
219 {
220 rakFree_Ex(sp->data, _FILE_AND_LINE_);
221 SLNet::OP_DELETE(sp, _FILE_AND_LINE_);
222 }
223 RNS2_SendParameters_NativeClient* RNS2_NativeClient::CloneSP(RNS2_SendParameters *sp, RNS2_NativeClient *socket2, const char *file, unsigned int line)
224 {
225 RNS2_SendParameters_NativeClient *spNew = SLNet::OP_NEW<RNS2_SendParameters_NativeClient>(file, line);
226 spNew->data=(char*) rakMalloc(sp->length);
227 memcpy(spNew->data,sp->data,sp->length);
228 spNew->length = sp->length;
229 spNew->socket2=socket2;
230 spNew->systemAddress=sp->systemAddress;
231 spNew->ttl=0; // Unused
232 return spNew;
233 }
234 void RNS2_NativeClient::onSendTo(void* pData, int32_t dataSize)
235 {
236 if(dataSize <= 0)
237 RAKNET_DEBUG_PRINTF("onSendTo: send failed with error %d\n", dataSize);
238
239 RNS2_SendParameters_NativeClient *sp = (RNS2_SendParameters_NativeClient*) pData;
240
241 // Caller will check sendInProgress to send again if needed
242 sp->socket2->sendInProgressMutex.Lock();
243 sp->socket2->sendInProgress=false;
244 sp->socket2->sendInProgressMutex.Unlock();
245
246 DeallocSP(sp);
247
248 // if(dataSize == PP_ERROR_ABORTED)
249 // return;
250 }
251 RNS2SendResult RNS2_NativeClient::Send( RNS2_SendParameters *sendParameters, const char *file, unsigned int line )
252 {
253 if (bindState==BS_FAILED)
254 return -1;
255
256 // This is called from multiple threads. Always buffer the send, until native client is threadsafe
257 BufferSend(sendParameters, file, line);
258 return sendParameters->length;
259 }
260 void RNS2_NativeClient::BufferSend( RNS2_SendParameters *sendParameters, const char *file, unsigned int line )
261 {
262 if (bindState==BS_FAILED)
263 return;
264
265 RNS2_SendParameters_NativeClient* sp = CloneSP(sendParameters, this, file, line);
266 bufferedSendsMutex.Lock();
267 bufferedSends.Push(sp, file, line);
268 bufferedSendsMutex.Unlock();
269
270 // Do not check to send immediately, because this was probably invoked from a thread and native client is not threadsafe
271 }
272 void RNS2_NativeClient::GetMyIP( SystemAddress addresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS] ) {addresses[0]=UNASSIGNED_SYSTEM_ADDRESS; RakAssert("GetMyIP Unsupported?" && 0);}
273 const NativeClientBindParameters *RNS2_NativeClient::GetBindings(void) const {return &binding;}
274 void RNS2_NativeClient::Update(void)
275 {
276 // Don't send until bound
277 if (bindState==BS_BOUND)
278 {
279 do
280 {
281 ProcessBufferedSend();
282 } while (sendInProgress==false && bufferedSends.Size()>1);
283 }
284 }
285
286 #else // defined(__native_client__)
287 bool IRNS2_Berkley::IsPortInUse(unsigned short port, const char *hostAddress, unsigned short addressFamily, int type ) {
288 RNS2_BerkleyBindParameters bbp;
289 bbp.remotePortRakNetWasStartedOn_PS3_PS4_PSP2=0;
290 bbp.port=port; bbp.hostAddress=(char*) hostAddress; bbp.addressFamily=addressFamily;
291 bbp.type=type; bbp.protocol=0; bbp.nonBlockingSocket=false;
292 bbp.setBroadcast=false; bbp.doNotFragment=false; bbp.protocol=0;
293 bbp.setIPHdrIncl=false;
294 SystemAddress boundAddress;
295 RNS2_Berkley *rns2 = (RNS2_Berkley*) RakNetSocket2Allocator::AllocRNS2();
296 RNS2BindResult bindResult = rns2->Bind(&bbp, _FILE_AND_LINE_);
297 RakNetSocket2Allocator::DeallocRNS2(rns2);
298 return bindResult==BR_FAILED_TO_BIND_SOCKET;
299 }
300
301 #if defined(__APPLE__)
302 void SocketReadCallback(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void *data, void *info)
303 // This C routine is called by CFSocket when there's data waiting on our
304 // UDP socket. It just redirects the call to Objective-C code.
305 { }
306 #endif
307
308 RNS2BindResult RNS2_Berkley::BindShared( RNS2_BerkleyBindParameters *bindParameters, const char *file, unsigned int line ) {
309 RNS2BindResult br;
310 #if RAKNET_SUPPORT_IPV6==1
311 br=BindSharedIPV4And6(bindParameters, file, line);
312 #else
313 br=BindSharedIPV4(bindParameters, file, line);
314 #endif
315
316 if (br!=BR_SUCCESS)
317 return br;
318
319 unsigned long zero=0;
320 RNS2_SendParameters bsp;
321 bsp.data=(char*) &zero;
322 bsp.length=4;
323 bsp.systemAddress=boundAddress;
324 bsp.ttl=0;
325 RNS2SendResult sr = Send(&bsp, _FILE_AND_LINE_);
326 if (sr<0)
327 return BR_FAILED_SEND_TEST;
328
329 memcpy(&binding, bindParameters, sizeof(RNS2_BerkleyBindParameters));
330
331 /*
332 #if defined(__APPLE__)
333 const CFSocketContext context = { 0, this, NULL, NULL, NULL };
334 _cfSocket = CFSocketCreateWithNative(NULL, rns2Socket, kCFSocketReadCallBack, SocketReadCallback, &context);
335 #endif
336 */
337
338 return br;
339 }
340
341 RAK_THREAD_DECLARATION(RNS2_Berkley::RecvFromLoop)
342 {
343
344
345
346 RNS2_Berkley *b = ( RNS2_Berkley * ) arguments;
347
348 b->RecvFromLoopInt();
349 return 0;
350 }
351 unsigned RNS2_Berkley::RecvFromLoopInt(void)
352 {
353 isRecvFromLoopThreadActive.Increment();
354
355 while ( endThreads == false )
356 {
357 RNS2RecvStruct *recvFromStruct;
358 recvFromStruct=binding.eventHandler->AllocRNS2RecvStruct(_FILE_AND_LINE_);
359 if (recvFromStruct != NULL)
360 {
361 recvFromStruct->socket=this;
362 RecvFromBlocking(recvFromStruct);
363
364 if (recvFromStruct->bytesRead>0)
365 {
366 RakAssert(recvFromStruct->systemAddress.GetPort());
367 binding.eventHandler->OnRNS2Recv(recvFromStruct);
368 }
369 else
370 {
371 RakSleep(0);
372 binding.eventHandler->DeallocRNS2RecvStruct(recvFromStruct, _FILE_AND_LINE_);
373 }
374 }
375 }
376 isRecvFromLoopThreadActive.Decrement();
377
378
379
380
381 return 0;
382
383 }
384 RNS2_Berkley::RNS2_Berkley()
385 {
386 rns2Socket=(RNS2Socket)INVALID_SOCKET;
387 }
388 RNS2_Berkley::~RNS2_Berkley()
389 {
390 if (rns2Socket!=INVALID_SOCKET)
391 {
392 /*
393 #if defined(__APPLE__)
394 CFSocketInvalidate(_cfSocket);
395 #endif
396 */
397
398 closesocket__(rns2Socket);
399 }
400
401 }
402 int RNS2_Berkley::CreateRecvPollingThread(int threadPriority)
403 {
404 endThreads=false;
405
406
407
408
409
410
411 int errorCode = SLNet::RakThread::Create(RecvFromLoop, this, threadPriority);
412
413 return errorCode;
414 }
415 void RNS2_Berkley::SignalStopRecvPollingThread(void)
416 {
417 endThreads=true;
418 }
419 void RNS2_Berkley::BlockOnStopRecvPollingThread(void)
420 {
421 endThreads=true;
422
423 // Get recvfrom to unblock
424 RNS2_SendParameters bsp;
425 unsigned long zero=0;
426 bsp.data=(char*) &zero;
427 bsp.length=4;
428 bsp.systemAddress=boundAddress;
429 bsp.ttl=0;
430 Send(&bsp, _FILE_AND_LINE_);
431
432 SLNet::TimeMS timeout = SLNet::GetTimeMS()+1000;
433 while ( isRecvFromLoopThreadActive.GetValue()>0 && SLNet::GetTimeMS()<timeout )
434 {
435 // Get recvfrom to unblock
436 Send(&bsp, _FILE_AND_LINE_);
437 RakSleep(30);
438 }
439 }
440 const RNS2_BerkleyBindParameters *RNS2_Berkley::GetBindings(void) const {return &binding;}
441 RNS2Socket RNS2_Berkley::GetSocket(void) const {return rns2Socket;}
442 // See RakNetSocket2_Berkley.cpp for WriteSharedIPV4, BindSharedIPV4And6 and other implementations
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486 #if defined(_WIN32)
487 RNS2_Windows::RNS2_Windows() {slo=0;}
488 RNS2_Windows::~RNS2_Windows() {}
489 RNS2BindResult RNS2_Windows::Bind( RNS2_BerkleyBindParameters *bindParameters, const char *file, unsigned int line ) {
490 RNS2BindResult bindResult = BindShared(bindParameters, file, line);
491 if (bindResult == BR_FAILED_TO_BIND_SOCKET)
492 {
493 // Sometimes windows will fail if the socket is recreated too quickly
494 RakSleep(100);
495 bindResult = BindShared(bindParameters, file, line);
496 }
497 return bindResult;
498 }
499 RNS2SendResult RNS2_Windows::Send( RNS2_SendParameters *sendParameters, const char *file, unsigned int line ) {
500 if (slo)
501 {
502 RNS2SendResult len;
503 len = slo->RakNetSendTo(sendParameters->data, sendParameters->length,sendParameters->systemAddress);
504 if (len>=0)
505 return len;
506 }
507 return Send_Windows_Linux_360NoVDP(rns2Socket,sendParameters, file, line);
508 }
509 void RNS2_Windows::GetMyIP( SystemAddress addresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS] ) {return GetMyIP_Windows_Linux(addresses);}
510 void RNS2_Windows::SetSocketLayerOverride(SocketLayerOverride *_slo) {slo = _slo;}
511 SocketLayerOverride* RNS2_Windows::GetSocketLayerOverride(void) {return slo;}
512 #else
513 RNS2BindResult RNS2_Linux::Bind( RNS2_BerkleyBindParameters *bindParameters, const char *file, unsigned int line ) {return BindShared(bindParameters, file, line);}
514 RNS2SendResult RNS2_Linux::Send( RNS2_SendParameters *sendParameters, const char *file, unsigned int line ) {return Send_Windows_Linux_360NoVDP(rns2Socket,sendParameters, file, line);}
515 void RNS2_Linux::GetMyIP( SystemAddress addresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS] ) {return GetMyIP_Windows_Linux(addresses);}
516 #endif // Linux
517
518 #endif // defined(__native_client__)