fgms 0.11.8
The
FlightGear MultiPlayer Server
project
netSocket.cxx
Go to the documentation of this file.
1 /**
2  PLIB - A Suite of Portable Game Libraries
3  Copyright (C) 1998,2002 Steve Baker
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Library General Public License for more details.
14 
15  You should have received a copy of the GNU Library General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 
19  For further information visit http://plib.sourceforge.net
20 
21  $Id: netSocket.cxx,v 1.1.1.1 2007/06/12 10:10:24 oliver Exp $
22 */
23 
24 #include "netSocket.h"
25 
26 #if defined(UL_CYGWIN) || !defined (UL_WIN32)
27 
28 #if defined(UL_MAC_OSX)
29 # include <netinet/in.h>
30 #endif
31 
32 #include <iostream>
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
37 #include <time.h>
38 #include <sys/time.h> /* Need both for Mandrake 8.0!! */
39 #include <unistd.h>
40 #include <netdb.h>
41 #include <fcntl.h>
42 
43 #else
44 
45 #include <iostream>
46 #include <winsock2.h>
47 #include <stdarg.h>
48 
49 #endif
50 
51 #if defined(UL_MSVC) && !defined(socklen_t)
52 #define socklen_t int
53 #endif
54 
55 /* Paul Wiltsey says we need this for Solaris 2.8 */
56 
57 #ifndef INADDR_NONE
58 #define INADDR_NONE ((unsigned long)-1)
59 #endif
60 
61 #ifndef MSG_NOSIGNAL
62  #define MSG_NOSIGNAL 0
63 #endif
64 
65 using namespace std;
66 
67 netAddress::netAddress ( const char* host, int port )
68 {
69  set ( host, port ) ;
70 }
71 
72 
73 void netAddress::set ( const char* host, int port )
74 {
75  memset(this, 0, sizeof(netAddress));
76 
77 #if __FreeBSD__
78  sin_len = sizeof(netAddress);
79 #endif
80  sin_family = AF_INET ;
81  sin_port = htons (port);
82  sin_addr = INADDR_ANY;
83 
84  /* Convert a string specifying a host name or one of a few symbolic
85  ** names to a numeric IP address. This usually calls gethostbyname()
86  ** to do the work; the names "" and "<broadcast>" are special.
87  */
88 
89  if (host[0] == '\0')
90  sin_addr = INADDR_ANY;
91  else
92  if (host[0] == '<' && strcmp(host, "<broadcast>") == 0)
93  sin_addr = INADDR_BROADCAST;
94  else
95  {
96  sin_addr = inet_addr ( host ) ;
97 
98  if ( sin_addr == INADDR_NONE )
99  {
100  struct hostent *hp = gethostbyname ( host ) ;
101  if ( hp != NULL )
102  {
103  memcpy ( (char *) &sin_addr, hp->h_addr, hp->h_length ) ;
104  }
105  else
106  {
107  sin_addr = INADDR_ANY ;
108  }
109  }
110  }
111 }
112 
114 {
115  sin_port = htons (port);
116 }
117 
118 /**
119  * @brief Create a string object representing an IP address.
120  * This is always a string of the form 'dd.dd.dd.dd' (with variable
121  * size numbers).
122  */
123 const string netAddress::getHost () const
124 {
125  long x = ntohl(sin_addr);
126  string result = NumToStr ((x>>24) & 0xff, 0) + ".";
127  result += NumToStr ((x>>16) & 0xff, 0) + ".";
128  result += NumToStr ((x>> 8) & 0xff, 0) + ".";
129  result += NumToStr ((x>> 0) & 0xff, 0);
130  return result;
131 }
132 
133 unsigned int
135 {
136  return sin_addr;
137 }
138 /**
139  * @brief Return the port no as int */
140 unsigned int netAddress::getPort() const
141 {
142  return ntohs(sin_port);
143 }
144 
145 unsigned int
147 {
148  return sin_family;
149 }
150 
152 {
153  //gethostbyname(gethostname())
154 
155  char buf[256];
156  memset(buf, 0, sizeof(buf));
157  gethostname(buf, sizeof(buf)-1);
158  const hostent *hp = gethostbyname(buf);
159 
160  if (hp && *hp->h_addr_list)
161  {
162  in_addr addr = *((in_addr*)*hp->h_addr_list);
163  const char* host = inet_ntoa(addr);
164 
165  if ( host )
166  return host ;
167  }
168 
169  return "127.0.0.1" ;
170 }
171 
172 
174 {
175  return sin_addr == INADDR_BROADCAST;
176 }
177 
178 bool netAddress::operator == (const netAddress& Value) const
179 {
180  if ((this->sin_family == Value.sin_family)
181  && (this->sin_addr == Value.sin_addr))
182  return (true);
183  return (false);
184 }
185 
186 bool netAddress::operator != (const netAddress& Value) const
187 {
188  if ((this->sin_family == Value.sin_family)
189  && (this->sin_addr == Value.sin_addr))
190  return (false);
191  return (true);
192 }
193 
195 {
196 
197  this->sin_family = Value.sin_family;
198  this->sin_port = Value.sin_port;
199  this->sin_addr = Value.sin_addr;
200  for (int i=0; i<8; i++)
201  this->sin_zero[i] = Value.sin_zero[i];
202 }
203 
205 {
206  handle = -1 ;
207  isStream = false;
208 }
209 
210 
212 {
213  close () ;
214 }
215 
216 
217 void netSocket::setHandle (int _handle)
218 {
219  close () ;
220  handle = _handle ;
221 }
222 
223 
224 bool netSocket::open ( bool stream )
225 {
226  close () ;
227  handle = ::socket ( AF_INET, (stream? SOCK_STREAM: SOCK_DGRAM), 0 ) ;
228  isStream = stream;
229  return (handle != -1);
230 }
231 
232 
233 void netSocket::setBlocking ( bool blocking )
234 {
235  assert ( handle != -1 ) ;
236 
237 #if defined(UL_CYGWIN) || !defined (UL_WIN32)
238 
239  int delay_flag = ::fcntl (handle, F_GETFL, 0);
240 
241  if (blocking)
242  delay_flag &= (~O_NDELAY);
243  else
244  delay_flag |= O_NDELAY;
245 
246  ::fcntl (handle, F_SETFL, delay_flag);
247 
248 #else
249 
250  u_long nblocking = blocking? 0: 1;
251  ::ioctlsocket(handle, FIONBIO, &nblocking);
252 
253 #endif
254 }
255 
256 
257 void netSocket::setSockOpt ( int SocketOption, bool Set )
258 {
259  assert ( handle != -1 ) ;
260  int result;
261  if ( Set == true ) {
262  int one = 1;
263 #ifdef UL_WIN32
264  result = ::setsockopt( handle, SOL_SOCKET, SocketOption, (char*)&one, sizeof(one) );
265 #else
266  result = ::setsockopt( handle, SOL_SOCKET, SocketOption, &one, sizeof(one) );
267 #endif
268  } else {
269  result = ::setsockopt( handle, SOL_SOCKET, SocketOption, NULL, 0 );
270  }
271  if ( result < 0 ) {
272  perror("set sockopt:");
273  }
274  assert ( result != -1 );
275 }
276 
277 void netSocket::setBroadcast ( bool broadcast )
278 {
279  assert ( handle != -1 ) ;
280  int result;
281  if ( broadcast ) {
282  int one = 1;
283 #ifdef UL_WIN32
284  result = ::setsockopt( handle, SOL_SOCKET, SO_BROADCAST, (char*)&one, sizeof(one) );
285 #else
286  result = ::setsockopt( handle, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one) );
287 #endif
288  } else {
289  result = ::setsockopt( handle, SOL_SOCKET, SO_BROADCAST, NULL, 0 );
290  }
291  if ( result < 0 ) {
292  perror("set broadcast:");
293  }
294  assert ( result != -1 );
295 }
296 
297 
298 int netSocket::bind ( const char* host, int port )
299 {
300  assert ( handle != -1 ) ;
301  netAddress addr ( host, port ) ;
302  return ::bind(handle,(const sockaddr*)&addr,sizeof(netAddress));
303 }
304 
305 
306 int netSocket::listen ( int backlog )
307 {
308  assert ( handle != -1 ) ;
309  return ::listen(handle,backlog);
310 }
311 
312 
314 {
315  assert ( handle != -1 ) ;
316 
317  if ( addr == NULL )
318  {
319  return ::accept(handle,NULL,NULL);
320  }
321  else
322  {
323  socklen_t addr_len = (socklen_t) sizeof(netAddress) ;
324  return ::accept(handle,(sockaddr*)addr,&addr_len);
325  }
326 }
327 
328 
329 int netSocket::connect ( const char* host, int port )
330 {
331  assert ( handle != -1 ) ;
332  netAddress addr ( host, port ) ;
333  if ( addr.getBroadcast() ) {
334  setBroadcast( true );
335  }
336  return ::connect(handle,(const sockaddr*)&addr,sizeof(netAddress));
337 }
338 
339 int netSocket::write_str ( const char* str, int len )
340 {
341  char* p = (char*) str;
342  int left = len;
343  int written = 0;
344 
345  while (left > 0)
346  {
347  written = ::send (handle, p, left, MSG_NOSIGNAL);
348  if (written == SOCKET_ERROR)
349  {
350  if (RECOVERABLE_ERROR)
351  written = 0;
352  else
353  return -1;
354  }
355  left -= written;
356  p += written;
357  }
358  return len;
359 }
360 
361 int netSocket::write_str ( const string& str )
362 {
363  return write_str (str.c_str(), str.length());
364 }
365 
366 int netSocket::write_char ( const char& c )
367 {
368  return ::send (handle, &c, 1, 0);
369 }
370 
371 int netSocket::send (const void * buffer, int size, int flags)
372 {
373  assert ( handle != -1 ) ;
374  return ::send (handle, (const char*)buffer, size, flags);
375 }
376 
377 
378 int netSocket::sendto ( const void * buffer, int size,
379  int flags, const netAddress* to )
380 {
381  assert ( handle != -1 ) ;
382  return ::sendto(handle,(const char*)buffer,size,flags,
383  (const sockaddr*)to,sizeof(netAddress));
384 }
385 
386 int netSocket::read_char ( unsigned char& c )
387 {
388  int n;
389  while (1)
390  {
391  n = ::recv (handle, (char *)&c, 1, 0 );
392  if (n == SOCKET_ERROR)
393  {
394  if (RECOVERABLE_ERROR)
395  continue;
396  return -1;
397  }
398  return n;
399  }
400  return n;
401 }
402 
403 int netSocket::recv (void * buffer, int size, int flags)
404 {
405  assert ( handle != -1 ) ;
406  return ::recv (handle, (char*)buffer, size, flags);
407 }
408 
409 
410 int netSocket::recvfrom ( void * buffer, int size,
411  int flags, netAddress* from )
412 {
413  assert ( handle != -1 ) ;
414  socklen_t fromlen = (socklen_t) sizeof(netAddress) ;
415  return ::recvfrom(handle,(char*)buffer,size,flags,(sockaddr*)from,&fromlen);
416 }
417 
418 
419 void netSocket::close (void)
420 {
421  if ( handle != -1 )
422  {
423 #if defined(UL_CYGWIN) || !defined (UL_WIN32)
424  errno = 0;
425  if (::close( handle ) != 0)
426  {
427  printf ("netSocket::close: %s\n", strerror (errno));
428  }
429 #else
430  ::closesocket( handle );
431 #endif
432  handle = -1 ;
433  }
434 }
435 
437 {
438  if ( handle != -1 )
439  {
440 #if defined(UL_CYGWIN) || !defined (UL_WIN32)
441  if (isStream)
442  {
443  errno = 0;
444  if (::shutdown (handle, SHUT_RDWR) != 0)
445  {
446  printf ("netSocket::shutdown: %s on fd %u\n", strerror (errno),
447  handle);
448  }
449  }
450 #endif
451  handle = -1 ;
452  }
453 }
454 
455 
457 {
458 #if defined(UL_CYGWIN) || !defined (UL_WIN32)
459  switch (errno) {
460  case EWOULDBLOCK: // always == NET_EAGAIN?
461  case EALREADY:
462  case EINPROGRESS:
463  return true;
464  }
465  return false;
466 #else
467  int wsa_errno = WSAGetLastError();
468  if ( wsa_errno != 0 )
469  {
470  WSASetLastError(0);
471  switch (wsa_errno) {
472  case WSAEWOULDBLOCK: // always == NET_EAGAIN?
473  case WSAEALREADY:
474  case WSAEINPROGRESS:
475  return true;
476  }
477  printf("WARNING: WSAGetLastError() = %d",wsa_errno);
478  }
479  return false;
480 #endif
481 }
482 
483 
484 //////////////////////////////////////////////////////////////////////
485 //
486 //
487 //
488 //////////////////////////////////////////////////////////////////////
489 int netSocket::select ( netSocket** reads, netSocket** writes, int timeout )
490 {
491  fd_set r,w;
492  int retval;
493  FD_ZERO (&r);
494  FD_ZERO (&w);
495  int i;
496  int num = 0 ;
497  if ((reads == 0) || (reads[0] == 0))
498  return (0);
499  if (reads)
500  {
501  for ( i=0; reads[i]; i++ )
502  {
503  int fd = reads[i]->getHandle();
504  FD_SET (fd, &r);
505  num++;
506  }
507  }
508  if (writes)
509  {
510  for ( i=0; writes[i]; i++ )
511  {
512  int fd = writes[i]->getHandle();
513  FD_SET (fd, &w);
514  num++;
515  }
516  }
517  if (!num)
518  return num ;
519  /* Set up the timeout */
520  struct timeval tv ;
521  /*
522  tv.tv_sec = timeout/1000;
523  tv.tv_usec = (timeout%1000)*1000;
524  */
525  tv.tv_sec = timeout;
526  tv.tv_usec = 0;
527  // It bothers me that select()'s first argument does not appear to
528  // work as advertised... [it hangs like this if called with
529  // anything less than FD_SETSIZE, which seems wasteful?]
530  // Note: we ignore the 'exception' fd_set - I have never had a
531  // need to use it. The name is somewhat misleading - the only
532  // thing I have ever seen it used for is to detect urgent data -
533  // which is an unportable feature anyway.
534  retval = ::select (FD_SETSIZE, &r, &w, 0, &tv);
535  if (retval <= 0) // timeout or error
536  return retval;
537  //remove sockets that had no activity
538  num = 0 ;
539  if (reads)
540  {
541  for ( i=0; reads[i]; i++ )
542  {
543  int fd = reads[i]->getHandle();
544  if (! FD_ISSET (fd, &r)) {
545  reads[i] = 0;
546  }
547  else
548  num++;
549  }
550  reads[i] = NULL ;
551  }
552  if (writes)
553  {
554  for ( i=0; writes[i]; i++ )
555  {
556  int fd = writes[i]->getHandle();
557  if (! FD_ISSET (fd, &w)) {
558  writes[i] = 0;
559  }
560  else
561  num++;
562  }
563  writes[i] = NULL ;
564  }
565  return num ;
566 }
567 
568 /* Init/Exit functions */
569 
570 static void netExit ( void )
571 {
572 #if defined(UL_CYGWIN) || !defined (UL_WIN32)
573 #else
574  /* Clean up windows networking */
575  if ( WSACleanup() == SOCKET_ERROR ) {
576  if ( WSAGetLastError() == WSAEINPROGRESS ) {
577  WSACancelBlockingCall();
578  WSACleanup();
579  }
580  }
581 #endif
582 }
583 
584 
585 int netInit ()
586 {
587  assert ( sizeof(sockaddr_in) == sizeof(netAddress) ) ;
588 
589 #if defined(UL_CYGWIN) || !defined (UL_WIN32)
590 #else
591  /* Start up the windows networking */
592  WORD version_wanted = MAKEWORD(1,1);
593  WSADATA wsaData;
594 
595  if ( WSAStartup(version_wanted, &wsaData) != 0 ) {
596  printf("Couldn't initialize Winsock 1.1\n");
597  return(-1);
598  }
599 #endif
600 
601  atexit( netExit ) ;
602  return(0);
603 }
604 
605 
606 const char* netFormat ( const char* format, ... )
607 {
608  static char buffer[ 256 ];
609  va_list argptr;
610  va_start(argptr, format);
611  vsprintf( buffer, format, argptr );
612  va_end(argptr);
613  return( buffer );
614 }
615 
616 #if defined(UL_WIN32)
617 #ifndef SPRTF
618 #define SPRTF printf
619 #endif
620 // get a message from the system for this error value
621 char *get_errmsg_text( int err )
622 {
623  LPSTR ptr = 0;
624  DWORD fm = FormatMessage(
625  FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
626  NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&ptr, 0, NULL );
627  if (ptr) {
628  size_t len = strlen(ptr);
629  while(len--) {
630  if (ptr[len] > ' ') break;
631  ptr[len] = 0;
632  }
633  if (len) return ptr;
634  LocalFree(ptr);
635  }
636  return NULL;
637 }
638 
639 void win_wsa_perror( char * msg )
640 {
641  int err = WSAGetLastError();
642  LPSTR ptr = get_errmsg_text(err);
643  if (ptr) {
644  SPRTF("%s = %s (%d)\n", msg, ptr, err);
645  LocalFree(ptr);
646  } else {
647  SPRTF("%s %d\n", msg, err);
648  }
649 }
650 
651 #endif /* UL_WIN32 */
unsigned int getPort() const
Return the port no as int.
Definition: netSocket.cxx:140
int getHandle() const
Definition: netSocket.h:135
#define RECOVERABLE_ERROR
Definition: netSocket.h:79
#define INADDR_NONE
Definition: netSocket.cxx:58
int sendto(const void *buffer, int size, int flags, const netAddress *to)
Definition: netSocket.cxx:378
void set(const char *host, int port)
Definition: netSocket.cxx:73
int accept(netAddress *addr)
Definition: netSocket.cxx:313
Socket type.
Definition: netSocket.h:125
unsigned int getFamily() const
Definition: netSocket.cxx:146
unsigned int getIP() const
Definition: netSocket.cxx:134
unsigned int sin_addr
Definition: netSocket.h:98
void close(void)
Definition: netSocket.cxx:419
void setHandle(int handle)
Definition: netSocket.cxx:217
#define MSG_NOSIGNAL
Definition: netSocket.cxx:62
bool operator!=(const netAddress &Value) const
Definition: netSocket.cxx:186
bool open(bool stream=true)
Definition: netSocket.cxx:224
void operator=(const netAddress &Value)
Definition: netSocket.cxx:194
int read_char(unsigned char &c)
Definition: netSocket.cxx:386
void shutdown(void)
Definition: netSocket.cxx:436
unsigned short sin_port
Definition: netSocket.h:97
int send(const void *buffer, int size, int flags=0)
Definition: netSocket.cxx:371
string NumToStr(T n_Number, int n_Precision=2, int n_Base=10)
Convert a number to string.
Definition: fg_util.hxx:193
int bind(const char *host, int port)
Definition: netSocket.cxx:298
bool operator==(const netAddress &Value) const
Definition: netSocket.cxx:178
int listen(int backlog)
Definition: netSocket.cxx:306
int recv(void *buffer, int size, int flags=0)
Definition: netSocket.cxx:403
#define SOCKET_ERROR
Definition: netSocket.h:80
const char * netFormat(const char *format,...)
Definition: netSocket.cxx:606
static int select(netSocket **reads, netSocket **writes, int timeout)
Definition: netSocket.cxx:489
int write_str(const char *str, int len)
Definition: netSocket.cxx:339
static void netExit(void)
Definition: netSocket.cxx:570
int connect(const char *host, int port)
Definition: netSocket.cxx:329
void setPort(int port)
Definition: netSocket.cxx:113
static bool isNonBlockingError()
Definition: netSocket.cxx:456
static char * port
Definition: server.c:69
static const char * getLocalHost()
Definition: netSocket.cxx:151
bool getBroadcast() const
Definition: netSocket.cxx:173
int recvfrom(void *buffer, int size, int flags, netAddress *from)
Definition: netSocket.cxx:410
void setBlocking(bool blocking)
Definition: netSocket.cxx:233
void setSockOpt(int SocketOption, bool Set)
Definition: netSocket.cxx:257
char sin_zero[8]
Definition: netSocket.h:100
int netInit()
Definition: netSocket.cxx:585
void setBroadcast(bool broadcast)
Definition: netSocket.cxx:277
int write_char(const char &c)
Definition: netSocket.cxx:366
const std::string getHost() const
Create a string object representing an IP address. This is always a string of the form 'dd...
Definition: netSocket.cxx:123
Socket address, internet style.
Definition: netSocket.h:87
short sin_family
Definition: netSocket.h:96
#define SHUT_RDWR
Definition: fg_common.hxx:99
netSocket is a thin C++ wrapper over bsd sockets to facilitate porting to other platforms. Part of PLIB - A Suite of Portable Game Libraries
virtual ~netSocket()
Definition: netSocket.cxx:211