Moved to SimGear.
This commit is contained in:
parent
dda7ebfe0d
commit
22812a0aae
17
simgear/io/Makefile.am
Normal file
17
simgear/io/Makefile.am
Normal file
@ -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)
|
74
simgear/io/iochannel.cxx
Normal file
74
simgear/io/iochannel.cxx
Normal file
@ -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;
|
||||
}
|
78
simgear/io/iochannel.hxx
Normal file
78
simgear/io/iochannel.hxx
Normal file
@ -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
|
||||
|
||||
|
155
simgear/io/sg_file.cxx
Normal file
155
simgear/io/sg_file.cxx
Normal file
@ -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;
|
||||
}
|
83
simgear/io/sg_file.hxx
Normal file
83
simgear/io/sg_file.hxx
Normal file
@ -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
|
||||
|
||||
|
153
simgear/io/sg_serial.cxx
Normal file
153
simgear/io/sg_serial.cxx
Normal file
@ -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;
|
||||
}
|
90
simgear/io/sg_serial.hxx
Normal file
90
simgear/io/sg_serial.hxx
Normal file
@ -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
|
||||
|
||||
|
377
simgear/io/sg_socket.cxx
Normal file
377
simgear/io/sg_socket.cxx
Normal file
@ -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;
|
||||
}
|
97
simgear/io/sg_socket.hxx
Normal file
97
simgear/io/sg_socket.hxx
Normal file
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user