| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554 |
- /*
- * Copyright (c) 2014, Oculus VR, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- */
- #include "EmptyHeader.h"
- #ifdef RAKNET_SOCKET_2_INLINE_FUNCTIONS
- #ifndef RAKNETSOCKET2_BERKLEY_CPP
- #define RAKNETSOCKET2_BERKLEY_CPP
- // Every platform except windows store 8 and native client supports Berkley sockets
- #if !defined(WINDOWS_STORE_RT) && !defined(__native_client__)
- #include "Itoa.h"
- void RNS2_Berkley::SetSocketOptions(void)
- {
- int r;
- // This doubles the max throughput rate
- int sock_opt=1024*256;
- r = setsockopt__( rns2Socket, SOL_SOCKET, SO_RCVBUF, ( char * ) & sock_opt, sizeof ( sock_opt ) );
- RakAssert(r==0);
- // Immediate hard close. Don't linger the socket, or recreating the socket quickly on Vista fails.
- // Fail with voice and xbox
- sock_opt=0;
- r = setsockopt__( rns2Socket, SOL_SOCKET, SO_LINGER, ( char * ) & sock_opt, sizeof ( sock_opt ) );
- // Do not assert, ignore failure
- // This doesn't make much difference: 10% maybe
- // Not supported on console 2
- sock_opt=1024*16;
- r = setsockopt__( rns2Socket, SOL_SOCKET, SO_SNDBUF, ( char * ) & sock_opt, sizeof ( sock_opt ) );
- RakAssert(r==0);
- }
- void RNS2_Berkley::SetNonBlockingSocket(unsigned long nonblocking)
- {
- #ifdef _WIN32
- int res = ioctlsocket__( rns2Socket, FIONBIO, &nonblocking );
- RakAssert(res==0);
- #else
- if (nonblocking)
- fcntl( rns2Socket, F_SETFL, O_NONBLOCK );
- #endif
- }
- void RNS2_Berkley::SetBroadcastSocket(int broadcast)
- {
- setsockopt__( rns2Socket, SOL_SOCKET, SO_BROADCAST, ( char * ) & broadcast, sizeof( broadcast ) );
- }
- void RNS2_Berkley::SetIPHdrIncl(int ipHdrIncl)
- {
- setsockopt__( rns2Socket, IPPROTO_IP, IP_HDRINCL, ( char * ) & ipHdrIncl, sizeof( ipHdrIncl ) );
- }
- void RNS2_Berkley::SetDoNotFragment( int opt )
- {
- #if defined( IP_DONTFRAGMENT )
- #if defined(_WIN32) && !defined(_DEBUG)
- // If this assert hit you improperly linked against WSock32.h
- RakAssert(IP_DONTFRAGMENT==14);
- #endif
- setsockopt__( rns2Socket, boundAddress.GetIPPROTO(), IP_DONTFRAGMENT, ( char * ) & opt, sizeof ( opt ) );
- #endif
- }
- void RNS2_Berkley::GetSystemAddressIPV4 ( RNS2Socket rns2Socket, SystemAddress *systemAddressOut )
- {
- sockaddr_in sa;
- memset(&sa,0,sizeof(sockaddr_in));
- socklen_t len = sizeof(sa);
- //int r =
- getsockname__(rns2Socket, (sockaddr*)&sa, &len);
- systemAddressOut->SetPortNetworkOrder(sa.sin_port);
- systemAddressOut->address.addr4.sin_addr.s_addr=sa.sin_addr.s_addr;
- if (systemAddressOut->address.addr4.sin_addr.s_addr == INADDR_ANY)
- {
- systemAddressOut->address.addr4.sin_addr.s_addr=inet_addr__("127.0.0.1");
- }
- }
- void RNS2_Berkley::GetSystemAddressIPV4And6 ( RNS2Socket rns2Socket, SystemAddress *systemAddressOut )
- {
- #if RAKNET_SUPPORT_IPV6==1
- socklen_t slen;
- sockaddr_storage ss;
- slen = sizeof(ss);
- if ( getsockname__(rns2Socket, (struct sockaddr *)&ss, &slen)!=0)
- {
- #if defined(_WIN32) && defined(_DEBUG)
- DWORD dwIOError = GetLastError();
- LPVOID messageBuffer;
- FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
- ( LPTSTR ) & messageBuffer, 0, NULL );
- // something has gone wrong here...
- RAKNET_DEBUG_PRINTF( "getsockname failed:Error code - %d\n%s", dwIOError, messageBuffer );
- //Free the buffer.
- LocalFree( messageBuffer );
- #endif
- systemAddressOut->FromString(0);
- return;
- }
- if (ss.ss_family==AF_INET)
- {
- memcpy(&systemAddressOut->address.addr4,(sockaddr_in *)&ss,sizeof(sockaddr_in));
- systemAddressOut->debugPort=ntohs(systemAddressOut->address.addr4.sin_port);
- uint32_t zero = 0;
- if (memcmp(&systemAddressOut->address.addr4.sin_addr.s_addr, &zero, sizeof(zero))==0)
- systemAddressOut->SetToLoopback(4);
- // systemAddressOut->address.addr4.sin_port=ntohs(systemAddressOut->address.addr4.sin_port);
- }
- else
- {
- memcpy(&systemAddressOut->address.addr6,(sockaddr_in6 *)&ss,sizeof(sockaddr_in6));
- systemAddressOut->debugPort=ntohs(systemAddressOut->address.addr6.sin6_port);
- char zero[16];
- memset(zero,0,sizeof(zero));
- if (memcmp(&systemAddressOut->address.addr4.sin_addr.s_addr, &zero, sizeof(zero))==0)
- systemAddressOut->SetToLoopback(6);
- // systemAddressOut->address.addr6.sin6_port=ntohs(systemAddressOut->address.addr6.sin6_port);
- }
- #else
- (void) rns2Socket;
- (void) systemAddressOut;
- return;
- #endif
- }
- #ifdef _MSC_VER
- #pragma warning( disable : 4702 ) // warning C4702: unreachable code
- #endif
- RNS2BindResult RNS2_Berkley::BindSharedIPV4( RNS2_BerkleyBindParameters *bindParameters, const char *file, unsigned int line ) {
- (void) file;
- (void) line;
- int ret;
- memset(&boundAddress.address.addr4,0,sizeof(sockaddr_in));
- boundAddress.address.addr4.sin_port = htons( bindParameters->port );
- rns2Socket = (int) socket__( bindParameters->addressFamily, bindParameters->type, bindParameters->protocol );
- if (rns2Socket == -1)
- return BR_FAILED_TO_BIND_SOCKET;
- SetSocketOptions();
- SetNonBlockingSocket(bindParameters->nonBlockingSocket);
- SetBroadcastSocket(bindParameters->setBroadcast);
- SetIPHdrIncl(bindParameters->setIPHdrIncl);
- // Fill in the rest of the address structure
- boundAddress.address.addr4.sin_family = AF_INET;
-
- if (bindParameters->hostAddress && bindParameters->hostAddress[0])
- {
- boundAddress.address.addr4.sin_addr.s_addr = inet_addr__( bindParameters->hostAddress );
- }
- else
- {
- // RAKNET_DEBUG_PRINTF("Binding any on port %i\n", port);
- boundAddress.address.addr4.sin_addr.s_addr = INADDR_ANY;
- }
- // bind our name to the socket
- ret = bind__( rns2Socket, ( struct sockaddr * ) &boundAddress.address.addr4, sizeof( boundAddress.address.addr4 ) );
- if ( ret <= -1 )
- {
- #if defined(_WIN32)
- closesocket__(rns2Socket);
- return BR_FAILED_TO_BIND_SOCKET;
- #elif (defined(__GNUC__) || defined(__GCCXML__) ) && !defined(_WIN32)
- closesocket__(rns2Socket);
- switch (ret)
- {
- case EBADF:
- RAKNET_DEBUG_PRINTF("bind__(): sockfd is not a valid descriptor.\n"); break;
- case ENOTSOCK:
- RAKNET_DEBUG_PRINTF("bind__(): Argument is a descriptor for a file, not a socket.\n"); break;
- case EINVAL:
- RAKNET_DEBUG_PRINTF("bind__(): The addrlen is wrong, or the socket was not in the AF_UNIX family.\n"); break;
- case EROFS:
- RAKNET_DEBUG_PRINTF("bind__(): The socket inode would reside on a read-only file system.\n"); break;
- case EFAULT:
- RAKNET_DEBUG_PRINTF("bind__(): my_addr points outside the user's accessible address space.\n"); break;
- case ENAMETOOLONG:
- RAKNET_DEBUG_PRINTF("bind__(): my_addr is too long.\n"); break;
- case ENOENT:
- RAKNET_DEBUG_PRINTF("bind__(): The file does not exist.\n"); break;
- case ENOMEM:
- RAKNET_DEBUG_PRINTF("bind__(): Insufficient kernel memory was available.\n"); break;
- case ENOTDIR:
- RAKNET_DEBUG_PRINTF("bind__(): A component of the path prefix is not a directory.\n"); break;
- case EACCES:
- // Port reserved on PS4
- RAKNET_DEBUG_PRINTF("bind__(): Search permission is denied on a component of the path prefix.\n"); break;
- case ELOOP:
- RAKNET_DEBUG_PRINTF("bind__(): Too many symbolic links were encountered in resolving my_addr.\n"); break;
- default:
- RAKNET_DEBUG_PRINTF("Unknown bind__() error %i.\n", ret); break;
- }
- #endif
-
- return BR_FAILED_TO_BIND_SOCKET;
- }
- GetSystemAddressIPV4(rns2Socket, &boundAddress );
- return BR_SUCCESS;
- }
- RNS2BindResult RNS2_Berkley::BindSharedIPV4And6( RNS2_BerkleyBindParameters *bindParameters, const char *file, unsigned int line ) {
-
- (void) file;
- (void) line;
- (void) bindParameters;
- #if RAKNET_SUPPORT_IPV6==1
- int ret=0;
- struct addrinfo hints;
- struct addrinfo *servinfo=0, *aip; // will point to the results
- PrepareAddrInfoHints2(&hints);
- hints.ai_family=bindParameters->addressFamily;
- char portStr[32];
- Itoa(bindParameters->port,portStr,10);
- // On Ubuntu, "" returns "No address associated with hostname" while 0 works.
- if (bindParameters->hostAddress &&
- (_stricmp(bindParameters->hostAddress,"UNASSIGNED_SYSTEM_ADDRESS")==0 || bindParameters->hostAddress[0]==0))
- {
- getaddrinfo(0, portStr, &hints, &servinfo);
- }
- else
- {
- getaddrinfo(bindParameters->hostAddress, portStr, &hints, &servinfo);
- }
- // Try all returned addresses until one works
- for (aip = servinfo; aip != NULL; aip = aip->ai_next)
- {
- // Open socket. The address type depends on what
- // getaddrinfo() gave us.
- rns2Socket = socket__(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
- if (rns2Socket == -1)
- return BR_FAILED_TO_BIND_SOCKET;
- ret = bind__(rns2Socket, aip->ai_addr, (int) aip->ai_addrlen );
- if (ret>=0)
- {
- // Is this valid?
- memcpy(&boundAddress.address.addr6, aip->ai_addr, sizeof(boundAddress.address.addr6));
- freeaddrinfo(servinfo); // free the linked-list
- SetSocketOptions();
- SetNonBlockingSocket(bindParameters->nonBlockingSocket);
- SetBroadcastSocket(bindParameters->setBroadcast);
- SetIPHdrIncl(bindParameters->setIPHdrIncl);
- GetSystemAddressIPV4And6( rns2Socket, &boundAddress );
-
- return BR_SUCCESS;
- }
- else
- {
- closesocket__(rns2Socket);
- }
- }
-
- return BR_FAILED_TO_BIND_SOCKET;
- #else
- return BR_REQUIRES_RAKNET_SUPPORT_IPV6_DEFINE;
- #endif
- }
- void RNS2_Berkley::RecvFromBlockingIPV4And6(RNS2RecvStruct *recvFromStruct)
- {
- #if RAKNET_SUPPORT_IPV6==1
- sockaddr_storage their_addr;
- sockaddr* sockAddrPtr;
- socklen_t sockLen;
- socklen_t* socketlenPtr=(socklen_t*) &sockLen;
- memset(&their_addr,0,sizeof(their_addr));
- int dataOutSize;
- const int flag=0;
- {
- sockLen=sizeof(their_addr);
- sockAddrPtr=(sockaddr*) &their_addr;
- }
- dataOutSize=MAXIMUM_MTU_SIZE;
- recvFromStruct->bytesRead = recvfrom__(rns2Socket, recvFromStruct->data, dataOutSize, flag, sockAddrPtr, socketlenPtr );
- #if defined(_WIN32) && defined(_DEBUG) && !defined(WINDOWS_PHONE_8)
- if (recvFromStruct->bytesRead==-1)
- {
- DWORD dwIOError = GetLastError();
- if (dwIoError != 10035)
- {
- LPVOID messageBuffer;
- FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
- ( LPTSTR ) & messageBuffer, 0, NULL );
- // I see this hit on XP with IPV6 for some reason
- RAKNET_DEBUG_PRINTF( "Warning: recvfrom failed:Error code - %d\n%s", dwIOError, messageBuffer );
- LocalFree( messageBuffer );
- }
- }
- #endif
- if (recvFromStruct->bytesRead<=0)
- return;
- recvFromStruct->timeRead=RakNet::GetTimeUS();
- {
- if (their_addr.ss_family==AF_INET)
- {
- memcpy(&recvFromStruct->systemAddress.address.addr4,(sockaddr_in *)&their_addr,sizeof(sockaddr_in));
- recvFromStruct->systemAddress.debugPort=ntohs(recvFromStruct->systemAddress.address.addr4.sin_port);
- // systemAddressOut->address.addr4.sin_port=ntohs( systemAddressOut->address.addr4.sin_port );
- }
- else
- {
- memcpy(&recvFromStruct->systemAddress.address.addr6,(sockaddr_in6 *)&their_addr,sizeof(sockaddr_in6));
- recvFromStruct->systemAddress.debugPort=ntohs(recvFromStruct->systemAddress.address.addr6.sin6_port);
- // systemAddressOut->address.addr6.sin6_port=ntohs( systemAddressOut->address.addr6.sin6_port );
- }
- }
- #else
- (void) recvFromStruct;
- #endif
- }
- void RNS2_Berkley::RecvFromBlockingIPV4(RNS2RecvStruct *recvFromStruct)
- {
- sockaddr* sockAddrPtr;
- socklen_t sockLen;
- socklen_t* socketlenPtr=(socklen_t*) &sockLen;
- sockaddr_in sa;
- memset(&sa,0,sizeof(sockaddr_in));
- const int flag=0;
-
-
- {
- sockLen=sizeof(sa);
- sa.sin_family = AF_INET;
- sa.sin_port=0;
- sockAddrPtr=(sockaddr*) &sa;
- }
- recvFromStruct->bytesRead = recvfrom__( GetSocket(), recvFromStruct->data, sizeof(recvFromStruct->data), flag, sockAddrPtr, socketlenPtr );
- if (recvFromStruct->bytesRead<=0)
- {
- /*
- DWORD dwIOError = WSAGetLastError();
- if ( dwIOError == WSAECONNRESET )
- {
- #if defined(_DEBUG)
- RAKNET_DEBUG_PRINTF( "A previous send operation resulted in an ICMP Port Unreachable message.\n" );
- #endif
- }
- else if ( dwIOError != WSAEWOULDBLOCK && dwIOError != WSAEADDRNOTAVAIL)
- {
- #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)
- LPVOID messageBuffer;
- FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
- ( LPTSTR ) & messageBuffer, 0, NULL );
- // something has gone wrong here...
- RAKNET_DEBUG_PRINTF( "sendto failed:Error code - %d\n%s", dwIOError, messageBuffer );
- //Free the buffer.
- LocalFree( messageBuffer );
- #endif
- }
- */
- return;
- }
- recvFromStruct->timeRead=RakNet::GetTimeUS();
- {
-
- recvFromStruct->systemAddress.SetPortNetworkOrder( sa.sin_port );
- recvFromStruct->systemAddress.address.addr4.sin_addr.s_addr=sa.sin_addr.s_addr;
- }
- // printf("--- Got %i bytes from %s\n", recvFromStruct->bytesRead, recvFromStruct->systemAddress.ToString());
- }
- void RNS2_Berkley::RecvFromBlocking(RNS2RecvStruct *recvFromStruct)
- {
- #if RAKNET_SUPPORT_IPV6==1
- return RecvFromBlockingIPV4And6(recvFromStruct);
- #else
- return RecvFromBlockingIPV4(recvFromStruct);
- #endif
- }
- #endif // !defined(WINDOWS_STORE_RT) && !defined(__native_client__)
- #endif // file header
- #endif // #ifdef RAKNET_SOCKET_2_INLINE_FUNCTIONS
|