diff --git a/src/Main/fg_io.cxx b/src/Main/fg_io.cxx index d98cc0769..e6352f0c5 100644 --- a/src/Main/fg_io.cxx +++ b/src/Main/fg_io.cxx @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -51,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -68,172 +70,126 @@ io_container global_io_list; // configure a port based on the config string static FGProtocol *parse_port_config( const string& config ) { - bool short_circuit = false; - - string::size_type begin, end; - - begin = 0; - SG_LOG( SG_IO, SG_INFO, "Parse I/O channel request: " << config ); - // determine protocol - end = config.find(",", begin); - if ( end == string::npos ) { - return NULL; // dummy + vector tokens = simgear::strutils::split( config, "," ); + if (tokens.empty()) + { + SG_LOG( SG_IO, SG_ALERT, + "Port configuration error: empty config string" ); + return 0; } - - string protocol = config.substr(begin, end - begin); - begin = end + 1; + + string protocol = tokens[0]; SG_LOG( SG_IO, SG_INFO, " protocol = " << protocol ); - FGProtocol *io; - if ( protocol == "atc610x" ) { - FGATC610x *atc610x = new FGATC610x; - io = atc610x; - short_circuit = true; - cout << "here ..." << endl; - } else if ( protocol == "atlas" ) { - FGAtlas *atlas = new FGAtlas; - io = atlas; - } else if ( protocol == "opengc" ) { - // char wait; - // printf("Parsed opengc\n"); cin >> wait; - FGOpenGC *opengc = new FGOpenGC; - io = opengc; - } else if ( protocol == "garmin" ) { - FGGarmin *garmin = new FGGarmin; - io = garmin; - } else if ( protocol == "httpd" ) { - // determine port - string port = config.substr(begin); - FGHttpd *httpd = new FGHttpd( atoi(port.c_str()) ); - io = httpd; - short_circuit = true; + FGProtocol *io = 0; + + try + { + if ( protocol == "atc610x" ) { + return new FGATC610x; + } else if ( protocol == "atlas" ) { + FGAtlas *atlas = new FGAtlas; + io = atlas; + } else if ( protocol == "opengc" ) { + // char wait; + // printf("Parsed opengc\n"); cin >> wait; + FGOpenGC *opengc = new FGOpenGC; + io = opengc; + } else if ( protocol == "garmin" ) { + FGGarmin *garmin = new FGGarmin; + io = garmin; + } else if ( protocol == "httpd" ) { + // determine port + string port = tokens[1]; + return new FGHttpd( atoi(port.c_str()) ); #ifdef FG_JPEG_SERVER - } else if ( protocol == "jpg-httpd" ) { - // determine port - string port = config.substr(begin); - FGJpegHttpd *jpeg_httpd = new FGJpegHttpd( atoi(port.c_str()) ); - io = jpeg_httpd; - short_circuit = true; + } else if ( protocol == "jpg-httpd" ) { + // determine port + string port = tokens[1]; + return new FGJpegHttpd( atoi(port.c_str()) ); #endif - } else if ( protocol == "joyclient" ) { - FGJoyClient *joyclient = new FGJoyClient; - io = joyclient; - } else if ( protocol == "native" ) { - FGNative *native = new FGNative; - io = native; - } else if ( protocol == "native_ctrls" ) { - FGNativeCtrls *native_ctrls = new FGNativeCtrls; - io = native_ctrls; - } else if ( protocol == "native_fdm" ) { - FGNativeFDM *native_fdm = new FGNativeFDM; - io = native_fdm; - } else if ( protocol == "nmea" ) { - FGNMEA *nmea = new FGNMEA; - io = nmea; - } else if ( protocol == "props" ) { - FGProps *props = new FGProps; - io = props; - } else if ( protocol == "pve" ) { - FGPVE *pve = new FGPVE; - io = pve; - } else if ( protocol == "ray" ) { - FGRAY *ray = new FGRAY; - io = ray; - } else if ( protocol == "rul" ) { - FGRUL *rul = new FGRUL; - io = rul; - } else { - return NULL; + } else if ( protocol == "joyclient" ) { + FGJoyClient *joyclient = new FGJoyClient; + io = joyclient; + } else if ( protocol == "native" ) { + FGNative *native = new FGNative; + io = native; + } else if ( protocol == "native_ctrls" ) { + FGNativeCtrls *native_ctrls = new FGNativeCtrls; + io = native_ctrls; + } else if ( protocol == "native_fdm" ) { + FGNativeFDM *native_fdm = new FGNativeFDM; + io = native_fdm; + } else if ( protocol == "nmea" ) { + FGNMEA *nmea = new FGNMEA; + io = nmea; + } else if ( protocol == "props" ) { + io = new FGProps(); + } else if ( protocol == "telnet" ) { + io = new FGTelnet( tokens ); + return io; + } else if ( protocol == "pve" ) { + FGPVE *pve = new FGPVE; + io = pve; + } else if ( protocol == "ray" ) { + FGRAY *ray = new FGRAY; + io = ray; + } else if ( protocol == "rul" ) { + FGRUL *rul = new FGRUL; + io = rul; + } else { + return NULL; + } + } + catch (FGProtocolConfigError& err) + { + SG_LOG( SG_IO, SG_ALERT, "Port configuration error: " << err.what() ); + delete io; + return 0; } - if ( ! short_circuit ) { - // determine medium - end = config.find(",", begin); - if ( end == string::npos ) { - return NULL; // dummy - } - - string medium = config.substr(begin, end - begin); - begin = end + 1; - SG_LOG( SG_IO, SG_INFO, " medium = " << medium ); + string medium = tokens[1]; + SG_LOG( SG_IO, SG_INFO, " medium = " << medium ); - // determine direction - end = config.find(",", begin); - if ( end == string::npos ) { - return NULL; // dummy - } - - string direction = config.substr(begin, end - begin); - begin = end + 1; - io->set_direction( direction ); - SG_LOG( SG_IO, SG_INFO, " direction = " << direction ); + string direction = tokens[2]; + io->set_direction( direction ); + SG_LOG( SG_IO, SG_INFO, " direction = " << direction ); - // determine hertz - end = config.find(",", begin); - if ( end == string::npos ) { - return NULL; // dummy - } - - string hertz_str = config.substr(begin, end - begin); - begin = end + 1; - double hertz = atof( hertz_str.c_str() ); - io->set_hz( hertz ); - SG_LOG( SG_IO, SG_INFO, " hertz = " << hertz ); + string hertz_str = tokens[3]; + double hertz = atof( hertz_str.c_str() ); + io->set_hz( hertz ); + SG_LOG( SG_IO, SG_INFO, " hertz = " << hertz ); - if ( medium == "serial" ) { - // device name - end = config.find(",", begin); - if ( end == string::npos ) { - return NULL; - } - - string device = config.substr(begin, end - begin); - begin = end + 1; - SG_LOG( SG_IO, SG_INFO, " device = " << device ); + if ( medium == "serial" ) { + // device name + string device = tokens[4]; + SG_LOG( SG_IO, SG_INFO, " device = " << device ); - // baud - string baud = config.substr(begin); - SG_LOG( SG_IO, SG_INFO, " baud = " << baud ); + // baud + string baud = tokens[5]; + SG_LOG( SG_IO, SG_INFO, " baud = " << baud ); - SGSerial *ch = new SGSerial( device, baud ); - io->set_io_channel( ch ); - } else if ( medium == "file" ) { - // file name - string file = config.substr(begin); - SG_LOG( SG_IO, SG_INFO, " file name = " << file ); + SGSerial *ch = new SGSerial( device, baud ); + io->set_io_channel( ch ); + } else if ( medium == "file" ) { + // file name + string file = tokens[4]; + SG_LOG( SG_IO, SG_INFO, " file name = " << file ); - SGFile *ch = new SGFile( file ); - io->set_io_channel( ch ); - } else if ( medium == "socket" ) { - // hostname - end = config.find(",", begin); - if ( end == string::npos ) { - return NULL; - } - - string hostname = config.substr(begin, end - begin); - begin = end + 1; - SG_LOG( SG_IO, SG_INFO, " hostname = " << hostname ); + SGFile *ch = new SGFile( file ); + io->set_io_channel( ch ); + } else if ( medium == "socket" ) { + string hostname = tokens[4]; + string port = tokens[5]; + string style = tokens[6]; - // port string - end = config.find(",", begin); - if ( end == string::npos ) { - return NULL; - } - - string port = config.substr(begin, end - begin); - begin = end + 1; - SG_LOG( SG_IO, SG_INFO, " port string = " << port ); - - // socket style - string style_str = config.substr(begin); - SG_LOG( SG_IO, SG_INFO, " style string = " << style_str ); + SG_LOG( SG_IO, SG_INFO, " hostname = " << hostname ); + SG_LOG( SG_IO, SG_INFO, " port = " << port ); + SG_LOG( SG_IO, SG_INFO, " style = " << style ); - SGSocket *ch = new SGSocket( hostname, port, style_str ); - io->set_io_channel( ch ); - } + io->set_io_channel( new SGSocket( hostname, port, style ) ); } return io; @@ -273,8 +229,6 @@ void fgIOInit() { // process any serial port work void fgIOProcess() { - FGProtocol *p; - // cout << "processing I/O channels" << endl; static int inited = 0; @@ -292,9 +246,9 @@ void fgIOProcess() { last = current; } - for ( int i = 0; i < (int)global_io_list.size(); ++i ) { + for ( unsigned int i = 0; i < global_io_list.size(); ++i ) { // cout << " channel = " << i << endl; - p = global_io_list[i]; + FGProtocol* p = global_io_list[i]; if ( p->is_enabled() ) { p->dec_count_down( interval ); diff --git a/src/Main/main.cxx b/src/Main/main.cxx index dc0ec237f..11e2ef141 100644 --- a/src/Main/main.cxx +++ b/src/Main/main.cxx @@ -1332,7 +1332,8 @@ int mainLoop( int argc, char **argv ) { version = "unknown version"; #endif SG_LOG( SG_GENERAL, SG_INFO, "FlightGear: Version " - << version << endl ); + << version ); + SG_LOG( SG_GENERAL, SG_INFO, "Built with " << SG_COMPILER_STR ); // Allocate global data structures. This needs to happen before // we parse command line options diff --git a/src/Network/Makefile.am b/src/Network/Makefile.am index 7766c0977..de3c00fde 100644 --- a/src/Network/Makefile.am +++ b/src/Network/Makefile.am @@ -24,7 +24,8 @@ libNetwork_a_SOURCES = \ pve.cxx pve.hxx \ raw_ctrls.hxx \ ray.cxx ray.hxx \ - rul.cxx rul.hxx + rul.cxx rul.hxx \ + telnet.cxx telnet.hxx if OLD_AUTOMAKE INCLUDES += -I$(top_srcdir) -I$(top_srcdir)/src diff --git a/src/Network/protocol.cxx b/src/Network/protocol.cxx index ea1e66678..be4883ecf 100644 --- a/src/Network/protocol.cxx +++ b/src/Network/protocol.cxx @@ -95,3 +95,14 @@ bool FGProtocol::parse_message() { } +void FGProtocol::set_direction( const string& d ) { + if ( d == "in" ) { + dir = SG_IO_IN; + } else if ( d == "out" ) { + dir = SG_IO_OUT; + } else if ( d == "bi" ) { + dir = SG_IO_BI; + } else { + dir = SG_IO_NONE; + } +} diff --git a/src/Network/protocol.hxx b/src/Network/protocol.hxx index 8c6535b52..4b73d1893 100644 --- a/src/Network/protocol.hxx +++ b/src/Network/protocol.hxx @@ -26,6 +26,7 @@ #include +#include #include STL_STRING #include @@ -36,10 +37,6 @@ SG_USING_STD(vector); #define FG_MAX_MSG_SIZE 16384 -// forward declaration -class SGIOChannel; - - class FGProtocol { private: @@ -68,17 +65,7 @@ public: virtual bool close(); inline SGProtocolDir get_direction() const { return dir; } - inline void set_direction( const string& d ) { - if ( d == "in" ) { - dir = SG_IO_IN; - } else if ( d == "out" ) { - dir = SG_IO_OUT; - } else if ( d == "bi" ) { - dir = SG_IO_BI; - } else { - dir = SG_IO_NONE; - } - } + void set_direction( const string& d ); inline double get_hz() const { return hz; } inline void set_hz( double t ) { hz = t; } @@ -108,6 +95,18 @@ typedef vector < FGProtocol * > io_container; typedef io_container::iterator io_iterator; typedef io_container::const_iterator const_io_iterator; +#include +SG_USING_STD(invalid_argument); + +//namespace flightgear { namespace network { +class FGProtocolConfigError : public invalid_argument +{ +public: + FGProtocolConfigError( const string& what_string ) + : invalid_argument(what_string) {} +}; +//}} // end namespace flightgear::network + #endif // _PROTOCOL_HXX diff --git a/src/Network/telnet.cxx b/src/Network/telnet.cxx new file mode 100644 index 000000000..8af97dbbb --- /dev/null +++ b/src/Network/telnet.cxx @@ -0,0 +1,547 @@ +// \file telnet.cx +// Property telnet server class. +// +// Written by Bernie Bright, started May 2002. +// +// Copyright (C) 2002 Bernie Bright - bbright@bigpond.net.au +// +// 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$ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#include STL_STRSTREAM + +#include
+#include
+ +#include + +#include "telnet.hxx" + +#if !defined(SG_HAVE_NATIVE_SGI_COMPILERS) +SG_USING_STD(strstream); +#endif + +/** + * Telnet connection class. + * This class represents a connection to a telnet-style client. + */ +class TelnetChannel : public netChat +{ + netBuffer buffer; + + /** + * Current property node name. + */ + string path; + + enum Mode { + PROMPT, + DATA + }; + Mode mode; + +public: + /** + * Constructor. + */ + TelnetChannel(); + + /** + * Append incoming data to our request buffer. + * + * @param s Character string to append to buffer + * @param n Number of characters to append. + */ + void collectIncomingData( const char* s, int n ); + + /** + * Process a complete request from the telnet client. + */ + void foundTerminator(); + +private: + /** + * Return a "Node no found" error message to the client. + */ + void node_not_found_error( const string& node_name ); + + void view_cmd( const vector& ); +}; + +/** + * + */ +TelnetChannel::TelnetChannel() + : buffer(512), + path("/"), + mode(PROMPT) +{ + setTerminator( "\r\n" ); +} + +/** + * + */ +void +TelnetChannel::collectIncomingData( const char* s, int n ) +{ + buffer.append( s, n ); +} + +/** + * + */ +void +TelnetChannel::node_not_found_error( const string& node_name ) +{ + string error = "ERR Node \""; + error += node_name; + error += "\" not found."; + push( error.c_str() ); + push( getTerminator() ); +} + +// return a human readable form of the value "type" +static string +getValueTypeString( const SGPropertyNode *node ) +{ + string result; + + if ( node == NULL ) + { + return "unknown"; + } + + SGPropertyNode::Type type = node->getType(); + if ( type == SGPropertyNode::UNSPECIFIED ) { + result = "unspecified"; + } else if ( type == SGPropertyNode::NONE ) { + result = "none"; + } else if ( type == SGPropertyNode::BOOL ) { + result = "bool"; + } else if ( type == SGPropertyNode::INT ) { + result = "int"; + } else if ( type == SGPropertyNode::LONG ) { + result = "long"; + } else if ( type == SGPropertyNode::FLOAT ) { + result = "float"; + } else if ( type == SGPropertyNode::DOUBLE ) { + result = "double"; + } else if ( type == SGPropertyNode::STRING ) { + result = "string"; + } + + return result; +} + +/** + * We have a command. + * + * TODO: possible future commands: + * panel + * panel load [path] + * panel mouse