RakNetSocket2_Berkley.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. /*
  2. * 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. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. */
  10. #include "EmptyHeader.h"
  11. #ifdef RAKNET_SOCKET_2_INLINE_FUNCTIONS
  12. #ifndef RAKNETSOCKET2_BERKLEY_CPP
  13. #define RAKNETSOCKET2_BERKLEY_CPP
  14. // Every platform except windows store 8 and native client supports Berkley sockets
  15. #if !defined(WINDOWS_STORE_RT) && !defined(__native_client__)
  16. #include "Itoa.h"
  17. void RNS2_Berkley::SetSocketOptions(void)
  18. {
  19. int r;
  20. // This doubles the max throughput rate
  21. int sock_opt=1024*256;
  22. r = setsockopt__( rns2Socket, SOL_SOCKET, SO_RCVBUF, ( char * ) & sock_opt, sizeof ( sock_opt ) );
  23. RakAssert(r==0);
  24. // Immediate hard close. Don't linger the socket, or recreating the socket quickly on Vista fails.
  25. // Fail with voice and xbox
  26. sock_opt=0;
  27. r = setsockopt__( rns2Socket, SOL_SOCKET, SO_LINGER, ( char * ) & sock_opt, sizeof ( sock_opt ) );
  28. // Do not assert, ignore failure
  29. // This doesn't make much difference: 10% maybe
  30. // Not supported on console 2
  31. sock_opt=1024*16;
  32. r = setsockopt__( rns2Socket, SOL_SOCKET, SO_SNDBUF, ( char * ) & sock_opt, sizeof ( sock_opt ) );
  33. RakAssert(r==0);
  34. }
  35. void RNS2_Berkley::SetNonBlockingSocket(unsigned long nonblocking)
  36. {
  37. #ifdef _WIN32
  38. int res = ioctlsocket__( rns2Socket, FIONBIO, &nonblocking );
  39. RakAssert(res==0);
  40. #else
  41. if (nonblocking)
  42. fcntl( rns2Socket, F_SETFL, O_NONBLOCK );
  43. #endif
  44. }
  45. void RNS2_Berkley::SetBroadcastSocket(int broadcast)
  46. {
  47. setsockopt__( rns2Socket, SOL_SOCKET, SO_BROADCAST, ( char * ) & broadcast, sizeof( broadcast ) );
  48. }
  49. void RNS2_Berkley::SetIPHdrIncl(int ipHdrIncl)
  50. {
  51. setsockopt__( rns2Socket, IPPROTO_IP, IP_HDRINCL, ( char * ) & ipHdrIncl, sizeof( ipHdrIncl ) );
  52. }
  53. void RNS2_Berkley::SetDoNotFragment( int opt )
  54. {
  55. #if defined( IP_DONTFRAGMENT )
  56. #if defined(_WIN32) && !defined(_DEBUG)
  57. // If this assert hit you improperly linked against WSock32.h
  58. RakAssert(IP_DONTFRAGMENT==14);
  59. #endif
  60. setsockopt__( rns2Socket, boundAddress.GetIPPROTO(), IP_DONTFRAGMENT, ( char * ) & opt, sizeof ( opt ) );
  61. #endif
  62. }
  63. void RNS2_Berkley::GetSystemAddressIPV4 ( RNS2Socket rns2Socket, SystemAddress *systemAddressOut )
  64. {
  65. sockaddr_in sa;
  66. memset(&sa,0,sizeof(sockaddr_in));
  67. socklen_t len = sizeof(sa);
  68. //int r =
  69. getsockname__(rns2Socket, (sockaddr*)&sa, &len);
  70. systemAddressOut->SetPortNetworkOrder(sa.sin_port);
  71. systemAddressOut->address.addr4.sin_addr.s_addr=sa.sin_addr.s_addr;
  72. if (systemAddressOut->address.addr4.sin_addr.s_addr == INADDR_ANY)
  73. {
  74. systemAddressOut->address.addr4.sin_addr.s_addr=inet_addr__("127.0.0.1");
  75. }
  76. }
  77. void RNS2_Berkley::GetSystemAddressIPV4And6 ( RNS2Socket rns2Socket, SystemAddress *systemAddressOut )
  78. {
  79. #if RAKNET_SUPPORT_IPV6==1
  80. socklen_t slen;
  81. sockaddr_storage ss;
  82. slen = sizeof(ss);
  83. if ( getsockname__(rns2Socket, (struct sockaddr *)&ss, &slen)!=0)
  84. {
  85. #if defined(_WIN32) && defined(_DEBUG)
  86. DWORD dwIOError = GetLastError();
  87. LPVOID messageBuffer;
  88. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  89. NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
  90. ( LPTSTR ) & messageBuffer, 0, NULL );
  91. // something has gone wrong here...
  92. RAKNET_DEBUG_PRINTF( "getsockname failed:Error code - %d\n%s", dwIOError, messageBuffer );
  93. //Free the buffer.
  94. LocalFree( messageBuffer );
  95. #endif
  96. systemAddressOut->FromString(0);
  97. return;
  98. }
  99. if (ss.ss_family==AF_INET)
  100. {
  101. memcpy(&systemAddressOut->address.addr4,(sockaddr_in *)&ss,sizeof(sockaddr_in));
  102. systemAddressOut->debugPort=ntohs(systemAddressOut->address.addr4.sin_port);
  103. uint32_t zero = 0;
  104. if (memcmp(&systemAddressOut->address.addr4.sin_addr.s_addr, &zero, sizeof(zero))==0)
  105. systemAddressOut->SetToLoopback(4);
  106. // systemAddressOut->address.addr4.sin_port=ntohs(systemAddressOut->address.addr4.sin_port);
  107. }
  108. else
  109. {
  110. memcpy(&systemAddressOut->address.addr6,(sockaddr_in6 *)&ss,sizeof(sockaddr_in6));
  111. systemAddressOut->debugPort=ntohs(systemAddressOut->address.addr6.sin6_port);
  112. char zero[16];
  113. memset(zero,0,sizeof(zero));
  114. if (memcmp(&systemAddressOut->address.addr4.sin_addr.s_addr, &zero, sizeof(zero))==0)
  115. systemAddressOut->SetToLoopback(6);
  116. // systemAddressOut->address.addr6.sin6_port=ntohs(systemAddressOut->address.addr6.sin6_port);
  117. }
  118. #else
  119. (void) rns2Socket;
  120. (void) systemAddressOut;
  121. return;
  122. #endif
  123. }
  124. #ifdef _MSC_VER
  125. #pragma warning( disable : 4702 ) // warning C4702: unreachable code
  126. #endif
  127. RNS2BindResult RNS2_Berkley::BindSharedIPV4( RNS2_BerkleyBindParameters *bindParameters, const char *file, unsigned int line ) {
  128. (void) file;
  129. (void) line;
  130. int ret;
  131. memset(&boundAddress.address.addr4,0,sizeof(sockaddr_in));
  132. boundAddress.address.addr4.sin_port = htons( bindParameters->port );
  133. rns2Socket = (int) socket__( bindParameters->addressFamily, bindParameters->type, bindParameters->protocol );
  134. if (rns2Socket == -1)
  135. return BR_FAILED_TO_BIND_SOCKET;
  136. SetSocketOptions();
  137. SetNonBlockingSocket(bindParameters->nonBlockingSocket);
  138. SetBroadcastSocket(bindParameters->setBroadcast);
  139. SetIPHdrIncl(bindParameters->setIPHdrIncl);
  140. // Fill in the rest of the address structure
  141. boundAddress.address.addr4.sin_family = AF_INET;
  142. if (bindParameters->hostAddress && bindParameters->hostAddress[0])
  143. {
  144. boundAddress.address.addr4.sin_addr.s_addr = inet_addr__( bindParameters->hostAddress );
  145. }
  146. else
  147. {
  148. // RAKNET_DEBUG_PRINTF("Binding any on port %i\n", port);
  149. boundAddress.address.addr4.sin_addr.s_addr = INADDR_ANY;
  150. }
  151. // bind our name to the socket
  152. ret = bind__( rns2Socket, ( struct sockaddr * ) &boundAddress.address.addr4, sizeof( boundAddress.address.addr4 ) );
  153. if ( ret <= -1 )
  154. {
  155. #if defined(_WIN32)
  156. closesocket__(rns2Socket);
  157. return BR_FAILED_TO_BIND_SOCKET;
  158. #elif (defined(__GNUC__) || defined(__GCCXML__) ) && !defined(_WIN32)
  159. closesocket__(rns2Socket);
  160. switch (ret)
  161. {
  162. case EBADF:
  163. RAKNET_DEBUG_PRINTF("bind__(): sockfd is not a valid descriptor.\n"); break;
  164. case ENOTSOCK:
  165. RAKNET_DEBUG_PRINTF("bind__(): Argument is a descriptor for a file, not a socket.\n"); break;
  166. case EINVAL:
  167. RAKNET_DEBUG_PRINTF("bind__(): The addrlen is wrong, or the socket was not in the AF_UNIX family.\n"); break;
  168. case EROFS:
  169. RAKNET_DEBUG_PRINTF("bind__(): The socket inode would reside on a read-only file system.\n"); break;
  170. case EFAULT:
  171. RAKNET_DEBUG_PRINTF("bind__(): my_addr points outside the user's accessible address space.\n"); break;
  172. case ENAMETOOLONG:
  173. RAKNET_DEBUG_PRINTF("bind__(): my_addr is too long.\n"); break;
  174. case ENOENT:
  175. RAKNET_DEBUG_PRINTF("bind__(): The file does not exist.\n"); break;
  176. case ENOMEM:
  177. RAKNET_DEBUG_PRINTF("bind__(): Insufficient kernel memory was available.\n"); break;
  178. case ENOTDIR:
  179. RAKNET_DEBUG_PRINTF("bind__(): A component of the path prefix is not a directory.\n"); break;
  180. case EACCES:
  181. // Port reserved on PS4
  182. RAKNET_DEBUG_PRINTF("bind__(): Search permission is denied on a component of the path prefix.\n"); break;
  183. case ELOOP:
  184. RAKNET_DEBUG_PRINTF("bind__(): Too many symbolic links were encountered in resolving my_addr.\n"); break;
  185. default:
  186. RAKNET_DEBUG_PRINTF("Unknown bind__() error %i.\n", ret); break;
  187. }
  188. #endif
  189. return BR_FAILED_TO_BIND_SOCKET;
  190. }
  191. GetSystemAddressIPV4(rns2Socket, &boundAddress );
  192. return BR_SUCCESS;
  193. }
  194. RNS2BindResult RNS2_Berkley::BindSharedIPV4And6( RNS2_BerkleyBindParameters *bindParameters, const char *file, unsigned int line ) {
  195. (void) file;
  196. (void) line;
  197. (void) bindParameters;
  198. #if RAKNET_SUPPORT_IPV6==1
  199. int ret=0;
  200. struct addrinfo hints;
  201. struct addrinfo *servinfo=0, *aip; // will point to the results
  202. PrepareAddrInfoHints2(&hints);
  203. hints.ai_family=bindParameters->addressFamily;
  204. char portStr[32];
  205. Itoa(bindParameters->port,portStr,10);
  206. // On Ubuntu, "" returns "No address associated with hostname" while 0 works.
  207. if (bindParameters->hostAddress &&
  208. (_stricmp(bindParameters->hostAddress,"UNASSIGNED_SYSTEM_ADDRESS")==0 || bindParameters->hostAddress[0]==0))
  209. {
  210. getaddrinfo(0, portStr, &hints, &servinfo);
  211. }
  212. else
  213. {
  214. getaddrinfo(bindParameters->hostAddress, portStr, &hints, &servinfo);
  215. }
  216. // Try all returned addresses until one works
  217. for (aip = servinfo; aip != NULL; aip = aip->ai_next)
  218. {
  219. // Open socket. The address type depends on what
  220. // getaddrinfo() gave us.
  221. rns2Socket = socket__(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
  222. if (rns2Socket == -1)
  223. return BR_FAILED_TO_BIND_SOCKET;
  224. ret = bind__(rns2Socket, aip->ai_addr, (int) aip->ai_addrlen );
  225. if (ret>=0)
  226. {
  227. // Is this valid?
  228. memcpy(&boundAddress.address.addr6, aip->ai_addr, sizeof(boundAddress.address.addr6));
  229. freeaddrinfo(servinfo); // free the linked-list
  230. SetSocketOptions();
  231. SetNonBlockingSocket(bindParameters->nonBlockingSocket);
  232. SetBroadcastSocket(bindParameters->setBroadcast);
  233. SetIPHdrIncl(bindParameters->setIPHdrIncl);
  234. GetSystemAddressIPV4And6( rns2Socket, &boundAddress );
  235. return BR_SUCCESS;
  236. }
  237. else
  238. {
  239. closesocket__(rns2Socket);
  240. }
  241. }
  242. return BR_FAILED_TO_BIND_SOCKET;
  243. #else
  244. return BR_REQUIRES_RAKNET_SUPPORT_IPV6_DEFINE;
  245. #endif
  246. }
  247. void RNS2_Berkley::RecvFromBlockingIPV4And6(RNS2RecvStruct *recvFromStruct)
  248. {
  249. #if RAKNET_SUPPORT_IPV6==1
  250. sockaddr_storage their_addr;
  251. sockaddr* sockAddrPtr;
  252. socklen_t sockLen;
  253. socklen_t* socketlenPtr=(socklen_t*) &sockLen;
  254. memset(&their_addr,0,sizeof(their_addr));
  255. int dataOutSize;
  256. const int flag=0;
  257. {
  258. sockLen=sizeof(their_addr);
  259. sockAddrPtr=(sockaddr*) &their_addr;
  260. }
  261. dataOutSize=MAXIMUM_MTU_SIZE;
  262. recvFromStruct->bytesRead = recvfrom__(rns2Socket, recvFromStruct->data, dataOutSize, flag, sockAddrPtr, socketlenPtr );
  263. #if defined(_WIN32) && defined(_DEBUG) && !defined(WINDOWS_PHONE_8)
  264. if (recvFromStruct->bytesRead==-1)
  265. {
  266. DWORD dwIOError = GetLastError();
  267. if (dwIoError != 10035)
  268. {
  269. LPVOID messageBuffer;
  270. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  271. NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
  272. ( LPTSTR ) & messageBuffer, 0, NULL );
  273. // I see this hit on XP with IPV6 for some reason
  274. RAKNET_DEBUG_PRINTF( "Warning: recvfrom failed:Error code - %d\n%s", dwIOError, messageBuffer );
  275. LocalFree( messageBuffer );
  276. }
  277. }
  278. #endif
  279. if (recvFromStruct->bytesRead<=0)
  280. return;
  281. recvFromStruct->timeRead=RakNet::GetTimeUS();
  282. {
  283. if (their_addr.ss_family==AF_INET)
  284. {
  285. memcpy(&recvFromStruct->systemAddress.address.addr4,(sockaddr_in *)&their_addr,sizeof(sockaddr_in));
  286. recvFromStruct->systemAddress.debugPort=ntohs(recvFromStruct->systemAddress.address.addr4.sin_port);
  287. // systemAddressOut->address.addr4.sin_port=ntohs( systemAddressOut->address.addr4.sin_port );
  288. }
  289. else
  290. {
  291. memcpy(&recvFromStruct->systemAddress.address.addr6,(sockaddr_in6 *)&their_addr,sizeof(sockaddr_in6));
  292. recvFromStruct->systemAddress.debugPort=ntohs(recvFromStruct->systemAddress.address.addr6.sin6_port);
  293. // systemAddressOut->address.addr6.sin6_port=ntohs( systemAddressOut->address.addr6.sin6_port );
  294. }
  295. }
  296. #else
  297. (void) recvFromStruct;
  298. #endif
  299. }
  300. void RNS2_Berkley::RecvFromBlockingIPV4(RNS2RecvStruct *recvFromStruct)
  301. {
  302. sockaddr* sockAddrPtr;
  303. socklen_t sockLen;
  304. socklen_t* socketlenPtr=(socklen_t*) &sockLen;
  305. sockaddr_in sa;
  306. memset(&sa,0,sizeof(sockaddr_in));
  307. const int flag=0;
  308. {
  309. sockLen=sizeof(sa);
  310. sa.sin_family = AF_INET;
  311. sa.sin_port=0;
  312. sockAddrPtr=(sockaddr*) &sa;
  313. }
  314. recvFromStruct->bytesRead = recvfrom__( GetSocket(), recvFromStruct->data, sizeof(recvFromStruct->data), flag, sockAddrPtr, socketlenPtr );
  315. if (recvFromStruct->bytesRead<=0)
  316. {
  317. /*
  318. DWORD dwIOError = WSAGetLastError();
  319. if ( dwIOError == WSAECONNRESET )
  320. {
  321. #if defined(_DEBUG)
  322. RAKNET_DEBUG_PRINTF( "A previous send operation resulted in an ICMP Port Unreachable message.\n" );
  323. #endif
  324. }
  325. else if ( dwIOError != WSAEWOULDBLOCK && dwIOError != WSAEADDRNOTAVAIL)
  326. {
  327. #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)
  328. LPVOID messageBuffer;
  329. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  330. NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
  331. ( LPTSTR ) & messageBuffer, 0, NULL );
  332. // something has gone wrong here...
  333. RAKNET_DEBUG_PRINTF( "sendto failed:Error code - %d\n%s", dwIOError, messageBuffer );
  334. //Free the buffer.
  335. LocalFree( messageBuffer );
  336. #endif
  337. }
  338. */
  339. return;
  340. }
  341. recvFromStruct->timeRead=RakNet::GetTimeUS();
  342. {
  343. recvFromStruct->systemAddress.SetPortNetworkOrder( sa.sin_port );
  344. recvFromStruct->systemAddress.address.addr4.sin_addr.s_addr=sa.sin_addr.s_addr;
  345. }
  346. // printf("--- Got %i bytes from %s\n", recvFromStruct->bytesRead, recvFromStruct->systemAddress.ToString());
  347. }
  348. void RNS2_Berkley::RecvFromBlocking(RNS2RecvStruct *recvFromStruct)
  349. {
  350. #if RAKNET_SUPPORT_IPV6==1
  351. return RecvFromBlockingIPV4And6(recvFromStruct);
  352. #else
  353. return RecvFromBlockingIPV4(recvFromStruct);
  354. #endif
  355. }
  356. #endif // !defined(WINDOWS_STORE_RT) && !defined(__native_client__)
  357. #endif // file header
  358. #endif // #ifdef RAKNET_SOCKET_2_INLINE_FUNCTIONS
粤ICP备19079148号