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_Berkley.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/EmptyHeader.h"
17
18 #ifdef RAKNET_SOCKET_2_INLINE_FUNCTIONS
19
20 #ifndef RAKNETSOCKET2_BERKLEY_CPP
21 #define RAKNETSOCKET2_BERKLEY_CPP
22
23 // Every platform except windows store 8 and native client supports Berkley sockets
24 #if !defined(WINDOWS_STORE_RT) && !defined(__native_client__)
25
26 #ifdef _WIN32
27 #include <tchar.h> // used for _tprintf() (via RAKNET_DEBUG_TPRINTF)
28 #else
29 #include "slikenet/LinuxStrings.h" // used for _stricmp()
30 #endif
31
32 #include "slikenet/Itoa.h"
33
34 void RNS2_Berkley::SetSocketOptions(void)
35 {
36 int r;
37 // This doubles the max throughput rate
38 int sock_opt=1024*256;
39 r = setsockopt__( rns2Socket, SOL_SOCKET, SO_RCVBUF, ( char * ) & sock_opt, sizeof ( sock_opt ) );
40 RakAssert(r==0);
41
42 // Immediate hard close. Don't linger the socket, or recreating the socket quickly on Vista fails.
43 // Fail with voice and xbox
44
45 sock_opt=0;
46 r = setsockopt__( rns2Socket, SOL_SOCKET, SO_LINGER, ( char * ) & sock_opt, sizeof ( sock_opt ) );
47 // Do not assert, ignore failure
48
49
50
51 // This doesn't make much difference: 10% maybe
52 // Not supported on console 2
53 sock_opt=1024*16;
54 r = setsockopt__( rns2Socket, SOL_SOCKET, SO_SNDBUF, ( char * ) & sock_opt, sizeof ( sock_opt ) );
55 RakAssert(r==0);
56
57 }
58
59 void RNS2_Berkley::SetNonBlockingSocket(unsigned long nonblocking)
60 {
61 #ifdef _WIN32
62 int res = ioctlsocket__( rns2Socket, FIONBIO, &nonblocking );
63 RakAssert(res==0);
64
65
66
67 #else
68 if (nonblocking)
69 fcntl( rns2Socket, F_SETFL, O_NONBLOCK );
70 #endif
71 }
72 void RNS2_Berkley::SetBroadcastSocket(int broadcast)
73 {
74 setsockopt__( rns2Socket, SOL_SOCKET, SO_BROADCAST, ( char * ) & broadcast, sizeof( broadcast ) );
75 }
76 void RNS2_Berkley::SetIPHdrIncl(int ipHdrIncl)
77 {
78
79 setsockopt__( rns2Socket, IPPROTO_IP, IP_HDRINCL, ( char * ) & ipHdrIncl, sizeof( ipHdrIncl ) );
80
81 }
82 void RNS2_Berkley::SetDoNotFragment( int opt )
83 {
84 #if defined( IP_DONTFRAGMENT )
85 #if defined(_WIN32) && !defined(_DEBUG)
86 // If this assert hit you improperly linked against WSock32.h
87 RakAssert(IP_DONTFRAGMENT==14);
88 #endif
89 setsockopt__( rns2Socket, boundAddress.GetIPPROTO(), IP_DONTFRAGMENT, ( char * ) & opt, sizeof ( opt ) );
90 #endif
91 }
92
93 void RNS2_Berkley::GetSystemAddressIPV4 ( RNS2Socket rns2Socket, SystemAddress *systemAddressOut )
94 {
95 sockaddr_in sa;
96 memset(&sa,0,sizeof(sockaddr_in));
97 socklen_t len = sizeof(sa);
98 //int r =
99 getsockname__(rns2Socket, (sockaddr*)&sa, &len);
100 systemAddressOut->SetPortNetworkOrder(sa.sin_port);
101 systemAddressOut->address.addr4.sin_addr.s_addr=sa.sin_addr.s_addr;
102
103 if (systemAddressOut->address.addr4.sin_addr.s_addr == INADDR_ANY)
104 {
105
106
107
108
109 inet_pton(AF_INET, "127.0.0.1", &systemAddressOut->address.addr4.sin_addr.s_addr);
110
111 }
112 }
113 void RNS2_Berkley::GetSystemAddressIPV4And6 ( RNS2Socket rns2Socket, SystemAddress *systemAddressOut )
114 {
115 #if RAKNET_SUPPORT_IPV6==1
116
117 socklen_t slen;
118 sockaddr_storage ss;
119 slen = sizeof(ss);
120
121 if ( getsockname__(rns2Socket, (struct sockaddr *)&ss, &slen)!=0)
122 {
123 #if defined(_WIN32) && defined(_DEBUG)
124 DWORD dwIOError = GetLastError();
125 LPVOID messageBuffer;
126 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
127 NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
128 ( LPTSTR ) & messageBuffer, 0, NULL );
129 // something has gone wrong here...
130 RAKNET_DEBUG_TPRINTF( _T("getsockname failed:Error code - %d\n%s"), dwIOError, static_cast<LPTSTR>(messageBuffer));
131
132 //Free the buffer.
133 LocalFree( messageBuffer );
134 #endif
135 systemAddressOut->FromString(0);
136 return;
137 }
138
139 if (ss.ss_family==AF_INET)
140 {
141 memcpy(&systemAddressOut->address.addr4,(sockaddr_in *)&ss,sizeof(sockaddr_in));
142 systemAddressOut->debugPort=ntohs(systemAddressOut->address.addr4.sin_port);
143
144 uint32_t zero = 0;
145 if (memcmp(&systemAddressOut->address.addr4.sin_addr.s_addr, &zero, sizeof(zero))==0)
146 systemAddressOut->SetToLoopback(4);
147 // systemAddressOut->address.addr4.sin_port=ntohs(systemAddressOut->address.addr4.sin_port);
148 }
149 else
150 {
151 memcpy(&systemAddressOut->address.addr6,(sockaddr_in6 *)&ss,sizeof(sockaddr_in6));
152 systemAddressOut->debugPort=ntohs(systemAddressOut->address.addr6.sin6_port);
153
154 char zero[16];
155 memset(zero,0,sizeof(zero));
156 if (memcmp(&systemAddressOut->address.addr4.sin_addr.s_addr, &zero, sizeof(zero))==0)
157 systemAddressOut->SetToLoopback(6);
158
159 // systemAddressOut->address.addr6.sin6_port=ntohs(systemAddressOut->address.addr6.sin6_port);
160 }
161
162 #else
163 (void) rns2Socket;
164 (void) systemAddressOut;
165 return;
166 #endif
167 }
168
169 RNS2BindResult RNS2_Berkley::BindSharedIPV4( RNS2_BerkleyBindParameters *bindParameters, const char *file, unsigned int line ) {
170
171 (void) file;
172 (void) line;
173
174 int ret;
175 memset(&boundAddress.address.addr4,0,sizeof(sockaddr_in));
176 boundAddress.address.addr4.sin_port = htons( bindParameters->port );
177 rns2Socket = (int) socket__( bindParameters->addressFamily, bindParameters->type, bindParameters->protocol );
178 if (rns2Socket == -1)
179 return BR_FAILED_TO_BIND_SOCKET;
180
181 SetSocketOptions();
182 SetNonBlockingSocket(bindParameters->nonBlockingSocket);
183 SetBroadcastSocket(bindParameters->setBroadcast);
184 SetIPHdrIncl(bindParameters->setIPHdrIncl);
185
186 // Fill in the rest of the address structure
187 boundAddress.address.addr4.sin_family = AF_INET;
188
189
190
191
192
193 if (bindParameters->hostAddress && bindParameters->hostAddress[0])
194 {
195
196
197
198
199
200 inet_pton(AF_INET, bindParameters->hostAddress, &boundAddress.address.addr4.sin_addr.s_addr);
201
202 }
203 else
204 {
205 // RAKNET_DEBUG_PRINTF("Binding any on port %i\n", port);
206 boundAddress.address.addr4.sin_addr.s_addr = INADDR_ANY;
207 }
208
209
210
211
212
213 // bind our name to the socket
214 ret = bind__( rns2Socket, ( struct sockaddr * ) &boundAddress.address.addr4, sizeof( boundAddress.address.addr4 ) );
215
216 if ( ret <= -1 )
217 {
218
219
220
221
222
223
224
225
226 #if defined(_WIN32)
227 closesocket__(rns2Socket);
228 return BR_FAILED_TO_BIND_SOCKET;
229 #elif (defined(__GNUC__) || defined(__GCCXML__) ) && !defined(_WIN32)
230 closesocket__(rns2Socket);
231 switch (errno)
232 {
233 case EBADF:
234 RAKNET_DEBUG_PRINTF("bind__(): sockfd is not a valid descriptor.\n"); break;
235
236 case ENOTSOCK:
237 RAKNET_DEBUG_PRINTF("bind__(): Argument is a descriptor for a file, not a socket.\n"); break;
238
239 case EINVAL:
240 RAKNET_DEBUG_PRINTF("bind__(): The addrlen is wrong, or the socket was not in the AF_UNIX family.\n"); break;
241 case EROFS:
242 RAKNET_DEBUG_PRINTF("bind__(): The socket inode would reside on a read-only file system.\n"); break;
243 case EFAULT:
244 RAKNET_DEBUG_PRINTF("bind__(): my_addr points outside the user's accessible address space.\n"); break;
245 case ENAMETOOLONG:
246 RAKNET_DEBUG_PRINTF("bind__(): my_addr is too long.\n"); break;
247 case ENOENT:
248 RAKNET_DEBUG_PRINTF("bind__(): The file does not exist.\n"); break;
249 case ENOMEM:
250 RAKNET_DEBUG_PRINTF("bind__(): Insufficient kernel memory was available.\n"); break;
251 case ENOTDIR:
252 RAKNET_DEBUG_PRINTF("bind__(): A component of the path prefix is not a directory.\n"); break;
253 case EACCES:
254 // Port reserved on PS4
255 RAKNET_DEBUG_PRINTF("bind__(): Search permission is denied on a component of the path prefix.\n"); break;
256
257 case ELOOP:
258 RAKNET_DEBUG_PRINTF("bind__(): Too many symbolic links were encountered in resolving my_addr.\n"); break;
259
260 default:
261 RAKNET_DEBUG_PRINTF("Unknown bind__() error %i.\n", errno); break;
262 }
263
264 return BR_FAILED_TO_BIND_SOCKET;
265 #endif
266 }
267
268 GetSystemAddressIPV4(rns2Socket, &boundAddress );
269
270 return BR_SUCCESS;
271
272 }
273 RNS2BindResult RNS2_Berkley::BindSharedIPV4And6( RNS2_BerkleyBindParameters *bindParameters, const char *file, unsigned int line ) {
274
275 (void) file;
276 (void) line;
277 (void) bindParameters;
278
279 #if RAKNET_SUPPORT_IPV6==1
280
281 int ret=0;
282 struct addrinfo hints;
283 struct addrinfo *servinfo=0, *aip; // will point to the results
284 PrepareAddrInfoHints2(&hints);
285 hints.ai_family=bindParameters->addressFamily;
286 char portStr[32];
287 Itoa(bindParameters->port,portStr,10);
288
289
290 // On Ubuntu, "" returns "No address associated with hostname" while 0 works.
291 if (bindParameters->hostAddress &&
292 (_stricmp(bindParameters->hostAddress,"UNASSIGNED_SYSTEM_ADDRESS")==0 || bindParameters->hostAddress[0]==0))
293 {
294 getaddrinfo(0, portStr, &hints, &servinfo);
295 }
296 else
297 {
298 getaddrinfo(bindParameters->hostAddress, portStr, &hints, &servinfo);
299 }
300
301 // Try all returned addresses until one works
302 for (aip = servinfo; aip != NULL; aip = aip->ai_next)
303 {
304 // Open socket. The address type depends on what
305 // getaddrinfo() gave us.
306 rns2Socket = socket__(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
307
308 if (rns2Socket == -1)
309 return BR_FAILED_TO_BIND_SOCKET;
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329 ret = bind__(rns2Socket, aip->ai_addr, (int) aip->ai_addrlen );
330 if (ret>=0)
331 {
332 if (aip->ai_family == AF_INET)
333 {
334 memcpy(&boundAddress.address.addr4, aip->ai_addr, sizeof(sockaddr_in));
335 }
336 else
337 {
338 memcpy(&boundAddress.address.addr6, aip->ai_addr, sizeof(sockaddr_in6));
339 }
340
341 freeaddrinfo(servinfo); // free the linked-list
342
343 SetSocketOptions();
344 SetNonBlockingSocket(bindParameters->nonBlockingSocket);
345 SetBroadcastSocket(bindParameters->setBroadcast);
346 SetIPHdrIncl(bindParameters->setIPHdrIncl);
347
348 GetSystemAddressIPV4And6( rns2Socket, &boundAddress );
349
350 return BR_SUCCESS;
351 }
352 else
353 {
354 closesocket__(rns2Socket);
355 }
356 }
357
358 return BR_FAILED_TO_BIND_SOCKET;
359
360 #else
361 return BR_REQUIRES_RAKNET_SUPPORT_IPV6_DEFINE;
362 #endif
363 }
364
365 void RNS2_Berkley::RecvFromBlockingIPV4And6(RNS2RecvStruct *recvFromStruct)
366 {
367 #if RAKNET_SUPPORT_IPV6==1
368
369 sockaddr_storage their_addr;
370 sockaddr* sockAddrPtr;
371 socklen_t sockLen;
372 socklen_t* socketlenPtr=(socklen_t*) &sockLen;
373 memset(&their_addr,0,sizeof(their_addr));
374 int dataOutSize;
375 const int flag=0;
376
377
378
379
380
381
382
383
384
385
386
387 {
388 sockLen=sizeof(their_addr);
389 sockAddrPtr=(sockaddr*) &their_addr;
390 }
391
392
393
394
395 dataOutSize=MAXIMUM_MTU_SIZE;
396
397
398 recvFromStruct->bytesRead = recvfrom__(rns2Socket, recvFromStruct->data, dataOutSize, flag, sockAddrPtr, socketlenPtr );
399
400 #if defined(_WIN32) && defined(_DEBUG) && !defined(WINDOWS_PHONE_8)
401 if (recvFromStruct->bytesRead==-1)
402 {
403 DWORD dwIOError = GetLastError();
404 if (dwIOError != 10035)
405 {
406 LPVOID messageBuffer;
407 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
408 NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
409 ( LPTSTR ) & messageBuffer, 0, NULL );
410 // I see this hit on XP with IPV6 for some reason
411 RAKNET_DEBUG_TPRINTF( _T("Warning: recvfrom failed:Error code - %d\n%s"), dwIOError, static_cast<LPTSTR>(messageBuffer) );
412 LocalFree( messageBuffer );
413 }
414 }
415 #endif
416
417
418
419
420
421
422
423
424
425
426 if (recvFromStruct->bytesRead<=0)
427 return;
428 recvFromStruct->timeRead= SLNet::GetTimeUS();
429
430
431
432
433
434
435
436
437
438 {
439 if (their_addr.ss_family==AF_INET)
440 {
441 memcpy(&recvFromStruct->systemAddress.address.addr4,(sockaddr_in *)&their_addr,sizeof(sockaddr_in));
442 recvFromStruct->systemAddress.debugPort=ntohs(recvFromStruct->systemAddress.address.addr4.sin_port);
443 // systemAddressOut->address.addr4.sin_port=ntohs( systemAddressOut->address.addr4.sin_port );
444 }
445 else
446 {
447 memcpy(&recvFromStruct->systemAddress.address.addr6,(sockaddr_in6 *)&their_addr,sizeof(sockaddr_in6));
448 recvFromStruct->systemAddress.debugPort=ntohs(recvFromStruct->systemAddress.address.addr6.sin6_port);
449 // systemAddressOut->address.addr6.sin6_port=ntohs( systemAddressOut->address.addr6.sin6_port );
450 }
451 }
452
453
454 #else
455 (void) recvFromStruct;
456 #endif
457 }
458
459 void RNS2_Berkley::RecvFromBlockingIPV4(RNS2RecvStruct *recvFromStruct)
460 {
461 sockaddr* sockAddrPtr;
462 socklen_t sockLen;
463 socklen_t* socketlenPtr=(socklen_t*) &sockLen;
464 sockaddr_in sa;
465 memset(&sa,0,sizeof(sockaddr_in));
466 const int flag=0;
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488 {
489 sockLen=sizeof(sa);
490 sa.sin_family = AF_INET;
491 sa.sin_port=0;
492 sockAddrPtr=(sockaddr*) &sa;
493 }
494
495 recvFromStruct->bytesRead = recvfrom__( GetSocket(), recvFromStruct->data, sizeof(recvFromStruct->data), flag, sockAddrPtr, socketlenPtr );
496
497
498
499
500
501
502
503
504
505 if (recvFromStruct->bytesRead<=0)
506 {
507 /*
508 DWORD dwIOError = WSAGetLastError();
509
510 if ( dwIOError == WSAECONNRESET )
511 {
512 #if defined(_DEBUG)
513 RAKNET_DEBUG_PRINTF( "A previous send operation resulted in an ICMP Port Unreachable message.\n" );
514 #endif
515
516 }
517 else if ( dwIOError != WSAEWOULDBLOCK && dwIOError != WSAEADDRNOTAVAIL)
518 {
519 #if defined(_WIN32) && !defined(_XBOX) && !defined(_XBOX_720_COMPILE_AS_WINDOWS) && !defined(X360) && defined(_DEBUG) && !defined(_XBOX_720_COMPILE_AS_WINDOWS) && !defined(WINDOWS_PHONE_8)
520 LPVOID messageBuffer;
521 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
522 NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
523 ( LPTSTR ) & messageBuffer, 0, NULL );
524 // something has gone wrong here...
525 RAKNET_DEBUG_PRINTF( "sendto failed:Error code - %d\n%s", dwIOError, static_cast<LPTSTR>(messageBuffer) );
526
527 //Free the buffer.
528 LocalFree( messageBuffer );
529 #endif
530 }
531 */
532
533 return;
534 }
535 recvFromStruct->timeRead= SLNet::GetTimeUS();
536
537
538
539
540
541
542
543
544
545 {
546
547 recvFromStruct->systemAddress.SetPortNetworkOrder( sa.sin_port );
548 recvFromStruct->systemAddress.address.addr4.sin_addr.s_addr=sa.sin_addr.s_addr;
549 }
550
551 // printf("--- Got %i bytes from %s\n", recvFromStruct->bytesRead, recvFromStruct->systemAddress.ToString());
552 }
553
554 void RNS2_Berkley::RecvFromBlocking(RNS2RecvStruct *recvFromStruct)
555 {
556 #if RAKNET_SUPPORT_IPV6==1
557 return RecvFromBlockingIPV4And6(recvFromStruct);
558 #else
559 return RecvFromBlockingIPV4(recvFromStruct);
560 #endif
561 }
562
563 #endif // !defined(WINDOWS_STORE_RT) && !defined(__native_client__)
564
565 #endif // file header
566
567 #endif // #ifdef RAKNET_SOCKET_2_INLINE_FUNCTIONS