From 0c0b1506614b61901fc0c2dff3895423f4cb8937 Mon Sep 17 00:00:00 2001 From: curt Date: Fri, 2 Aug 2002 22:49:34 +0000 Subject: [PATCH] Bernie Bright: I've merged FGProps and FGTelnet so there is just a single property server. I've left in the --telnet=port# command line option but it could be removed if we wanted to. The command line accepts two forms of the --props option. The original (--props=medium,dir,hz,host,port#,style) and the shorter --props=port#. If you accept this change then src/Network/telnet.[ch]xx can be removed from the cvs repository. --- src/Main/fg_io.cxx | 9 +- src/Network/Makefile.am | 3 +- src/Network/atc610x.cxx | 4 +- src/Network/props.cxx | 567 +++++++++++++++++++++++++--------------- src/Network/props.hxx | 72 +++-- src/Network/telnet.cxx | 454 -------------------------------- src/Network/telnet.hxx | 89 ------- 7 files changed, 409 insertions(+), 789 deletions(-) delete mode 100644 src/Network/telnet.cxx delete mode 100644 src/Network/telnet.hxx diff --git a/src/Main/fg_io.cxx b/src/Main/fg_io.cxx index e6352f0c5..db276d884 100644 --- a/src/Main/fg_io.cxx +++ b/src/Main/fg_io.cxx @@ -52,14 +52,13 @@ #include #include #include -#include #include #include #include #include "globals.hxx" +#include "fg_io.hxx" -SG_USING_NAMESPACE(std); SG_USING_STD(string); @@ -125,10 +124,8 @@ static FGProtocol *parse_port_config( const string& config ) } 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 ); + } else if ( protocol == "props" || protocol == "telnet" ) { + io = new FGProps( tokens ); return io; } else if ( protocol == "pve" ) { FGPVE *pve = new FGPVE; diff --git a/src/Network/Makefile.am b/src/Network/Makefile.am index de3c00fde..7766c0977 100644 --- a/src/Network/Makefile.am +++ b/src/Network/Makefile.am @@ -24,8 +24,7 @@ libNetwork_a_SOURCES = \ pve.cxx pve.hxx \ raw_ctrls.hxx \ ray.cxx ray.hxx \ - rul.cxx rul.hxx \ - telnet.cxx telnet.hxx + rul.cxx rul.hxx if OLD_AUTOMAKE INCLUDES += -I$(top_srcdir) -I$(top_srcdir)/src diff --git a/src/Network/atc610x.cxx b/src/Network/atc610x.cxx index ba6064157..fef95670f 100644 --- a/src/Network/atc610x.cxx +++ b/src/Network/atc610x.cxx @@ -1402,8 +1402,8 @@ bool FGATC610x::do_switches() { fuel2 = fuel1; fuel1 = fuel; if ( fuel1 == fuel2 && fuel2 == fuel3 ) { - fgSetBool( "/controls/fuel-selector[0]", fuel & 0x01 ); - fgSetBool( "/controls/fuel-selector[1]", fuel & 0x02 ); + fgSetBool( "/controls/fuel-selector[0]", (fuel & 0x01) > 0 ); + fgSetBool( "/controls/fuel-selector[1]", (fuel & 0x02) > 0 ); } return true; diff --git a/src/Network/props.cxx b/src/Network/props.cxx index 3692a5cfe..8752da41b 100644 --- a/src/Network/props.cxx +++ b/src/Network/props.cxx @@ -1,6 +1,8 @@ -// props.hxx -- FGFS property manager interaction class +// \file props.cxx +// Property server class. // // Written by Curtis Olson, started September 2000. +// Modified by Bernie Bright, May 2002. // // Copyright (C) 2000 Curtis L. Olson - curt@flightgear.org // @@ -21,72 +23,116 @@ // $Id$ +#ifdef HAVE_CONFIG_H +# include +#endif #include #include -#include -#include +#include #include #include -#include
+#include STL_STRSTREAM -#include // atoi() atof() +#include
+#include
-#include STL_STRSTREAM +#include #include "props.hxx" #if !defined(SG_HAVE_NATIVE_SGI_COMPILERS) -SG_USING_STD(cout); -SG_USING_STD(istrstream); SG_USING_STD(strstream); +SG_USING_STD(ends); #endif -FGProps::FGProps() { -} - -FGProps::~FGProps() { +/** + * Props connection class. + * This class represents a connection to props client. + */ +class PropsChannel : public netChat +{ + netBuffer buffer; + + /** + * Current property node name. + */ + string path; + + enum Mode { + PROMPT, + DATA + }; + Mode mode; + +public: + /** + * Constructor. + */ + PropsChannel(); + + /** + * 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 props client. + */ + void foundTerminator(); + +private: + /** + * Return a "Node no found" error message to the client. + */ + void node_not_found_error( const string& node_name ); +}; + +/** + * + */ +PropsChannel::PropsChannel() + : buffer(512), + path("/"), + mode(PROMPT) +{ + setTerminator( "\r\n" ); } - -// open hailing frequencies -bool FGProps::open() { - reset(); - - if ( is_enabled() ) { - SG_LOG( SG_IO, SG_ALERT, "This shouldn't happen, but the channel " - << "is already in use, ignoring" ); - return false; - } - - SGIOChannel *io = get_io_channel(); - - if ( ! io->open( get_direction() ) ) { - SG_LOG( SG_IO, SG_ALERT, "Error opening channel communication layer." ); - return false; - } - - set_enabled( true ); - SG_LOG( SG_IO, SG_INFO, "Opening properties channel communication layer." ); - - return true; +/** + * + */ +void +PropsChannel::collectIncomingData( const char* s, int n ) +{ + buffer.append( s, n ); } - -// prepare for new connection -bool FGProps::reset() { - path = "/"; - mode = PROMPT; - return true; +/** + * + */ +void +PropsChannel::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 ) { +static string +getValueTypeString( const SGPropertyNode *node ) +{ string result; - if ( node == NULL ) { + if ( node == NULL ) + { return "unknown"; } @@ -112,207 +158,308 @@ static string getValueTypeString( const SGPropertyNode *node ) { return result; } +/** + * We have a command. + * + */ +void +PropsChannel::foundTerminator() +{ + const char* cmd = buffer.getData(); + SG_LOG( SG_IO, SG_INFO, "processing command = \"" << cmd << "\"" ); + + vector tokens = simgear::strutils::split( cmd ); + + SGPropertyNode* node = globals->get_props()->getNode( path.c_str() ); + + if (!tokens.empty()) + { + string command = tokens[0]; + + if (command == "ls") + { + SGPropertyNode* dir = node; + if (tokens.size() == 2) + { + if (tokens[1][0] == '/') + { + dir = globals->get_props()->getNode( tokens[1].c_str() ); + } + else + { + string s = path; + s += "/"; + s += tokens[1]; + dir = globals->get_props()->getNode( s.c_str() ); + } -bool FGProps::process_command( const char *cmd ) { - SGIOChannel *io = get_io_channel(); - - cout << "processing command = " << cmd; - string_list tokens; - tokens.clear(); - - istrstream in(cmd); - - while ( !in.eof() ) { - string token; - in >> token; - tokens.push_back( token ); - } + if (dir == 0) + { + node_not_found_error( tokens[1] ); + goto prompt; + } + } - string command = tokens[0]; + for (int i = 0; i < dir->nChildren(); i++) + { + SGPropertyNode * child = dir->getChild(i); + string name = child->getName(); + string line = name; + + if (dir->getChild( name.c_str(), 1 )) + { + char buf[16]; + sprintf(buf, "[%d]", child->getIndex()); + line += buf; + } - SGPropertyNode * node = globals->get_props()->getNode(path.c_str()); + if ( child->nChildren() > 0 ) + { + line += "/"; + } + else + { + if (mode == PROMPT) + { + string value = dir->getStringValue( name.c_str(), "" ); + line += " =\t'" + value + "'\t("; + line += getValueTypeString( + dir->getNode( name.c_str() ) ); + line += ")"; + } + } - if ( command == "ls" ) { - SGPropertyNode * dir = node; - if ( tokens.size() > 2 ) { - if ( tokens[1][0] == '/' ) { - dir = globals->get_props()->getNode(tokens[1].c_str()); - } else { - dir = globals->get_props()->getNode((path + "/" + tokens[1]).c_str()); - } - if ( dir == 0 ) { - tokens[1] = "ERR Node \"" + tokens[1] + "\" not found.\n"; - io->writestring( tokens[1].c_str() ); - return true; + line += getTerminator(); + push( line.c_str() ); } } - - for (int i = 0; i < (int)dir->nChildren(); i++) { - SGPropertyNode * child = dir->getChild(i); - string name = child->getName(); - string line = name; - if ( dir->getChild(name.c_str(), 1) ) { - char buf[16]; - sprintf(buf, "[%d]", child->getIndex()); - line += buf; + else if ( command == "dump" ) + { + strstream buf; + if ( tokens.size() <= 1 ) + { + writeProperties( buf, node ); + buf << ends; // null terminate the string + push( buf.str() ); + push( getTerminator() ); } - if ( child->nChildren() > 0 ) { - line += "/"; - } else { - if ( mode == PROMPT ) { - string value = dir->getStringValue ( name.c_str(), "" ); - line += " =\t'" + value + "'\t("; - line += getValueTypeString( dir->getNode( name.c_str() ) ); - line += ")"; + else + { + SGPropertyNode *child = node->getNode( tokens[1].c_str() ); + if ( child ) + { + writeProperties ( buf, child ); + buf << ends; // null terminate the string + push( buf.str() ); + push( getTerminator() ); + } + else + { + node_not_found_error( tokens[1] ); } } - line += "\n"; - io->writestring( line.c_str() ); } - } else if ( command == "dump" ) { - strstream buf; - if ( tokens.size() <= 1 ) { - writeProperties ( buf, node); - io->writestring( buf.str() ); - } - else { - SGPropertyNode *child = node->getNode(tokens[1].c_str()); - if ( child ) { - writeProperties ( buf, child ); - io->writestring( buf.str() ); - } else { - tokens[1] = "ERR Node \"" + tokens[1] + "\" not found.\n"; - io->writestring( tokens[1].c_str() ); + else if ( command == "cd" ) + { + if (tokens.size() == 2) + { + try + { + SGPropertyNode* child = node->getNode( tokens[1].c_str() ); + if ( child ) + { + node = child; + path = node->getPath(); + } + else + { + node_not_found_error( tokens[1] ); + } + } + catch (...) + { + // Ignore attempt to move past root node with ".." + } } } - } else if ( command == "cd" ) { - // string tmp = "current path = " + node.getPath() + "\n"; - // io->writestring( tmp.c_str() ); - - if ( tokens.size() <= 1 ) { - // do nothing - } else { - SGPropertyNode *child = node->getNode(tokens[1].c_str()); - if ( child ) { - node = child; - path = node->getPath(); - } else { - tokens[1] = "ERR Node \"" + tokens[1] + "\" not found.\n"; - io->writestring( tokens[1].c_str() ); + else if ( command == "pwd" ) + { + string ttt = node->getPath(); + if (ttt.empty()) + { + ttt = "/"; } + + push( ttt.c_str() ); + push( getTerminator() ); } - } else if ( command == "pwd" ) { - string ttt = node->getPath(); - if ( ttt.empty() ) { - ttt = "/"; - } - ttt += "\n"; - io->writestring( ttt.c_str() ); - } else if ( command == "get" || command == "show" ) { - if ( tokens.size() <= 1 ) { - // do nothing - } else { - string tmp; - string value = node->getStringValue ( tokens[1].c_str(), "" ); - if ( mode == PROMPT ) { - tmp = tokens[1] + " = '" + value + "' ("; - tmp += getValueTypeString( node->getNode( tokens[1].c_str() ) ); - tmp += ")\n"; - } else { - tmp = value + "\n"; + else if ( command == "get" || command == "show" ) + { + if ( tokens.size() == 2 ) + { + string tmp; + string value = node->getStringValue ( tokens[1].c_str(), "" ); + if ( mode == PROMPT ) + { + tmp = tokens[1]; + tmp += " = '"; + tmp += value; + tmp += "' ("; + tmp += getValueTypeString( + node->getNode( tokens[1].c_str() ) ); + tmp += ")"; + } + else + { + tmp = value; + } + push( tmp.c_str() ); + push( getTerminator() ); } - io->writestring( tmp.c_str() ); } - } else if ( command == "set" ) { - if ( tokens.size() <= 2 ) { - // do nothing - } else { - string tmp = tokens[2]; - for ( unsigned int i = 3; i < tokens.size() - 1; i++ ) { - tmp += " " + tokens[i]; - } - node->getNode( tokens[1].c_str(), true )->setStringValue(tmp.c_str()); - - if ( mode == PROMPT ) { - // now fetch and write out the new value as confirmation - // of the change - string value = node->getStringValue ( tokens[1].c_str(), "" ); - string tmp = tokens[1] + " = '" + value + "' ("; - tmp += getValueTypeString( node->getNode( tokens[1].c_str() ) ); - tmp += ")\n"; - - io->writestring( tmp.c_str() ); + else if ( command == "set" ) + { + if ( tokens.size() == 3 ) + { + node->getNode( tokens[1].c_str(), true )->setStringValue(tokens[2].c_str()); + + if ( mode == PROMPT ) + { + // now fetch and write out the new value as confirmation + // of the change + string value = node->getStringValue ( tokens[1].c_str(), "" ); + string tmp = tokens[1] + " = '" + value + "' ("; + tmp += getValueTypeString( node->getNode( tokens[1].c_str() ) ); + tmp += ")"; + push( tmp.c_str() ); + push( getTerminator() ); + } } } - } else if ( command == "quit" ) { - close(); - reset(); - return true; - } else if ( command == "data" ) { - mode = DATA; - } else if ( command == "prompt" ) { - mode = PROMPT; - } else { - io->writestring( "\n" ); - io->writestring( "Valid commands are:\n" ); - io->writestring( "\n" ); - io->writestring( "help show help message\n" ); - io->writestring( "ls [] list directory\n" ); - io->writestring( "dump dump current state (in xml)\n" ); - io->writestring( "cd cd to a directory, '..' to move back\n" ); - io->writestring( "pwd display your current path\n" ); - io->writestring( "get show the value of a parameter\n" ); - io->writestring( "show synonym for get\n" ); - io->writestring( "set set to a new \n" ); - io->writestring( "data switch to raw data mode\n" ); - io->writestring( "prompt switch to interactive mode (default)\n" ); - io->writestring( "quit terminate connection\n" ); - io->writestring( "\n" ); + else if (command == "quit") + { + close(); + shouldDelete(); + return; + } + else if ( command == "data" ) + { + mode = DATA; + } + else if ( command == "prompt" ) + { + mode = PROMPT; + } + else + { + const char* msg = "\ +Valid commands are:\r\n\ +\r\n\ +cd cd to a directory, '..' to move back\r\n\ +data switch to raw data mode\r\n\ +dump dump current state (in xml)\r\n\ +get show the value of a parameter\r\n\ +help show this help message\r\n\ +ls [] list directory\r\n\ +prompt switch to interactive mode (default)\r\n\ +pwd display your current path\r\n\ +quit terminate connection\r\n\ +set set to a new \r\n\ +show synonym for get\r\n"; + push( msg ); + } } - if ( mode == PROMPT ) { + prompt: + if (mode == PROMPT) + { string prompt = node->getPath(); - if ( prompt.empty() ) { + if (prompt.empty()) + { prompt = "/"; } prompt += "> "; - io->writestring( prompt.c_str() ); + push( prompt.c_str() ); } - return true; -} + buffer.remove(); +} -// process work for this port -bool FGProps::process() { - SGIOChannel *io = get_io_channel(); - char buf[max_cmd_len]; +/** + * + */ +FGProps::FGProps( const vector& tokens ) +{ + // tokens: + // props,port# + // props,medium,direction,hz,hostname,port#,style + if (tokens.size() == 2) + port = atoi( tokens[1].c_str() ); + else if (tokens.size() == 7) + port = atoi( tokens[5].c_str() ); + else + throw FGProtocolConfigError( "FGProps: incorrect number of configuration arguments" ); +} - // cout << "processing incoming props command" << endl; +/** + * + */ +FGProps::~FGProps() +{ +} - if ( get_direction() == SG_IO_BI ) { - // cout << " (bi directional)" << endl; - while ( io->readline( buf, max_cmd_len ) > 0 ) { - SG_LOG( SG_IO, SG_ALERT, "Success reading data." ); - process_command( buf ); - } - } else { - SG_LOG( SG_IO, SG_ALERT, - "in or out direction not supported for FGProps." ); +/** + * + */ +bool +FGProps::open() +{ + if ( is_enabled() ) + { + SG_LOG( SG_IO, SG_ALERT, "This shouldn't happen, but the channel " + << "is already in use, ignoring" ); + return false; } + netChannel::open(); + netChannel::bind( "", port ); + netChannel::listen( 5 ); + SG_LOG( SG_IO, SG_INFO, "Props server started on port " << port ); + + set_hz( 5 ); // default to processing requests @ 5Hz + set_enabled( true ); return true; } +/** + * + */ +bool +FGProps::close() +{ + return true; +} -// close the channel -bool FGProps::close() { - SGIOChannel *io = get_io_channel(); - - if ( ! io->close() ) { - return false; - } - - cout << "successfully closed channel\n"; - +/** + * + */ +bool +FGProps::process() +{ + netChannel::poll(); return true; } + +/** + * + */ +void +FGProps::handleAccept() +{ + netAddress addr; + int handle = accept( &addr ); + SG_LOG( SG_IO, SG_INFO, "Props server accepted connection from " + << addr.getHost() << ":" << addr.getPort() ); + PropsChannel* channel = new PropsChannel(); + channel->setHandle( handle ); +} diff --git a/src/Network/props.hxx b/src/Network/props.hxx index 5c26bd2ca..866baefbd 100644 --- a/src/Network/props.hxx +++ b/src/Network/props.hxx @@ -1,6 +1,8 @@ -// props.hxx -- FGFS property manager interaction class +// \file props.hxx +// Property server class. // // Written by Curtis Olson, started September 2000. +// Modified by Bernie Bright, May 2002. // // Copyright (C) 2000 Curtis L. Olson - curt@flightgear.org // @@ -24,48 +26,66 @@ #ifndef _FG_PROPS_HXX #define _FG_PROPS_HXX - #include -#include - #include STL_STRING - -#include "protocol.hxx" +#include SG_USING_STD(string); +SG_USING_STD(vector); +#include -const static int max_cmd_len = 256; - -class FGProps : public FGProtocol { - - enum Mode { - PROMPT, - DATA - }; - Mode mode; +#include "protocol.hxx" - // tree view of property list - string path; +/** + * Property server class. + * This class provides a telnet-like server for remote access to + * FlightGear properties. + */ +class FGProps : public FGProtocol, + public netChannel +{ +private: + + /** + * Server port to listen on. + */ + int port; - bool reset(); - bool process_command( const char *cmd ); - public: - - FGProps(); + /** + * Create a new TCP server. + * + * @param tokens Tokenized configuration parameters + */ + FGProps( const vector& tokens ); + + /** + * Destructor. + */ ~FGProps(); - // open hailing frequencies + /** + * Start the telnet server. + */ bool open(); - // process work for this port + /** + * Process network activity. + */ bool process(); - // close the channel + /** + * + */ bool close(); -}; + /** + * Accept a new client connection. + */ + void handleAccept(); +}; #endif // _FG_PROPS_HXX + diff --git a/src/Network/telnet.cxx b/src/Network/telnet.cxx deleted file mode 100644 index 158a65900..000000000 --- a/src/Network/telnet.cxx +++ /dev/null @@ -1,454 +0,0 @@ -// \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); -SG_USING_STD(ends); -#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 ); -}; - -/** - * - */ -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. - * - */ -void -TelnetChannel::foundTerminator() -{ - const char* cmd = buffer.getData(); - SG_LOG( SG_IO, SG_INFO, "processing command = \"" << cmd << "\"" ); - - vector tokens = simgear::strutils::split( cmd ); - - SGPropertyNode* node = globals->get_props()->getNode( path.c_str() ); - - if (!tokens.empty()) - { - string command = tokens[0]; - - if (command == "ls") - { - SGPropertyNode* dir = node; - if (tokens.size() == 2) - { - if (tokens[1][0] == '/') - { - dir = globals->get_props()->getNode( tokens[1].c_str() ); - } - else - { - string s = path; - s += "/"; - s += tokens[1]; - dir = globals->get_props()->getNode( s.c_str() ); - } - - if (dir == 0) - { - node_not_found_error( tokens[1] ); - goto prompt; - } - } - - for (int i = 0; i < dir->nChildren(); i++) - { - SGPropertyNode * child = dir->getChild(i); - string line = child->getDisplayName(true); - - if ( child->nChildren() > 0 ) - { - line += "/"; - } - else - { - if (mode == PROMPT) - { - string value = child->getStringValue(); - line += " =\t'" + value + "'\t("; - line += getValueTypeString( child ); - line += ")"; - } - } - - line += getTerminator(); - push( line.c_str() ); - } - } - else if ( command == "dump" ) - { - strstream buf; - if ( tokens.size() <= 1 ) - { - writeProperties( buf, node ); - buf << ends; // null terminate the string - push( buf.str() ); - push( getTerminator() ); - } - else - { - SGPropertyNode *child = node->getNode( tokens[1].c_str() ); - if ( child ) - { - writeProperties ( buf, child ); - buf << ends; // null terminate the string - push( buf.str() ); - push( getTerminator() ); - } - else - { - node_not_found_error( tokens[1] ); - } - } - } - else if ( command == "cd" ) - { - if (tokens.size() == 2) - { - try - { - SGPropertyNode* child = node->getNode( tokens[1].c_str() ); - if ( child ) - { - node = child; - path = node->getPath(); - } - else - { - node_not_found_error( tokens[1] ); - } - } - catch (...) - { - // Ignore attempt to move past root node with ".." - } - } - } - else if ( command == "pwd" ) - { - string ttt = node->getPath(); - if (ttt.empty()) - { - ttt = "/"; - } - - push( ttt.c_str() ); - push( getTerminator() ); - } - else if ( command == "get" || command == "show" ) - { - if ( tokens.size() == 2 ) - { - string tmp; - string value = node->getStringValue ( tokens[1].c_str(), "" ); - if ( mode == PROMPT ) - { - tmp = tokens[1]; - tmp += " = '"; - tmp += value; - tmp += "' ("; - tmp += getValueTypeString( - node->getNode( tokens[1].c_str() ) ); - tmp += ")"; - } - else - { - tmp = value; - } - push( tmp.c_str() ); - push( getTerminator() ); - } - } - else if ( command == "set" ) - { - if ( tokens.size() == 3 ) - { - node->getNode( tokens[1].c_str(), true )->setStringValue(tokens[2].c_str()); - - if ( mode == PROMPT ) - { - // now fetch and write out the new value as confirmation - // of the change - string value = node->getStringValue ( tokens[1].c_str(), "" ); - string tmp = tokens[1] + " = '" + value + "' ("; - tmp += getValueTypeString( node->getNode( tokens[1].c_str() ) ); - tmp += ")"; - push( tmp.c_str() ); - push( getTerminator() ); - } - } - } - else if (command == "quit") - { - close(); - shouldDelete(); - return; - } - else if ( command == "data" ) - { - mode = DATA; - } - else if ( command == "prompt" ) - { - mode = PROMPT; - } - else - { - const char* msg = "\ -Valid commands are:\r\n\ -\r\n\ -cd cd to a directory, '..' to move back\r\n\ -data switch to raw data mode\r\n\ -dump dump current state (in xml)\r\n\ -get show the value of a parameter\r\n\ -help show this help message\r\n\ -ls [] list directory\r\n\ -prompt switch to interactive mode (default)\r\n\ -pwd display your current path\r\n\ -quit terminate connection\r\n\ -set set to a new \r\n\ -show synonym for get\r\n"; - push( msg ); - } - } - - prompt: - if (mode == PROMPT) - { - string prompt = node->getPath(); - if (prompt.empty()) - { - prompt = "/"; - } - prompt += "> "; - push( prompt.c_str() ); - } - - buffer.remove(); -} - -/** - * - */ -FGTelnet::FGTelnet( const vector& tokens ) -{ - // tokens: - // telnet,port# - // props,medium,direction,hz,hostname,port#,style - if (tokens.size() == 2) - port = atoi( tokens[1].c_str() ); - else if (tokens.size() == 7) - port = atoi( tokens[5].c_str() ); - else - throw FGProtocolConfigError( "FGTelnet: incorrect number of configuration arguments" ); -} - -/** - * - */ -FGTelnet::~FGTelnet() -{ -} - -/** - * - */ -bool -FGTelnet::open() -{ - if ( is_enabled() ) - { - SG_LOG( SG_IO, SG_ALERT, "This shouldn't happen, but the channel " - << "is already in use, ignoring" ); - return false; - } - - netChannel::open(); - netChannel::bind( "", port ); - netChannel::listen( 5 ); - SG_LOG( SG_IO, SG_INFO, "Telnet server started on port " << port ); - - set_hz( 5 ); // default to processing requests @ 5Hz - set_enabled( true ); - return true; -} - -/** - * - */ -bool -FGTelnet::close() -{ - return true; -} - -/** - * - */ -bool -FGTelnet::process() -{ - netChannel::poll(); - return true; -} - -/** - * - */ -void -FGTelnet::handleAccept() -{ - netAddress addr; - int handle = accept( &addr ); - SG_LOG( SG_IO, SG_INFO, "Telnet server accepted connection from " - << addr.getHost() << ":" << addr.getPort() ); - TelnetChannel* channel = new TelnetChannel(); - channel->setHandle( handle ); -} diff --git a/src/Network/telnet.hxx b/src/Network/telnet.hxx deleted file mode 100644 index 3d7bf2f44..000000000 --- a/src/Network/telnet.hxx +++ /dev/null @@ -1,89 +0,0 @@ -// \file telnet.hxx -// Property 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$ - -#ifndef TELNET_HXX_INCLUDED -#define TELNET_HXX_INCLUDED 1 - -#include -#include STL_STRING -#include - -SG_USING_STD(string); -SG_USING_STD(vector); - -#include - -#include "protocol.hxx" - -/** - * Property server class. - * This class provides a telnet-like server for remote access to - * FlightGear properties. - */ -class FGTelnet : public FGProtocol, - public netChannel -{ -private: - - /** - * Server port to listen on. - */ - int port; - -public: - /** - * Create a new TCP server. - * - * @param tokens Tokenized configuration parameters - */ - FGTelnet( const vector& tokens ); - - /** - * Destructor. - */ - ~FGTelnet(); - - /** - * Start the telnet server. - */ - bool open(); - - /** - * Process network activity. - */ - bool process(); - - /** - * - */ - bool close(); - - /** - * Accept a new client connection. - */ - void handleAccept(); - -}; - -#endif //TELNET_HXX_INCLUDED - -- 2.39.5