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 // extremely losely 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 #ifndef NET_SOCKET_H
35 #define NET_SOCKET_H
36 
37 #include <iostream>
38 #include "tConsole.h"
39 #include "tException.h"
40 #include <vector>
41 
42 class nScoket;
43 struct nHostInfo;
44 // struct addrinfo;
45 struct hostentry;
46 struct sockaddr;
47 
48 #ifdef WIN32
49 #include  <winsock.h>
50 #else
51 #include <sys/socket.h>
52 #include <netinet/in.h>
53 #endif
54 
55 typedef  char int8;
56 
57 //! union of supported internet addresses
58 union nAddressBase
59 {
60     struct sockaddr     addr;       //!< generic address
61     struct sockaddr_in  addr_in;    //!< IPV4 address
62     // struct sockaddr_in6 addr_in6;   //!< IPV6 address ( not supported yet )
63 };
64 
65 //! internet address
66 class nAddress
67 {
68 public:
69     nAddress();         //!< constructor
70     ~nAddress();        //!< destructor
71 
72     // these functions handle address representation in the form hostname:port
73     nAddress const & 	ToString    ( tString & string ) const   ; //!< turns address to complete string
74     tString 			ToString    ()                   const   ; //!< turns address to complete string
75     int    			 	FromString  ( const char * string )      ; //!< turns complete string into address
76 
77     //  void                FromAddrInfo( const addrinfo & info )    ; //!< copy address from addrinfo
78 
79     void                FromHostent ( int l, const char * addr ) ; //!< copy address from hostent data
80 
81     nAddress & 			SetHostname	( const char * hostname )    ; //!< Sets the hostname part of the address (with DNS lookup)
82     tString 			GetHostname	( void ) const               ; //!< Gets the hostname part of the address (with DNS lookup)
83     nAddress const & 	GetHostname	( tString & hostname ) const ; //!< Gets the hostname part of the address (with DNS lookup)
84 
85     nAddress & 			SetAddress	( const char * address )     ; //!< Sets the hostname part of the address
86     tString 			GetAddress	( void ) const               ; //!< Gets the hostname part of the address
87     nAddress const & 	GetAddress	( tString & address ) const  ; //!< Gets the hostname part of the address
88 
89     nAddress & 			SetPort		( int port )                 ; //!< Sets the port of the address
90     int 				GetPort		( void ) const               ; //!< Gets the port of the address
91     nAddress const & 	GetPort		( int & port ) const         ; //!< Gets the port of the address
92 
93     bool                IsSet       () const                     ; //!< returns true only if address is not INETADDR_ANY
94 
95     static int 	Compare ( const nAddress & a1, const nAddress & a2 );	//!< compares two addresses
96 
97     operator struct sockaddr *      ()       { return &addr_.addr; }   //!< conversion to sockaddr
98     operator struct sockaddr const *() const { return &addr_.addr; }   //!< conversion to sockaddr
99 
100     //! comparison operator
101     bool operator == ( nAddress const & other ) const
102     {
103         return Compare( *this, other ) == 0;
104     }
105 
106     //! comparison operator
107     bool operator != ( nAddress const & other ) const
108     {
109         return Compare( *this, other ) != 0;
110     }
111 
112     enum{ size = sizeof( nAddressBase ) };
113 
114     unsigned int GetAddressLength( void ) const;	//!< Gets the length of the stored address
115 private:
116     nAddressBase addr_;	    //!< the lowlevel network address
117     unsigned int addrLen_;  //!< the length of the really stored address
118 };
119 
120 //! wrapper for low level sockets.
121 class nSocket
122 {
123 public:
124     nSocket();          //!< constructor
125     ~nSocket();         //!< destructor
126 
127     //! exception thrown on probably unrecoverable error
128 class PermanentError: public tException
129     {
130     public:
131         PermanentError();                                       //!< default constructor
132         PermanentError( const tString & details );              //!< constructor giving details on error
133         ~PermanentError();                                      //!< destructor
134     private:
135         virtual tString DoGetName()         const;              //!< returns the name of the exception
136         virtual tString DoGetDescription()  const;              //!< returns a detailed description
137 
138         tString description_;
139     };
140 
141     int Open ();                            //!< open socket for sending data ( not bound to a specific IP or port )
142     int Open ( nAddress const & address );  //!< open socket for listening on the specified address info
143     int Open ( int port );                  //!< open socket for listening bound to the specified port
144     //  int Open ( const addrinfo & addr );     //!< open socket for listening on the specified address info
145     int Open ( const nHostInfo & addr );    //!< open socket for listening on the specified host info
146     int Close ();                           //!< close the socket
147     bool IsOpen () const;                   //!< returns whether the socket is open
148     void Reset () const;                    //!< resets ( closes and reopens ) the socket
149 
150     int Connect ( const nAddress & addr );          //!< connects the socket to the specified address
151     const nSocket * CheckNewConnection() const;     //!< listens for new data
152 
153     int Read        ( int8 *buf, int len, nAddress & addr )             const; //!< reads data from the socket
154     int Write       ( const int8 *buf, int len, const nAddress & addr ) const; //!< writes data to the socket
155     int Broadcast   ( const char *buf, int len, unsigned int port )     const; //!< broadcasts data over the socket to the LAN
156 
157     nAddress const &   GetAddress( void )                  const   ;	//!< Gets the address the socket is bound to
158     nSocket const &    GetAddress( nAddress & address )    const   ;	//!< Gets the address the socket is bound to
159 
160     inline int             GetSocket( void )         const; //!< Gets the raw socket
161     inline nSocket const & GetSocket( int & socket ) const;	//!< Gets the raw socket
162 
163     // moving copy semantics
164     void MoveFrom( const nSocket & other );       //!< move data from other to this
165     nSocket( const nSocket & other );             //!< copy constructor. Warning: uses data move semantics
166     nSocket & operator=( const nSocket & other ); //!< copy operator. Warning: uses data move semantics
167 private:
168     int Create ();                            //!< creates the socket without binding it
169     int Bind ( nAddress const & address );    //!< binds the socket to a specific address
170 
171     int Write       ( const int8 *buf, int len, const sockaddr * addr, int addrlen ) const; //!< writes data to the socket
172 
173     nSocket & SetAddress( nAddress const & address );  //!< Sets the address the socket is bound to
174     inline nSocket & SetSocket( int socket );	       //!< Sets the raw socket
175 
176     int socket_;            //!< the raw socket
177     nAddress address_;      //!< the address the socket is bound to
178     nAddress trueAddress_;  //!< the address the socket is really bound to
179     int family_, socktype_, protocol_;    //!< more low level data determining the socket type
180     mutable bool broadcast_;              //!< flag indicating whether this socket has been prepared for broadcasts
181 };
182 
183 //! collection of listening server sockets
184 class nSocketListener
185 {
186 public:
187     nSocketListener();      //!< constructor
188     ~nSocketListener();     //!< destructor
189 
190     bool Listen ( bool state );                                 //!< enables/disables listening state
191 
192     typedef std::vector< nSocket > SocketArray;                 //!< array of sockets
193     typedef SocketArray::const_iterator const_iterator;         //!< iterator in that array
194     typedef SocketArray::const_iterator iterator;               //!< iterator in that array
195 
196     // almost std:: compliant iterator functions
197     iterator begin() const;                                    //!< returns iterator to first socket
198     iterator end() const;                                      //!< returns iterator to end of sockets
199 
200     nSocketListener &       SetPort     ( unsigned int port );	        //!<  Sets the network port to listen on
201     unsigned int            GetPort     ( void ) const;	                //!< Gets the network port to listen on
202     nSocketListener const & GetPort     ( unsigned int & port ) const;	//!< Gets the network port to listen on
203     nSocketListener &       SetIpList   ( tString const & ipList );	    //!< Sets list of IPs to bind to
204     tString const &         GetIpList   ( void ) const;	                //!< Gets list of IPs to bind to
205     nSocketListener const & GetIpList   ( tString & ipList ) const;	    //!< Gets list of IPs to bind to
206     inline SocketArray const     & GetSockets ( void ) const;	                //!< Gets the listening sockets
207     inline nSocketListener const & GetSockets ( SocketArray & sockets ) const;	//!< Gets the listening sockets
208 private:
209     SocketArray  sockets_;   //!< the listening sockets
210     unsigned int port_;      //!< the network port to listen on
211     tString      ipList_;    //!< list of IPs to bind to
212 
213     // forbid copying
214     nSocketListener( const nSocketListener & );
215     nSocketListener & operator=( const nSocketListener & );
216 
217     inline nSocketListener & SetSockets( SocketArray const & sockets );	//!< Sets the listening sockets
218 };
219 
220 //! basic network system: manages sockets
221 class nBasicNetworkSystem
222 {
223 public:
224     nBasicNetworkSystem();              //!< constructor
225     ~nBasicNetworkSystem();             //!< destructor
226 
227     nSocket*  Init (void);              //!< initializes the network
228     void      Shutdown (void);          //!< shuts donw the network
229 
230     bool      Select (REAL dt);         //!< waits the specified time for data to arrive on the sockets
231 
232     nSocketListener &             AccessListener      ( void )                                ;	//!< Accesses listening sockets
233     nBasicNetworkSystem &         SetListener         ( nSocketListener const & listener )    ;	//!< Sets listening sockets
234     nSocketListener const &       GetListener         ( void ) const                          ;	//!< Gets listening sockets
235     // nBasicNetworkSystem const &   GetListener         ( nSocketListener & listener ) const    ;	//!< Gets listening sockets
236 
237     // nBasicNetworkSystem &         SetControlSocket    ( nSocket const & controlSocket )       ;	//!< Sets network control socket
238     nSocket const &               GetControlSocket    ( void ) const                          ;	//!< Gets network control socket
239     // nBasicNetworkSystem const &   GetControlSocket    ( nSocket & controlSocket ) const       ;	//!< Gets network control socket
240 private:
241 
242     nSocketListener listener_;          //!< listening sockets
243     nSocket         controlSocket_;     //!< network control socket
244 
245     // forbid copying
246     nBasicNetworkSystem( const nBasicNetworkSystem & );
247     nBasicNetworkSystem & operator=( const nBasicNetworkSystem & );
248 
249     nSocket &                     AccessControlSocket ( void )                                ; //!< Accesses network control socket
250 };
251 
252 // *******************************************************************************
253 // *
254 // *	GetSockets
255 // *
256 // *******************************************************************************
257 //!
258 //!		@return		the listening sockets
259 //!
260 // *******************************************************************************
261 
GetSockets(void)262 nSocketListener::SocketArray const & nSocketListener::GetSockets( void ) const
263 {
264     return this->sockets_;
265 }
266 
267 // *******************************************************************************
268 // *
269 // *	GetSockets
270 // *
271 // *******************************************************************************
272 //!
273 //!		@param	sockets	the listening sockets to fill
274 //!		@return		A reference to this to allow chaining
275 //!
276 // *******************************************************************************
277 
GetSockets(SocketArray & sockets)278 nSocketListener const & nSocketListener::GetSockets( SocketArray & sockets ) const
279 {
280     sockets = this->sockets_;
281     return *this;
282 }
283 
284 // *******************************************************************************
285 // *
286 // *	SetSockets
287 // *
288 // *******************************************************************************
289 //!
290 //!		@param	sockets	the listening sockets to set
291 //!		@return		A reference to this to allow chaining
292 //!
293 // *******************************************************************************
294 
SetSockets(SocketArray const & sockets)295 nSocketListener & nSocketListener::SetSockets( SocketArray const & sockets )
296 {
297     this->sockets_ = sockets;
298     return *this;
299 }
300 
301 // *******************************************************************************
302 // *
303 // *	GetSocket
304 // *
305 // *******************************************************************************
306 //!
307 //!		@return		the raw socket
308 //!
309 // *******************************************************************************
310 
GetSocket(void)311 int nSocket::GetSocket( void ) const
312 {
313     return this->socket_;
314 }
315 
316 // *******************************************************************************
317 // *
318 // *	GetSocket
319 // *
320 // *******************************************************************************
321 //!
322 //!		@param	socket	the raw socket to fill
323 //!		@return		A reference to this to allow chaining
324 //!
325 // *******************************************************************************
326 
GetSocket(int & socket)327 nSocket const & nSocket::GetSocket( int & socket ) const
328 {
329     socket = this->socket_;
330     return *this;
331 }
332 
333 // *******************************************************************************
334 // *
335 // *	SetSocket
336 // *
337 // *******************************************************************************
338 //!
339 //!		@param	socket	the raw socket to set
340 //!		@return		A reference to this to allow chaining
341 //!
342 // *******************************************************************************
343 
SetSocket(int socket)344 nSocket & nSocket::SetSocket( int socket )
345 {
346     this->socket_ = socket;
347     return *this;
348 }
349 
350 #endif
351