UDPForwarder.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  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 "UDPForwarder.h"
  11. #if _RAKNET_SUPPORT_UDPForwarder==1
  12. #include "GetTime.h"
  13. #include "MTUSize.h"
  14. #include "SocketLayer.h"
  15. #include "WSAStartupSingleton.h"
  16. #include "RakSleep.h"
  17. #include "DS_OrderedList.h"
  18. #include "LinuxStrings.h"
  19. #include "SocketDefines.h"
  20. #include "VitaIncludes.h"
  21. #include "errno.h"
  22. #ifndef INVALID_SOCKET
  23. #define INVALID_SOCKET -1
  24. #endif
  25. using namespace RakNet;
  26. static const unsigned short DEFAULT_MAX_FORWARD_ENTRIES=64;
  27. namespace RakNet
  28. {
  29. RAK_THREAD_DECLARATION(UpdateUDPForwarderGlobal);
  30. }
  31. UDPForwarder::ForwardEntry::ForwardEntry()
  32. {
  33. socket=INVALID_SOCKET;
  34. timeLastDatagramForwarded=RakNet::GetTimeMS();
  35. addr1Confirmed=UNASSIGNED_SYSTEM_ADDRESS;
  36. addr2Confirmed=UNASSIGNED_SYSTEM_ADDRESS;
  37. }
  38. UDPForwarder::ForwardEntry::~ForwardEntry() {
  39. if (socket!=INVALID_SOCKET)
  40. closesocket__(socket);
  41. }
  42. UDPForwarder::UDPForwarder()
  43. {
  44. #ifdef _WIN32
  45. WSAStartupSingleton::AddRef();
  46. #endif
  47. maxForwardEntries=DEFAULT_MAX_FORWARD_ENTRIES;
  48. nextInputId=0;
  49. startForwardingInput.SetPageSize(sizeof(StartForwardingInputStruct)*16);
  50. stopForwardingCommands.SetPageSize(sizeof(StopForwardingStruct)*16);
  51. }
  52. UDPForwarder::~UDPForwarder()
  53. {
  54. Shutdown();
  55. #ifdef _WIN32
  56. WSAStartupSingleton::Deref();
  57. #endif
  58. }
  59. void UDPForwarder::Startup(void)
  60. {
  61. if (isRunning.GetValue()>0)
  62. return;
  63. isRunning.Increment();
  64. int errorCode;
  65. errorCode = RakNet::RakThread::Create(UpdateUDPForwarderGlobal, this);
  66. if ( errorCode != 0 )
  67. {
  68. RakAssert(0);
  69. return;
  70. }
  71. while (threadRunning.GetValue()==0)
  72. RakSleep(30);
  73. }
  74. void UDPForwarder::Shutdown(void)
  75. {
  76. if (isRunning.GetValue()==0)
  77. return;
  78. isRunning.Decrement();
  79. while (threadRunning.GetValue()>0)
  80. RakSleep(30);
  81. unsigned int j;
  82. for (j=0; j < forwardListNotUpdated.Size(); j++)
  83. RakNet::OP_DELETE(forwardListNotUpdated[j],_FILE_AND_LINE_);
  84. forwardListNotUpdated.Clear(false, _FILE_AND_LINE_);
  85. }
  86. void UDPForwarder::SetMaxForwardEntries(unsigned short maxEntries)
  87. {
  88. RakAssert(maxEntries>0 && maxEntries<65535/2);
  89. maxForwardEntries=maxEntries;
  90. }
  91. int UDPForwarder::GetMaxForwardEntries(void) const
  92. {
  93. return maxForwardEntries;
  94. }
  95. int UDPForwarder::GetUsedForwardEntries(void) const
  96. {
  97. return (int) forwardListNotUpdated.Size();
  98. }
  99. UDPForwarderResult UDPForwarder::StartForwarding(SystemAddress source, SystemAddress destination, RakNet::TimeMS timeoutOnNoDataMS, const char *forceHostAddress, unsigned short socketFamily,
  100. unsigned short *forwardingPort, __UDPSOCKET__ *forwardingSocket)
  101. {
  102. // Invalid parameters?
  103. if (timeoutOnNoDataMS == 0 || timeoutOnNoDataMS > UDP_FORWARDER_MAXIMUM_TIMEOUT || source==UNASSIGNED_SYSTEM_ADDRESS || destination==UNASSIGNED_SYSTEM_ADDRESS)
  104. return UDPFORWARDER_INVALID_PARAMETERS;
  105. if (isRunning.GetValue()==0)
  106. return UDPFORWARDER_NOT_RUNNING;
  107. (void) socketFamily;
  108. unsigned int inputId = nextInputId++;
  109. StartForwardingInputStruct *sfis;
  110. sfis = startForwardingInput.Allocate(_FILE_AND_LINE_);
  111. sfis->source=source;
  112. sfis->destination=destination;
  113. sfis->timeoutOnNoDataMS=timeoutOnNoDataMS;
  114. RakAssert(timeoutOnNoDataMS!=0);
  115. if (forceHostAddress && forceHostAddress[0])
  116. sfis->forceHostAddress=forceHostAddress;
  117. sfis->socketFamily=socketFamily;
  118. sfis->inputId=inputId;
  119. startForwardingInput.Push(sfis);
  120. #ifdef _MSC_VER
  121. #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
  122. #endif
  123. while (1)
  124. {
  125. RakSleep(0);
  126. startForwardingOutputMutex.Lock();
  127. for (unsigned int i=0; i < startForwardingOutput.Size(); i++)
  128. {
  129. if (startForwardingOutput[i].inputId==inputId)
  130. {
  131. if (startForwardingOutput[i].result==UDPFORWARDER_SUCCESS)
  132. {
  133. if (forwardingPort)
  134. *forwardingPort = startForwardingOutput[i].forwardingPort;
  135. if (forwardingSocket)
  136. *forwardingSocket = startForwardingOutput[i].forwardingSocket;
  137. }
  138. UDPForwarderResult res = startForwardingOutput[i].result;
  139. startForwardingOutput.RemoveAtIndex(i);
  140. startForwardingOutputMutex.Unlock();
  141. return res;
  142. }
  143. }
  144. startForwardingOutputMutex.Unlock();
  145. }
  146. return UDPFORWARDER_RESULT_COUNT;
  147. }
  148. void UDPForwarder::StopForwarding(SystemAddress source, SystemAddress destination)
  149. {
  150. StopForwardingStruct *sfs;
  151. sfs = stopForwardingCommands.Allocate(_FILE_AND_LINE_);
  152. sfs->destination=destination;
  153. sfs->source=source;
  154. stopForwardingCommands.Push(sfs);
  155. }
  156. void UDPForwarder::RecvFrom(RakNet::TimeMS curTime, ForwardEntry *forwardEntry)
  157. {
  158. #ifndef __native_client__
  159. char data[ MAXIMUM_MTU_SIZE ];
  160. #if RAKNET_SUPPORT_IPV6==1
  161. sockaddr_storage their_addr;
  162. memset(&their_addr,0,sizeof(their_addr));
  163. sockaddr* sockAddrPtr;
  164. socklen_t sockLen;
  165. socklen_t* socketlenPtr=(socklen_t*) &sockLen;
  166. sockaddr_in *sockAddrIn;
  167. sockaddr_in6 *sockAddrIn6;
  168. sockLen=sizeof(their_addr);
  169. sockAddrPtr=(sockaddr*) &their_addr;
  170. #else
  171. sockaddr_in sockAddrIn;
  172. memset(&sockAddrIn,0,sizeof(sockaddr_in));
  173. socklen_t len2;
  174. len2 = sizeof( sockAddrIn );
  175. sockAddrIn.sin_family = AF_INET;
  176. #endif
  177. #if defined(__GNUC__)
  178. #if defined(MSG_DONTWAIT)
  179. const int flag=MSG_DONTWAIT;
  180. #else
  181. const int flag=0x40;
  182. #endif
  183. #else
  184. const int flag=0;
  185. #endif
  186. int receivedDataLen, len=0;
  187. //unsigned short portnum=0;
  188. #if RAKNET_SUPPORT_IPV6==1
  189. receivedDataLen = recvfrom__( forwardEntry->socket, data, MAXIMUM_MTU_SIZE, flag, sockAddrPtr, socketlenPtr );
  190. #else
  191. receivedDataLen = recvfrom__( forwardEntry->socket, data, MAXIMUM_MTU_SIZE, flag, ( sockaddr* ) & sockAddrIn, ( socklen_t* ) & len2 );
  192. #endif
  193. if (receivedDataLen<0)
  194. {
  195. #if defined(_WIN32) && defined(_DEBUG) && !defined(WINDOWS_PHONE_8) && !defined(WINDOWS_STORE_RT)
  196. DWORD dwIOError = WSAGetLastError();
  197. if (dwIOError!=WSAECONNRESET && dwIOError!=WSAEINTR && dwIOError!=WSAETIMEDOUT && dwIOError!=WSAEWOULDBLOCK)
  198. {
  199. LPVOID messageBuffer;
  200. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  201. NULL, dwIOError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
  202. ( LPTSTR ) & messageBuffer, 0, NULL );
  203. // something has gone wrong here...
  204. RAKNET_DEBUG_PRINTF( "recvfrom failed:Error code - %d\n%s", dwIOError, messageBuffer );
  205. //Free the buffer.
  206. LocalFree( messageBuffer );
  207. }
  208. #else
  209. if (errno!=EAGAIN
  210. && errno!=0
  211. #if defined(__GNUC__)
  212. && errno!=EWOULDBLOCK
  213. #endif
  214. )
  215. {
  216. printf("errno=%i\n", errno);
  217. }
  218. #endif
  219. }
  220. if (receivedDataLen<=0)
  221. return;
  222. SystemAddress receivedAddr;
  223. #if RAKNET_SUPPORT_IPV6==1
  224. if (their_addr.ss_family==AF_INET)
  225. {
  226. sockAddrIn=(sockaddr_in *)&their_addr;
  227. sockAddrIn6=0;
  228. memcpy(&receivedAddr.address.addr4,sockAddrIn,sizeof(sockaddr_in));
  229. }
  230. else
  231. {
  232. sockAddrIn=0;
  233. sockAddrIn6=(sockaddr_in6 *)&their_addr;
  234. memcpy(&receivedAddr.address.addr6,sockAddrIn6,sizeof(sockaddr_in6));
  235. }
  236. #else
  237. memcpy(&receivedAddr.address.addr4,&sockAddrIn,sizeof(sockaddr_in));
  238. #endif
  239. //portnum=receivedAddr.GetPort();
  240. SystemAddress forwardTarget;
  241. bool confirmed1 = forwardEntry->addr1Confirmed!=UNASSIGNED_SYSTEM_ADDRESS;
  242. bool confirmed2 = forwardEntry->addr2Confirmed!=UNASSIGNED_SYSTEM_ADDRESS;
  243. bool matchConfirmed1 =
  244. confirmed1 &&
  245. forwardEntry->addr1Confirmed==receivedAddr;
  246. bool matchConfirmed2 =
  247. confirmed2 &&
  248. forwardEntry->addr2Confirmed==receivedAddr;
  249. bool matchUnconfirmed1 = forwardEntry->addr1Unconfirmed.EqualsExcludingPort(receivedAddr);
  250. bool matchUnconfirmed2 = forwardEntry->addr2Unconfirmed.EqualsExcludingPort(receivedAddr);
  251. if (matchConfirmed1==true || (matchConfirmed2==false && confirmed1==false && matchUnconfirmed1==true))
  252. {
  253. // Forward to addr2
  254. if (forwardEntry->addr1Confirmed==UNASSIGNED_SYSTEM_ADDRESS)
  255. {
  256. forwardEntry->addr1Confirmed=receivedAddr;
  257. }
  258. if (forwardEntry->addr2Confirmed!=UNASSIGNED_SYSTEM_ADDRESS)
  259. forwardTarget=forwardEntry->addr2Confirmed;
  260. else
  261. forwardTarget=forwardEntry->addr2Unconfirmed;
  262. }
  263. else if (matchConfirmed2==true || (confirmed2==false && matchUnconfirmed2==true))
  264. {
  265. // Forward to addr1
  266. if (forwardEntry->addr2Confirmed==UNASSIGNED_SYSTEM_ADDRESS)
  267. {
  268. forwardEntry->addr2Confirmed=receivedAddr;
  269. }
  270. if (forwardEntry->addr1Confirmed!=UNASSIGNED_SYSTEM_ADDRESS)
  271. forwardTarget=forwardEntry->addr1Confirmed;
  272. else
  273. forwardTarget=forwardEntry->addr1Unconfirmed;
  274. }
  275. else
  276. {
  277. return;
  278. }
  279. // Forward to dest
  280. len=0;
  281. // sockaddr_in saOut;
  282. // saOut.sin_port = forwardTarget.GetPortNetworkOrder(); // User port
  283. // saOut.sin_addr.s_addr = forwardTarget.address.addr4.sin_addr.s_addr;
  284. // saOut.sin_family = AF_INET;
  285. do
  286. {
  287. #if RAKNET_SUPPORT_IPV6==1
  288. if (forwardTarget.address.addr4.sin_family==AF_INET)
  289. {
  290. do
  291. {
  292. len = sendto__( forwardEntry->socket, data, receivedDataLen, 0, ( const sockaddr* ) & forwardTarget.address.addr4, sizeof( sockaddr_in ) );
  293. }
  294. while ( len == 0 );
  295. }
  296. else
  297. {
  298. do
  299. {
  300. len = sendto__( forwardEntry->socket, data, receivedDataLen, 0, ( const sockaddr* ) & forwardTarget.address.addr6, sizeof( sockaddr_in6 ) );
  301. }
  302. while ( len == 0 );
  303. }
  304. #else
  305. do
  306. {
  307. len = sendto__( forwardEntry->socket, data, receivedDataLen, 0, ( const sockaddr* ) & forwardTarget.address.addr4, sizeof( sockaddr_in ) );
  308. }
  309. while ( len == 0 );
  310. #endif
  311. }
  312. while ( len == 0 );
  313. forwardEntry->timeLastDatagramForwarded=curTime;
  314. #endif // __native_client__
  315. }
  316. void UDPForwarder::UpdateUDPForwarder(void)
  317. {
  318. /*
  319. #if !defined(SN_TARGET_PSP2)
  320. timeval tv;
  321. tv.tv_sec=0;
  322. tv.tv_usec=0;
  323. #endif
  324. */
  325. RakNet::TimeMS curTime = RakNet::GetTimeMS();
  326. StartForwardingInputStruct *sfis;
  327. StartForwardingOutputStruct sfos;
  328. sfos.forwardingSocket=INVALID_SOCKET;
  329. sfos.forwardingPort=0;
  330. sfos.inputId=0;
  331. sfos.result=UDPFORWARDER_RESULT_COUNT;
  332. #ifdef _MSC_VER
  333. #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
  334. #endif
  335. while (1)
  336. {
  337. sfis = startForwardingInput.Pop();
  338. if (sfis==0)
  339. break;
  340. if (GetUsedForwardEntries()>maxForwardEntries)
  341. {
  342. sfos.result=UDPFORWARDER_NO_SOCKETS;
  343. }
  344. else
  345. {
  346. sfos.result=UDPFORWARDER_RESULT_COUNT;
  347. for (unsigned int i=0; i < forwardListNotUpdated.Size(); i++)
  348. {
  349. if (
  350. (forwardListNotUpdated[i]->addr1Unconfirmed==sfis->source &&
  351. forwardListNotUpdated[i]->addr2Unconfirmed==sfis->destination)
  352. ||
  353. (forwardListNotUpdated[i]->addr1Unconfirmed==sfis->destination &&
  354. forwardListNotUpdated[i]->addr2Unconfirmed==sfis->source)
  355. )
  356. {
  357. ForwardEntry *fe = forwardListNotUpdated[i];
  358. sfos.forwardingPort = SocketLayer::GetLocalPort ( fe->socket );
  359. sfos.forwardingSocket=fe->socket;
  360. sfos.result=UDPFORWARDER_FORWARDING_ALREADY_EXISTS;
  361. break;
  362. }
  363. }
  364. if (sfos.result==UDPFORWARDER_RESULT_COUNT)
  365. {
  366. int sock_opt;
  367. sockaddr_in listenerSocketAddress;
  368. listenerSocketAddress.sin_port = 0;
  369. ForwardEntry *fe = RakNet::OP_NEW<UDPForwarder::ForwardEntry>(_FILE_AND_LINE_);
  370. fe->addr1Unconfirmed=sfis->source;
  371. fe->addr2Unconfirmed=sfis->destination;
  372. fe->timeoutOnNoDataMS=sfis->timeoutOnNoDataMS;
  373. #if RAKNET_SUPPORT_IPV6!=1
  374. fe->socket = socket__( AF_INET, SOCK_DGRAM, 0 );
  375. listenerSocketAddress.sin_family = AF_INET;
  376. if (sfis->forceHostAddress.IsEmpty()==false)
  377. {
  378. listenerSocketAddress.sin_addr.s_addr = inet_addr__( sfis->forceHostAddress.C_String() );
  379. }
  380. else
  381. {
  382. listenerSocketAddress.sin_addr.s_addr = INADDR_ANY;
  383. }
  384. int ret = bind__( fe->socket, ( struct sockaddr * ) & listenerSocketAddress, sizeof( listenerSocketAddress ) );
  385. if (ret==-1)
  386. {
  387. RakNet::OP_DELETE(fe,_FILE_AND_LINE_);
  388. sfos.result=UDPFORWARDER_BIND_FAILED;
  389. }
  390. else
  391. {
  392. sfos.result=UDPFORWARDER_SUCCESS;
  393. }
  394. #else // RAKNET_SUPPORT_IPV6==1
  395. struct addrinfo hints;
  396. memset(&hints, 0, sizeof (addrinfo)); // make sure the struct is empty
  397. hints.ai_family = sfis->socketFamily;
  398. hints.ai_socktype = SOCK_DGRAM; // UDP sockets
  399. hints.ai_flags = AI_PASSIVE; // fill in my IP for me
  400. struct addrinfo *servinfo=0, *aip; // will point to the results
  401. if (sfis->forceHostAddress.IsEmpty() || sfis->forceHostAddress=="UNASSIGNED_SYSTEM_ADDRESS")
  402. getaddrinfo(0, "0", &hints, &servinfo);
  403. else
  404. getaddrinfo(sfis->forceHostAddress.C_String(), "0", &hints, &servinfo);
  405. for (aip = servinfo; aip != NULL; aip = aip->ai_next)
  406. {
  407. // Open socket. The address type depends on what
  408. // getaddrinfo() gave us.
  409. fe->socket = socket__(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
  410. if (fe->socket != INVALID_SOCKET)
  411. {
  412. int ret = bind__( fe->socket, aip->ai_addr, (int) aip->ai_addrlen );
  413. if (ret>=0)
  414. {
  415. break;
  416. }
  417. else
  418. {
  419. closesocket__(fe->socket);
  420. fe->socket=INVALID_SOCKET;
  421. }
  422. }
  423. }
  424. if (fe->socket==INVALID_SOCKET)
  425. sfos.result=UDPFORWARDER_BIND_FAILED;
  426. else
  427. sfos.result=UDPFORWARDER_SUCCESS;
  428. #endif // RAKNET_SUPPORT_IPV6==1
  429. if (sfos.result==UDPFORWARDER_SUCCESS)
  430. {
  431. sfos.forwardingPort = SocketLayer::GetLocalPort ( fe->socket );
  432. sfos.forwardingSocket=fe->socket;
  433. sock_opt=1024*256;
  434. setsockopt__(fe->socket, SOL_SOCKET, SO_RCVBUF, ( char * ) & sock_opt, sizeof ( sock_opt ) );
  435. sock_opt=0;
  436. setsockopt__(fe->socket, SOL_SOCKET, SO_LINGER, ( char * ) & sock_opt, sizeof ( sock_opt ) );
  437. #ifdef _WIN32
  438. unsigned long nonblocking = 1;
  439. ioctlsocket__( fe->socket, FIONBIO, &nonblocking );
  440. #else
  441. fcntl( fe->socket, F_SETFL, O_NONBLOCK );
  442. #endif
  443. forwardListNotUpdated.Insert(fe,_FILE_AND_LINE_);
  444. }
  445. }
  446. }
  447. // Push result
  448. sfos.inputId=sfis->inputId;
  449. startForwardingOutputMutex.Lock();
  450. startForwardingOutput.Push(sfos,_FILE_AND_LINE_);
  451. startForwardingOutputMutex.Unlock();
  452. startForwardingInput.Deallocate(sfis, _FILE_AND_LINE_);
  453. }
  454. StopForwardingStruct *sfs;
  455. #ifdef _MSC_VER
  456. #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
  457. #endif
  458. while (1)
  459. {
  460. sfs = stopForwardingCommands.Pop();
  461. if (sfs==0)
  462. break;
  463. ForwardEntry *fe;
  464. for (unsigned int i=0; i < forwardListNotUpdated.Size(); i++)
  465. {
  466. if (
  467. (forwardListNotUpdated[i]->addr1Unconfirmed==sfs->source &&
  468. forwardListNotUpdated[i]->addr2Unconfirmed==sfs->destination)
  469. ||
  470. (forwardListNotUpdated[i]->addr1Unconfirmed==sfs->destination &&
  471. forwardListNotUpdated[i]->addr2Unconfirmed==sfs->source)
  472. )
  473. {
  474. fe = forwardListNotUpdated[i];
  475. forwardListNotUpdated.RemoveAtIndexFast(i);
  476. RakNet::OP_DELETE(fe, _FILE_AND_LINE_);
  477. break;
  478. }
  479. }
  480. stopForwardingCommands.Deallocate(sfs, _FILE_AND_LINE_);
  481. }
  482. unsigned int i;
  483. i=0;
  484. while (i < forwardListNotUpdated.Size())
  485. {
  486. if (curTime > forwardListNotUpdated[i]->timeLastDatagramForwarded && // Account for timestamp wrap
  487. curTime > forwardListNotUpdated[i]->timeLastDatagramForwarded+forwardListNotUpdated[i]->timeoutOnNoDataMS)
  488. {
  489. RakNet::OP_DELETE(forwardListNotUpdated[i],_FILE_AND_LINE_);
  490. forwardListNotUpdated.RemoveAtIndex(i);
  491. }
  492. else
  493. i++;
  494. }
  495. ForwardEntry *forwardEntry;
  496. for (i=0; i < forwardListNotUpdated.Size(); i++)
  497. {
  498. forwardEntry = forwardListNotUpdated[i];
  499. RecvFrom(curTime, forwardEntry);
  500. }
  501. }
  502. namespace RakNet {
  503. RAK_THREAD_DECLARATION(UpdateUDPForwarderGlobal)
  504. {
  505. UDPForwarder * udpForwarder = ( UDPForwarder * ) arguments;
  506. udpForwarder->threadRunning.Increment();
  507. while (udpForwarder->isRunning.GetValue()>0)
  508. {
  509. udpForwarder->UpdateUDPForwarder();
  510. // 12/1/2010 Do not change from 0
  511. // See http://www.jenkinssoftware.com/forum/index.php?topic=4033.0;topicseen
  512. // Avoid 100% reported CPU usage
  513. if (udpForwarder->forwardListNotUpdated.Size()==0)
  514. RakSleep(30);
  515. else
  516. RakSleep(0);
  517. }
  518. udpForwarder->threadRunning.Decrement();
  519. return 0;
  520. }
  521. } // namespace RakNet
  522. #endif // #if _RAKNET_SUPPORT_FileOperations==1
粤ICP备19079148号