posix_net.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include <signal.h>
  21. #include <unistd.h>
  22. #include <fcntl.h>
  23. #include <sys/socket.h>
  24. #include <sys/time.h>
  25. #include <netinet/in.h>
  26. #include <netinet/tcp.h>
  27. #include <arpa/inet.h>
  28. #include <netdb.h>
  29. #include <sys/param.h>
  30. #include <sys/ioctl.h>
  31. #include <sys/uio.h>
  32. #include <errno.h>
  33. #include <sys/select.h>
  34. #include <net/if.h>
  35. #if MACOS_X
  36. #include <ifaddrs.h>
  37. #endif
  38. #include "../../idlib/precompiled.h"
  39. idPort clientPort, serverPort;
  40. idCVar net_ip( "net_ip", "localhost", CVAR_SYSTEM, "local IP address" );
  41. idCVar net_port( "net_port", "", CVAR_SYSTEM | CVAR_INTEGER, "local IP port number" );
  42. typedef struct {
  43. unsigned long ip;
  44. unsigned long mask;
  45. } net_interface;
  46. #define MAX_INTERFACES 32
  47. int num_interfaces = 0;
  48. net_interface netint[MAX_INTERFACES];
  49. /*
  50. =============
  51. NetadrToSockadr
  52. =============
  53. */
  54. static void NetadrToSockadr( const netadr_t * a, struct sockaddr_in *s ) {
  55. memset(s, 0, sizeof(*s));
  56. if ( a->type == NA_BROADCAST ) {
  57. s->sin_family = AF_INET;
  58. s->sin_port = htons( (short)a->port );
  59. *(int *) &s->sin_addr = -1;
  60. } else if ( a->type == NA_IP || a->type == NA_LOOPBACK ) {
  61. s->sin_family = AF_INET;
  62. *(int *) &s->sin_addr = *(int *) &a->ip;
  63. s->sin_port = htons( (short)a->port );
  64. }
  65. }
  66. /*
  67. =============
  68. SockadrToNetadr
  69. =============
  70. */
  71. static void SockadrToNetadr(struct sockaddr_in *s, netadr_t * a) {
  72. unsigned int ip = *(int *)&s->sin_addr;
  73. *(int *)&a->ip = ip;
  74. a->port = ntohs( s->sin_port );
  75. // we store in network order, that loopback test is host order..
  76. ip = ntohl( ip );
  77. if ( ip == INADDR_LOOPBACK ) {
  78. a->type = NA_LOOPBACK;
  79. } else {
  80. a->type = NA_IP;
  81. }
  82. }
  83. /*
  84. =============
  85. ExtractPort
  86. =============
  87. */
  88. static bool ExtractPort( const char *src, char *buf, int bufsize, int *port ) {
  89. char *p;
  90. strncpy( buf, src, bufsize );
  91. p = buf; p += Min( bufsize - 1, (int)strlen( src ) ); *p = '\0';
  92. p = strchr( buf, ':' );
  93. if ( !p ) {
  94. return false;
  95. }
  96. *p = '\0';
  97. *port = strtol( p+1, NULL, 10 );
  98. if ( ( *port == 0 && errno == EINVAL ) ||
  99. ( ( *port == LONG_MIN || *port == LONG_MAX ) && errno == ERANGE ) ) {
  100. return false;
  101. }
  102. return true;
  103. }
  104. /*
  105. =============
  106. StringToSockaddr
  107. =============
  108. */
  109. static bool StringToSockaddr( const char *s, struct sockaddr_in *sadr, bool doDNSResolve ) {
  110. struct hostent *h;
  111. char buf[256];
  112. int port;
  113. memset( sadr, 0, sizeof( *sadr ) );
  114. sadr->sin_family = AF_INET;
  115. sadr->sin_port = 0;
  116. if (s[0] >= '0' && s[0] <= '9') {
  117. if ( !inet_aton( s, &sadr->sin_addr ) ) {
  118. // check for port
  119. if ( !ExtractPort( s, buf, sizeof( buf ), &port ) ) {
  120. return false;
  121. }
  122. if ( !inet_aton( buf, &sadr->sin_addr ) ) {
  123. return false;
  124. }
  125. sadr->sin_port = htons( port );
  126. }
  127. } else if ( doDNSResolve ) {
  128. // try to remove the port first, otherwise the DNS gets confused into multiple timeouts
  129. // failed or not failed, buf is expected to contain the appropriate host to resolve
  130. if ( ExtractPort( s, buf, sizeof( buf ), &port ) ) {
  131. sadr->sin_port = htons( port );
  132. }
  133. if ( !( h = gethostbyname( buf ) ) ) {
  134. return false;
  135. }
  136. *(int *) &sadr->sin_addr =
  137. *(int *) h->h_addr_list[0];
  138. }
  139. return true;
  140. }
  141. /*
  142. =============
  143. Sys_StringToAdr
  144. =============
  145. */
  146. bool Sys_StringToNetAdr( const char *s, netadr_t * a, bool doDNSResolve ) {
  147. struct sockaddr_in sadr;
  148. if ( !StringToSockaddr( s, &sadr, doDNSResolve ) ) {
  149. return false;
  150. }
  151. SockadrToNetadr( &sadr, a );
  152. return true;
  153. }
  154. /*
  155. =============
  156. Sys_NetAdrToString
  157. =============
  158. */
  159. const char *Sys_NetAdrToString( const netadr_t a ) {
  160. static char s[64];
  161. if ( a.type == NA_LOOPBACK ) {
  162. if ( a.port ) {
  163. idStr::snPrintf( s, sizeof(s), "localhost:%i", a.port );
  164. } else {
  165. idStr::snPrintf( s, sizeof(s), "localhost" );
  166. }
  167. } else if ( a.type == NA_IP ) {
  168. idStr::snPrintf( s, sizeof(s), "%i.%i.%i.%i:%i",
  169. a.ip[0], a.ip[1], a.ip[2], a.ip[3], a.port );
  170. }
  171. return s;
  172. }
  173. /*
  174. ==================
  175. Sys_IsLANAddress
  176. ==================
  177. */
  178. bool Sys_IsLANAddress( const netadr_t adr ) {
  179. int i;
  180. unsigned long *p_ip;
  181. unsigned long ip;
  182. #if ID_NOLANADDRESS
  183. common->Printf( "Sys_IsLANAddress: ID_NOLANADDRESS\n" );
  184. return false;
  185. #endif
  186. if ( adr.type == NA_LOOPBACK ) {
  187. return true;
  188. }
  189. if ( adr.type != NA_IP ) {
  190. return false;
  191. }
  192. if ( !num_interfaces ) {
  193. return false; // well, if there's no networking, there are no LAN addresses, right
  194. }
  195. for ( i = 0; i < num_interfaces; i++ ) {
  196. p_ip = (unsigned long *)&adr.ip[0];
  197. ip = ntohl( *p_ip );
  198. if( ( netint[i].ip & netint[i].mask ) == ( ip & netint[i].mask ) ) {
  199. return true;
  200. }
  201. }
  202. return false;
  203. }
  204. /*
  205. ===================
  206. Sys_CompareNetAdrBase
  207. Compares without the port
  208. ===================
  209. */
  210. bool Sys_CompareNetAdrBase( const netadr_t a, const netadr_t b ) {
  211. if ( a.type != b.type ) {
  212. return false;
  213. }
  214. if ( a.type == NA_LOOPBACK ) {
  215. return true;
  216. }
  217. if ( a.type == NA_IP ) {
  218. if ( a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] && a.ip[2] == b.ip[2] && a.ip[3] == b.ip[3] ) {
  219. return true;
  220. }
  221. return false;
  222. }
  223. common->Printf( "Sys_CompareNetAdrBase: bad address type\n" );
  224. return false;
  225. }
  226. /*
  227. ====================
  228. NET_InitNetworking
  229. ====================
  230. */
  231. void Sys_InitNetworking(void)
  232. {
  233. // haven't been able to clearly pinpoint which standards or RFCs define SIOCGIFCONF, SIOCGIFADDR, SIOCGIFNETMASK ioctls
  234. // it seems fairly widespread, in Linux kernel ioctl, and in BSD .. so let's assume it's always available on our targets
  235. #if MACOS_X
  236. unsigned int ip, mask;
  237. struct ifaddrs *ifap, *ifp;
  238. num_interfaces = 0;
  239. if( getifaddrs( &ifap ) < 0 ) {
  240. common->FatalError( "InitNetworking: SIOCGIFCONF error - %s\n", strerror( errno ) );
  241. return;
  242. }
  243. for( ifp = ifap; ifp; ifp = ifp->ifa_next ) {
  244. if ( ifp->ifa_addr->sa_family != AF_INET )
  245. continue;
  246. if ( !( ifp->ifa_flags & IFF_UP ) )
  247. continue;
  248. if ( !ifp->ifa_addr )
  249. continue;
  250. if ( !ifp->ifa_netmask )
  251. continue;
  252. ip = ntohl( *( unsigned long *)&ifp->ifa_addr->sa_data[2] );
  253. mask = ntohl( *( unsigned long *)&ifp->ifa_netmask->sa_data[2] );
  254. if ( ip == INADDR_LOOPBACK ) {
  255. common->Printf( "loopback\n" );
  256. } else {
  257. common->Printf( "IP: %d.%d.%d.%d\n",
  258. (unsigned char)ifp->ifa_addr->sa_data[2],
  259. (unsigned char)ifp->ifa_addr->sa_data[3],
  260. (unsigned char)ifp->ifa_addr->sa_data[4],
  261. (unsigned char)ifp->ifa_addr->sa_data[5] );
  262. common->Printf( "NetMask: %d.%d.%d.%d\n",
  263. (unsigned char)ifp->ifa_netmask->sa_data[2],
  264. (unsigned char)ifp->ifa_netmask->sa_data[3],
  265. (unsigned char)ifp->ifa_netmask->sa_data[4],
  266. (unsigned char)ifp->ifa_netmask->sa_data[5] );
  267. }
  268. netint[ num_interfaces ].ip = ip;
  269. netint[ num_interfaces ].mask = mask;
  270. num_interfaces++;
  271. }
  272. #else
  273. int s;
  274. char buf[ MAX_INTERFACES*sizeof( ifreq ) ];
  275. ifconf ifc;
  276. ifreq *ifr;
  277. int ifindex;
  278. unsigned int ip, mask;
  279. num_interfaces = 0;
  280. s = socket( AF_INET, SOCK_DGRAM, 0 );
  281. ifc.ifc_len = MAX_INTERFACES*sizeof( ifreq );
  282. ifc.ifc_buf = buf;
  283. if ( ioctl( s, SIOCGIFCONF, &ifc ) < 0 ) {
  284. common->FatalError( "InitNetworking: SIOCGIFCONF error - %s\n", strerror( errno ) );
  285. return;
  286. }
  287. ifindex = 0;
  288. while ( ifindex < ifc.ifc_len ) {
  289. common->Printf( "found interface %s - ", ifc.ifc_buf + ifindex );
  290. // find the type - ignore interfaces for which we can find we can't get IP and mask ( not configured )
  291. ifr = (ifreq*)( ifc.ifc_buf + ifindex );
  292. if ( ioctl( s, SIOCGIFADDR, ifr ) < 0 ) {
  293. common->Printf( "SIOCGIFADDR failed: %s\n", strerror( errno ) );
  294. } else {
  295. if ( ifr->ifr_addr.sa_family != AF_INET ) {
  296. common->Printf( "not AF_INET\n" );
  297. } else {
  298. ip = ntohl( *( unsigned long *)&ifr->ifr_addr.sa_data[2] );
  299. if ( ip == INADDR_LOOPBACK ) {
  300. common->Printf( "loopback\n" );
  301. } else {
  302. common->Printf( "%d.%d.%d.%d",
  303. (unsigned char)ifr->ifr_addr.sa_data[2],
  304. (unsigned char)ifr->ifr_addr.sa_data[3],
  305. (unsigned char)ifr->ifr_addr.sa_data[4],
  306. (unsigned char)ifr->ifr_addr.sa_data[5] );
  307. }
  308. if ( ioctl( s, SIOCGIFNETMASK, ifr ) < 0 ) {
  309. common->Printf( " SIOCGIFNETMASK failed: %s\n", strerror( errno ) );
  310. } else {
  311. mask = ntohl( *( unsigned long *)&ifr->ifr_addr.sa_data[2] );
  312. if ( ip != INADDR_LOOPBACK ) {
  313. common->Printf( "/%d.%d.%d.%d\n",
  314. (unsigned char)ifr->ifr_addr.sa_data[2],
  315. (unsigned char)ifr->ifr_addr.sa_data[3],
  316. (unsigned char)ifr->ifr_addr.sa_data[4],
  317. (unsigned char)ifr->ifr_addr.sa_data[5] );
  318. }
  319. netint[ num_interfaces ].ip = ip;
  320. netint[ num_interfaces ].mask = mask;
  321. num_interfaces++;
  322. }
  323. }
  324. }
  325. ifindex += sizeof( ifreq );
  326. }
  327. #endif
  328. }
  329. /*
  330. ====================
  331. IPSocket
  332. ====================
  333. */
  334. static int IPSocket( const char *net_interface, int port, netadr_t *bound_to = NULL ) {
  335. int newsocket;
  336. struct sockaddr_in address;
  337. int i = 1;
  338. if ( net_interface ) {
  339. common->Printf( "Opening IP socket: %s:%i\n", net_interface, port );
  340. } else {
  341. common->Printf( "Opening IP socket: localhost:%i\n", port );
  342. }
  343. if ( ( newsocket = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) == -1 ) {
  344. common->Printf( "ERROR: IPSocket: socket: %s", strerror( errno ) );
  345. return 0;
  346. }
  347. // make it non-blocking
  348. int on = 1;
  349. if ( ioctl( newsocket, FIONBIO, &on ) == -1 ) {
  350. common->Printf( "ERROR: IPSocket: ioctl FIONBIO:%s\n",
  351. strerror( errno ) );
  352. return 0;
  353. }
  354. // make it broadcast capable
  355. if ( setsockopt( newsocket, SOL_SOCKET, SO_BROADCAST, (char *) &i, sizeof(i) ) == -1 ) {
  356. common->Printf( "ERROR: IPSocket: setsockopt SO_BROADCAST:%s\n", strerror( errno ) );
  357. return 0;
  358. }
  359. if ( !net_interface || !net_interface[ 0 ]
  360. || !idStr::Icmp( net_interface, "localhost" ) ) {
  361. address.sin_addr.s_addr = INADDR_ANY;
  362. } else {
  363. StringToSockaddr( net_interface, &address, true );
  364. }
  365. if ( port == PORT_ANY ) {
  366. address.sin_port = 0;
  367. } else {
  368. address.sin_port = htons((short) port);
  369. }
  370. address.sin_family = AF_INET;
  371. if ( bind( newsocket, (const struct sockaddr *)&address, sizeof( address ) ) == -1 ) {
  372. common->Printf( "ERROR: IPSocket: bind: %s\n", strerror( errno ) );
  373. close( newsocket );
  374. return 0;
  375. }
  376. if ( bound_to ) {
  377. unsigned int len = sizeof( address );
  378. if ( (unsigned int)(getsockname( newsocket, (struct sockaddr *)&address, (socklen_t*)&len )) == -1 ) {
  379. common->Printf( "ERROR: IPSocket: getsockname: %s\n", strerror( errno ) );
  380. close( newsocket );
  381. return 0;
  382. }
  383. SockadrToNetadr( &address, bound_to );
  384. }
  385. return newsocket;
  386. }
  387. /*
  388. ==================
  389. idPort::idPort
  390. ==================
  391. */
  392. idPort::idPort() {
  393. netSocket = 0;
  394. memset( &bound_to, 0, sizeof( bound_to ) );
  395. }
  396. /*
  397. ==================
  398. idPort::~idPort
  399. ==================
  400. */
  401. idPort::~idPort() {
  402. Close();
  403. }
  404. /*
  405. ==================
  406. idPort::Close
  407. ==================
  408. */
  409. void idPort::Close() {
  410. if ( netSocket ) {
  411. close(netSocket);
  412. netSocket = 0;
  413. memset( &bound_to, 0, sizeof( bound_to ) );
  414. }
  415. }
  416. /*
  417. ==================
  418. idPort::GetPacket
  419. ==================
  420. */
  421. bool idPort::GetPacket( netadr_t &net_from, void *data, int &size, int maxSize ) {
  422. int ret;
  423. struct sockaddr_in from;
  424. int fromlen;
  425. if ( !netSocket ) {
  426. return false;
  427. }
  428. fromlen = sizeof( from );
  429. ret = recvfrom( netSocket, data, maxSize, 0, (struct sockaddr *) &from, (socklen_t *) &fromlen );
  430. if ( ret == -1 ) {
  431. if (errno == EWOULDBLOCK || errno == ECONNREFUSED) {
  432. // those commonly happen, don't verbose
  433. return false;
  434. }
  435. common->DPrintf( "idPort::GetPacket recvfrom(): %s\n", strerror( errno ) );
  436. return false;
  437. }
  438. assert( ret < maxSize );
  439. SockadrToNetadr( &from, &net_from );
  440. size = ret;
  441. return true;
  442. }
  443. /*
  444. ==================
  445. idPort::GetPacketBlocking
  446. ==================
  447. */
  448. bool idPort::GetPacketBlocking( netadr_t &net_from, void *data, int &size, int maxSize, int timeout ) {
  449. fd_set set;
  450. struct timeval tv;
  451. int ret;
  452. if ( !netSocket ) {
  453. return false;
  454. }
  455. if ( timeout < 0 ) {
  456. return GetPacket( net_from, data, size, maxSize );
  457. }
  458. FD_ZERO( &set );
  459. FD_SET( netSocket, &set );
  460. tv.tv_sec = timeout / 1000;
  461. tv.tv_usec = ( timeout % 1000 ) * 1000;
  462. ret = select( netSocket+1, &set, NULL, NULL, &tv );
  463. if ( ret == -1 ) {
  464. if ( errno == EINTR ) {
  465. common->DPrintf( "idPort::GetPacketBlocking: select EINTR\n" );
  466. return false;
  467. } else {
  468. common->Error( "idPort::GetPacketBlocking: select failed: %s\n", strerror( errno ) );
  469. }
  470. }
  471. if ( ret == 0 ) {
  472. // timed out
  473. return false;
  474. }
  475. struct sockaddr_in from;
  476. int fromlen;
  477. fromlen = sizeof( from );
  478. ret = recvfrom( netSocket, data, maxSize, 0, (struct sockaddr *)&from, (socklen_t *)&fromlen );
  479. if ( ret == -1 ) {
  480. // there should be no blocking errors once select declares things are good
  481. common->DPrintf( "idPort::GetPacketBlocking: %s\n", strerror( errno ) );
  482. return false;
  483. }
  484. assert( ret < maxSize );
  485. SockadrToNetadr( &from, &net_from );
  486. size = ret;
  487. return true;
  488. }
  489. /*
  490. ==================
  491. idPort::SendPacket
  492. ==================
  493. */
  494. void idPort::SendPacket( const netadr_t to, const void *data, int size ) {
  495. int ret;
  496. struct sockaddr_in addr;
  497. if ( to.type == NA_BAD ) {
  498. common->Warning( "idPort::SendPacket: bad address type NA_BAD - ignored" );
  499. return;
  500. }
  501. if ( !netSocket ) {
  502. return;
  503. }
  504. NetadrToSockadr( &to, &addr );
  505. ret = sendto( netSocket, data, size, 0, (struct sockaddr *) &addr, sizeof(addr) );
  506. if ( ret == -1 ) {
  507. common->Printf( "idPort::SendPacket ERROR: to %s: %s\n", Sys_NetAdrToString( to ), strerror( errno ) );
  508. }
  509. }
  510. /*
  511. ==================
  512. idPort::InitForPort
  513. ==================
  514. */
  515. bool idPort::InitForPort( int portNumber ) {
  516. netSocket = IPSocket( net_ip.GetString(), portNumber, &bound_to );
  517. if ( netSocket <= 0 ) {
  518. netSocket = 0;
  519. memset( &bound_to, 0, sizeof( bound_to ) );
  520. return false;
  521. }
  522. return true;
  523. }
  524. //=============================================================================
  525. /*
  526. ==================
  527. idTCP::idTCP
  528. ==================
  529. */
  530. idTCP::idTCP() {
  531. fd = 0;
  532. memset(&address, 0, sizeof(address));
  533. }
  534. /*
  535. ==================
  536. idTCP::~idTCP
  537. ==================
  538. */
  539. idTCP::~idTCP() {
  540. Close();
  541. }
  542. /*
  543. ==================
  544. idTCP::Init
  545. ==================
  546. */
  547. bool idTCP::Init( const char *host, short port ) {
  548. struct sockaddr_in sadr;
  549. if ( !Sys_StringToNetAdr( host, &address, true ) ) {
  550. common->Printf( "Couldn't resolve server name \"%s\"\n", host );
  551. return false;
  552. }
  553. address.type = NA_IP;
  554. if (!address.port) {
  555. address.port = port;
  556. }
  557. common->Printf( "\"%s\" resolved to %i.%i.%i.%i:%i\n", host,
  558. address.ip[0], address.ip[1], address.ip[2], address.ip[3], address.port );
  559. NetadrToSockadr(&address, &sadr);
  560. if (fd) {
  561. common->Warning("idTCP::Init: already initialized?\n");
  562. }
  563. if ((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
  564. fd = 0;
  565. common->Printf("ERROR: idTCP::Init: socket: %s\n", strerror(errno));
  566. return false;
  567. }
  568. if ( connect( fd, (const sockaddr *)&sadr, sizeof( sadr ) ) == -1 ) {
  569. common->Printf( "ERROR: idTCP::Init: connect: %s\n", strerror( errno ) );
  570. close( fd );
  571. fd = 0;
  572. return false;
  573. }
  574. int status;
  575. if ((status = fcntl(fd, F_GETFL, 0)) != -1) {
  576. status |= O_NONBLOCK; /* POSIX */
  577. status = fcntl(fd, F_SETFL, status);
  578. }
  579. if (status == -1) {
  580. common->Printf("ERROR: idTCP::Init: fcntl / O_NONBLOCK: %s\n", strerror(errno));
  581. close(fd);
  582. fd = 0;
  583. return false;
  584. }
  585. common->DPrintf("Opened TCP connection\n");
  586. return true;
  587. }
  588. /*
  589. ==================
  590. idTCP::Close
  591. ==================
  592. */
  593. void idTCP::Close() {
  594. if (fd) {
  595. close(fd);
  596. }
  597. fd = 0;
  598. }
  599. /*
  600. ==================
  601. idTCP::Read
  602. ==================
  603. */
  604. int idTCP::Read(void *data, int size) {
  605. int nbytes;
  606. if (!fd) {
  607. common->Printf("idTCP::Read: not initialized\n");
  608. return -1;
  609. }
  610. #if defined(_GNU_SOURCE)
  611. // handle EINTR interrupted system call with TEMP_FAILURE_RETRY - this is probably GNU libc specific
  612. if ( ( nbytes = TEMP_FAILURE_RETRY( read( fd, data, size ) ) ) == -1 ) {
  613. #else
  614. do {
  615. nbytes = read( fd, data, size );
  616. } while ( nbytes == -1 && errno == EINTR );
  617. if ( nbytes == -1 ) {
  618. #endif
  619. if (errno == EAGAIN) {
  620. return 0;
  621. }
  622. common->Printf("ERROR: idTCP::Read: %s\n", strerror(errno));
  623. Close();
  624. return -1;
  625. }
  626. // a successful read of 0 bytes indicates remote has closed the connection
  627. if ( nbytes == 0 ) {
  628. common->DPrintf( "idTCP::Read: read 0 bytes - assume connection closed\n" );
  629. return -1;
  630. }
  631. return nbytes;
  632. }
  633. /*
  634. ==================
  635. idTCP::Write
  636. ==================
  637. */
  638. static void got_SIGPIPE( int signum ) {
  639. common->Printf( "idTCP: SIGPIPE\n" );
  640. }
  641. int idTCP::Write(void *data, int size) {
  642. int nbytes;
  643. if ( !fd ) {
  644. common->Printf( "idTCP::Write: not initialized\n");
  645. return -1;
  646. }
  647. struct sigaction bak_action;
  648. struct sigaction action;
  649. action.sa_handler = got_SIGPIPE;
  650. sigemptyset( &action.sa_mask );
  651. action.sa_flags = 0;
  652. if ( sigaction( SIGPIPE, &action, &bak_action ) != 0 ) {
  653. common->Printf( "ERROR: idTCP::Write: failed to set temporary SIGPIPE handler\n" );
  654. Close();
  655. return -1;
  656. }
  657. #if defined(_GNU_SOURCE)
  658. // handle EINTR interrupted system call with TEMP_FAILURE_RETRY - this is probably GNU libc specific
  659. if ( ( nbytes = TEMP_FAILURE_RETRY ( write( fd, data, size ) ) ) == -1 ) {
  660. #else
  661. do {
  662. nbytes = write( fd, data, size );
  663. } while ( nbytes == -1 && errno == EINTR );
  664. if ( nbytes == -1 ) {
  665. #endif
  666. common->Printf( "ERROR: idTCP::Write: %s\n", strerror( errno ) );
  667. Close();
  668. return -1;
  669. }
  670. if ( sigaction( SIGPIPE, &bak_action, NULL ) != 0 ) {
  671. common->Printf( "ERROR: idTCP::Write: failed to reset SIGPIPE handler\n" );
  672. Close();
  673. return -1;
  674. }
  675. return nbytes;
  676. }