/ghost-legacy/socket.cpp

http://ghostcb.googlecode.com/ · C++ · 797 lines · 564 code · 161 blank · 72 comment · 131 complexity · 623ab957816fa85c6c7c982534ca044e MD5 · raw file

  1. /*
  2. Copyright [2008] [Trevor Hogan]
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. CODE PORTED FROM THE ORIGINAL GHOST PROJECT: http://ghost.pwner.org/
  13. */
  14. #include "ghost.h"
  15. #include "util.h"
  16. #include "socket.h"
  17. #include <string.h>
  18. #ifndef WIN32
  19. int GetLastError( ) { return errno; }
  20. #endif
  21. //
  22. // CSocket
  23. //
  24. CSocket :: CSocket( )
  25. {
  26. m_Socket = INVALID_SOCKET;
  27. memset( &m_SIN, 0, sizeof( m_SIN ) );
  28. m_HasError = false;
  29. m_Error = 0;
  30. }
  31. CSocket :: CSocket( SOCKET nSocket, struct sockaddr_in nSIN )
  32. {
  33. m_Socket = nSocket;
  34. m_SIN = nSIN;
  35. m_HasError = false;
  36. m_Error = 0;
  37. }
  38. CSocket :: ~CSocket( )
  39. {
  40. if( m_Socket != INVALID_SOCKET )
  41. closesocket( m_Socket );
  42. }
  43. BYTEARRAY CSocket :: GetPort( )
  44. {
  45. return UTIL_CreateByteArray( m_SIN.sin_port, false );
  46. }
  47. BYTEARRAY CSocket :: GetIP( )
  48. {
  49. return UTIL_CreateByteArray( (uint32_t)m_SIN.sin_addr.s_addr, false );
  50. }
  51. string CSocket :: GetIPString( )
  52. {
  53. return inet_ntoa( m_SIN.sin_addr );
  54. }
  55. string CSocket :: GetErrorString( )
  56. {
  57. if( !m_HasError )
  58. return "NO ERROR";
  59. switch( m_Error )
  60. {
  61. case EWOULDBLOCK: return "EWOULDBLOCK";
  62. case EINPROGRESS: return "EINPROGRESS";
  63. case EALREADY: return "EALREADY";
  64. case ENOTSOCK: return "ENOTSOCK";
  65. case EDESTADDRREQ: return "EDESTADDRREQ";
  66. case EMSGSIZE: return "EMSGSIZE";
  67. case EPROTOTYPE: return "EPROTOTYPE";
  68. case ENOPROTOOPT: return "ENOPROTOOPT";
  69. case EPROTONOSUPPORT: return "EPROTONOSUPPORT";
  70. case ESOCKTNOSUPPORT: return "ESOCKTNOSUPPORT";
  71. case EOPNOTSUPP: return "EOPNOTSUPP";
  72. case EPFNOSUPPORT: return "EPFNOSUPPORT";
  73. case EAFNOSUPPORT: return "EAFNOSUPPORT";
  74. case EADDRINUSE: return "EADDRINUSE";
  75. case EADDRNOTAVAIL: return "EADDRNOTAVAIL";
  76. case ENETDOWN: return "ENETDOWN";
  77. case ENETUNREACH: return "ENETUNREACH";
  78. case ENETRESET: return "ENETRESET";
  79. case ECONNABORTED: return "ECONNABORTED";
  80. case ECONNRESET: return "ECONNRESET";
  81. case ENOBUFS: return "ENOBUFS";
  82. case EISCONN: return "EISCONN";
  83. case ENOTCONN: return "ENOTCONN";
  84. case ESHUTDOWN: return "ESHUTDOWN";
  85. case ETOOMANYREFS: return "ETOOMANYREFS";
  86. case ETIMEDOUT: return "ETIMEDOUT";
  87. case ECONNREFUSED: return "ECONNREFUSED";
  88. case ELOOP: return "ELOOP";
  89. case ENAMETOOLONG: return "ENAMETOOLONG";
  90. case EHOSTDOWN: return "EHOSTDOWN";
  91. case EHOSTUNREACH: return "EHOSTUNREACH";
  92. case ENOTEMPTY: return "ENOTEMPTY";
  93. case EUSERS: return "EUSERS";
  94. case EDQUOT: return "EDQUOT";
  95. case ESTALE: return "ESTALE";
  96. case EREMOTE: return "EREMOTE";
  97. }
  98. return "UNKNOWN ERROR (" + UTIL_ToString( m_Error ) + ")";
  99. }
  100. void CSocket :: SetFD( fd_set *fd, fd_set *send_fd, int *nfds )
  101. {
  102. if( m_Socket == INVALID_SOCKET )
  103. return;
  104. FD_SET( m_Socket, fd );
  105. FD_SET( m_Socket, send_fd );
  106. #ifndef WIN32
  107. if( m_Socket > *nfds )
  108. *nfds = m_Socket;
  109. #endif
  110. }
  111. void CSocket :: Allocate( int type )
  112. {
  113. m_Socket = socket( AF_INET, type, 0 );
  114. if( m_Socket == INVALID_SOCKET )
  115. {
  116. m_HasError = true;
  117. m_Error = GetLastError( );
  118. CONSOLE_Print( "[SOCKET] error (socket) - " + GetErrorString( ) );
  119. return;
  120. }
  121. }
  122. void CSocket :: Reset( )
  123. {
  124. if( m_Socket != INVALID_SOCKET )
  125. closesocket( m_Socket );
  126. m_Socket = INVALID_SOCKET;
  127. memset( &m_SIN, 0, sizeof( m_SIN ) );
  128. m_HasError = false;
  129. m_Error = 0;
  130. }
  131. //
  132. // CTCPSocket
  133. //
  134. CTCPSocket :: CTCPSocket( ) : CSocket( )
  135. {
  136. Allocate( SOCK_STREAM );
  137. m_Connected = false;
  138. m_LastRecv = GetTime( );
  139. m_LastSend = GetTime( );
  140. // make socket non blocking
  141. #ifdef WIN32
  142. int iMode = 1;
  143. ioctlsocket( m_Socket, FIONBIO, (u_long FAR *)&iMode );
  144. #else
  145. fcntl( m_Socket, F_SETFL, fcntl( m_Socket, F_GETFL ) | O_NONBLOCK );
  146. #endif
  147. }
  148. CTCPSocket :: CTCPSocket( SOCKET nSocket, struct sockaddr_in nSIN ) : CSocket( nSocket, nSIN )
  149. {
  150. m_Connected = true;
  151. m_LastRecv = GetTime( );
  152. m_LastSend = GetTime( );
  153. // make socket non blocking
  154. #ifdef WIN32
  155. int iMode = 1;
  156. ioctlsocket( m_Socket, FIONBIO, (u_long FAR *)&iMode );
  157. #else
  158. fcntl( m_Socket, F_SETFL, fcntl( m_Socket, F_GETFL ) | O_NONBLOCK );
  159. #endif
  160. }
  161. CTCPSocket :: ~CTCPSocket( )
  162. {
  163. }
  164. void CTCPSocket :: Reset( )
  165. {
  166. CSocket :: Reset( );
  167. Allocate( SOCK_STREAM );
  168. m_Connected = false;
  169. m_RecvBuffer.clear( );
  170. m_SendBuffer.clear( );
  171. m_LastRecv = GetTime( );
  172. m_LastSend = GetTime( );
  173. // make socket non blocking
  174. #ifdef WIN32
  175. int iMode = 1;
  176. ioctlsocket( m_Socket, FIONBIO, (u_long FAR *)&iMode );
  177. #else
  178. fcntl( m_Socket, F_SETFL, fcntl( m_Socket, F_GETFL ) | O_NONBLOCK );
  179. #endif
  180. if( !m_LogFile.empty( ) )
  181. {
  182. ofstream Log;
  183. Log.open( m_LogFile.c_str( ), ios :: app );
  184. if( !Log.fail( ) )
  185. {
  186. Log << "----------RESET----------" << endl;
  187. Log.close( );
  188. }
  189. }
  190. }
  191. void CTCPSocket :: PutBytes( string bytes )
  192. {
  193. m_SendBuffer += bytes;
  194. }
  195. void CTCPSocket :: PutBytes( BYTEARRAY bytes )
  196. {
  197. m_SendBuffer += string( bytes.begin( ), bytes.end( ) );
  198. }
  199. void CTCPSocket :: DoRecv( fd_set *fd )
  200. {
  201. if( m_Socket == INVALID_SOCKET || m_HasError || !m_Connected )
  202. return;
  203. if( FD_ISSET( m_Socket, fd ) )
  204. {
  205. // data is waiting, receive it
  206. char buffer[1024];
  207. int c = recv( m_Socket, buffer, 1024, 0 );
  208. if( c == SOCKET_ERROR && GetLastError( ) != EWOULDBLOCK )
  209. {
  210. // receive error
  211. m_HasError = true;
  212. m_Error = GetLastError( );
  213. CONSOLE_Print( "[TCPSOCKET] error (recv) - " + GetErrorString( ) );
  214. return;
  215. }
  216. else if( c == 0 )
  217. {
  218. // the other end closed the connection
  219. CONSOLE_Print( "[TCPSOCKET] closed by remote host" );
  220. m_Connected = false;
  221. }
  222. else if( c > 0 )
  223. {
  224. // success! add the received data to the buffer
  225. if( !m_LogFile.empty( ) )
  226. {
  227. ofstream Log;
  228. Log.open( m_LogFile.c_str( ), ios :: app );
  229. if( !Log.fail( ) )
  230. {
  231. Log << " RECEIVE <<< " << UTIL_ByteArrayToHexString( UTIL_CreateByteArray( (unsigned char *)buffer, c ) ) << endl;
  232. Log.close( );
  233. }
  234. }
  235. m_RecvBuffer += string( buffer, c );
  236. m_LastRecv = GetTime( );
  237. }
  238. }
  239. }
  240. void CTCPSocket :: DoSend( fd_set *send_fd )
  241. {
  242. if( m_Socket == INVALID_SOCKET || m_HasError || !m_Connected || m_SendBuffer.empty( ) )
  243. return;
  244. if( FD_ISSET( m_Socket, send_fd ) )
  245. {
  246. // socket is ready, send it
  247. int s = send( m_Socket, m_SendBuffer.c_str( ), (int)m_SendBuffer.size( ), MSG_NOSIGNAL );
  248. if( s == SOCKET_ERROR && GetLastError( ) != EWOULDBLOCK )
  249. {
  250. // send error
  251. m_HasError = true;
  252. m_Error = GetLastError( );
  253. CONSOLE_Print( "[TCPSOCKET] error (send) - " + GetErrorString( ) );
  254. return;
  255. }
  256. else if( s > 0 )
  257. {
  258. // success! only some of the data may have been sent, remove it from the buffer
  259. if( !m_LogFile.empty( ) )
  260. {
  261. ofstream Log;
  262. Log.open( m_LogFile.c_str( ), ios :: app );
  263. if( !Log.fail( ) )
  264. {
  265. Log << "SEND >>> " << UTIL_ByteArrayToHexString( BYTEARRAY( m_SendBuffer.begin( ), m_SendBuffer.begin( ) + s ) ) << endl;
  266. Log.close( );
  267. }
  268. }
  269. m_SendBuffer = m_SendBuffer.substr( s );
  270. m_LastSend = GetTime( );
  271. }
  272. }
  273. }
  274. void CTCPSocket :: Disconnect( )
  275. {
  276. if( m_Socket != INVALID_SOCKET )
  277. shutdown( m_Socket, SHUT_RDWR );
  278. m_Connected = false;
  279. }
  280. void CTCPSocket :: SetNoDelay( bool noDelay )
  281. {
  282. int OptVal = 0;
  283. if( noDelay )
  284. OptVal = 1;
  285. setsockopt( m_Socket, IPPROTO_TCP, TCP_NODELAY, (const char *)&OptVal, sizeof( int ) );
  286. }
  287. //
  288. // CTCPClient
  289. //
  290. CTCPClient :: CTCPClient( ) : CTCPSocket( )
  291. {
  292. m_Connecting = false;
  293. }
  294. CTCPClient :: ~CTCPClient( )
  295. {
  296. }
  297. void CTCPClient :: Reset( )
  298. {
  299. CTCPSocket :: Reset( );
  300. m_Connecting = false;
  301. }
  302. void CTCPClient :: Disconnect( )
  303. {
  304. CTCPSocket :: Disconnect( );
  305. m_Connecting = false;
  306. }
  307. void CTCPClient :: Connect( string localaddress, string address, uint16_t port )
  308. {
  309. if( m_Socket == INVALID_SOCKET || m_HasError || m_Connecting || m_Connected )
  310. return;
  311. if( !localaddress.empty( ) )
  312. {
  313. struct sockaddr_in LocalSIN;
  314. memset( &LocalSIN, 0, sizeof( LocalSIN ) );
  315. LocalSIN.sin_family = AF_INET;
  316. if( ( LocalSIN.sin_addr.s_addr = inet_addr( localaddress.c_str( ) ) ) == INADDR_NONE )
  317. LocalSIN.sin_addr.s_addr = INADDR_ANY;
  318. LocalSIN.sin_port = htons( 0 );
  319. if( bind( m_Socket, (struct sockaddr *)&LocalSIN, sizeof( LocalSIN ) ) == SOCKET_ERROR )
  320. {
  321. m_HasError = true;
  322. m_Error = GetLastError( );
  323. CONSOLE_Print( "[TCPCLIENT] error (bind) - " + GetErrorString( ) );
  324. return;
  325. }
  326. }
  327. // get IP address
  328. struct hostent *HostInfo;
  329. uint32_t HostAddress;
  330. HostInfo = gethostbyname( address.c_str( ) );
  331. if( !HostInfo )
  332. {
  333. m_HasError = true;
  334. // m_Error = h_error;
  335. CONSOLE_Print( "[TCPCLIENT] error (gethostbyname)" );
  336. return;
  337. }
  338. memcpy( &HostAddress, HostInfo->h_addr, HostInfo->h_length );
  339. // connect
  340. m_SIN.sin_family = AF_INET;
  341. m_SIN.sin_addr.s_addr = HostAddress;
  342. m_SIN.sin_port = htons( port );
  343. if( connect( m_Socket, (struct sockaddr *)&m_SIN, sizeof( m_SIN ) ) == SOCKET_ERROR )
  344. {
  345. if( GetLastError( ) != EINPROGRESS && GetLastError( ) != EWOULDBLOCK )
  346. {
  347. // connect error
  348. m_HasError = true;
  349. m_Error = GetLastError( );
  350. CONSOLE_Print( "[TCPCLIENT] error (connect) - " + GetErrorString( ) );
  351. return;
  352. }
  353. }
  354. m_Connecting = true;
  355. }
  356. bool CTCPClient :: CheckConnect( )
  357. {
  358. if( m_Socket == INVALID_SOCKET || m_HasError || !m_Connecting )
  359. return false;
  360. fd_set fd;
  361. FD_ZERO( &fd );
  362. FD_SET( m_Socket, &fd );
  363. struct timeval tv;
  364. tv.tv_sec = 0;
  365. tv.tv_usec = 0;
  366. // check if the socket is connected
  367. #ifdef WIN32
  368. if( select( 1, NULL, &fd, NULL, &tv ) == SOCKET_ERROR )
  369. #else
  370. if( select( m_Socket + 1, NULL, &fd, NULL, &tv ) == SOCKET_ERROR )
  371. #endif
  372. {
  373. m_HasError = true;
  374. m_Error = GetLastError( );
  375. return false;
  376. }
  377. if( FD_ISSET( m_Socket, &fd ) )
  378. {
  379. m_Connecting = false;
  380. m_Connected = true;
  381. return true;
  382. }
  383. return false;
  384. }
  385. //
  386. // CTCPServer
  387. //
  388. CTCPServer :: CTCPServer( ) : CTCPSocket( )
  389. {
  390. // set the socket to reuse the address in case it hasn't been released yet
  391. int optval = 1;
  392. #ifdef WIN32
  393. setsockopt( m_Socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&optval, sizeof( int ) );
  394. #else
  395. setsockopt( m_Socket, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval, sizeof( int ) );
  396. #endif
  397. }
  398. CTCPServer :: ~CTCPServer( )
  399. {
  400. }
  401. bool CTCPServer :: Listen( string address, uint16_t port )
  402. {
  403. if( m_Socket == INVALID_SOCKET || m_HasError )
  404. return false;
  405. m_SIN.sin_family = AF_INET;
  406. if( !address.empty( ) )
  407. {
  408. if( ( m_SIN.sin_addr.s_addr = inet_addr( address.c_str( ) ) ) == INADDR_NONE )
  409. m_SIN.sin_addr.s_addr = INADDR_ANY;
  410. }
  411. else
  412. m_SIN.sin_addr.s_addr = INADDR_ANY;
  413. m_SIN.sin_port = htons( port );
  414. if( bind( m_Socket, (struct sockaddr *)&m_SIN, sizeof( m_SIN ) ) == SOCKET_ERROR )
  415. {
  416. m_HasError = true;
  417. m_Error = GetLastError( );
  418. CONSOLE_Print( "[TCPSERVER] error (bind) - " + GetErrorString( ) );
  419. return false;
  420. }
  421. // listen, queue length 8
  422. if( listen( m_Socket, 8 ) == SOCKET_ERROR )
  423. {
  424. m_HasError = true;
  425. m_Error = GetLastError( );
  426. CONSOLE_Print( "[TCPSERVER] error (listen) - " + GetErrorString( ) );
  427. return false;
  428. }
  429. return true;
  430. }
  431. CTCPSocket *CTCPServer :: Accept( fd_set *fd )
  432. {
  433. if( m_Socket == INVALID_SOCKET || m_HasError )
  434. return NULL;
  435. if( FD_ISSET( m_Socket, fd ) )
  436. {
  437. // a connection is waiting, accept it
  438. struct sockaddr_in Addr;
  439. int AddrLen = sizeof( Addr );
  440. SOCKET NewSocket;
  441. #ifdef WIN32
  442. if( ( NewSocket = accept( m_Socket, (struct sockaddr *)&Addr, &AddrLen ) ) == INVALID_SOCKET )
  443. #else
  444. if( ( NewSocket = accept( m_Socket, (struct sockaddr *)&Addr, (socklen_t *)&AddrLen ) ) == INVALID_SOCKET )
  445. #endif
  446. {
  447. // accept error, ignore it
  448. }
  449. else
  450. {
  451. // success! return the new socket
  452. return new CTCPSocket( NewSocket, Addr );
  453. }
  454. }
  455. return NULL;
  456. }
  457. //
  458. // CUDPSocket
  459. //
  460. CUDPSocket :: CUDPSocket( ) : CSocket( )
  461. {
  462. Allocate( SOCK_DGRAM );
  463. // enable broadcast support
  464. int OptVal = 1;
  465. setsockopt( m_Socket, SOL_SOCKET, SO_BROADCAST, (const char *)&OptVal, sizeof( int ) );
  466. // set default broadcast target
  467. m_BroadcastTarget.s_addr = INADDR_BROADCAST;
  468. }
  469. CUDPSocket :: ~CUDPSocket( )
  470. {
  471. }
  472. bool CUDPSocket :: SendTo( struct sockaddr_in sin, BYTEARRAY message )
  473. {
  474. if( m_Socket == INVALID_SOCKET || m_HasError )
  475. return false;
  476. string MessageString = string( message.begin( ), message.end( ) );
  477. if( sendto( m_Socket, MessageString.c_str( ), MessageString.size( ), 0, (struct sockaddr *)&sin, sizeof( sin ) ) == -1 )
  478. return false;
  479. return true;
  480. }
  481. bool CUDPSocket :: SendTo( string address, uint16_t port, BYTEARRAY message )
  482. {
  483. if( m_Socket == INVALID_SOCKET || m_HasError )
  484. return false;
  485. // get IP address
  486. struct hostent *HostInfo;
  487. uint32_t HostAddress;
  488. HostInfo = gethostbyname( address.c_str( ) );
  489. if( !HostInfo )
  490. {
  491. m_HasError = true;
  492. // m_Error = h_error;
  493. CONSOLE_Print( "[UDPSOCKET] error (gethostbyname)" );
  494. return false;
  495. }
  496. memcpy( &HostAddress, HostInfo->h_addr, HostInfo->h_length );
  497. struct sockaddr_in sin;
  498. sin.sin_family = AF_INET;
  499. sin.sin_addr.s_addr = HostAddress;
  500. sin.sin_port = htons( port );
  501. return SendTo( sin, message );
  502. }
  503. bool CUDPSocket :: Broadcast( uint16_t port, BYTEARRAY message )
  504. {
  505. if( m_Socket == INVALID_SOCKET || m_HasError )
  506. return false;
  507. struct sockaddr_in sin;
  508. sin.sin_family = AF_INET;
  509. sin.sin_addr.s_addr = m_BroadcastTarget.s_addr;
  510. sin.sin_port = htons( port );
  511. string MessageString = string( message.begin( ), message.end( ) );
  512. if( sendto( m_Socket, MessageString.c_str( ), MessageString.size( ), 0, (struct sockaddr *)&sin, sizeof( sin ) ) == -1 )
  513. {
  514. CONSOLE_Print( "[UDPSOCKET] failed to broadcast packet (port " + UTIL_ToString( port ) + ", size " + UTIL_ToString( MessageString.size( ) ) + " bytes)" );
  515. return false;
  516. }
  517. return true;
  518. }
  519. void CUDPSocket :: SetBroadcastTarget( string subnet )
  520. {
  521. if( subnet.empty( ) )
  522. {
  523. CONSOLE_Print( "[UDPSOCKET] using default broadcast target" );
  524. m_BroadcastTarget.s_addr = INADDR_BROADCAST;
  525. }
  526. else
  527. {
  528. // this function does not check whether the given subnet is a valid subnet the user is on
  529. // convert string representation of ip/subnet to in_addr
  530. CONSOLE_Print( "[UDPSOCKET] using broadcast target [" + subnet + "]" );
  531. m_BroadcastTarget.s_addr = inet_addr( subnet.c_str( ) );
  532. // if conversion fails, inet_addr( ) returns INADDR_NONE
  533. if( m_BroadcastTarget.s_addr == INADDR_NONE )
  534. {
  535. CONSOLE_Print( "[UDPSOCKET] invalid broadcast target, using default broadcast target" );
  536. m_BroadcastTarget.s_addr = INADDR_BROADCAST;
  537. }
  538. }
  539. }
  540. void CUDPSocket :: SetDontRoute( bool dontRoute )
  541. {
  542. int OptVal = 0;
  543. if( dontRoute )
  544. OptVal = 1;
  545. // don't route packets; make them ignore routes set by routing table and send them to the interface
  546. // belonging to the target address directly
  547. setsockopt( m_Socket, SOL_SOCKET, SO_DONTROUTE, (const char *)&OptVal, sizeof( int ) );
  548. }
  549. //
  550. // CUDPServer
  551. //
  552. CUDPServer :: CUDPServer( ) : CUDPSocket( )
  553. {
  554. // make socket non blocking
  555. #ifdef WIN32
  556. int iMode = 1;
  557. ioctlsocket( m_Socket, FIONBIO, (u_long FAR *)&iMode );
  558. #else
  559. fcntl( m_Socket, F_SETFL, fcntl( m_Socket, F_GETFL ) | O_NONBLOCK );
  560. #endif
  561. // set the socket to reuse the address
  562. // with UDP sockets this allows more than one program to listen on the same port
  563. int optval = 1;
  564. #ifdef WIN32
  565. setsockopt( m_Socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&optval, sizeof( int ) );
  566. #else
  567. setsockopt( m_Socket, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval, sizeof( int ) );
  568. #endif
  569. }
  570. CUDPServer :: ~CUDPServer( )
  571. {
  572. }
  573. bool CUDPServer :: Bind( struct sockaddr_in sin )
  574. {
  575. if( m_Socket == INVALID_SOCKET || m_HasError )
  576. return false;
  577. m_SIN = sin;
  578. if( bind( m_Socket, (struct sockaddr *)&m_SIN, sizeof( m_SIN ) ) == SOCKET_ERROR )
  579. {
  580. m_HasError = true;
  581. m_Error = GetLastError( );
  582. CONSOLE_Print( "[UDPSERVER] error (bind) - " + GetErrorString( ) );
  583. return false;
  584. }
  585. return true;
  586. }
  587. bool CUDPServer :: Bind( string address, uint16_t port )
  588. {
  589. if( m_Socket == INVALID_SOCKET || m_HasError )
  590. return false;
  591. struct sockaddr_in sin;
  592. sin.sin_family = AF_INET;
  593. if( !address.empty( ) )
  594. {
  595. if( ( sin.sin_addr.s_addr = inet_addr( address.c_str( ) ) ) == INADDR_NONE )
  596. sin.sin_addr.s_addr = INADDR_ANY;
  597. }
  598. else
  599. sin.sin_addr.s_addr = INADDR_ANY;
  600. sin.sin_port = htons( port );
  601. return Bind( sin );
  602. }
  603. void CUDPServer :: RecvFrom( fd_set *fd, struct sockaddr_in *sin, string *message )
  604. {
  605. if( m_Socket == INVALID_SOCKET || m_HasError || !sin || !message )
  606. return;
  607. int AddrLen = sizeof( *sin );
  608. if( FD_ISSET( m_Socket, fd ) )
  609. {
  610. // data is waiting, receive it
  611. char buffer[1024];
  612. #ifdef WIN32
  613. int c = recvfrom( m_Socket, buffer, 1024, 0, (struct sockaddr *)sin, &AddrLen );
  614. #else
  615. int c = recvfrom( m_Socket, buffer, 1024, 0, (struct sockaddr *)sin, (socklen_t *)&AddrLen );
  616. #endif
  617. if( c == SOCKET_ERROR && GetLastError( ) != EWOULDBLOCK )
  618. {
  619. // receive error
  620. m_HasError = true;
  621. m_Error = GetLastError( );
  622. CONSOLE_Print( "[UDPSERVER] error (recvfrom) - " + GetErrorString( ) );
  623. }
  624. else if( c > 0 )
  625. {
  626. // success!
  627. *message = string( buffer, c );
  628. }
  629. }
  630. }