TracySocket.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. #include <assert.h>
  2. #include <inttypes.h>
  3. #include <new>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <sys/types.h>
  8. #include "TracyAlloc.hpp"
  9. #include "TracySocket.hpp"
  10. #ifdef _WIN32
  11. # ifndef NOMINMAX
  12. # define NOMINMAX
  13. # endif
  14. # include <winsock2.h>
  15. # include <ws2tcpip.h>
  16. # ifdef _MSC_VER
  17. # pragma warning(disable:4244)
  18. # pragma warning(disable:4267)
  19. # endif
  20. # define poll WSAPoll
  21. #else
  22. # include <arpa/inet.h>
  23. # include <sys/socket.h>
  24. # include <sys/param.h>
  25. # include <errno.h>
  26. # include <fcntl.h>
  27. # include <netinet/in.h>
  28. # include <netdb.h>
  29. # include <unistd.h>
  30. # include <poll.h>
  31. #endif
  32. #ifndef MSG_NOSIGNAL
  33. # define MSG_NOSIGNAL 0
  34. #endif
  35. namespace tracy
  36. {
  37. #ifdef _WIN32
  38. typedef SOCKET socket_t;
  39. #else
  40. typedef int socket_t;
  41. #endif
  42. #ifdef _WIN32
  43. struct __wsinit
  44. {
  45. __wsinit()
  46. {
  47. WSADATA wsaData;
  48. if( WSAStartup( MAKEWORD( 2, 2 ), &wsaData ) != 0 )
  49. {
  50. fprintf( stderr, "Cannot init winsock.\n" );
  51. exit( 1 );
  52. }
  53. }
  54. };
  55. void InitWinSock()
  56. {
  57. static __wsinit init;
  58. }
  59. #endif
  60. enum { BufSize = 128 * 1024 };
  61. Socket::Socket()
  62. : m_buf( (char*)tracy_malloc( BufSize ) )
  63. , m_bufPtr( nullptr )
  64. , m_sock( -1 )
  65. , m_bufLeft( 0 )
  66. , m_ptr( nullptr )
  67. {
  68. #ifdef _WIN32
  69. InitWinSock();
  70. #endif
  71. }
  72. Socket::Socket( int sock )
  73. : m_buf( (char*)tracy_malloc( BufSize ) )
  74. , m_bufPtr( nullptr )
  75. , m_sock( sock )
  76. , m_bufLeft( 0 )
  77. , m_ptr( nullptr )
  78. {
  79. }
  80. Socket::~Socket()
  81. {
  82. tracy_free( m_buf );
  83. if( m_sock.load( std::memory_order_relaxed ) != -1 )
  84. {
  85. Close();
  86. }
  87. if( m_ptr )
  88. {
  89. freeaddrinfo( m_res );
  90. #ifdef _WIN32
  91. closesocket( m_connSock );
  92. #else
  93. close( m_connSock );
  94. #endif
  95. }
  96. }
  97. bool Socket::Connect( const char* addr, uint16_t port )
  98. {
  99. assert( !IsValid() );
  100. if( m_ptr )
  101. {
  102. const auto c = connect( m_connSock, m_ptr->ai_addr, m_ptr->ai_addrlen );
  103. if( c == -1 )
  104. {
  105. #if defined _WIN32
  106. const auto err = WSAGetLastError();
  107. if( err == WSAEALREADY || err == WSAEINPROGRESS ) return false;
  108. if( err != WSAEISCONN )
  109. {
  110. freeaddrinfo( m_res );
  111. closesocket( m_connSock );
  112. m_ptr = nullptr;
  113. return false;
  114. }
  115. #else
  116. const auto err = errno;
  117. if( err == EALREADY || err == EINPROGRESS ) return false;
  118. if( err != EISCONN )
  119. {
  120. freeaddrinfo( m_res );
  121. close( m_connSock );
  122. m_ptr = nullptr;
  123. return false;
  124. }
  125. #endif
  126. }
  127. #if defined _WIN32
  128. u_long nonblocking = 0;
  129. ioctlsocket( m_connSock, FIONBIO, &nonblocking );
  130. #else
  131. int flags = fcntl( m_connSock, F_GETFL, 0 );
  132. fcntl( m_connSock, F_SETFL, flags & ~O_NONBLOCK );
  133. #endif
  134. m_sock.store( m_connSock, std::memory_order_relaxed );
  135. freeaddrinfo( m_res );
  136. m_ptr = nullptr;
  137. return true;
  138. }
  139. struct addrinfo hints;
  140. struct addrinfo *res, *ptr;
  141. memset( &hints, 0, sizeof( hints ) );
  142. hints.ai_family = AF_UNSPEC;
  143. hints.ai_socktype = SOCK_STREAM;
  144. char portbuf[32];
  145. sprintf( portbuf, "%" PRIu16, port );
  146. if( getaddrinfo( addr, portbuf, &hints, &res ) != 0 ) return false;
  147. int sock = 0;
  148. for( ptr = res; ptr; ptr = ptr->ai_next )
  149. {
  150. if( ( sock = socket( ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol ) ) == -1 ) continue;
  151. #if defined __APPLE__
  152. int val = 1;
  153. setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );
  154. #endif
  155. #if defined _WIN32
  156. u_long nonblocking = 1;
  157. ioctlsocket( sock, FIONBIO, &nonblocking );
  158. #else
  159. int flags = fcntl( sock, F_GETFL, 0 );
  160. fcntl( sock, F_SETFL, flags | O_NONBLOCK );
  161. #endif
  162. if( connect( sock, ptr->ai_addr, ptr->ai_addrlen ) == 0 )
  163. {
  164. break;
  165. }
  166. else
  167. {
  168. #if defined _WIN32
  169. const auto err = WSAGetLastError();
  170. if( err != WSAEWOULDBLOCK )
  171. {
  172. closesocket( sock );
  173. continue;
  174. }
  175. #else
  176. if( errno != EINPROGRESS )
  177. {
  178. close( sock );
  179. continue;
  180. }
  181. #endif
  182. }
  183. m_res = res;
  184. m_ptr = ptr;
  185. m_connSock = sock;
  186. return false;
  187. }
  188. freeaddrinfo( res );
  189. if( !ptr ) return false;
  190. #if defined _WIN32
  191. u_long nonblocking = 0;
  192. ioctlsocket( sock, FIONBIO, &nonblocking );
  193. #else
  194. int flags = fcntl( sock, F_GETFL, 0 );
  195. fcntl( sock, F_SETFL, flags & ~O_NONBLOCK );
  196. #endif
  197. m_sock.store( sock, std::memory_order_relaxed );
  198. return true;
  199. }
  200. bool Socket::ConnectBlocking( const char* addr, uint16_t port )
  201. {
  202. assert( !IsValid() );
  203. assert( !m_ptr );
  204. struct addrinfo hints;
  205. struct addrinfo *res, *ptr;
  206. memset( &hints, 0, sizeof( hints ) );
  207. hints.ai_family = AF_UNSPEC;
  208. hints.ai_socktype = SOCK_STREAM;
  209. char portbuf[32];
  210. sprintf( portbuf, "%" PRIu16, port );
  211. if( getaddrinfo( addr, portbuf, &hints, &res ) != 0 ) return false;
  212. int sock = 0;
  213. for( ptr = res; ptr; ptr = ptr->ai_next )
  214. {
  215. if( ( sock = socket( ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol ) ) == -1 ) continue;
  216. #if defined __APPLE__
  217. int val = 1;
  218. setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );
  219. #endif
  220. if( connect( sock, ptr->ai_addr, ptr->ai_addrlen ) == -1 )
  221. {
  222. #ifdef _WIN32
  223. closesocket( sock );
  224. #else
  225. close( sock );
  226. #endif
  227. continue;
  228. }
  229. break;
  230. }
  231. freeaddrinfo( res );
  232. if( !ptr ) return false;
  233. m_sock.store( sock, std::memory_order_relaxed );
  234. return true;
  235. }
  236. void Socket::Close()
  237. {
  238. const auto sock = m_sock.load( std::memory_order_relaxed );
  239. assert( sock != -1 );
  240. #ifdef _WIN32
  241. closesocket( sock );
  242. #else
  243. close( sock );
  244. #endif
  245. m_sock.store( -1, std::memory_order_relaxed );
  246. }
  247. int Socket::Send( const void* _buf, int len )
  248. {
  249. const auto sock = m_sock.load( std::memory_order_relaxed );
  250. auto buf = (const char*)_buf;
  251. assert( sock != -1 );
  252. auto start = buf;
  253. while( len > 0 )
  254. {
  255. auto ret = send( sock, buf, len, MSG_NOSIGNAL );
  256. if( ret == -1 ) return -1;
  257. len -= ret;
  258. buf += ret;
  259. }
  260. return int( buf - start );
  261. }
  262. int Socket::GetSendBufSize()
  263. {
  264. const auto sock = m_sock.load( std::memory_order_relaxed );
  265. int bufSize;
  266. #if defined _WIN32
  267. int sz = sizeof( bufSize );
  268. getsockopt( sock, SOL_SOCKET, SO_SNDBUF, (char*)&bufSize, &sz );
  269. #else
  270. socklen_t sz = sizeof( bufSize );
  271. getsockopt( sock, SOL_SOCKET, SO_SNDBUF, &bufSize, &sz );
  272. #endif
  273. return bufSize;
  274. }
  275. int Socket::RecvBuffered( void* buf, int len, int timeout )
  276. {
  277. if( len <= m_bufLeft )
  278. {
  279. memcpy( buf, m_bufPtr, len );
  280. m_bufPtr += len;
  281. m_bufLeft -= len;
  282. return len;
  283. }
  284. if( m_bufLeft > 0 )
  285. {
  286. memcpy( buf, m_bufPtr, m_bufLeft );
  287. const auto ret = m_bufLeft;
  288. m_bufLeft = 0;
  289. return ret;
  290. }
  291. if( len >= BufSize ) return Recv( buf, len, timeout );
  292. m_bufLeft = Recv( m_buf, BufSize, timeout );
  293. if( m_bufLeft <= 0 ) return m_bufLeft;
  294. const auto sz = len < m_bufLeft ? len : m_bufLeft;
  295. memcpy( buf, m_buf, sz );
  296. m_bufPtr = m_buf + sz;
  297. m_bufLeft -= sz;
  298. return sz;
  299. }
  300. int Socket::Recv( void* _buf, int len, int timeout )
  301. {
  302. const auto sock = m_sock.load( std::memory_order_relaxed );
  303. auto buf = (char*)_buf;
  304. struct pollfd fd;
  305. fd.fd = (socket_t)sock;
  306. fd.events = POLLIN;
  307. if( poll( &fd, 1, timeout ) > 0 )
  308. {
  309. return recv( sock, buf, len, 0 );
  310. }
  311. else
  312. {
  313. return -1;
  314. }
  315. }
  316. int Socket::ReadUpTo( void* _buf, int len, int timeout )
  317. {
  318. const auto sock = m_sock.load( std::memory_order_relaxed );
  319. auto buf = (char*)_buf;
  320. int rd = 0;
  321. while( len > 0 )
  322. {
  323. const auto res = recv( sock, buf, len, 0 );
  324. if( res == 0 ) break;
  325. if( res == -1 ) return -1;
  326. len -= res;
  327. rd += res;
  328. buf += res;
  329. }
  330. return rd;
  331. }
  332. bool Socket::Read( void* buf, int len, int timeout )
  333. {
  334. auto cbuf = (char*)buf;
  335. while( len > 0 )
  336. {
  337. if( !ReadImpl( cbuf, len, timeout ) ) return false;
  338. }
  339. return true;
  340. }
  341. bool Socket::ReadImpl( char*& buf, int& len, int timeout )
  342. {
  343. const auto sz = RecvBuffered( buf, len, timeout );
  344. switch( sz )
  345. {
  346. case 0:
  347. return false;
  348. case -1:
  349. #ifdef _WIN32
  350. {
  351. auto err = WSAGetLastError();
  352. if( err == WSAECONNABORTED || err == WSAECONNRESET ) return false;
  353. }
  354. #endif
  355. break;
  356. default:
  357. len -= sz;
  358. buf += sz;
  359. break;
  360. }
  361. return true;
  362. }
  363. bool Socket::ReadRaw( void* _buf, int len, int timeout )
  364. {
  365. auto buf = (char*)_buf;
  366. while( len > 0 )
  367. {
  368. const auto sz = Recv( buf, len, timeout );
  369. if( sz <= 0 ) return false;
  370. len -= sz;
  371. buf += sz;
  372. }
  373. return true;
  374. }
  375. bool Socket::HasData()
  376. {
  377. const auto sock = m_sock.load( std::memory_order_relaxed );
  378. if( m_bufLeft > 0 ) return true;
  379. struct pollfd fd;
  380. fd.fd = (socket_t)sock;
  381. fd.events = POLLIN;
  382. return poll( &fd, 1, 0 ) > 0;
  383. }
  384. bool Socket::IsValid() const
  385. {
  386. return m_sock.load( std::memory_order_relaxed ) >= 0;
  387. }
  388. ListenSocket::ListenSocket()
  389. : m_sock( -1 )
  390. {
  391. #ifdef _WIN32
  392. InitWinSock();
  393. #endif
  394. }
  395. ListenSocket::~ListenSocket()
  396. {
  397. if( m_sock != -1 ) Close();
  398. }
  399. static int addrinfo_and_socket_for_family( uint16_t port, int ai_family, struct addrinfo** res )
  400. {
  401. struct addrinfo hints;
  402. memset( &hints, 0, sizeof( hints ) );
  403. hints.ai_family = ai_family;
  404. hints.ai_socktype = SOCK_STREAM;
  405. #ifndef TRACY_ONLY_LOCALHOST
  406. const char* onlyLocalhost = getenv( "TRACY_ONLY_LOCALHOST" );
  407. if( !onlyLocalhost || onlyLocalhost[0] != '1' )
  408. {
  409. hints.ai_flags = AI_PASSIVE;
  410. }
  411. #endif
  412. char portbuf[32];
  413. sprintf( portbuf, "%" PRIu16, port );
  414. if( getaddrinfo( nullptr, portbuf, &hints, res ) != 0 ) return -1;
  415. int sock = socket( (*res)->ai_family, (*res)->ai_socktype, (*res)->ai_protocol );
  416. if (sock == -1) freeaddrinfo( *res );
  417. return sock;
  418. }
  419. bool ListenSocket::Listen( uint16_t port, int backlog )
  420. {
  421. assert( m_sock == -1 );
  422. struct addrinfo* res = nullptr;
  423. #if !defined TRACY_ONLY_IPV4 && !defined TRACY_ONLY_LOCALHOST
  424. const char* onlyIPv4 = getenv( "TRACY_ONLY_IPV4" );
  425. if( !onlyIPv4 || onlyIPv4[0] != '1' )
  426. {
  427. m_sock = addrinfo_and_socket_for_family( port, AF_INET6, &res );
  428. }
  429. #endif
  430. if (m_sock == -1)
  431. {
  432. // IPV6 protocol may not be available/is disabled. Try to create a socket
  433. // with the IPV4 protocol
  434. m_sock = addrinfo_and_socket_for_family( port, AF_INET, &res );
  435. if( m_sock == -1 ) return false;
  436. }
  437. #if defined _WIN32 || defined __CYGWIN__
  438. unsigned long val = 0;
  439. setsockopt( m_sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&val, sizeof( val ) );
  440. #elif defined BSD
  441. int val = 0;
  442. setsockopt( m_sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&val, sizeof( val ) );
  443. val = 1;
  444. setsockopt( m_sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof( val ) );
  445. #else
  446. int val = 1;
  447. setsockopt( m_sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof( val ) );
  448. #endif
  449. if( bind( m_sock, res->ai_addr, res->ai_addrlen ) == -1 ) { freeaddrinfo( res ); Close(); return false; }
  450. if( listen( m_sock, backlog ) == -1 ) { freeaddrinfo( res ); Close(); return false; }
  451. freeaddrinfo( res );
  452. return true;
  453. }
  454. Socket* ListenSocket::Accept()
  455. {
  456. struct sockaddr_storage remote;
  457. socklen_t sz = sizeof( remote );
  458. struct pollfd fd;
  459. fd.fd = (socket_t)m_sock;
  460. fd.events = POLLIN;
  461. if( poll( &fd, 1, 10 ) > 0 )
  462. {
  463. int sock = accept( m_sock, (sockaddr*)&remote, &sz);
  464. if( sock == -1 ) return nullptr;
  465. #if defined __APPLE__
  466. int val = 1;
  467. setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );
  468. #endif
  469. auto ptr = (Socket*)tracy_malloc( sizeof( Socket ) );
  470. new(ptr) Socket( sock );
  471. return ptr;
  472. }
  473. else
  474. {
  475. return nullptr;
  476. }
  477. }
  478. void ListenSocket::Close()
  479. {
  480. assert( m_sock != -1 );
  481. #ifdef _WIN32
  482. closesocket( m_sock );
  483. #else
  484. close( m_sock );
  485. #endif
  486. m_sock = -1;
  487. }
  488. UdpBroadcast::UdpBroadcast()
  489. : m_sock( -1 )
  490. {
  491. #ifdef _WIN32
  492. InitWinSock();
  493. #endif
  494. }
  495. UdpBroadcast::~UdpBroadcast()
  496. {
  497. if( m_sock != -1 ) Close();
  498. }
  499. bool UdpBroadcast::Open( const char* addr, uint16_t port )
  500. {
  501. assert( m_sock == -1 );
  502. struct addrinfo hints;
  503. struct addrinfo *res, *ptr;
  504. memset( &hints, 0, sizeof( hints ) );
  505. hints.ai_family = AF_INET;
  506. hints.ai_socktype = SOCK_DGRAM;
  507. char portbuf[32];
  508. sprintf( portbuf, "%" PRIu16, port );
  509. if( getaddrinfo( addr, portbuf, &hints, &res ) != 0 ) return false;
  510. int sock = 0;
  511. for( ptr = res; ptr; ptr = ptr->ai_next )
  512. {
  513. if( ( sock = socket( ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol ) ) == -1 ) continue;
  514. #if defined __APPLE__
  515. int val = 1;
  516. setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );
  517. #endif
  518. #if defined _WIN32
  519. unsigned long broadcast = 1;
  520. if( setsockopt( sock, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof( broadcast ) ) == -1 )
  521. #else
  522. int broadcast = 1;
  523. if( setsockopt( sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof( broadcast ) ) == -1 )
  524. #endif
  525. {
  526. #ifdef _WIN32
  527. closesocket( sock );
  528. #else
  529. close( sock );
  530. #endif
  531. continue;
  532. }
  533. break;
  534. }
  535. freeaddrinfo( res );
  536. if( !ptr ) return false;
  537. m_sock = sock;
  538. inet_pton( AF_INET, addr, &m_addr );
  539. return true;
  540. }
  541. void UdpBroadcast::Close()
  542. {
  543. assert( m_sock != -1 );
  544. #ifdef _WIN32
  545. closesocket( m_sock );
  546. #else
  547. close( m_sock );
  548. #endif
  549. m_sock = -1;
  550. }
  551. int UdpBroadcast::Send( uint16_t port, const void* data, int len )
  552. {
  553. assert( m_sock != -1 );
  554. struct sockaddr_in addr;
  555. addr.sin_family = AF_INET;
  556. addr.sin_port = htons( port );
  557. addr.sin_addr.s_addr = m_addr;
  558. return sendto( m_sock, (const char*)data, len, MSG_NOSIGNAL, (sockaddr*)&addr, sizeof( addr ) );
  559. }
  560. IpAddress::IpAddress()
  561. : m_number( 0 )
  562. {
  563. *m_text = '\0';
  564. }
  565. IpAddress::~IpAddress()
  566. {
  567. }
  568. void IpAddress::Set( const struct sockaddr& addr )
  569. {
  570. #if defined _WIN32 && ( !defined NTDDI_WIN10 || NTDDI_VERSION < NTDDI_WIN10 )
  571. struct sockaddr_in tmp;
  572. memcpy( &tmp, &addr, sizeof( tmp ) );
  573. auto ai = &tmp;
  574. #else
  575. auto ai = (const struct sockaddr_in*)&addr;
  576. #endif
  577. inet_ntop( AF_INET, &ai->sin_addr, m_text, 17 );
  578. m_number = ai->sin_addr.s_addr;
  579. }
  580. UdpListen::UdpListen()
  581. : m_sock( -1 )
  582. {
  583. #ifdef _WIN32
  584. InitWinSock();
  585. #endif
  586. }
  587. UdpListen::~UdpListen()
  588. {
  589. if( m_sock != -1 ) Close();
  590. }
  591. bool UdpListen::Listen( uint16_t port )
  592. {
  593. assert( m_sock == -1 );
  594. int sock;
  595. if( ( sock = socket( AF_INET, SOCK_DGRAM, 0 ) ) == -1 ) return false;
  596. #if defined __APPLE__
  597. int val = 1;
  598. setsockopt( sock, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof( val ) );
  599. #endif
  600. #if defined _WIN32
  601. unsigned long reuse = 1;
  602. setsockopt( m_sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof( reuse ) );
  603. #else
  604. int reuse = 1;
  605. setsockopt( m_sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof( reuse ) );
  606. #endif
  607. #if defined _WIN32
  608. unsigned long broadcast = 1;
  609. if( setsockopt( sock, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof( broadcast ) ) == -1 )
  610. #else
  611. int broadcast = 1;
  612. if( setsockopt( sock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof( broadcast ) ) == -1 )
  613. #endif
  614. {
  615. #ifdef _WIN32
  616. closesocket( sock );
  617. #else
  618. close( sock );
  619. #endif
  620. return false;
  621. }
  622. struct sockaddr_in addr;
  623. addr.sin_family = AF_INET;
  624. addr.sin_port = htons( port );
  625. addr.sin_addr.s_addr = INADDR_ANY;
  626. if( bind( sock, (sockaddr*)&addr, sizeof( addr ) ) == -1 )
  627. {
  628. #ifdef _WIN32
  629. closesocket( sock );
  630. #else
  631. close( sock );
  632. #endif
  633. return false;
  634. }
  635. m_sock = sock;
  636. return true;
  637. }
  638. void UdpListen::Close()
  639. {
  640. assert( m_sock != -1 );
  641. #ifdef _WIN32
  642. closesocket( m_sock );
  643. #else
  644. close( m_sock );
  645. #endif
  646. m_sock = -1;
  647. }
  648. const char* UdpListen::Read( size_t& len, IpAddress& addr, int timeout )
  649. {
  650. static char buf[2048];
  651. struct pollfd fd;
  652. fd.fd = (socket_t)m_sock;
  653. fd.events = POLLIN;
  654. if( poll( &fd, 1, timeout ) <= 0 ) return nullptr;
  655. sockaddr sa;
  656. socklen_t salen = sizeof( struct sockaddr );
  657. len = (size_t)recvfrom( m_sock, buf, 2048, 0, &sa, &salen );
  658. addr.Set( sa );
  659. return buf;
  660. }
  661. }