]> git.mxchange.org Git - simgear.git/commitdiff
Moved to SimGear.
authorcurt <curt>
Tue, 11 Jul 2000 18:37:49 +0000 (18:37 +0000)
committercurt <curt>
Tue, 11 Jul 2000 18:37:49 +0000 (18:37 +0000)
simgear/io/Makefile.am [new file with mode: 0644]
simgear/io/iochannel.cxx [new file with mode: 0644]
simgear/io/iochannel.hxx [new file with mode: 0644]
simgear/io/sg_file.cxx [new file with mode: 0644]
simgear/io/sg_file.hxx [new file with mode: 0644]
simgear/io/sg_serial.cxx [new file with mode: 0644]
simgear/io/sg_serial.hxx [new file with mode: 0644]
simgear/io/sg_socket.cxx [new file with mode: 0644]
simgear/io/sg_socket.hxx [new file with mode: 0644]

diff --git a/simgear/io/Makefile.am b/simgear/io/Makefile.am
new file mode 100644 (file)
index 0000000..12bd629
--- /dev/null
@@ -0,0 +1,17 @@
+includedir = @includedir@/io
+
+lib_LIBRARIES = libsgio.a
+
+include_HEADERS = \
+       iochannel.hxx \
+       sg_file.hxx \
+       sg_serial.hxx \
+       sg_socket.hxx
+
+libsgio_a_SOURCES = \
+       iochannel.cxx \
+       sg_file.cxx \
+       sg_serial.cxx \
+       sg_socket.cxx 
+
+INCLUDES += -I$(top_builddir)
diff --git a/simgear/io/iochannel.cxx b/simgear/io/iochannel.cxx
new file mode 100644 (file)
index 0000000..ab83fc0
--- /dev/null
@@ -0,0 +1,74 @@
+// iochannel.cxx -- High level IO channel class
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+
+
+#include "iochannel.hxx"
+// #include "garmin.hxx"
+// #include "nmea.hxx"
+
+
+// constructor
+SGIOChannel::SGIOChannel()
+{
+}
+
+
+// destructor
+SGIOChannel::~SGIOChannel()
+{
+}
+
+
+// dummy configure routine
+bool SGIOChannel::open( SGProtocolDir dir ) {
+    return false;
+}
+
+
+// dummy process routine
+int SGIOChannel::read( char *buf, int length ) {
+    return 0;
+}
+
+
+// dummy process routine
+int SGIOChannel::readline( char *buf, int length ) {
+    return 0;
+}
+
+
+// dummy process routine
+int SGIOChannel::write( char *buf, int length ) {
+    return false;
+}
+
+
+// dummy process routine
+int SGIOChannel::writestring( char *str ) {
+    return false;
+}
+
+
+// dummy close routine
+bool SGIOChannel::close() {
+    return false;
+}
diff --git a/simgear/io/iochannel.hxx b/simgear/io/iochannel.hxx
new file mode 100644 (file)
index 0000000..941cdc0
--- /dev/null
@@ -0,0 +1,78 @@
+// iochannel.hxx -- High level IO channel class
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+
+
+#ifndef _IOCHANNEL_HXX
+#define _IOCHANNEL_HXX
+
+
+#include <simgear/compiler.h>
+
+// #include "protocol.hxx"
+
+#include STL_STRING
+#include <vector>
+
+FG_USING_STD(vector);
+FG_USING_STD(string);
+
+
+#define SG_IO_MAX_MSG_SIZE 16384
+
+enum SGProtocolDir {
+    SG_IO_NONE = 0,
+    SG_IO_IN = 1,
+    SG_IO_OUT = 2,
+    SG_IO_BI = 3
+};
+
+
+enum SGChannelType {
+    sgFileType = 0,
+    sgSerialType = 1,
+    sgSocketType = 2
+};
+
+class SGIOChannel {
+
+    SGChannelType type;
+
+public:
+
+    SGIOChannel();
+    virtual ~SGIOChannel();
+
+    virtual bool open( SGProtocolDir dir );
+    virtual int read( char *buf, int length );
+    virtual int readline( char *buf, int length );
+    virtual int write( char *buf, int length );
+    virtual int writestring( char *str );
+    virtual bool close();
+
+    virtual void set_type( SGChannelType t ) { type = t; }
+    virtual SGChannelType get_type() const { return type; }
+};
+
+
+#endif // _IOCHANNEL_HXX
+
+
diff --git a/simgear/io/sg_file.cxx b/simgear/io/sg_file.cxx
new file mode 100644 (file)
index 0000000..687a5a0
--- /dev/null
@@ -0,0 +1,155 @@
+// sg_file.cxx -- File I/O routines
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+
+
+#include <simgear/compiler.h>
+
+#include STL_STRING
+
+#ifdef _MSC_VER
+#  include <io.h>
+#endif
+
+#include <simgear/debug/logstream.hxx>
+
+#include "sg_file.hxx"
+
+FG_USING_STD(string);
+
+
+SGFile::SGFile() {
+    set_type( sgFileType );
+}
+
+
+SGFile::~SGFile() {
+}
+
+
+// open the file based on specified direction
+bool SGFile::open( SGProtocolDir dir ) {
+    if ( dir == SG_IO_OUT ) {
+#ifdef _MSC_VER
+       fp = _open( file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC,
+                       00666 );
+#else
+       fp = std::open( file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC,
+                       S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | 
+                       S_IROTH | S_IWOTH );
+#endif
+    } else if ( dir == SG_IO_IN ) {
+#ifdef _MSC_VER
+       fp = _open( file_name.c_str(), O_RDONLY );
+#else
+       fp = std::open( file_name.c_str(), O_RDONLY );
+#endif
+    } else {
+       FG_LOG( FG_IO, FG_ALERT, 
+               "Error:  bidirection mode not available for files." );
+       return false;
+    }
+
+    if ( fp == -1 ) {
+       FG_LOG( FG_IO, FG_ALERT, "Error opening file: " << file_name );
+       return false;
+    }
+
+    return true;
+}
+
+
+// read a block of data of specified size
+int SGFile::read( char *buf, int length ) {
+    // read a chunk
+#ifdef _MSC_VER
+    int result = _read( fp, buf, length );
+#else
+    int result = std::read( fp, buf, length );
+#endif
+
+    return result;
+}
+
+
+// read a line of data, length is max size of input buffer
+int SGFile::readline( char *buf, int length ) {
+    // save our current position
+    int pos = lseek( fp, 0, SEEK_CUR );
+
+    // read a chunk
+#ifdef _MSC_VER
+    int result = _read( fp, buf, length );
+#else
+    int result = std::read( fp, buf, length );
+#endif
+
+    // find the end of line and reset position
+    int i;
+    for ( i = 0; i < result && buf[i] != '\n'; ++i );
+    if ( buf[i] == '\n' ) {
+       result = i + 1;
+    } else {
+       result = i;
+    }
+    lseek( fp, pos + result, SEEK_SET );
+    
+    // just in case ...
+    buf[ result ] = '\0';
+
+    return result;
+}
+
+
+// write data to a file
+int SGFile::write( char *buf, int length ) {
+#ifdef _MSC_VER
+    int result = _write( fp, buf, length );
+#else
+    int result = std::write( fp, buf, length );
+#endif
+    if ( result != length ) {
+       FG_LOG( FG_IO, FG_ALERT, "Error writing data: " << file_name );
+    }
+
+    return result;
+}
+
+
+// write null terminated string to a file
+int SGFile::writestring( char *str ) {
+    int length = strlen( str );
+    return write( str, length );
+}
+
+
+// close the port
+bool SGFile::close() {
+#ifdef _MSC_VER
+    if ( _close( fp ) == -1 ) {
+#else
+    if ( std::close( fp ) == -1 ) {
+#endif
+       return false;
+    }
+
+    return true;
+}
diff --git a/simgear/io/sg_file.hxx b/simgear/io/sg_file.hxx
new file mode 100644 (file)
index 0000000..994cc27
--- /dev/null
@@ -0,0 +1,83 @@
+// sg_file.hxx -- File I/O routines
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+
+
+#ifndef _SG_FILE_HXX
+#define _SG_FILE_HXX
+
+
+#ifndef __cplusplus
+# error This library requires C++
+#endif
+
+#include <simgear/compiler.h>
+
+#include <string>
+
+#include <sys/types.h>         // for open(), read(), write(), close()
+#include <sys/stat.h>          // for open(), read(), write(), close()
+#include <fcntl.h>             // for open(), read(), write(), close()
+#if !defined( _MSC_VER )
+#  include <unistd.h>          // for open(), read(), write(), close()
+#endif
+
+#include "iochannel.hxx"
+
+FG_USING_STD(string);
+
+
+class SGFile : public SGIOChannel {
+
+    string file_name;
+    int fp;
+
+public:
+
+    SGFile();
+    ~SGFile();
+
+    // open the file based on specified direction
+    bool open( SGProtocolDir dir );
+
+    // read a block of data of specified size
+    int read( char *buf, int length );
+
+    // read a line of data, length is max size of input buffer
+    int readline( char *buf, int length );
+
+    // write data to a file
+    int write( char *buf, int length );
+
+    // write null terminated string to a file
+    int writestring( char *str );
+
+    // close file
+    bool close();
+
+    inline string get_file_name() const { return file_name; }
+    inline void set_file_name( const string& fn ) { file_name = fn; }
+};
+
+
+#endif // _SG_FILE_HXX
+
+
diff --git a/simgear/io/sg_serial.cxx b/simgear/io/sg_serial.cxx
new file mode 100644 (file)
index 0000000..2d409fb
--- /dev/null
@@ -0,0 +1,153 @@
+// sg_serial.cxx -- Serial I/O routines
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+
+
+#include <simgear/compiler.h>
+
+#include STL_STRING
+
+#include <simgear/debug/logstream.hxx>
+#include <simgear/serial/serial.hxx>
+
+#include "sg_serial.hxx"
+
+FG_USING_STD(string);
+
+
+SGSerial::SGSerial() :
+    save_len(0)
+{
+    set_type( sgSerialType );
+}
+
+
+SGSerial::~SGSerial() {
+}
+
+
+// open the serial port based on specified direction
+bool SGSerial::open( SGProtocolDir dir ) {
+    if ( ! port.open_port( device ) ) {
+       FG_LOG( FG_IO, FG_ALERT, "Error opening device: " << device );
+       return false;
+    }
+
+    // cout << "fd = " << port.fd << endl;
+
+    if ( ! port.set_baud( atoi( baud.c_str() ) ) ) {
+       FG_LOG( FG_IO, FG_ALERT, "Error setting baud: " << baud );
+       return false;
+    }
+
+    return true;
+}
+
+
+// Read data from port.  If we don't get enough data, save what we did
+// get in the save buffer and return 0.  The save buffer will be
+// prepended to subsequent reads until we get as much as is requested.
+
+int SGSerial::read( char *buf, int length ) {
+    int result;
+
+    // read a chunk, keep in the save buffer until we have the
+    // requested amount read
+
+    char *buf_ptr = save_buf + save_len;
+    result = port.read_port( buf_ptr, length - save_len );
+    
+    if ( result + save_len == length ) {
+       strncpy( buf, save_buf, length );
+       save_len = 0;
+
+       return length;
+    }
+    
+    return 0;
+}
+
+
+// read data from port
+int SGSerial::readline( char *buf, int length ) {
+    int result;
+
+    // read a chunk, keep in the save buffer until we have the
+    // requested amount read
+
+    char *buf_ptr = save_buf + save_len;
+    result = port.read_port( buf_ptr, SG_IO_MAX_MSG_SIZE - save_len );
+    save_len += result;
+
+    // look for the end of line in save_buf
+    int i;
+    for ( i = 0; i < save_len && save_buf[i] != '\n'; ++i );
+    if ( save_buf[i] == '\n' ) {
+       result = i + 1;
+    } else {
+       // no end of line yet
+       return 0;
+    }
+
+    // we found an end of line
+
+    // copy to external buffer
+    strncpy( buf, save_buf, result );
+    buf[result] = '\0';
+    FG_LOG( FG_IO, FG_INFO, "fg_serial line = " << buf );
+
+    // shift save buffer
+    for ( i = result; i < save_len; ++i ) {
+       save_buf[ i - result ] = save_buf[i];
+    }
+    save_len -= result;
+
+    return result;
+}
+
+
+// write data to port
+int SGSerial::write( char *buf, int length ) {
+    int result = port.write_port( buf, length );
+
+    if ( result != length ) {
+       FG_LOG( FG_IO, FG_ALERT, "Error writing data: " << device );
+    }
+
+    return result;
+}
+
+
+// write null terminated string to port
+int SGSerial::writestring( char *str ) {
+    int length = strlen( str );
+    return write( str, length );
+}
+
+
+// close the port
+bool SGSerial::close() {
+    if ( ! port.close_port() ) {
+       return false;
+    }
+
+    return true;
+}
diff --git a/simgear/io/sg_serial.hxx b/simgear/io/sg_serial.hxx
new file mode 100644 (file)
index 0000000..ce7a7d4
--- /dev/null
@@ -0,0 +1,90 @@
+// sg_serial.hxx -- Serial I/O routines
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+
+
+#ifndef _SG_SERIAL_HXX
+#define _SG_SERIAL_HXX
+
+
+#ifndef __cplusplus
+# error This library requires C++
+#endif
+
+#include <simgear/compiler.h>
+
+#include <string>
+
+// #ifdef FG_HAVE_STD_INCLUDES
+// #  include <ctime>
+// #else
+// #  include <time.h>
+// #endif
+
+#include <simgear/serial/serial.hxx>
+
+#include "iochannel.hxx"
+
+FG_USING_STD(string);
+
+
+class SGSerial : public SGIOChannel {
+
+    string device;
+    string baud;
+    FGSerialPort port;
+
+    char save_buf[ 2 * SG_IO_MAX_MSG_SIZE ];
+    int save_len;
+
+public:
+
+    SGSerial();
+    ~SGSerial();
+
+    // open the serial port based on specified direction
+    bool open( SGProtocolDir dir );
+
+    // read a block of data of specified size
+    int read( char *buf, int length );
+
+    // read a line of data, length is max size of input buffer
+    int readline( char *buf, int length );
+
+    // write data to port
+    int write( char *buf, int length );
+
+    // write null terminated string to port
+    int writestring( char *str );
+
+    // close port
+    bool close();
+
+    inline string get_device() const { return device; }
+    inline void set_device( const string& d ) { device = d; }
+    inline string get_baud() const { return baud; }
+    inline void set_baud( const string& b ) { baud = b; }
+};
+
+
+#endif // _SG_SERIAL_HXX
+
+
diff --git a/simgear/io/sg_socket.cxx b/simgear/io/sg_socket.cxx
new file mode 100644 (file)
index 0000000..1aadd28
--- /dev/null
@@ -0,0 +1,377 @@
+// sg_socket.cxx -- Socket I/O routines
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+
+
+#include <simgear/compiler.h>
+
+#if ! defined( _MSC_VER )
+#  include <sys/time.h>                // select()
+#  include <sys/types.h>       // socket(), bind(), select(), accept()
+#  include <sys/socket.h>      // socket(), bind(), listen(), accept()
+#  include <netinet/in.h>      // struct sockaddr_in
+#  include <netdb.h>           // gethostbyname()
+#  include <unistd.h>          // select(), fsync()/fdatasync()
+#else
+#  include <sys/timeb.h>       // select()
+#  include <winsock2.h>                // socket(), bind(), listen(), accept(),
+                               // struct sockaddr_in, gethostbyname()
+#  include <windows.h>
+#  include <io.h>
+#endif
+
+#if defined( sgi )
+#include <strings.h>
+#endif
+
+#include STL_STRING
+
+#include <simgear/debug/logstream.hxx>
+
+#include "sg_socket.hxx"
+
+FG_USING_STD(string);
+
+
+SGSocket::SGSocket() :
+    save_len(0)
+{
+    set_type( sgSocketType );
+}
+
+
+SGSocket::~SGSocket() {
+}
+
+
+int SGSocket::make_server_socket () {
+    struct sockaddr_in name;
+
+#if defined( __CYGWIN__ ) || defined( __CYGWIN32__ ) || defined( sgi ) || defined( _MSC_VER )
+    int length;
+#else
+    socklen_t length;
+#endif
+     
+    // Create the socket.
+    sock = socket (PF_INET, SOCK_STREAM, 0);
+    if (sock < 0) {
+       FG_LOG( FG_IO, FG_ALERT, 
+               "Error: socket() failed in make_server_socket()" );
+       return -1;
+    }
+     
+    // Give the socket a name.
+    name.sin_family = AF_INET;
+    name.sin_addr.s_addr = INADDR_ANY;
+    name.sin_port = htons(port); // set port to zero to let system pick
+    name.sin_addr.s_addr = htonl (INADDR_ANY);
+    if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) {
+       FG_LOG( FG_IO, FG_ALERT,
+               "Error: bind() failed in make_server_socket()" );
+       return -1;
+    }
+     
+    // Find the assigned port number
+    length = sizeof(struct sockaddr_in);
+    if ( getsockname(sock, (struct sockaddr *) &name, &length) ) {
+       FG_LOG( FG_IO, FG_ALERT,
+               "Error: getsockname() failed in make_server_socket()" );
+       return -1;
+    }
+    port = ntohs(name.sin_port);
+
+    return sock;
+}
+
+
+int SGSocket::make_client_socket () {
+    struct sockaddr_in name;
+    struct hostent *hp;
+     
+    FG_LOG( FG_IO, FG_INFO, "Make client socket()" );
+
+    // Create the socket.
+    sock = socket (PF_INET, SOCK_STREAM, 0);
+    if (sock < 0) {
+       FG_LOG( FG_IO, FG_ALERT, 
+               "Error: socket() failed in make_client_socket()" );
+       return -1;
+    }
+     
+    // specify address family
+    name.sin_family = AF_INET;
+
+    // get the hosts official name/info
+    hp = gethostbyname( hostname.c_str() );
+
+    // Connect this socket to the host and the port specified on the
+    // command line
+#if defined( __CYGWIN__ ) || defined( __CYGWIN32__ )
+    bcopy(hp->h_addr, (char *)(&(name.sin_addr.s_addr)), hp->h_length);
+#else
+    bcopy(hp->h_addr, &(name.sin_addr.s_addr), hp->h_length);
+#endif
+    name.sin_port = htons(port);
+
+    if ( connect(sock, (struct sockaddr *) &name, 
+                sizeof(struct sockaddr_in)) < 0 )
+    {
+#ifdef _MSC_VER
+       _close(sock);
+#else
+       std::close(sock);
+#endif
+       FG_LOG( FG_IO, FG_ALERT, 
+               "Error: connect() failed in make_client_socket()" );
+       return -1;
+    }
+
+    return sock;
+}
+
+
+// If specified as a server (out direction for now) open the master
+// listening socket.  If specified as a client, open a connection to a
+// server.
+
+bool SGSocket::open( SGProtocolDir dir ) {
+    if ( port_str == "" || port_str == "any" ) {
+       port = 0; 
+    } else {
+       port = atoi( port_str.c_str() );
+    }
+    
+    client_connections.clear();
+
+    if ( dir == SG_IO_OUT ) {
+       // this means server for now
+
+       // Setup socket to listen on.  Set "port" before making this
+       // call.  A port of "0" indicates that we want to let the os
+       // pick any available port.
+       sock = make_server_socket();
+       FG_LOG( FG_IO, FG_INFO, "socket is connected to port = " << port );
+
+       // Specify the maximum length of the connection queue
+       listen(sock, SG_MAX_SOCKET_QUEUE);
+
+    } else if ( dir == SG_IO_IN ) {
+       // this means client for now
+
+       sock = make_client_socket();
+    } else {
+       FG_LOG( FG_IO, FG_ALERT, 
+               "Error:  bidirection mode not available yet for sockets." );
+       return false;
+    }
+
+    if ( sock < 0 ) {
+       FG_LOG( FG_IO, FG_ALERT, "Error opening socket: " << hostname
+               << ":" << port );
+       return false;
+    }
+
+    return true;
+}
+
+
+// read data from socket (client)
+// read a block of data of specified size
+int SGSocket::read( char *buf, int length ) {
+    int result = 0;
+
+    // check for potential input
+    fd_set ready;
+    FD_ZERO(&ready);
+    FD_SET(sock, &ready);
+    struct timeval tv;
+    tv.tv_sec = 0;
+    tv.tv_usec = 0;
+
+    // test for any input read on sock (returning immediately, even if
+    // nothing)
+    select(32, &ready, 0, 0, &tv);
+
+    if ( FD_ISSET(sock, &ready) ) {
+#ifdef _MSC_VER
+       result = _read( sock, buf, length );
+#else
+       result = std::read( sock, buf, length );
+#endif
+       if ( result != length ) {
+           FG_LOG( FG_IO, FG_INFO, 
+                   "Warning: read() not enough bytes." );
+       }
+    }
+
+    return result;
+}
+
+
+// read a line of data, length is max size of input buffer
+int SGSocket::readline( char *buf, int length ) {
+    int result = 0;
+
+    // check for potential input
+    fd_set ready;
+    FD_ZERO(&ready);
+    FD_SET(sock, &ready);
+    struct timeval tv;
+    tv.tv_sec = 0;
+    tv.tv_usec = 0;
+
+    // test for any input read on sock (returning immediately, even if
+    // nothing)
+    select(32, &ready, 0, 0, &tv);
+
+    if ( FD_ISSET(sock, &ready) ) {
+       // read a chunk, keep in the save buffer until we have the
+       // requested amount read
+
+       char *buf_ptr = save_buf + save_len;
+#ifdef _MSC_VER
+       result = _read( sock, buf_ptr, SG_IO_MAX_MSG_SIZE - save_len );
+#else
+       result = std::read( sock, buf_ptr, SG_IO_MAX_MSG_SIZE - save_len );
+#endif
+       save_len += result;
+       // cout << "current read = " << buf_ptr << endl;
+       // cout << "current save_buf = " << save_buf << endl;
+       // cout << "save_len = " << save_len << endl;
+    }
+
+    // look for the end of line in save_buf
+    int i;
+    for ( i = 0; i < save_len && save_buf[i] != '\n'; ++i );
+    if ( save_buf[i] == '\n' ) {
+       result = i + 1;
+    } else {
+       // no end of line yet
+       // cout << "no eol found" << endl;
+       return 0;
+    }
+    // cout << "line length = " << result << endl;
+
+    // we found an end of line
+
+    // copy to external buffer
+    strncpy( buf, save_buf, result );
+    buf[result] = '\0';
+    // cout << "sg_socket line = " << buf << endl;
+    
+    // shift save buffer
+    for ( i = result; i < save_len; ++i ) {
+       save_buf[ i - result ] = save_buf[i];
+    }
+    save_len -= result;
+
+    return result;
+}
+
+
+// write data to socket (server)
+int SGSocket::write( char *buf, int length ) {
+
+    // check for any new client connection requests
+    fd_set ready;
+    FD_ZERO(&ready);
+    FD_SET(sock, &ready);
+    struct timeval tv;
+    tv.tv_sec = 0;
+    tv.tv_usec = 0;
+
+    // test for any input on sock (returning immediately, even if
+    // nothing)
+    select(32, &ready, 0, 0, &tv);
+
+    // any new connections?
+    if ( FD_ISSET(sock, &ready) ) {
+       int msgsock = accept(sock, 0, 0);
+       if ( msgsock < 0 ) {
+           FG_LOG( FG_IO, FG_ALERT, 
+                   "Error: accept() failed in write()" );
+           return 0;
+       } else {
+           client_connections.push_back( msgsock );
+       }
+    }
+
+    bool error_condition = false;
+    FG_LOG( FG_IO, FG_INFO, "Client connections = " << 
+           client_connections.size() );
+    for ( int i = 0; i < (int)client_connections.size(); ++i ) {
+       int msgsock = client_connections[i];
+
+       // read and junk any possible incoming messages.
+       // char junk[ SG_IO_MAX_MSG_SIZE ];
+       // std::read( msgsock, junk, SG_IO_MAX_MSG_SIZE );
+
+       // write the interesting data to the socket
+#ifdef _MSC_VER
+       if ( _write(msgsock, buf, length) < 0 ) {
+#else
+       if ( std::write(msgsock, buf, length) < 0 ) {
+#endif
+           FG_LOG( FG_IO, FG_ALERT, "Error writing to socket: " << port );
+           error_condition = true;
+       } else {
+#ifdef _POSIX_SYNCHRONIZED_IO
+           // fdatasync(msgsock);
+#else
+           // fsync(msgsock);
+#endif
+       }
+    }
+
+    if ( error_condition ) {
+       return 0;
+    }
+
+    return length;
+}
+
+
+// write null terminated string to socket (server)
+int SGSocket::writestring( char *str ) {
+    int length = strlen( str );
+    return write( str, length );
+}
+
+
+// close the port
+bool SGSocket::close() {
+    for ( int i = 0; i < (int)client_connections.size(); ++i ) {
+       int msgsock = client_connections[i];
+#ifdef _MSC_VER
+       _close( msgsock );
+#else
+       std::close( msgsock );
+#endif
+    }
+
+#ifdef _MSC_VER
+    _close( sock );
+#else
+    std::close( sock );
+#endif
+    return true;
+}
diff --git a/simgear/io/sg_socket.hxx b/simgear/io/sg_socket.hxx
new file mode 100644 (file)
index 0000000..199b6db
--- /dev/null
@@ -0,0 +1,97 @@
+// sg_socket.hxx -- Socket I/O routines
+//
+// Written by Curtis Olson, started November 1999.
+//
+// Copyright (C) 1999  Curtis L. Olson - curt@flightgear.org
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program 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
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+
+
+#ifndef _SG_SOCKET_HXX
+#define _SG_SOCKET_HXX
+
+
+#ifndef __cplusplus
+# error This library requires C++
+#endif
+
+#include <simgear/compiler.h>
+
+#include <string>
+
+#include <simgear/math/fg_types.hxx>
+
+#include "iochannel.hxx"
+
+FG_USING_STD(string);
+
+
+#define SG_MAX_SOCKET_QUEUE 32
+
+
+class SGSocket : public SGIOChannel {
+
+    string hostname;
+    string port_str;
+
+    char save_buf[ 2 * SG_IO_MAX_MSG_SIZE ];
+    int save_len;
+
+    int sock;
+    short unsigned int port;
+
+    // make a server (master listening) socket
+    int make_server_socket();
+
+    // make a client socket
+    int make_client_socket();
+
+    int_list client_connections;
+
+public:
+
+    SGSocket();
+    ~SGSocket();
+
+    // open the file based on specified direction
+    bool open( SGProtocolDir dir );
+
+    // read data from socket
+    int read( char *buf, int length );
+
+    // read data from socket
+    int readline( char *buf, int length );
+
+    // write data to a socket
+    int write( char *buf, int length );
+
+    // write null terminated string to a socket
+    int writestring( char *str );
+
+    // close file
+    bool close();
+
+    inline string get_hostname() const { return hostname; }
+    inline void set_hostname( const string& hn ) { hostname = hn; }
+    inline string get_port_str() const { return port_str; }
+    inline void set_port_str( const string& p ) { port_str = p; }
+};
+
+
+#endif // _SG_SOCKET_HXX
+
+