1 /*
2
3 *************************************************************************
4
5 ArmageTron -- Just another Tron Lightcycle Game in 3D.
6 Copyright (C) 2000 Manuel Moos (manuel@moosnet.de)
7
8 **************************************************************************
9
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 ***************************************************************************
25
26 */
27
28 // nSocket.h
29
30 // loosely based on the GNU Quake 1 base network code, so technicaly:
31 // Copyright (C) 1996-1997 Id Software, Inc.
32 // Modified for Armagetron by Manuel Moos (manuel@moosnet.de)
33
34 #include "config.h"
35 #include "tRandom.h"
36 #include "tSysTime.h"
37 #include "tRandom.h"
38
39 #include <string>
40 #include <stdio.h>
41 #include <string.h>
42
43 #include <sys/types.h>
44
45 #include <errno.h>
46 #include <stdlib.h>
47 #include <vector>
48
49 #ifndef WIN32
50 #include <arpa/inet.h>
51 #include <netinet/in_systm.h>
52 #include <netinet/in.h>
53 #include <netinet/ip.h>
54 #include <netdb.h>
55 #include <sys/param.h>
56 #include <sys/ioctl.h>
57 #include <sys/socket.h>
58 #else
59 //#include <winsock2.h>
60 //#include <ws2tcpip.h>
61 //#include <Ws2tcpip.h>
62 //#include <Wspiapi.h>
63
64 #define ioctl(a,b,c) ioctlsocket((a),(b),(u_long *)(c))
65
66 #undef EINVAL
67 #undef EINTR
68 #define EADDRINUSE WSAEADDRINUSE
69 #define EWOULDBLOCK WSAEWOULDBLOCK
70 #define ECONNREFUSED WSAECONNREFUSED
71 #define ENOTSOCK WSAENOTSOCK
72 #define ECONNRESET WSAECONNRESET
73 #define ECONNREFUSED WSAECONNREFUSED
74 #define ENETDOWN WSAENETDOWN
75 #ifndef EINTR
76 #define EINTR WSAEINTR
77 #endif
78 #define EINVAL WSAEINVAL
79 #define EISCONN WSAEISCONN
80 #define ENETRESET WSAENETRESET
81 #define EOPNOTSUPP WSAEOPNOTSUPP
82 #define EAFNOSUPPORT WSAEAFNOSUPPORT
83 #define EADDRNOTAVAIL WSAEADDRNOTAVAIL
84 #define ESHUTDOWN WSAESHUTDOWN
85 #define EMSGSIZE WSAEMSGSIZE
86 #define ETIMEDOUT WSAETIMEDOUT
87 #define ENETUNREACH WSAENETUNREACH
88 #define close closesocket
89 #define snprintf _snprintf
90 #endif
91
92
93 #ifdef __sun__
94 #include <sys/filio.h>
95 #endif
96
97 #ifdef NeXT
98 #include <libc.h>
99 #endif
100
101 #ifndef MAXHOSTNAMELEN
102 #define MAXHOSTNAMELEN 256
103 #endif
104
105 #if HAVE_UNISTD_H
106 #include <unistd.h>
107 #endif
108
109 #include "nSocket.h"
110 #include "tConfiguration.h"
111 #include "tRecorder.h"
112
113 // print packet sources and destinations
114 #ifdef DEBUG
115 #ifdef DEDICATED
116 //#define PRINTPACKETS
117 #endif
118 #endif
119
120 //! Exception to throw when a single socket was opened by request
121 class OneSocketOpened{};
122
123 //! structure defining a socket type
124 struct nSocketType
125 {
126 int family; //! socket family
127 int type; //! socket type
128 int protocol; //! protocol
129
130 //! default constructor
nSocketTypenSocketType131 nSocketType()
132 : family(PF_INET)
133 , type(SOCK_DGRAM)
134 , protocol(IPPROTO_UDP)
135 {}
136 };
137
138 //! all information to reach a host
139 struct nHostInfo
140 {
141 nSocketType type; //! type of socket to connect to
142 nAddress address; //! raw address
143 tString name; //! canonical hostname
144 };
145
146 // streaming operators for addresses, socket types and host infos
operator >>(std::istream & s,nAddress & address)147 std::istream & operator >> ( std::istream & s, nAddress & address )
148 {
149 // read address
150 tLineString line;
151 s >> line;
152 address.FromString( line );
153
154 return s;
155 }
156
operator >>(std::istream & s,nSocketType & type)157 std::istream & operator >> ( std::istream & s, nSocketType & type )
158 {
159 // read data
160 s >> type.family >> type.type >> type.protocol;
161
162 return s;
163 }
164
operator >>(std::istream & s,nHostInfo & hostInfo)165 std::istream & operator >> ( std::istream & s, nHostInfo & hostInfo )
166 {
167 // read name
168 tLineString name;
169 s >> name;
170 hostInfo.name = name;
171
172 // read address and type
173 s >> hostInfo.address;
174 s >> hostInfo.type;
175
176 return s;
177 }
178
operator <<(std::ostream & s,nAddress const & address)179 std::ostream & operator << ( std::ostream & s, nAddress const & address )
180 {
181 // write address
182 s << tLineString( address.ToString() );
183
184 return s;
185 }
186
operator <<(std::ostream & s,nSocketType const & type)187 std::ostream & operator << ( std::ostream & s, nSocketType const & type )
188 {
189 // write data
190 s << type.family << ' ' << type.type << ' ' << type.protocol;
191
192 return s;
193 }
194
operator <<(std::ostream & s,nHostInfo const & hostInfo)195 std::ostream & operator << ( std::ostream & s, nHostInfo const & hostInfo )
196 {
197 // write name
198 s << tLineString( hostInfo.name );
199
200 // write address and type
201 s << hostInfo.address;
202 s << hostInfo.type;
203
204 return s;
205 }
206
207 typedef std::vector< nHostInfo > nHostList;
208
209 enum nSocketError
210 {
211 nSocketError_Ignore, // nothing special happened
212 nSocketError_Reset // socket needs to be reset
213 };
214
215 tRECORD_AS( nSocketError, int );
216
217 // anonymous namespace of helper functions
218 namespace
219 {
220
221 char *ANET_AddrToString (const struct sockaddr *addr);
222 int ANET_GetSocketAddr (int sock, struct sockaddr *addr);
223
224 #define NET_NAMELEN 100
225
226 // typedef int Socket;
227
Sys_Error(const char * x)228 static inline void Sys_Error(const char *x){
229 con << x;
230 exit(-1);
231 }
232
Con_Printf(const char * x)233 static inline void Con_Printf(const char *x){
234 con << x;
235 }
236
Con_SafePrintf(const char * x)237 static inline void Con_SafePrintf(const char *x){
238 con << x;
239 }
240
Con_DPrintf(const char * x)241 static inline void Con_DPrintf(const char *x){
242 con << x;
243 }
244
245 #ifdef HAVE_SOCKLEN_T
246 typedef socklen_t NET_SIZE;
247 #else
248 typedef int NET_SIZE;
249 #endif
250
ANET_Error()251 static nSocketError ANET_Error()
252 {
253 int error = 0;
254 nSocketError aError = nSocketError_Ignore;
255
256 // play back error message
257 static char const * section = "NETERROR";
258 if ( !tRecorder::PlaybackStrict( section, aError ) )
259 {
260 // get error from OS
261 #ifdef WIN32
262 error = WSAGetLastError();
263 #else
264 error = errno;
265 #endif
266 switch ( error )
267 {
268 case EADDRINUSE:
269 break;
270 case ENOTSOCK:
271 aError = nSocketError_Reset;
272 break;
273 case ECONNRESET:
274 aError = nSocketError_Reset;
275 break;
276 case ECONNREFUSED:
277 break;
278 case EWOULDBLOCK:
279 case ENETUNREACH:
280 aError = nSocketError_Ignore;
281 break;
282 // case NOTINITIALISED:
283 // break;
284 case ENETDOWN:
285 break;
286 case EFAULT:
287 aError = nSocketError_Reset;
288 break;
289 case EINTR:
290 break;
291 case EINVAL:
292 break;
293 case EISCONN:
294 break;
295 case ENETRESET:
296 break;
297 case EOPNOTSUPP:
298 case EAFNOSUPPORT:
299 case EADDRNOTAVAIL:
300 aError = nSocketError_Reset;
301 break;
302 case ESHUTDOWN:
303 break;
304 #ifndef WIN32
305 case EMSGSIZE:
306 break;
307 #endif
308 case ETIMEDOUT:
309 break;
310 default:
311 #ifdef DEBUG
312 con << "Unknown network error " << error << "\n";
313 #endif
314 break;
315 }
316 }
317
318 // record error message
319 tRecorder::Record( section, aError );
320
321
322 // st_Breakpoint();
323 return aError;
324 }
325
326 typedef int Socket;
327
328
329 /*
330 int ANET_NewSocket ()
331 {
332 int newsocket=-1;
333 bool _true = true;
334
335 // create socket
336 if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
337 return -1;
338
339 // unblock it
340 if (ioctl (newsocket, FIONBIO, reinterpret_cast<char *>(&_true)) == -1)
341 goto ErrorReturn;
342
343 return newsocket;
344
345 ErrorReturn:
346 close (newsocket);
347 return -1;
348 }
349
350 int ANET_OpenSocket (int port )
351 {
352 struct sockaddr_in address;
353
354 // create socket
355 int newsocket = ANET_NewSocket();
356 if ( newsocket < 0 )
357 return -1;
358
359 // bind to no specific IP
360 address.sin_addr.s_addr = INADDR_ANY;
361 address.sin_family = AF_INET;
362
363 address.sin_port = htons(port);
364 if( bind (newsocket, reinterpret_cast<const sockaddr *>(&address), sizeof(address)) == -1)
365 goto ErrorReturn;
366
367 return newsocket;
368
369 ErrorReturn:
370 close (newsocket);
371 return -1;
372 }
373 */
374
375 /*
376 int ANET_OpenSocket (int port, const tString& ip )
377 {
378 if ( ip.Len() > 1 && ip != "ANY" && ip != "ALL" )
379 {
380 return ANET_OpenSocket( port, static_cast< const char * >( ip ) );
381 }
382 else
383 {
384 return ANET_OpenSocket( port, NULL );
385 }
386 }
387
388 int ANET_OpenSocket (int port)
389 {
390 return ANET_OpenSocket( port, net_hostip );
391 }
392 */
393
394 //=============================================================================
395 static bool sn_listen = false;
396
397 class nOSNetworking
398 {
399 #ifdef WIN32
400 public:
nOSNetworking()401 nOSNetworking()
402 {
403 WSADATA winsockdata;
404 WSAStartup( MAKEWORD(1, 1), &winsockdata );
405 }
406
~nOSNetworking()407 ~nOSNetworking()
408 {
409 WSACleanup();
410 }
411 #endif
412 };
413
414 //! initialize OS networking system and automatically shut it down later
sn_InitOSNetworking()415 static nOSNetworking const & sn_InitOSNetworking()
416 {
417 static nOSNetworking osNetworking;
418 return osNetworking;
419 }
420
421 static char const * hostnameSection = "HOSTNAME";
422
423 //! determine name of this host
GetMyHostName()424 tString const & GetMyHostName()
425 {
426 static tString ret;
427 if ( ret.Len() <= 1 )
428 {
429 // read hostname from recording
430 if ( !tRecorder::PlaybackStrict( hostnameSection, ret ) )
431 {
432 // look up hostname
433 char buff[MAXHOSTNAMELEN]="\0";
434 if ( 0 == gethostname(buff, MAXHOSTNAMELEN) )
435 ret = buff;
436 else
437 ret = "localhost";
438 }
439
440 // write hostname to recording
441 tRecorder::Record( hostnameSection, ret );
442 }
443
444 return ret;
445 }
446
447 // open ports that listens on the specified address list, returns true only if sockets for all addresses were created
ANET_ListenOn(nHostList const & addresses,nSocketListener::SocketArray & sockets,bool onesocketonly,bool ignoreErrors)448 bool ANET_ListenOn( nHostList const & addresses, nSocketListener::SocketArray & sockets, bool onesocketonly, bool ignoreErrors )
449 {
450 bool ret = true;
451
452 for (nHostList::const_iterator iter = addresses.begin(); iter != addresses.end(); ++iter)
453 {
454 nHostInfo const & address = *iter;
455
456 nSocket socket;
457 int error = -1;
458 try
459 {
460 error = socket.Open( address );
461 }
462 catch ( nSocket::PermanentError & e )
463 {
464 // ignore errors on request
465 if ( ignoreErrors )
466 {
467 con << "sn_SetNetState: can't setup listening socket. Reason given:\n"
468 << e.GetName() << ": " << e.GetDescription() << "\nIgnoring on user request.\n";
469 return true;
470 }
471 else
472 {
473 throw;
474 }
475 }
476
477 if ( error == 0 )
478 {
479 // store the socket
480 sockets.push_back( socket );
481
482 // return if we only want one socket
483 if ( onesocketonly )
484 {
485 #ifndef NOEXCEPT
486 throw OneSocketOpened();
487 #endif
488 return true;
489 }
490 }
491 else
492 {
493 // report error
494 ret = false;
495 }
496 }
497
498 // return result
499 return ret;
500 }
501
502
503 // determines addresses of hostentry and adds them to hostList
ANET_GetHostList(hostent const * hostentry,nHostList & hostList,int net_hostport,bool server=true)504 void ANET_GetHostList( hostent const * hostentry, nHostList & hostList, int net_hostport, bool server = true )
505 {
506 // iterate over addresses
507 char * * addressList = hostentry->h_addr_list;
508 while (*addressList)
509 {
510 // prepare host info (TODO: IPV6/TCP compatibility)
511 nHostInfo info;
512 info.type.type = hostentry->h_addrtype;
513 info.name = hostentry->h_name;
514 info.address.FromHostent( hostentry->h_length, *addressList );
515 info.address.SetPort( net_hostport );
516
517 // add it to list
518 hostList.push_back( info );
519
520 ++addressList; // next address
521 }
522 }
523
524 // determines addresses of hostname and fills them into to hostList
ANET_GetHostList(char const * hostname,nHostList & hostList,int net_hostport,bool server=true)525 void ANET_GetHostList( char const * hostname, nHostList & hostList, int net_hostport, bool server = true )
526 {
527 sn_InitOSNetworking();
528
529 hostList.clear();
530
531 // if hostname is NULL, add generic host entry
532 if ( !hostname )
533 {
534 nHostInfo info;
535 info.name = "localhost";
536 info.address.SetPort( net_hostport );
537
538 // add it to list and return
539 hostList.push_back( info );
540 return;
541 }
542
543 // read addresses from recording
544 static char const * section = "MULTIHOSTBYNAME";
545 static char const * sectionEnd = "MULTIHOSTBYNAMEEND";
546 nHostInfo read;
547 while ( tRecorder::Playback( section, read ) )
548 {
549 hostList.push_back( read );
550 }
551 if ( !tRecorder::Playback( sectionEnd ) )
552 {
553 // look up hostname
554 struct hostent *hostentry;
555 hostentry = gethostbyname (hostname);
556 if (!hostentry)
557 {
558 #ifndef WIN32
559 con << "Error looking up " << ( hostname ? hostname : "localhost" ) << " : " << gai_strerror( h_errno ) << "\n";
560 #endif
561 return;
562 }
563
564 // delegate
565 ANET_GetHostList( hostentry, hostList, net_hostport, server );
566 }
567
568 // write addresses to recording
569 for ( nHostList::const_iterator iter = hostList.begin(); iter != hostList.end(); ++iter )
570 tRecorder::Record( section, read );
571 tRecorder::Record( sectionEnd );
572 }
573
ANET_ListenOnConst(char const * hostname,int net_hostport,nSocketListener::SocketArray & sockets,bool & onesocketonly,bool & relaxed,bool & ignoreErrors)574 bool ANET_ListenOnConst( char const * hostname, int net_hostport, nSocketListener::SocketArray & sockets, bool & onesocketonly, bool & relaxed, bool & ignoreErrors )
575 {
576 if ( hostname )
577 {
578 // check if only one of the following sockets is required
579 if ( 0 == strcmp( hostname, "ONEOF" ) )
580 {
581 onesocketonly = true;
582 return true;
583 }
584
585 // check if partial failures are tolerated
586 if ( 0 == strcmp( hostname, "RELAXED" ) )
587 {
588 relaxed = true;
589 return true;
590 }
591
592 // check if errors should be ignored
593 if ( 0 == strcmp( hostname, "IGNOREERRORS" ) )
594 {
595 ignoreErrors = true;
596 return true;
597 }
598
599 // replace "ALL" by hostname
600 else if ( 0 == strcmp( hostname, "ALL" ) )
601 {
602 hostname = GetMyHostName();
603 }
604
605 // replace "ANY" by 0
606 if ( 0 == strcmp( hostname, "ANY" ) )
607 hostname = NULL;
608 }
609
610 // look up hostname
611 nHostList hostList;
612 ANET_GetHostList( hostname, hostList, net_hostport );
613
614 if ( hostList.empty() )
615 {
616 // name lookup failures won't be tolerated here
617 #ifndef NOEXCEPT
618 if ( !ignoreErrors )
619 {
620 tString details( "Hostname lookup failed for " );
621 details += hostname ? hostname : "localhost";
622 details += " while trying to open listening sockets.";
623 throw nSocket::PermanentError( details );
624 }
625 #endif
626
627 // fallback for nonexceptional systems
628 if ( hostname )
629 con << "ANET_ListenOn: Could not resolve " << hostname << " to bind socket to its IPs.\n";
630 else
631 con << "ANET_ListenOn: Could not determine generic IP to bind socket on.\n";
632
633 return ignoreErrors;
634 }
635 bool ret = ANET_ListenOn( hostList, sockets, onesocketonly, ignoreErrors );
636
637 // in relaxed mode, only one socket needs to be opened ( the caller needs to check that finally ). Otherwise, all socket openings need to have succeeded.
638 return relaxed || ret;
639 }
640
641 class nColonRestaurator
642 {
643 public:
nColonRestaurator(char * colon)644 nColonRestaurator( char * colon ): colon_(colon){}
~nColonRestaurator()645 ~nColonRestaurator()
646 {
647 if ( colon_ )
648 *colon_ = ':';
649 }
650
651 char * colon_;
652 };
653
ANET_ListenOn(char * hostname,int net_hostport,nSocketListener::SocketArray & sockets,bool & onesocketonly,bool & relaxed,bool & ignoreErrors)654 bool ANET_ListenOn( char * hostname, int net_hostport, nSocketListener::SocketArray & sockets, bool & onesocketonly, bool & relaxed, bool & ignoreErrors )
655 {
656 // skip whitespace
657 while ( isblank( *hostname ) )
658 hostname ++;
659
660 // quit silently on empty hostname
661 if ( !*hostname )
662 return true;
663
664 // replace colon by null temporarily, add port offset to net_hostport
665 char * colon = NULL;
666 if ( hostname )
667 colon = strrchr (hostname, ':');
668 if ( colon )
669 {
670 *colon = 0;
671 net_hostport += atoi ( colon + 1 );
672 }
673
674 // don't forget to restore the colon when we're done here
675 nColonRestaurator restaurator( colon );
676
677 // delegate to function that does not modify the hostname
678 return ANET_ListenOnConst( hostname, net_hostport, sockets, onesocketonly, relaxed, ignoreErrors );
679 }
680
ANET_Listen(bool state,int net_hostport,const tString & net_hostip,nSocketListener::SocketArray & sockets)681 bool ANET_Listen (bool state, int net_hostport, const tString & net_hostip, nSocketListener::SocketArray & sockets )
682 {
683 sn_listen = state;
684
685 // enable listening
686 if (state)
687 {
688 // reset sockets if we are already listening
689 if (!sockets.empty())
690 ANET_Listen( false, net_hostport, net_hostip, sockets );
691
692 bool relaxed = false, onesocketonly = false, ignoreErrors = false;
693
694 // first try: generate sockets for explicitly requested IP
695 tString ips = net_hostip; // copy of the hostname string
696 int lastpos = 0; // position where the current IP starts
697 for ( int pos = 0; pos < ips.Len(); ++pos )
698 {
699 if (isblank(ips[pos]))
700 {
701 ips[pos] = '\0';
702 if ( pos > lastpos )
703 if ( !ANET_ListenOn( &ips[lastpos], net_hostport, sockets, onesocketonly, relaxed, ignoreErrors ) )
704 return false;
705 ips[pos] = ' ';
706 lastpos = pos + 1;
707 }
708 }
709 // don't forget the last IP entry
710 if ( ips.Len() > lastpos )
711 if ( !ANET_ListenOn( &ips[lastpos], net_hostport, sockets, onesocketonly, relaxed, ignoreErrors ) )
712 return false;
713
714 //#else
715 // old fallback code
716 // nSocket socket;
717 // socket.Open( net_hostport );
718 // sockets.push_back( socket );
719 //#endif
720
721 // report success or failure ( in relaxed mode when no socket was created )
722 return !relaxed || !sockets.empty();
723 }
724
725 // disable listening
726 if (sockets.empty())
727 return false;
728
729 // close sockets
730 for ( nSocketListener::SocketArray::iterator iter = sockets.begin(); iter != sockets.end(); ++iter )
731 {
732 (*iter).Close();
733 }
734 sockets.clear();
735
736 return true;
737 }
738
739 //=============================================================================
740
ANET_CloseSocket(int sock)741 int ANET_CloseSocket (int sock)
742 {
743 //if (sock == net_broadcastsocket)
744 // net_broadcastsocket = 0;
745 return close (sock);
746 }
747
748
749 //=============================================================================
750 /*
751 ============
752 PartialIPAddress
753
754 this lets you type only as much of the net address as required, using
755 the passed defaults to fill in the rest
756 ============
757 */
PartialIPAddress(const char * in,struct sockaddr * hostaddr,int default_port,int default_addr)758 static int PartialIPAddress (const char *in, struct sockaddr *hostaddr, int default_port, int default_addr )
759 {
760 char buff[256];
761 char *b;
762 int addr;
763 int num;
764 int mask;
765 int run;
766 int port;
767
768 buff[0] = '.';
769 b = buff;
770 strncpy(buff+1, in,254);
771 if (buff[1] == '.')
772 b++;
773
774 addr = 0;
775 mask=-1;
776 while (*b == '.')
777 {
778 b++;
779 num = 0;
780 run = 0;
781 while (!( *b < '0' || *b > '9'))
782 {
783 num = num*10 + *b++ - '0';
784 if (++run > 3)
785 return -1;
786 }
787 if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0)
788 return -1;
789 if (num < 0 || num > 255)
790 return -1;
791 mask<<=8;
792 addr = (addr<<8) + num;
793 }
794
795 if (*b++ == ':')
796 port = atoi(b);
797 else
798 port = default_port;
799
800 hostaddr->sa_family = AF_INET;
801 ((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port);
802 ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (default_addr & htonl(mask)) | htonl(addr);
803
804 return 0;
805 }
806
807 //=============================================================================
808
ANET_AddrToString(const struct sockaddr * addr)809 char *ANET_AddrToString (const struct sockaddr *addr)
810 {
811 static char buffer[23];
812 int haddr;
813
814 haddr = ntohl(((struct sockaddr_in const *)addr)->sin_addr.s_addr);
815 snprintf(buffer,22, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff, (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff, ntohs(((struct sockaddr_in const *)addr)->sin_port));
816 return buffer;
817 }
818
819 //=============================================================================
820
ANET_GetSocketAddr(int sock,struct sockaddr * addr)821 int ANET_GetSocketAddr (int sock, struct sockaddr *addr)
822 {
823 NET_SIZE addrlen = sizeof(struct sockaddr);
824 // unsigned int a;
825
826 memset(addr, 0, sizeof(struct sockaddr));
827 getsockname(sock, (struct sockaddr *)addr, &addrlen);
828 // a = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
829 //if (a == 0 || a == inet_addr("127.0.0.1"))
830 // ((struct sockaddr_in *)addr)->sin_addr.s_addr = 0x7f000001;
831
832 return 0;
833 }
834
835 //=============================================================================
836
837 /*
838 int ANET_AddrCompare (struct sockaddr *addr1, struct sockaddr *addr2)
839 {
840 if (addr1->sa_family != addr2->sa_family)
841 return -1;
842
843 if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
844 return -1;
845
846 if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port)
847 return 1;
848
849 return 0;
850 }
851 */
852
853 } // namespace
854
855 //=============================================================================
856
857
858 // *******************************************************************************************
859 // *
860 // * GetListener
861 // *
862 // *******************************************************************************************
863 //!
864 //! @return listening sockets
865 //!
866 // *******************************************************************************************
867
GetListener(void) const868 nSocketListener const & nBasicNetworkSystem::GetListener( void ) const
869 {
870 return this->listener_;
871 }
872
873 /*
874 // *******************************************************************************************
875 // *
876 // * GetListener
877 // *
878 // *******************************************************************************************
879 //!
880 //! @param listener listening sockets to fill
881 //! @return A reference to this to allow chaining
882 //!
883 // *******************************************************************************************
884
885 nBasicNetworkSystem const & nBasicNetworkSystem::GetListener( nSocketListener & listener ) const
886 {
887 listener = this->listener_;
888 return *this;
889 }
890
891 // *******************************************************************************************
892 // *
893 // * SetListener
894 // *
895 // *******************************************************************************************
896 //!
897 //! @param listener listening sockets to set
898 //! @return A reference to this to allow chaining
899 //!
900 // *******************************************************************************************
901
902 nBasicNetworkSystem & nBasicNetworkSystem::SetListener( nSocketListener const & listener )
903 {
904 this->listener_ = listener;
905 return *this;
906 }
907 */
908
909 // *******************************************************************************************
910 // *
911 // * accessListener
912 // * This function is dangerous; use only if you absolutely have to and do not store the returned reference longer than required.
913 // *
914 // *******************************************************************************************
915 //!
916 //! @return listening sockets as a modifiable reference
917 //!
918 // *******************************************************************************************
919
AccessListener(void)920 nSocketListener & nBasicNetworkSystem::AccessListener( void )
921 {
922 return this->listener_;
923 }
924
925 // *******************************************************************************************
926 // *
927 // * GetControlSocket
928 // *
929 // *******************************************************************************************
930 //!
931 //! @return network control socket
932 //!
933 // *******************************************************************************************
934
GetControlSocket(void) const935 nSocket const & nBasicNetworkSystem::GetControlSocket( void ) const
936 {
937 return this->controlSocket_;
938 }
939
940 /*
941 // *******************************************************************************************
942 // *
943 // * GetControlSocket
944 // *
945 // *******************************************************************************************
946 //!
947 //! @param controlSocket network control socket to fill
948 //! @return A reference to this to allow chaining
949 //!
950 // *******************************************************************************************
951
952 nBasicNetworkSystem const & nBasicNetworkSystem::GetControlSocket( nSocket & controlSocket ) const
953 {
954 controlSocket = this->controlSocket_;
955 return *this;
956 }
957
958 // *******************************************************************************************
959 // *
960 // * SetControlSocket
961 // *
962 // *******************************************************************************************
963 //!
964 //! @param controlSocket network control socket to set
965 //! @return A reference to this to allow chaining
966 //!
967 // *******************************************************************************************
968
969 nBasicNetworkSystem & nBasicNetworkSystem::SetControlSocket( nSocket const & controlSocket )
970 {
971 this->controlSocket_ = controlSocket;
972 return *this;
973 }
974 */
975
976 // *******************************************************************************************
977 // *
978 // * accessControlSocket
979 // * This function is dangerous; use only if you absolutely have to and do not store the returned reference longer than required.
980 // *
981 // *******************************************************************************************
982 //!
983 //! @return network control socket as a modifiable reference
984 //!
985 // *******************************************************************************************
986
AccessControlSocket(void)987 nSocket & nBasicNetworkSystem::AccessControlSocket( void )
988 {
989 return this->controlSocket_;
990 }
991
992 // *******************************************************************************************
993 // *******************************************************************************************
994 // *******************************************************************************************
995 // *******************************************************************************************
996 // *******************************************************************************************
997 // *******************************************************************************************
998 // *******************************************************************************************
999 // *******************************************************************************************
1000
1001 // *******************************************************************************************
1002 // *
1003 // * nAddress
1004 // *
1005 // *******************************************************************************************
1006 //!
1007 //!
1008 // *******************************************************************************************
1009
nAddress(void)1010 nAddress::nAddress( void )
1011 {
1012 // clear address data, it's only POD
1013 memset( &addr_, 0, size );
1014 addrLen_ = size;
1015
1016 // set to unspecific IP4 address
1017 addr_.addr_in.sin_addr.s_addr = INADDR_ANY;
1018 addr_.addr_in.sin_family = AF_INET;
1019 addr_.addr_in.sin_port = 0;
1020 }
1021
1022 // *******************************************************************************************
1023 // *
1024 // * ~nAddress
1025 // *
1026 // *******************************************************************************************
1027 //!
1028 //!
1029 // *******************************************************************************************
1030
~nAddress(void)1031 nAddress::~nAddress( void )
1032 {
1033 // nothing to clean up
1034 }
1035
1036 // *******************************************************************************************
1037 // *
1038 // * ToString
1039 // *
1040 // *******************************************************************************************
1041 //!
1042 //! @param string the string to fill
1043 //! @return reference to this for chaining
1044 //!
1045 // *******************************************************************************************
1046
ToString(tString & string) const1047 const nAddress & nAddress::ToString( tString & string ) const
1048 {
1049 if( addr_.addr_in.sin_addr.s_addr != INADDR_ANY )
1050 string = ANET_AddrToString( *this );
1051 else
1052 {
1053 string = "*.*.*.*";
1054 string << ":" << GetPort();
1055 }
1056 return *this;
1057 }
1058
1059 // *******************************************************************************************
1060 // *
1061 // * ToString
1062 // *
1063 // *******************************************************************************************
1064 //!
1065 //! @return the string represendation of the address
1066 //!
1067 // *******************************************************************************************
1068
ToString(void) const1069 tString nAddress::ToString( void ) const
1070 {
1071 // delegate
1072 tString ret;
1073 ToString( ret );
1074 return ret;
1075 }
1076
1077 // *******************************************************************************************
1078 // *
1079 // * FromString
1080 // *
1081 // *******************************************************************************************
1082 //!
1083 //! @param string the string represendation of the address
1084 //! @return 0 on success
1085 //!
1086 // *******************************************************************************************
1087
FromString(const char * string)1088 int nAddress::FromString( const char * string )
1089 {
1090 int ha1, ha2, ha3, ha4, hp;
1091 int ipaddr;
1092
1093 // parse IP address if the passed name looks like one
1094 if (string[0] >= '0' && string[0] <= '9')
1095 {
1096 // parse IP address
1097 sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
1098 ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
1099
1100 // store values in address
1101 addr_.addr .sa_family = AF_INET;
1102 addr_.addr_in.sin_addr.s_addr = htonl(ipaddr);
1103 addr_.addr_in.sin_port = htons(hp);
1104 return 0;
1105 }
1106 else
1107 {
1108 addr_.addr .sa_family = AF_INET;
1109
1110 // copy input string
1111 tString stringCopy ( string );
1112
1113 // find colon
1114 char * colon = const_cast< char * >( strrchr (stringCopy, ':') );
1115 if ( colon )
1116 {
1117 *colon = 0;
1118 // extract port
1119 SetPort( atoi( colon + 1 ) );
1120
1121 // extract hostname
1122 if ( stringCopy == "*.*.*.*" )
1123 addr_.addr_in.sin_addr.s_addr = INADDR_ANY;
1124 else
1125 SetHostname( stringCopy );
1126 *colon = ':';
1127
1128 return 0;
1129 }
1130 else
1131 {
1132 tERR_ERROR( "Invalid string representation ( IP:PORT ): " << string );
1133
1134 return -1;
1135 }
1136 }
1137 }
1138
1139 // *******************************************************************************************
1140 // *
1141 // * FromAddrInfo
1142 // *
1143 // *******************************************************************************************
1144 //!
1145 //! @param info the addrinfo structure to copy the address from
1146 //!
1147 // *******************************************************************************************
1148
1149 /*
1150 void nAddress::FromAddrInfo( const addrinfo & info )
1151 {
1152 #ifdef HAVE_ADDRINFO
1153 // check address size
1154 tASSERT( info.ai_addrlen <= size );
1155
1156 // copy the address over
1157 memcpy( &addr_, info.ai_addr, info.ai_addrlen );
1158
1159 // store length
1160 addrLen_ = info.ai_addrlen;
1161 #endif
1162 }
1163 */
1164
1165 // *******************************************************************************************
1166 // *
1167 // * FromHostent
1168 // *
1169 // *******************************************************************************************
1170 //!
1171 //! @param l length of address
1172 //! @param addr pointer to address
1173 //!
1174 // *******************************************************************************************
1175
FromHostent(int length,const char * addr)1176 void nAddress::FromHostent( int length, const char * addr )
1177 {
1178 // check address size
1179 tASSERT( length == 4 );
1180
1181 // copy the address over
1182 addr_.addr .sa_family = AF_INET;
1183 addr_.addr_in.sin_addr.s_addr = *reinterpret_cast< int const * >( addr );
1184
1185 // store length
1186 addrLen_ = sizeof( sockaddr_in );
1187 }
1188
1189 // *******************************************************************************************
1190 // *
1191 // * GetHostname
1192 // *
1193 // *******************************************************************************************
1194 //!
1195 //! @param hostname the hostname to fill
1196 //! @return reference to this for chaining
1197 //!
1198 // *******************************************************************************************
1199
GetHostname(tString & hostname) const1200 const nAddress & nAddress::GetHostname( tString & hostname ) const
1201 {
1202 // initialize networking at OS level
1203 sn_InitOSNetworking();
1204
1205 int haddr;
1206 haddr = ntohl(addr_.addr_in.sin_addr.s_addr);
1207
1208 hostname.Clear();
1209 hostname << ((haddr >> 24) & 0xff) << "." << ((haddr >> 16) & 0xff) << "." << ((haddr >> 8) & 0xff) << "." << (haddr & 0xff);
1210
1211 // read hostname from recording
1212 static char const * section = "HOSTBYADDR";
1213 if ( !tRecorder::PlaybackStrict( section, hostname ) )
1214 {
1215 struct hostent *hostentry;
1216
1217 hostentry = gethostbyaddr ( reinterpret_cast< const char * >( &addr_ ), size, AF_INET);
1218 if (hostentry)
1219 {
1220 hostname = tString( (char *)hostentry->h_name );
1221 }
1222 }
1223
1224 // write hostname to recording
1225 tRecorder::Record( section, hostname );
1226
1227 return *this;
1228 }
1229
1230 // *******************************************************************************************
1231 // *
1232 // * GetHostname
1233 // *
1234 // *******************************************************************************************
1235 //!
1236 //! @return the hostname part of the address
1237 //!
1238 // *******************************************************************************************
1239
GetHostname(void) const1240 tString nAddress::GetHostname( void ) const
1241 {
1242 tString ret;
1243 GetHostname( ret );
1244 return ret;
1245 }
1246
1247 // *******************************************************************************************
1248 // *
1249 // * SetHostname
1250 // *
1251 // *******************************************************************************************
1252 //!
1253 //! @param hostname the hostname to set
1254 //! @return reference to this for chaining
1255 //!
1256 // *******************************************************************************************
1257
SetHostname(const char * hostname)1258 nAddress & nAddress::SetHostname( const char * hostname )
1259 {
1260 // initialize networking at OS level
1261 sn_InitOSNetworking();
1262
1263 // parse IP address if the passed name looks like one
1264 if (hostname[0] >= '0' && hostname[0] <= '9')
1265 {
1266 PartialIPAddress (hostname, &addr_.addr, GetPort(), 0x7f000001 );
1267 return *this;
1268 }
1269
1270 // read address from recording
1271 static char const * section = "SINGLEHOSTNAME";
1272 if ( !tRecorder::PlaybackStrict( section, *this ) )
1273 {
1274 // look up hostname ( TODO: error handling )
1275 struct hostent *hostentry;
1276 hostentry = gethostbyname (hostname);
1277 if (hostentry)
1278 {
1279 // store values
1280 addr_.addr .sa_family = AF_INET;
1281 addr_.addr_in.sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
1282 }
1283 else
1284 {
1285 // invalidate
1286 *this = nAddress();
1287 }
1288 }
1289
1290 // write address to recording
1291 tRecorder::Record( section, *this );
1292
1293 return *this;
1294 }
1295
1296 // *******************************************************************************************
1297 // *
1298 // * GetAddress
1299 // *
1300 // *******************************************************************************************
1301 //!
1302 //! @param address the raw IP to fill
1303 //! @return reference to this for chaining
1304 //!
1305 // *******************************************************************************************
1306
GetAddress(tString & hostname) const1307 const nAddress & nAddress::GetAddress( tString & hostname ) const
1308 {
1309 // initialize networking at OS level
1310 sn_InitOSNetworking();
1311
1312 int haddr;
1313 haddr = ntohl(addr_.addr_in.sin_addr.s_addr);
1314
1315 hostname << ((haddr >> 24) & 0xff) << "." << ((haddr >> 16) & 0xff) << "." << ((haddr >> 8) & 0xff) << "." << (haddr & 0xff);
1316
1317 return *this;
1318 }
1319
1320 // *******************************************************************************************
1321 // *
1322 // * GetAddress
1323 // *
1324 // *******************************************************************************************
1325 //!
1326 //! @return the raw IP part of the address
1327 //!
1328 // *******************************************************************************************
1329
GetAddress(void) const1330 tString nAddress::GetAddress( void ) const
1331 {
1332 tString ret;
1333 GetAddress( ret );
1334 return ret;
1335 }
1336
1337 // *******************************************************************************************
1338 // *
1339 // * SetAddress
1340 // *
1341 // *******************************************************************************************
1342 //!
1343 //! @param address the raw IP to set
1344 //! @return reference to this for chaining
1345 //!
1346 // *******************************************************************************************
1347
SetAddress(const char * hostname)1348 nAddress & nAddress::SetAddress( const char * hostname )
1349 {
1350 // initialize networking at OS level
1351 sn_InitOSNetworking();
1352
1353 // parse IP address if the passed name looks like one
1354 tVERIFY(hostname[0] >= '0' && hostname[0] <= '9')
1355
1356 PartialIPAddress (hostname, &addr_.addr, GetPort(), 0x7f000001 );
1357 return *this;
1358 }
1359
1360 // *******************************************************************************************
1361 // *
1362 // * SetPort
1363 // *
1364 // *******************************************************************************************
1365 //!
1366 //! @param port the port to set
1367 //! @return reference to this for chaining
1368 //!
1369 // *******************************************************************************************
1370
SetPort(int port)1371 nAddress & nAddress::SetPort( int port )
1372 {
1373 // store the port
1374 addr_.addr_in.sin_port = htons(port);
1375
1376 return *this;
1377 }
1378
1379 // *******************************************************************************************
1380 // *
1381 // * GetPort
1382 // *
1383 // *******************************************************************************************
1384 //!
1385 //! @return port of this address
1386 //!
1387 // *******************************************************************************************
1388
GetPort(void) const1389 int nAddress::GetPort( void ) const
1390 {
1391 return ntohs(addr_.addr_in.sin_port);
1392 }
1393
1394 // *******************************************************************************************
1395 // *
1396 // * GetPort
1397 // *
1398 // *******************************************************************************************
1399 //!
1400 //! @param port port of this address to fill
1401 //! @return reference to this for chaining
1402 //!
1403 // *******************************************************************************************
1404
GetPort(int & port) const1405 const nAddress & nAddress::GetPort( int & port ) const
1406 {
1407 port = GetPort();
1408
1409 return *this;
1410 }
1411
1412
1413 // *******************************************************************************************
1414 // *
1415 // * IsSet
1416 // *
1417 // *******************************************************************************************
1418 //!
1419 //! @return true only if address was set to something valid
1420 //!
1421 // *******************************************************************************************
1422
IsSet() const1423 bool nAddress::IsSet () const
1424 {
1425 return addr_.addr_in.sin_addr.s_addr != INADDR_ANY;
1426 }
1427
1428 // *******************************************************************************************
1429 // *
1430 // * Compare
1431 // *
1432 // *******************************************************************************************
1433 //!
1434 //! @param a1 first address to compare
1435 //! @param a2 second address to compare
1436 //! @return
1437 //!
1438 // *******************************************************************************************
1439
Compare(const nAddress & a1,const nAddress & a2)1440 int nAddress::Compare( const nAddress & a1, const nAddress & a2 )
1441 {
1442 if (a1.addr_.addr.sa_family != a2.addr_.addr.sa_family)
1443 return -1;
1444
1445 if (a1.addr_.addr_in.sin_addr.s_addr != a2.addr_.addr_in.sin_addr.s_addr)
1446 return -1;
1447
1448 if (a1.addr_.addr_in.sin_port != a2.addr_.addr_in.sin_port)
1449 return 1;
1450
1451 return 0;
1452 }
1453
1454 // *******************************************************************************************
1455 // *
1456 // * GetAddressLength
1457 // *
1458 // *******************************************************************************************
1459 //!
1460 //! @return the length of the stored address
1461 //!
1462 // *******************************************************************************************
1463
GetAddressLength(void) const1464 unsigned int nAddress::GetAddressLength( void ) const
1465 {
1466 return this->addrLen_;
1467 }
1468
1469 // *******************************************************************************************
1470 // *******************************************************************************************
1471 // *******************************************************************************************
1472 // *******************************************************************************************
1473 // *******************************************************************************************
1474
1475 // *******************************************************************************************
1476 // *
1477 // * nSocket
1478 // *
1479 // *******************************************************************************************
1480 //!
1481 //!
1482 // *******************************************************************************************
1483
nSocket(void)1484 nSocket::nSocket( void )
1485 :socket_( -1 ), family_( PF_INET ), socktype_( SOCK_DGRAM ), protocol_( IPPROTO_UDP ), broadcast_( false )
1486 {
1487 }
1488
1489 // *******************************************************************************************
1490 // *
1491 // * ~nSocket
1492 // *
1493 // *******************************************************************************************
1494 //!
1495 //!
1496 // *******************************************************************************************
1497
~nSocket(void)1498 nSocket::~nSocket( void )
1499 {
1500 if ( IsOpen() )
1501 Close();
1502 }
1503
1504 // *******************************************************************************************
1505 // *
1506 // * Create
1507 // *
1508 // *******************************************************************************************
1509 //!
1510 //! @return 0 on success
1511 //!
1512 // *******************************************************************************************
1513
Create(void)1514 int nSocket::Create( void )
1515 {
1516 tASSERT( !IsOpen() );
1517
1518 // initialize networking at OS level
1519 sn_InitOSNetworking();
1520
1521 // open new socket
1522 socket_ = socket( family_, socktype_, protocol_ );
1523 if ( socket_ < 0 )
1524 return -1;
1525
1526 // set TOS to low latency ( see manpages getsockopt(2), ip(7) and socket(7) )
1527 // maybe this works for Windows, too?
1528 #ifndef WIN32
1529 char tos = IPTOS_LOWDELAY;
1530
1531 setsockopt( socket_, IPPROTO_IP, IP_TOS, &tos, sizeof(char) );
1532 #endif
1533
1534 // unblock it
1535 bool _true = true;
1536 return ioctl (socket_, FIONBIO, reinterpret_cast<char *>(&_true)) == -1;
1537 }
1538
1539 // archives the binding procedure
1540 static char const * recordingSection = "BIND";
1541
1542 template< class Archiver > class BindArchiver
1543 {
1544 public:
Archive(Archiver & archiver,nAddress & trueAddress)1545 static void Archive( Archiver & archiver, nAddress & trueAddress )
1546 {
1547 // byte-archive the address
1548 struct sockaddr * addr = static_cast< struct sockaddr * >( trueAddress );
1549 unsigned char * addr_char = reinterpret_cast< unsigned char *>( addr );
1550 for( int i = sizeof( sockaddr )-1; i>=0; --i )
1551 archiver.Archive( addr_char[i] ).DontSeparate();
1552
1553 archiver.Separator();
1554 }
1555
Archive(int & ret,nAddress & trueAddress)1556 static bool Archive( int & ret, nAddress & trueAddress )
1557 {
1558 // start archive block if archiving is active
1559 Archiver archive;
1560 if ( archive.Initialize( recordingSection ) )
1561 {
1562 archive.Archive( ret );
1563 archive.Archive( trueAddress );
1564 //Archive( archive, trueAddress );
1565
1566 return true;
1567 }
1568
1569 return false;
1570 }
1571 };
1572
1573 // *******************************************************************************************
1574 // *
1575 // * Bind
1576 // *
1577 // *******************************************************************************************
1578 //!
1579 //! @param addr address to bind to
1580 //! @return 0 on success
1581 //!
1582 // *******************************************************************************************
1583
Bind(nAddress const & addr)1584 int nSocket::Bind( nAddress const & addr )
1585 {
1586 tASSERT( IsOpen() );
1587
1588 // copy address
1589 address_ = addr;
1590
1591 int ret = 0;
1592
1593 // see if the process was archived; if yes, return without action
1594 if ( !BindArchiver< tPlaybackBlock >::Archive( ret, trueAddress_ ) )
1595 {
1596 // just delegate
1597 ret = bind( socket_, addr, addr.GetAddressLength() );
1598
1599 // read true address
1600 if ( 0 == ret )
1601 ANET_GetSocketAddr( socket_, trueAddress_ );
1602 }
1603
1604 // record the bind
1605 BindArchiver< tRecordingBlock >::Archive( ret, trueAddress_ );
1606
1607 if ( 0 == ret )
1608 {
1609 // report success
1610 #ifdef DEDICATED
1611 static nAddress nullAddress;
1612 if ( 0 == nAddress::Compare( trueAddress_, addr ) || 0 == nAddress::Compare( nullAddress, addr ) )
1613 con << "Bound socket to " << trueAddress_.ToString() << ".\n";
1614 else
1615 con << "Bound socket to " << trueAddress_.ToString() << " ( " << address_.ToString() << " was requested ).\n";
1616 #endif
1617
1618 return 0;
1619 }
1620 else
1621 {
1622 // con << "nSocket::Open: Failed to bind socket to " << addr.ToString() << ".\n";
1623
1624 // close the socket and report an error
1625 ANET_CloseSocket( socket_ );
1626 socket_ = -1;
1627
1628 // throw exception on fatal error
1629 #ifndef NOEXCEPT
1630 // name lookup failures won't be tolerated here
1631 if ( ANET_Error() == nSocketError_Reset )
1632 {
1633 tString details( "Unable to bind to " );
1634 details += address_.ToString();
1635 details += " because that is not an address of the local machine.";
1636 throw nSocket::PermanentError( details );
1637 }
1638 #endif
1639
1640 return -1;
1641 }
1642
1643 return ret;
1644 }
1645
1646 // *******************************************************************************************
1647 // *
1648 // * Open
1649 // *
1650 // *******************************************************************************************
1651 //!
1652 //! @param addr address to bind to
1653 //! @return 0 on success
1654 //!
1655 // *******************************************************************************************
1656
Open(nAddress const & addr)1657 int nSocket::Open( nAddress const & addr )
1658 {
1659 tASSERT( !IsOpen() );
1660
1661 // create
1662 if ( Create() != 0 )
1663 {
1664 return -2;
1665 }
1666
1667 // bind
1668 return Bind( addr );
1669 }
1670
1671 // *******************************************************************************************
1672 // *
1673 // * Open
1674 // *
1675 // *******************************************************************************************
1676 //!
1677 //! @return 0 on success
1678 //!
1679 // *******************************************************************************************
1680
Open(void)1681 int nSocket::Open( void )
1682 {
1683 // bind to unspecific IP
1684 nAddress addr;
1685 return Open( addr );
1686 }
1687
1688 // *******************************************************************************************
1689 // *
1690 // * Open
1691 // *
1692 // *******************************************************************************************
1693 //!
1694 //! @param port port to bind to
1695 //! @return 0 on success
1696 //!
1697 // *******************************************************************************************
1698
Open(int port)1699 int nSocket::Open( int port )
1700 {
1701 // bind to unspecific IP, but specific port
1702 nAddress addr;
1703 addr.SetPort( port );
1704 return Open( addr );
1705 }
1706
1707 // *******************************************************************************************
1708 // *
1709 // * Open
1710 // *
1711 // *******************************************************************************************
1712 //!
1713 //! @param addr address to bind to
1714 //! @return 0 on success
1715 //!
1716 // *******************************************************************************************
1717
1718 /*
1719 int nSocket::Open( const addrinfo & addr )
1720 {
1721 #ifdef HAVE_ADDRINFO
1722 tASSERT( !IsOpen() );
1723
1724 // copy socket type data
1725 family_ = addr.ai_family;
1726 socktype_ = addr.ai_socktype;
1727 protocol_ = addr.ai_protocol;
1728
1729 // open
1730 nAddress address;
1731 address.FromAddrInfo( addr );
1732 return Open( address );
1733 #endif
1734 return -1;
1735 }
1736 */
1737
1738 // *******************************************************************************************
1739 // *
1740 // * Open
1741 // *
1742 // *******************************************************************************************
1743 //!
1744 //! @param addr host info to take opening information from
1745 //! @return 0 on success
1746 //!
1747 // *******************************************************************************************
1748
Open(const nHostInfo & addr)1749 int nSocket::Open( const nHostInfo & addr )
1750 {
1751 tASSERT( !IsOpen() );
1752
1753 family_ = addr.type.family;
1754 socktype_ = addr.type.type;
1755 protocol_ = addr.type.protocol;
1756
1757 return Open( addr.address );
1758 }
1759
1760 // *******************************************************************************************
1761 // *
1762 // * Close
1763 // *
1764 // *******************************************************************************************
1765 //!
1766 //! @return 0 on success
1767 //!
1768 // *******************************************************************************************
1769
Close(void)1770 int nSocket::Close( void )
1771 {
1772 #ifdef DEDICATED
1773 if ( socket_ != -1 )
1774 con << "Closing socket bound to " << trueAddress_.ToString() << "\n";
1775 #endif
1776
1777 ANET_CloseSocket( socket_ );
1778 socket_ = -1;
1779 broadcast_ = false;
1780
1781 return 0;
1782 }
1783
1784 // *******************************************************************************************
1785 // *
1786 // * Reset
1787 // *
1788 // *******************************************************************************************
1789 //!
1790 //! @return
1791 //!
1792 // *******************************************************************************************
1793
Reset(void) const1794 void nSocket::Reset( void ) const
1795 {
1796 // logically, resetting is const. Physically not. const_cast is required.
1797 nSocket * reset = const_cast< nSocket * >( this );
1798
1799 // remember the true address bound to
1800 nAddress trueAddress = trueAddress_;
1801
1802 // try to reset a socket without disturbing the rest of the system
1803 reset->Close();
1804
1805 // store old address
1806 nAddress oldAddress = address_;
1807
1808 // first try: reopen with the same port as last time
1809 nAddress wishAddress = address_;
1810 wishAddress.SetPort( trueAddress.GetPort() );
1811 if ( 0 == reset->Open( wishAddress ) )
1812 return;
1813
1814 // second try: reopen with the same premises
1815 if ( 0 == reset->Open( oldAddress ) )
1816 return;
1817
1818 // last try: reopen with the last true address ( this is most probably wrong )
1819 reset->Open( trueAddress );
1820 }
1821
1822 // *******************************************************************************************
1823 // *
1824 // * IsOpen
1825 // *
1826 // *******************************************************************************************
1827 //!
1828 //! @return true if the socket is open, false otherwise
1829 //!
1830 // *******************************************************************************************
1831
IsOpen(void) const1832 bool nSocket::IsOpen( void ) const
1833 {
1834 return socket_ >= 0;
1835 }
1836
1837 // *******************************************************************************************
1838 // *
1839 // * Connect
1840 // *
1841 // *******************************************************************************************
1842 //!
1843 //! @param addr
1844 //! @return
1845 //!
1846 // *******************************************************************************************
1847
Connect(const nAddress & addr)1848 int nSocket::Connect( const nAddress & addr )
1849 {
1850 // not implemented, does not make sense here
1851 return 0;
1852 }
1853
1854 #ifdef DEBUG
1855 // reset sockets just for fun
1856 bool sn_ResetSocket = false;
ResetSocket(std::istream & s)1857 void ResetSocket( std::istream& s )
1858 {
1859 sn_ResetSocket = true;
1860 }
1861
1862 static tConfItemFunc sn_cireset ( "RESET_SOCKET", ResetSocket );
1863 #endif
1864
1865
1866 // static char const * recordingSectionConnect = "CONNECT";
1867
1868 // *******************************************************************************************
1869 // *
1870 // * CheckNewConnection
1871 // *
1872 // *******************************************************************************************
1873 //!
1874 //! @return the new socket if a connection is there or NULL
1875 //!
1876 // *******************************************************************************************
1877
CheckNewConnection(void) const1878 const nSocket * nSocket::CheckNewConnection( void ) const
1879 {
1880 tASSERT( IsOpen() );
1881
1882 int available=-1;
1883
1884 // see if the playback has anything to say
1885 //if ( tRecorder::Playback( recordingSectionConnect, available ) )
1886 // return this;
1887
1888 // always return this when recoring or playback are running
1889 if ( tRecorder::IsRunning() )
1890 return this;
1891
1892
1893 #ifdef DEBUG
1894 if ( sn_ResetSocket )
1895 {
1896 sn_ResetSocket = false;
1897 Reset();
1898 }
1899 #endif
1900
1901 // for ( SocketArray::iterator iter = sockets.begin(); iter != sockets.end(); ++iter )
1902 int ret = ioctl (socket_, FIONREAD, &available);
1903 if ( ret == -1)
1904 {
1905 switch ( ANET_Error() )
1906 {
1907 case nSocketError_Reset:
1908 Reset();
1909 break;
1910 case nSocketError_Ignore:
1911 break;
1912 default:
1913 Sys_Error ("UDP: ioctlsocket (FIONREAD) failed\n");
1914 break;
1915 }
1916 }
1917
1918 if ( ret >= 0 )
1919 {
1920 // record result
1921 // tRecorder::Record( recordingSectionConnect, available );
1922 return this;
1923 }
1924
1925 return NULL;
1926 }
1927
1928
1929 static char const * recordingSectionRead = "READ";
1930
1931 //! Read or write network read data
1932 template< class Archiver > class ReadArchiver
1933 {
1934 public:
Archive(int8 * buf,int & len,nAddress & addr)1935 static bool Archive( int8 * buf, int & len, nAddress & addr )
1936 {
1937 // start archive block if archiving is active
1938 Archiver archive;
1939 if( archive.Initialize( recordingSectionRead ) )
1940 {
1941 // archive length of message
1942 archive.Archive( len );
1943 if ( len < 0 )
1944 return true;
1945
1946 // archive source address
1947 // BindArchiver< Archiver >::Archive( archive, addr );
1948 archive.Archive( addr );
1949
1950 // archive data
1951 for( int i = 0; i < len; ++i )
1952 archive.Archive( buf[ i ] );
1953
1954 archive.Separator();
1955
1956 return true;
1957 }
1958
1959 return false;
1960 }
1961 };
1962
1963 #ifdef DEBUG
1964 static REAL sn_simulateReceivePacketLoss = 0;
1965 static tSettingItem<REAL> sn_sumulateReceivePacketLossConfig( "SIMULATE_RECEIVE_PACKET_LOSS", sn_simulateReceivePacketLoss );
1966 #endif
1967
1968 // *******************************************************************************************
1969 // *
1970 // * Read
1971 // *
1972 // *******************************************************************************************
1973 //!
1974 //! @param buf buffer to read to
1975 //! @param len maximum number of bytes to read
1976 //! @param addr the address where the data came from is stored here
1977 //! @return number of bytes truly read or something negative on failure
1978 //!
1979 // *******************************************************************************************
1980
Read(int8 * buf,int len,nAddress & addr) const1981 int nSocket::Read( int8 * buf, int len, nAddress & addr ) const
1982 {
1983 tASSERT( IsOpen() );
1984
1985 // return value: real number of bytes read
1986 int ret = 0;
1987
1988 static tReproducibleRandomizer randomizer;
1989 #ifdef DEBUG
1990 // pretend nothing was received
1991 if ( sn_simulateReceivePacketLoss > randomizer.Get() )
1992 return -1;
1993 #endif
1994
1995 // check playback
1996 if ( !ReadArchiver< tPlaybackBlock >::Archive( buf, ret, addr ) )
1997 {
1998
1999 #ifdef DEBUG
2000 if ( sn_ResetSocket )
2001 {
2002 sn_ResetSocket = false;
2003 Reset();
2004 }
2005 #endif
2006
2007 // really receive
2008 NET_SIZE addrlen = addr.GetAddressLength();
2009 ret = recvfrom (socket_, buf, len, 0, addr, &addrlen );
2010 tASSERT( addrlen <= static_cast< NET_SIZE >( addr.GetAddressLength() ) );
2011 }
2012
2013 // write recording
2014 ReadArchiver< tRecordingBlock >::Archive( buf, ret, addr );
2015
2016 if ( ret <= 0 )
2017 {
2018 switch ( ANET_Error() )
2019 {
2020 case nSocketError_Reset:
2021 {
2022 Reset();
2023 return -1;
2024 }
2025 break;
2026 case nSocketError_Ignore:
2027 return -1;
2028 break;
2029 }
2030 }
2031
2032 if ( ret >= 0 )
2033 {
2034 // con << "Read " << ret << " bytes from socket " << GetSocket() << ".\n";
2035 }
2036
2037 #ifdef PRINTPACKETS
2038 con << trueAddress_.ToString() << " << " << addr.ToString() << "\n";
2039 #endif
2040
2041 return ret;
2042 }
2043
2044 #ifdef DEBUG
2045 static REAL sn_simulateSendPacketLoss = 0;
2046 static tSettingItem<REAL> sn_sumulateSendPacketLossConfig( "SIMULATE_SEND_PACKET_LOSS", sn_simulateSendPacketLoss );
2047 #endif
2048
2049 // *******************************************************************************************
2050 // *
2051 // * Write
2052 // *
2053 // *******************************************************************************************
2054 //!
2055 //! @param buf pointer to data to send
2056 //! @param len length of data to send
2057 //! @param addr address to send data to
2058 //! @param addrlen length of address data structure
2059 //! @return the number of bytes sent or something negative on error
2060 //!
2061 // *******************************************************************************************
2062
Write(const int8 * buf,int len,const sockaddr * addr,int addrlen) const2063 int nSocket::Write( const int8 * buf, int len, const sockaddr * addr, int addrlen ) const
2064 {
2065 tASSERT( IsOpen() );
2066
2067 #ifdef DEBUG
2068 if ( sn_ResetSocket )
2069 {
2070 sn_ResetSocket = false;
2071 Reset();
2072 }
2073 #endif
2074
2075 int ret = 0;
2076
2077 // check if return value was archived
2078 static char const * section = "SEND";
2079 if ( !tRecorder::Playback( section, ret ) )
2080 {
2081 static tReproducibleRandomizer randomizer;
2082 #ifdef DEBUG
2083 // pretend send was successful in packet loss simulation
2084 if ( sn_simulateSendPacketLoss > randomizer.Get() )
2085 ret = len;
2086 else
2087 #endif
2088 {
2089 // don't send if a playback is running
2090 if ( !tRecorder::IsPlayingBack() )
2091 ret = sendto (socket_, buf, len, 0, addr, addrlen );
2092 }
2093 }
2094
2095 if ( ret < 0 )
2096 {
2097 // log error
2098 tRecorder::Record( section, ret );
2099
2100 // handle error
2101 switch ( ANET_Error() )
2102 {
2103 case nSocketError_Reset:
2104 {
2105 Reset();
2106 return -1;
2107 }
2108 break;
2109 case nSocketError_Ignore:
2110 return -1;
2111 break;
2112 }
2113 }
2114
2115 return ret;
2116 }
2117
2118 // *******************************************************************************************
2119 // *
2120 // * Write
2121 // *
2122 // *******************************************************************************************
2123 //!
2124 //! @param buf pointer to data to send
2125 //! @param len length of data to send
2126 //! @param addr address to send data to
2127 //! @return the number of bytes sent or something negative on error
2128 //!
2129 // *******************************************************************************************
2130
Write(const int8 * buf,int len,const nAddress & addr) const2131 int nSocket::Write( const int8 * buf, int len, const nAddress & addr ) const
2132 {
2133 #ifdef PRINTPACKETS
2134 con << trueAddress_.ToString() << " >> " << addr.ToString() << "\n";
2135 #endif
2136
2137 // delegate to low level write
2138 return Write( buf, len, addr, addr.GetAddressLength() );
2139 }
2140
2141 // *******************************************************************************************
2142 // *
2143 // * Broadcast
2144 // *
2145 // *******************************************************************************************
2146 //!
2147 //! @param buf pointer to data to send
2148 //! @param len length of data to send
2149 //! @param port port to broadcast on
2150 //! @return number of bytes truly send or something negative on error
2151 //!
2152 // *******************************************************************************************
2153
Broadcast(const char * buf,int len,unsigned int port) const2154 int nSocket::Broadcast( const char * buf, int len, unsigned int port ) const
2155 {
2156 tASSERT( IsOpen() );
2157
2158 if ( !broadcast_ )
2159 {
2160 int i = 1;
2161
2162 // make this socket broadcast capable
2163 if (setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0)
2164 {
2165 Con_Printf("Unable to make socket broadcast capable\n");
2166 return -1;
2167 }
2168
2169 broadcast_ = true;
2170 }
2171
2172 // prepare broadcasting address
2173 sockaddr_in broadcastaddr;
2174 broadcastaddr.sin_family = AF_INET;
2175 broadcastaddr.sin_addr.s_addr = INADDR_BROADCAST;
2176 broadcastaddr.sin_port = htons(port);
2177
2178 // delegate to usual write function
2179 return Write ( buf, len, reinterpret_cast< sockaddr *>( &broadcastaddr ), sizeof( sockaddr_in ) );
2180 }
2181
2182 // *******************************************************************************************
2183 // *
2184 // * GetAddress
2185 // *
2186 // *******************************************************************************************
2187 //!
2188 //! @return the address the socket is bound to
2189 //!
2190 // *******************************************************************************************
2191
GetAddress(void) const2192 const nAddress & nSocket::GetAddress( void ) const
2193 {
2194 return trueAddress_;
2195 }
2196
2197 // *******************************************************************************************
2198 // *
2199 // * GetAddress
2200 // *
2201 // *******************************************************************************************
2202 //!
2203 //! @param address the address that the socket is bound to to fill
2204 //! @return reference to this for chaining
2205 //!
2206 // *******************************************************************************************
2207
GetAddress(nAddress & address) const2208 const nSocket & nSocket::GetAddress( nAddress & address ) const
2209 {
2210 address = trueAddress_;
2211
2212 return *this;
2213 }
2214
2215 // *******************************************************************************************
2216 // *
2217 // * SetAddress
2218 // *
2219 // *******************************************************************************************
2220 //!
2221 //! @param address address the address that the socket should be bound to
2222 //! @return
2223 //!
2224 // *******************************************************************************************
2225
SetAddress(nAddress const & address)2226 nSocket & nSocket::SetAddress( nAddress const & address )
2227 {
2228 address_ = address;
2229 trueAddress_ = address;
2230
2231 return *this;
2232 }
2233
2234
2235 // *******************************************************************************************
2236 // *
2237 // * MoveFrom
2238 // *
2239 // *******************************************************************************************
2240 //!
2241 //! @param other socket to move data from
2242 //!
2243 // *******************************************************************************************
2244
MoveFrom(const nSocket & other)2245 void nSocket::MoveFrom( const nSocket & other )
2246 {
2247 // close this socket
2248 if ( IsOpen() )
2249 Close();
2250
2251
2252 // copy uncritical data
2253 address_ = other.address_;
2254 trueAddress_ = other.trueAddress_;
2255 family_ = other.family_;
2256 socktype_ = other.socktype_;
2257 protocol_ = other.protocol_;
2258 broadcast_ = other.broadcast_;
2259
2260 // move socket
2261 socket_ = other.socket_;
2262 const_cast< nSocket & >( other ).socket_ = -1;
2263 }
2264
2265 // *******************************************************************************************
2266 // *
2267 // * nSocket
2268 // *
2269 // *******************************************************************************************
2270 //!
2271 //! @param other socket to move data from
2272 //!
2273 // *******************************************************************************************
2274
nSocket(const nSocket & other)2275 nSocket::nSocket( const nSocket & other )
2276 {
2277 socket_ = -1;
2278 MoveFrom( other );
2279 }
2280
2281 // *******************************************************************************************
2282 // *
2283 // * operator =
2284 // *
2285 // *******************************************************************************************
2286 //!
2287 //! @param other socket to move data from
2288 //! @return reference to this
2289 //!
2290 // *******************************************************************************************
2291
operator =(const nSocket & other)2292 nSocket & nSocket::operator =( const nSocket & other )
2293 {
2294 MoveFrom( other );
2295 return *this;
2296 }
2297
2298 // *******************************************************************************************
2299 // *******************************************************************************************
2300 // *******************************************************************************************
2301 // *******************************************************************************************
2302 // *******************************************************************************************
2303
2304 // *******************************************************************************************
2305 // *
2306 // * nSocketListener
2307 // *
2308 // *******************************************************************************************
2309 //!
2310 //!
2311 // *******************************************************************************************
2312
nSocketListener(void)2313 nSocketListener::nSocketListener( void )
2314 : port_( 0 ), ipList_( "ANY" )
2315 {
2316 }
2317
2318 // *******************************************************************************************
2319 // *
2320 // * ~nSocketListener
2321 // *
2322 // *******************************************************************************************
2323 //!
2324 //!
2325 // *******************************************************************************************
2326
~nSocketListener(void)2327 nSocketListener::~nSocketListener( void )
2328 {
2329 // not really required since the sockets close themselves automatically, but stop listening anyway
2330 Listen( false );
2331 }
2332
2333 // *******************************************************************************************
2334 // *
2335 // * Listen
2336 // *
2337 // *******************************************************************************************
2338 //!
2339 //! @param state listening state ( on or off )
2340 //! @return true on success
2341 //!
2342 // *******************************************************************************************
2343
Listen(bool state)2344 bool nSocketListener::Listen( bool state )
2345 {
2346 bool ret = false;
2347 try{
2348 // delegate to helper function
2349 ret = ANET_Listen( state, port_, ipList_, sockets_ );
2350 }
2351 catch ( OneSocketOpened const & )
2352 {
2353 // only one socket was upened on user request; this counts as succes
2354 ret = true;
2355 }
2356
2357 // close sockets if opening failed
2358 if ( state && !ret )
2359 Listen( false );
2360
2361 // return result
2362 return ret;
2363 }
2364
2365 // *******************************************************************************************
2366 // *
2367 // * begin
2368 // *
2369 // *******************************************************************************************
2370 //!
2371 //! @return iterator to the beginning of the sockets
2372 //!
2373 // *******************************************************************************************
2374
begin(void) const2375 nSocketListener::iterator nSocketListener::begin( void ) const
2376 {
2377 return sockets_.begin();
2378 }
2379
2380 // *******************************************************************************************
2381 // *
2382 // * end
2383 // *
2384 // *******************************************************************************************
2385 //!
2386 //! @return iterator past the end of the sockets
2387 //!
2388 // *******************************************************************************************
2389
end(void) const2390 nSocketListener::iterator nSocketListener::end( void ) const
2391 {
2392 return sockets_.end();
2393 }
2394
2395 // *******************************************************************************************
2396 // *
2397 // * GetPort
2398 // *
2399 // *******************************************************************************************
2400 //!
2401 //! @return the network port to listen on
2402 //!
2403 // *******************************************************************************************
2404
GetPort(void) const2405 unsigned int nSocketListener::GetPort( void ) const
2406 {
2407 return this->port_;
2408 }
2409
2410 // *******************************************************************************************
2411 // *
2412 // * GetPort
2413 // *
2414 // *******************************************************************************************
2415 //!
2416 //! @param port the network port to listen on to fill
2417 //! @return A reference to this to allow chaining
2418 //!
2419 // *******************************************************************************************
2420
GetPort(unsigned int & port) const2421 nSocketListener const & nSocketListener::GetPort( unsigned int & port ) const
2422 {
2423 port = this->port_;
2424 return *this;
2425 }
2426
2427 // *******************************************************************************************
2428 // *
2429 // * SetPort
2430 // *
2431 // *******************************************************************************************
2432 //!
2433 //! @param port the network port to listen on to set
2434 //! @return A reference to this to allow chaining
2435 //!
2436 // *******************************************************************************************
2437
SetPort(unsigned int port)2438 nSocketListener & nSocketListener::SetPort( unsigned int port )
2439 {
2440 Listen( false );
2441
2442 this->port_ = port;
2443 return *this;
2444 }
2445
2446 // *******************************************************************************************
2447 // *
2448 // * GetIpList
2449 // *
2450 // *******************************************************************************************
2451 //!
2452 //! @return list of IPs to bind to
2453 //!
2454 // *******************************************************************************************
2455
GetIpList(void) const2456 tString const & nSocketListener::GetIpList( void ) const
2457 {
2458 return this->ipList_;
2459 }
2460
2461 // *******************************************************************************************
2462 // *
2463 // * GetIpList
2464 // *
2465 // *******************************************************************************************
2466 //!
2467 //! @param ipList list of IPs to bind to to fill
2468 //! @return A reference to this to allow chaining
2469 //!
2470 // *******************************************************************************************
2471
GetIpList(tString & ipList) const2472 nSocketListener const & nSocketListener::GetIpList( tString & ipList ) const
2473 {
2474 ipList = this->ipList_;
2475 return *this;
2476 }
2477
2478 // *******************************************************************************************
2479 // *
2480 // * SetIpList
2481 // *
2482 // *******************************************************************************************
2483 //!
2484 //! @param ipList list of IPs to bind to to set
2485 //! @return A reference to this to allow chaining
2486 //!
2487 // *******************************************************************************************
2488
SetIpList(tString const & ipList)2489 nSocketListener & nSocketListener::SetIpList( tString const & ipList )
2490 {
2491 Listen( false );
2492
2493 this->ipList_ = ipList;
2494 return *this;
2495 }
2496
2497 // *******************************************************************************************
2498 // *******************************************************************************************
2499 // *******************************************************************************************
2500 // *******************************************************************************************
2501 // *******************************************************************************************
2502 // *******************************************************************************************
2503
2504 // *******************************************************************************************
2505 // *
2506 // * nBasicNetworkSystem
2507 // *
2508 // *******************************************************************************************
2509 //!
2510 //!
2511 // *******************************************************************************************
2512
nBasicNetworkSystem(void)2513 nBasicNetworkSystem::nBasicNetworkSystem( void )
2514 {
2515 // nothing to do
2516 }
2517
2518 // *******************************************************************************************
2519 // *
2520 // * ~nBasicNetworkSystem
2521 // *
2522 // *******************************************************************************************
2523 //!
2524 //!
2525 // *******************************************************************************************
2526
~nBasicNetworkSystem(void)2527 nBasicNetworkSystem::~nBasicNetworkSystem( void )
2528 {
2529 // shut down the system
2530 Shutdown();
2531 }
2532
2533 // *******************************************************************************************
2534 // *
2535 // * Init
2536 // *
2537 // *******************************************************************************************
2538 //!
2539 //! @return
2540 //!
2541 // *******************************************************************************************
2542
Init()2543 nSocket * nBasicNetworkSystem::Init()
2544 {
2545 // test if network was already initialized
2546 if ( controlSocket_.IsOpen() )
2547 return &controlSocket_;
2548
2549 // initialize networking at OS level
2550 sn_InitOSNetworking();
2551
2552 if ( 0 != controlSocket_.Open() )
2553 Sys_Error("ANET_Init: Unable to open control socket\n");
2554
2555 return &controlSocket_;
2556
2557 //struct hostent *local;
2558 //char buff[MAXHOSTNAMELEN]="\0";
2559 //struct sockaddr addr;
2560 //char *colon;
2561
2562 /* not for armagetron
2563 if (COM_CheckParm ("-noudp"))
2564 return -1;
2565 */
2566
2567 // determine my name & address
2568 //int myAddr = 0;
2569 //int hostnameres = gethostname(buff, MAXHOSTNAMELEN);
2570 //if ( 0 == hostnameres )
2571 //{
2572 // local = gethostbyname(buff);
2573 // if ( local )
2574 // {
2575 // myAddr = *reinterpret_cast<int *>(local->h_addr_list[0]);
2576 // }
2577 // else
2578 // {
2579 // Con_Printf ("ANET_Init: Unable to determine IP adress.\n");
2580 // }
2581 //}
2582 //else
2583 //{
2584 // Con_Printf ("ANET_Init: Unable to determine hostname.\n");
2585 // }
2586
2587 // fallback: use loopback
2588 //if ( myAddr == 0 )
2589 //{
2590 // myAddr = inet_addr("127.0.0.1");
2591 //}
2592
2593 //tString hostname;
2594
2595 // if the armagetron hostname isn't set, set it to the clamped machine name
2596 //if (strcmp(hostname, "UNNAMED") == 0 && buff[0] && hostnameres == 0 )
2597 //{
2598 // buff[15] = 0;
2599 // hostname=buff;
2600 //}
2601
2602 //ANET_GetSocketAddr (controlSocket_, &addr);
2603 //my_tcpip_address=ANET_AddrToString (&addr);
2604 //colon = strrchr (my_tcpip_address, ':');
2605 //if (colon)
2606 // *colon = 0;
2607
2608 // Con_Printf("UDP Initialized\n");
2609 //tcpipAvailable = true;
2610
2611 }
2612
2613 // *******************************************************************************
2614 // *
2615 // * Select
2616 // *
2617 // *******************************************************************************
2618 //!
2619 //! @param dt the time in seconds to wait at max
2620 //! @return true if data came in
2621 //!
2622 // *******************************************************************************
2623
Select(REAL dt)2624 bool nBasicNetworkSystem::Select( REAL dt )
2625 {
2626 int retval = 0;
2627 static char const * section = "NETSELECT";
2628 if ( !tRecorder::PlaybackStrict( section, retval ) )
2629 {
2630 if ( controlSocket_.GetSocket() < 0 )
2631 {
2632 tDelay( int( dt * 1000000 ) );
2633 return false;
2634 }
2635
2636 fd_set rfds; // set of sockets to wathc
2637 struct timeval tv; // time value to pass to select()
2638
2639 FD_ZERO( &rfds );
2640
2641 // watch the control socket
2642 FD_SET( controlSocket_.GetSocket(), &rfds );
2643 // con << "Watching " << controlSocket_.GetSocket();
2644
2645 int max = controlSocket_.GetSocket();
2646
2647 // watch listening sockets
2648 for( nSocketListener::SocketArray::const_iterator iter = listener_.GetSockets().begin(); iter != listener_.GetSockets().end(); ++iter )
2649 {
2650 FD_SET( (*iter).GetSocket(), &rfds );
2651 if ( (*iter).GetSocket() > max )
2652 max = (*iter).GetSocket();
2653 // con << ", " << (*iter).GetSocket();
2654 }
2655
2656 // set time
2657 tv.tv_sec = static_cast< long int >( dt );
2658 tv.tv_usec = static_cast< long int >( (dt-tv.tv_sec)*1000000 );
2659
2660 // delegate to system select
2661 retval = select(max+1, &rfds, NULL, NULL, &tv);
2662 }
2663 tRecorder::Record( section, retval );
2664
2665 // con << " : " << retval << "\n";
2666
2667 // return result
2668 return ( retval > 0 );
2669 }
2670
2671 // *******************************************************************************************
2672 // *
2673 // * Shutdown
2674 // *
2675 // *******************************************************************************************
2676 //!
2677 //!
2678 // *******************************************************************************************
2679
Shutdown()2680 void nBasicNetworkSystem::Shutdown()
2681 {
2682 // stop listening
2683 listener_.Listen(false);
2684
2685 // close the control socket
2686 controlSocket_.Close();
2687 }
2688
2689
2690 // *******************************************************************************************
2691 // *
2692 // * PermanentError
2693 // *
2694 // *******************************************************************************************
2695 //!
2696 //!
2697 // *******************************************************************************************
2698
PermanentError(void)2699 nSocket::PermanentError::PermanentError( void )
2700 : description_( "No details available" )
2701 {
2702 }
2703
2704 // *******************************************************************************************
2705 // *
2706 // * PermanentError
2707 // *
2708 // *******************************************************************************************
2709 //!
2710 //! @param details
2711 //!
2712 // *******************************************************************************************
2713
PermanentError(const tString & details)2714 nSocket::PermanentError::PermanentError( const tString & details )
2715 : description_( details )
2716 {
2717 }
2718
2719 // *******************************************************************************************
2720 // *
2721 // * ~PermanentError
2722 // *
2723 // *******************************************************************************************
2724 //!
2725 //!
2726 // *******************************************************************************************
2727
~PermanentError(void)2728 nSocket::PermanentError::~PermanentError( void )
2729 {
2730 }
2731
2732 // *******************************************************************************************
2733 // *
2734 // * DoGetName
2735 // *
2736 // *******************************************************************************************
2737 //!
2738 //! @return
2739 //!
2740 // *******************************************************************************************
2741
DoGetName(void) const2742 tString nSocket::PermanentError::DoGetName( void ) const
2743 {
2744 return tString( "Permanent network error" );
2745 }
2746
2747 // *******************************************************************************************
2748 // *
2749 // * DoGetDescription
2750 // *
2751 // *******************************************************************************************
2752 //!
2753 //! @return
2754 //!
2755 // *******************************************************************************************
2756
DoGetDescription(void) const2757 tString nSocket::PermanentError::DoGetDescription( void ) const
2758 {
2759 return description_;
2760 }
2761
2762
2763