diff --git a/projects/VC90/SimGear.vcproj b/projects/VC90/SimGear.vcproj
index 24484e8c..7ef14fc9 100644
--- a/projects/VC90/SimGear.vcproj
+++ b/projects/VC90/SimGear.vcproj
@@ -495,6 +495,14 @@
RelativePath="..\..\simgear\io\sg_socket_udp.hxx"
>
+
+
+
+
+#endif
+
+#include
+
+#include "sg_socket.hxx"
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+# define WINSOCK // use winsock convetions, otherwise standard POSIX
+#endif
+
+#include
+#include
+#include
+#include
+#include // for snprintf
+
+#if defined(WINSOCK)
+# include
+# include
+#else
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+#endif
+
+#if defined(_MSC_VER) && !defined(socklen_t)
+#define socklen_t int
+#endif
+
+#include
+#include
+
+namespace simgear
+{
+
+IPAddress::IPAddress ( const char* host, int port )
+{
+ set ( host, port ) ;
+}
+
+
+void IPAddress::set ( const char* host, int port )
+{
+ memset(this, 0, sizeof(IPAddress));
+
+ sin_family = AF_INET ;
+ sin_port = htons (port);
+
+ /* Convert a string specifying a host name or one of a few symbolic
+ ** names to a numeric IP address. This usually calls gethostbyname()
+ ** to do the work; the names "" and "" are special.
+ */
+
+ if (!host || host[0] == '\0') {
+ sin_addr = INADDR_ANY;
+ return;
+ }
+
+ if (strcmp(host, "") == 0) {
+ sin_addr = INADDR_BROADCAST;
+ return;
+ }
+
+ sin_addr = inet_addr ( host ) ;
+ if (sin_addr != INADDR_NONE) {
+ return;
+ }
+// finally, try gethostbyname
+ struct hostent *hp = gethostbyname ( host ) ;
+ if (!hp) {
+ SG_LOG(SG_IO, SG_WARN, "gethostbyname failed for " << host);
+ sin_addr = INADDR_ANY ;
+ return;
+ }
+
+ memcpy ( (char *) &sin_addr, hp->h_addr, hp->h_length ) ;
+}
+
+
+/* Create a string object representing an IP address.
+ This is always a string of the form 'dd.dd.dd.dd' (with variable
+ size numbers). */
+
+const char* IPAddress::getHost () const
+{
+#if 0
+ const char* buf = inet_ntoa ( sin_addr ) ;
+#else
+ static char buf [32];
+ long x = ntohl(sin_addr);
+ sprintf(buf, "%d.%d.%d.%d",
+ (int) (x>>24) & 0xff, (int) (x>>16) & 0xff,
+ (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff );
+#endif
+ return buf;
+}
+
+unsigned int IPAddress::getIP () const
+{
+ return sin_addr;
+}
+
+unsigned int IPAddress::getPort() const
+{
+ return ntohs(sin_port);
+}
+
+unsigned int IPAddress::getFamily () const
+{
+ return sin_family;
+}
+
+const char* IPAddress::getLocalHost ()
+{
+ //gethostbyname(gethostname())
+
+ char buf[256];
+ memset(buf, 0, sizeof(buf));
+ gethostname(buf, sizeof(buf)-1);
+ const hostent *hp = gethostbyname(buf);
+
+ if (hp && *hp->h_addr_list)
+ {
+ in_addr addr = *((in_addr*)*hp->h_addr_list);
+ const char* host = inet_ntoa(addr);
+
+ if ( host )
+ return host ;
+ }
+
+ return "127.0.0.1" ;
+}
+
+
+bool IPAddress::getBroadcast () const
+{
+ return sin_addr == INADDR_BROADCAST;
+}
+
+
+Socket::Socket ()
+{
+ handle = -1 ;
+}
+
+
+Socket::~Socket ()
+{
+ close () ;
+}
+
+
+void Socket::setHandle (int _handle)
+{
+ close () ;
+ handle = _handle ;
+}
+
+
+bool Socket::open ( bool stream )
+{
+ close () ;
+ handle = ::socket ( AF_INET, (stream? SOCK_STREAM: SOCK_DGRAM), 0 ) ;
+ return (handle != -1);
+}
+
+
+void Socket::setBlocking ( bool blocking )
+{
+ assert ( handle != -1 ) ;
+
+#if defined(WINSOCK)
+ u_long nblocking = blocking? 0: 1;
+ ::ioctlsocket(handle, FIONBIO, &nblocking);
+#else
+
+ int delay_flag = ::fcntl (handle, F_GETFL, 0);
+
+ if (blocking)
+ delay_flag &= (~O_NDELAY);
+ else
+ delay_flag |= O_NDELAY;
+
+ ::fcntl (handle, F_SETFL, delay_flag);
+#endif
+}
+
+
+void Socket::setBroadcast ( bool broadcast )
+{
+ assert ( handle != -1 ) ;
+ int result;
+ if ( broadcast ) {
+ int one = 1;
+#if defined(_WIN32) || defined(__CYGWIN__)
+ result = ::setsockopt( handle, SOL_SOCKET, SO_BROADCAST, (char*)&one, sizeof(one) );
+#else
+ result = ::setsockopt( handle, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one) );
+#endif
+ } else {
+ result = ::setsockopt( handle, SOL_SOCKET, SO_BROADCAST, NULL, 0 );
+ }
+
+ if ( result < 0 ) {
+ throw sg_exception("Socket::setBroadcast failed");
+ }
+}
+
+
+int Socket::bind ( const char* host, int port )
+{
+ assert ( handle != -1 ) ;
+ IPAddress addr ( host, port ) ;
+ return ::bind(handle,(const sockaddr*)&addr,sizeof(IPAddress));
+}
+
+
+int Socket::listen ( int backlog )
+{
+ assert ( handle != -1 ) ;
+ return ::listen(handle,backlog);
+}
+
+
+int Socket::accept ( IPAddress* addr )
+{
+ assert ( handle != -1 ) ;
+
+ if ( addr == NULL )
+ {
+ return ::accept(handle,NULL,NULL);
+ }
+ else
+ {
+ socklen_t addr_len = (socklen_t) sizeof(IPAddress) ;
+ return ::accept(handle,(sockaddr*)addr,&addr_len);
+ }
+}
+
+
+int Socket::connect ( const char* host, int port )
+{
+ assert ( handle != -1 ) ;
+ IPAddress addr ( host, port ) ;
+ if ( addr.getBroadcast() ) {
+ setBroadcast( true );
+ }
+ return ::connect(handle,(const sockaddr*)&addr,sizeof(IPAddress));
+}
+
+
+int Socket::send (const void * buffer, int size, int flags)
+{
+ assert ( handle != -1 ) ;
+ return ::send (handle, (const char*)buffer, size, flags);
+}
+
+
+int Socket::sendto ( const void * buffer, int size,
+ int flags, const IPAddress* to )
+{
+ assert ( handle != -1 ) ;
+ return ::sendto(handle,(const char*)buffer,size,flags,
+ (const sockaddr*)to,sizeof(IPAddress));
+}
+
+
+int Socket::recv (void * buffer, int size, int flags)
+{
+ assert ( handle != -1 ) ;
+ return ::recv (handle, (char*)buffer, size, flags);
+}
+
+
+int Socket::recvfrom ( void * buffer, int size,
+ int flags, IPAddress* from )
+{
+ assert ( handle != -1 ) ;
+ socklen_t fromlen = (socklen_t) sizeof(IPAddress) ;
+ return ::recvfrom(handle,(char*)buffer,size,flags,(sockaddr*)from,&fromlen);
+}
+
+
+void Socket::close (void)
+{
+ if ( handle != -1 )
+ {
+#if defined(WINSOCK)
+ ::closesocket( handle );
+#else
+ ::close( handle );
+#endif
+ handle = -1 ;
+ }
+}
+
+
+bool Socket::isNonBlockingError ()
+{
+#if defined(WINSOCK)
+ int wsa_errno = WSAGetLastError();
+ if ( wsa_errno != 0 )
+ {
+ WSASetLastError(0);
+ ulSetError(UL_WARNING,"WSAGetLastError() => %d",wsa_errno);
+ switch (wsa_errno) {
+ case WSAEWOULDBLOCK: // always == NET_EAGAIN?
+ case WSAEALREADY:
+ case WSAEINPROGRESS:
+ return true;
+ }
+ }
+ return false;
+#else
+ switch (errno) {
+ case EWOULDBLOCK: // always == NET_EAGAIN?
+ case EALREADY:
+ case EINPROGRESS:
+ return true;
+ }
+ return false;
+
+#endif
+}
+
+
+//////////////////////////////////////////////////////////////////////
+//
+// modified version by os
+//
+//////////////////////////////////////////////////////////////////////
+int Socket::select ( Socket** reads, Socket** writes, int timeout )
+{
+ fd_set r,w;
+ int retval;
+
+ FD_ZERO (&r);
+ FD_ZERO (&w);
+
+ int i, k ;
+ int num = 0 ;
+
+ if ( reads )
+ {
+ for ( i=0; reads[i]; i++ )
+ {
+ int fd = reads[i]->getHandle();
+ FD_SET (fd, &r);
+ num++;
+ }
+ }
+
+ if ( writes )
+ {
+ for ( i=0; writes[i]; i++ )
+ {
+ int fd = writes[i]->getHandle();
+ FD_SET (fd, &w);
+ num++;
+ }
+ }
+
+ if (!num)
+ return num ;
+
+ /* Set up the timeout */
+ struct timeval tv ;
+ tv.tv_sec = timeout/1000;
+ tv.tv_usec = (timeout%1000)*1000;
+
+ // It bothers me that select()'s first argument does not appear to
+ // work as advertised... [it hangs like this if called with
+ // anything less than FD_SETSIZE, which seems wasteful?]
+
+ // Note: we ignore the 'exception' fd_set - I have never had a
+ // need to use it. The name is somewhat misleading - the only
+ // thing I have ever seen it used for is to detect urgent data -
+ // which is an unportable feature anyway.
+
+ retval = ::select (FD_SETSIZE, &r, &w, 0, &tv);
+
+ //remove sockets that had no activity
+
+ num = 0 ;
+
+ if ( reads )
+ {
+ for ( k=i=0; reads[i]; i++ )
+ {
+ int fd = reads[i]->getHandle();
+ if ( FD_ISSET (fd, &r) )
+ {
+ reads[k++] = reads[i];
+ num++;
+ }
+ }
+ reads[k] = NULL ;
+ }
+
+ if ( writes )
+ {
+ for ( k=i=0; writes[i]; i++ )
+ {
+ int fd = writes[i]->getHandle();
+ if ( FD_ISSET (fd, &w) )
+ {
+ writes[k++] = writes[i];
+ num++;
+ }
+ }
+ writes[k] = NULL ;
+ }
+
+ if (retval == 0) // timeout
+ return (-2);
+ if (retval == -1)// error
+ return (-1);
+
+ return num ;
+}
+
+
+/* Init/Exit functions */
+
+static void netExit ( void )
+{
+#if defined(WINSOCK)
+ /* Clean up windows networking */
+ if ( WSACleanup() == SOCKET_ERROR ) {
+ if ( WSAGetLastError() == WSAEINPROGRESS ) {
+ WSACancelBlockingCall();
+ WSACleanup();
+ }
+ }
+#endif
+}
+
+int Socket::initSockets()
+{
+ assert ( sizeof(sockaddr_in) == sizeof(IPAddress) ) ;
+
+#if defined(WINSOCK)
+ /* Start up the windows networking */
+ WORD version_wanted = MAKEWORD(1,1);
+ WSADATA wsaData;
+
+ if ( WSAStartup(version_wanted, &wsaData) != 0 ) {
+ ulSetError(UL_WARNING,"Couldn't initialize Winsock 1.1");
+ return(-1);
+ }
+#endif
+
+ atexit( netExit ) ;
+ return(0);
+}
+
+
+} // of namespace simgear
+
diff --git a/simgear/io/raw_socket.hxx b/simgear/io/raw_socket.hxx
new file mode 100644
index 00000000..f68ff105
--- /dev/null
+++ b/simgear/io/raw_socket.hxx
@@ -0,0 +1,110 @@
+/*
+ simgear::Socket, adapted from PLIB netSocket by James Turner
+ Copyright (C) 2010 James Turner
+
+ PLIB - A Suite of Portable Game Libraries
+ Copyright (C) 1998,2002 Steve Baker
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef SG_IO_SOCKET_HXX
+#define SG_IO_SOCKET_HXX
+
+#include
+
+#if defined(__APPLE__)
+# include
+#endif
+
+namespace simgear
+{
+
+/*
+ * Socket address, internet style.
+ */
+class IPAddress
+{
+ /* DANGER!!! This MUST match 'struct sockaddr_in' exactly! */
+#ifdef __APPLE__
+ __uint8_t sin_len;
+ __uint8_t sin_family;
+ in_port_t sin_port;
+ in_addr_t sin_addr;
+ char sin_zero[8];
+#else
+ short sin_family ;
+ unsigned short sin_port ;
+ unsigned int sin_addr ;
+ char sin_zero [ 8 ] ;
+#endif
+
+public:
+ IPAddress () {}
+ IPAddress ( const char* host, int port ) ;
+
+ void set ( const char* host, int port ) ;
+ const char* getHost () const ;
+ unsigned int getPort() const ;
+ unsigned int getIP () const ;
+ unsigned int getFamily () const ;
+ static const char* getLocalHost () ;
+
+ bool getBroadcast () const ;
+};
+
+
+/*
+ * Socket type
+ */
+class Socket
+{
+ int handle ;
+
+public:
+
+ Socket () ;
+ virtual ~Socket () ;
+
+ static int initSockets();
+
+ int getHandle () const { return handle; }
+ void setHandle (int handle) ;
+
+ bool open ( bool stream=true ) ;
+ void close ( void ) ;
+ int bind ( const char* host, int port ) ;
+ int listen ( int backlog ) ;
+ int accept ( IPAddress* addr ) ;
+ int connect ( const char* host, int port ) ;
+ int send ( const void * buffer, int size, int flags = 0 ) ;
+ int sendto ( const void * buffer, int size, int flags, const IPAddress* to ) ;
+ int recv ( void * buffer, int size, int flags = 0 ) ;
+ int recvfrom ( void * buffer, int size, int flags, IPAddress* from ) ;
+
+ void setBlocking ( bool blocking ) ;
+ void setBroadcast ( bool broadcast ) ;
+
+ static bool isNonBlockingError () ;
+
+ static int select ( Socket** reads, Socket** writes, int timeout ) ;
+} ;
+
+//const char* netFormat ( const char* fmt, ... ) ;
+
+} // of namespace simgear
+
+#endif // SG_IO_SOCKET_HXX
+
diff --git a/simgear/io/sg_socket.cxx b/simgear/io/sg_socket.cxx
index 8dcbd6be..14ae2969 100644
--- a/simgear/io/sg_socket.cxx
+++ b/simgear/io/sg_socket.cxx
@@ -27,10 +27,6 @@
#include
-#if defined( sgi )
-#include
-#endif
-
#include
#include
@@ -52,8 +48,8 @@ SGSocket::SGSocket( const string& host, const string& port_,
{
if (!init)
{
- netInit(NULL, NULL); // plib-1.4.2 compatible
- init = true;
+ simgear::Socket::initSockets();
+ init = true;
}
if ( style == "tcp" )
@@ -326,7 +322,7 @@ SGSocket::readline( char *buf, int length )
int
SGSocket::write( const char *buf, const int length )
{
- netSocket* s = client == 0 ? &sock : client;
+ simgear::Socket* s = client == 0 ? &sock : client;
if (s->getHandle() == -1)
{
return 0;
@@ -384,24 +380,24 @@ SGSocket::nonblock()
int
SGSocket::poll()
{
- netSocket* readers[2];
+ simgear::Socket* readers[2];
readers[0] = client != 0 ? client : &sock;
readers[1] = 0;
- netSocket* writers[1];
+ simgear::Socket* writers[1];
writers[0] = 0;
- int result = netSocket::select( readers, writers, timeout );
+ int result = simgear::Socket::select( readers, writers, timeout );
if (result > 0 && is_server && client == 0)
{
// Accept a new client connection
- netAddress addr;
+ simgear::IPAddress addr;
int new_fd = sock.accept( &addr );
SG_LOG( SG_IO, SG_INFO, "Accepted connection from "
<< addr.getHost() << ":" << addr.getPort() );
- client = new netSocket();
+ client = new simgear::Socket();
client->setHandle( new_fd );
return 0;
}
diff --git a/simgear/io/sg_socket.hxx b/simgear/io/sg_socket.hxx
index 78c9d2d8..8341cb34 100644
--- a/simgear/io/sg_socket.hxx
+++ b/simgear/io/sg_socket.hxx
@@ -27,21 +27,13 @@
#ifndef _SG_SOCKET_HXX
#define _SG_SOCKET_HXX
-
-#ifndef __cplusplus
-# error This library requires C++
-#endif
-
#include
#include
#include
#include
-
-#include
-
-using std::string;
+#include
#define SG_MAX_SOCKET_QUEUE 32
@@ -52,14 +44,14 @@ using std::string;
class SGSocket : public SGIOChannel {
public:
private:
- string hostname;
- string port_str;
+ std::string hostname;
+ std::string port_str;
char save_buf[ 2 * SG_IO_MAX_MSG_SIZE ];
int save_len;
- netSocket sock;
- netSocket* client;
+ simgear::Socket sock;
+ simgear::Socket* client;
unsigned short port;
bool is_tcp;
bool is_server;
@@ -126,7 +118,7 @@ public:
* @param port port number if we care to choose one.
* @param style specify "udp" or "tcp"
*/
- SGSocket( const string& host, const string& port, const string& style );
+ SGSocket( const std::string& host, const std::string& port, const std::string& style );
/** Destructor */
~SGSocket();
@@ -161,10 +153,10 @@ public:
inline void set_timeout(int i) { timeout = i; }
/** @return the remote host name */
- inline string get_hostname() const { return hostname; }
+ inline std::string get_hostname() const { return hostname; }
/** @return the port number (in string form) */
- inline string get_port_str() const { return port_str; }
+ inline std::string get_port_str() const { return port_str; }
};
diff --git a/simgear/io/sg_socket_udp.cxx b/simgear/io/sg_socket_udp.cxx
index 97f0d8e0..bdc04d11 100644
--- a/simgear/io/sg_socket_udp.cxx
+++ b/simgear/io/sg_socket_udp.cxx
@@ -26,10 +26,6 @@
#include
-#if defined( sgi )
-#include
-#endif
-
#include
#include "sg_socket_udp.hxx"
diff --git a/simgear/io/sg_socket_udp.hxx b/simgear/io/sg_socket_udp.hxx
index 9d8e8eb6..69a5b027 100644
--- a/simgear/io/sg_socket_udp.hxx
+++ b/simgear/io/sg_socket_udp.hxx
@@ -28,20 +28,13 @@
#define _SG_SOCKET_UDP_HXX
-#ifndef __cplusplus
-# error This library requires C++
-#endif
-
-#include
-
#include
#include
#include
#include
-
-using std::string;
+#include
/**
* A UDP socket I/O class based on SGIOChannel and plib/net.
@@ -50,10 +43,10 @@ class SGSocketUDP : public SGIOChannel {
private:
- netSocket sock;
+ simgear::Socket sock;
- string hostname;
- string port_str;
+ std::string hostname;
+ std::string port_str;
char save_buf[ 2 * SG_IO_MAX_MSG_SIZE ];
int save_len;
@@ -128,10 +121,10 @@ public:
bool setBlocking( bool value );
/** @return the remote host name */
- inline string get_hostname() const { return hostname; }
+ inline std::string get_hostname() const { return hostname; }
/** @return the port number (in string form) */
- inline string get_port_str() const { return port_str; }
+ inline std::string get_port_str() const { return port_str; }
};