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