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