// Written by Curtis Olson, started September 2000.
// Modified by Bernie Bright, May 2002.
//
-// Copyright (C) 2000 Curtis L. Olson - curt@flightgear.org
+// Copyright (C) 2000 Curtis L. Olson - http://www.flightgear.org/~curt
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
//
// 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.
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$
#include <simgear/props/props.hxx>
#include <simgear/props/props_io.hxx>
-#include STL_STRSTREAM
+#include <sstream>
+#include <iostream>
#include <Main/globals.hxx>
#include <Main/viewmgr.hxx>
-#include <plib/netChat.h>
+#include <simgear/io/sg_netChat.hxx>
#include "props.hxx"
-#if !defined(SG_HAVE_NATIVE_SGI_COMPILERS)
-SG_USING_STD(strstream);
-SG_USING_STD(ends);
-#endif
+using std::stringstream;
+using std::ends;
+
+using std::cout;
+using std::endl;
/**
* Props connection class.
* This class represents a connection to props client.
*/
-class PropsChannel : public netChat
+class PropsChannel : public simgear::NetChat
{
- netBuffer buffer;
+ simgear::NetBuffer buffer;
/**
* Current property node name.
string path;
enum Mode {
- PROMPT,
- DATA
+ PROMPT,
+ DATA
};
Mode mode;
* Constructor.
*/
PropsChannel();
-
+
/**
* Append incoming data to our request buffer.
*
void foundTerminator();
private:
- /**
- * Return a "Node no found" error message to the client.
- */
- void node_not_found_error( const string& node_name );
+ inline void node_not_found_error( const string& s ) const {
+ throw "node '" + s + "' not found";
+ }
};
/**
- *
+ *
*/
PropsChannel::PropsChannel()
: buffer(512),
}
/**
- *
+ *
*/
void
PropsChannel::collectIncomingData( const char* s, int n )
buffer.append( s, n );
}
-/**
- *
- */
-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 )
{
+ using namespace simgear;
+
string result;
if ( node == NULL )
{
- return "unknown";
+ return "unknown";
}
- SGPropertyNode::Type type = node->getType();
- if ( type == SGPropertyNode::UNSPECIFIED ) {
- result = "unspecified";
- } else if ( type == SGPropertyNode::NONE ) {
+ props::Type type = node->getType();
+ if ( type == props::UNSPECIFIED ) {
+ result = "unspecified";
+ } else if ( type == props::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";
+ } else if ( type == props::BOOL ) {
+ result = "bool";
+ } else if ( type == props::INT ) {
+ result = "int";
+ } else if ( type == props::LONG ) {
+ result = "long";
+ } else if ( type == props::FLOAT ) {
+ result = "float";
+ } else if ( type == props::DOUBLE ) {
+ result = "double";
+ } else if ( type == props::STRING ) {
+ result = "string";
}
return result;
/**
* We have a command.
- *
+ *
*/
void
PropsChannel::foundTerminator()
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() >= 2 ) {
- string value, tmp;
- if ( tokens.size() == 3 ) {
- value = tokens[2];
+ try {
+ 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] );
+ }
+ }
+
+ 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" ) {
+ stringstream buf;
+ if ( tokens.size() <= 1 ) {
+ writeProperties( buf, node );
+ buf << ends; // null terminate the string
+ push( buf.str().c_str() );
+ push( getTerminator() );
} else {
- value = "";
+ SGPropertyNode *child = node->getNode( tokens[1].c_str() );
+ if ( child ) {
+ writeProperties ( buf, child );
+ buf << ends; // null terminate the string
+ push( buf.str().c_str() );
+ push( getTerminator() );
+ } else {
+ node_not_found_error( tokens[1] );
+ }
}
- node->getNode( tokens[1].c_str(), true )
- ->setStringValue(value.c_str());
-
- if ( mode == PROMPT ) {
- // now fetch and write out the new value as confirmation
- // of the change
- value = node->getStringValue ( tokens[1].c_str(), "" );
- tmp = tokens[1] + " = '" + value + "' (";
- tmp += getValueTypeString( node->getNode( tokens[1].c_str() ) );
- tmp += ")";
- push( tmp.c_str() );
- push( getTerminator() );
- }
- }
- } else if ( command == "reinit" ) {
- if ( tokens.size() == 2 ) {
- string tmp;
- SGPropertyNode args;
- for ( unsigned int i = 1; i < tokens.size(); ++i ) {
- cout << "props: adding subsystem = " << tokens[i] << endl;
- SGPropertyNode *node = args.getNode("subsystem", i-1, true);
- node->setStringValue( tokens[i].c_str() );
+ }
+ else if ( command == "cd" ) {
+ if (tokens.size() == 2) {
+ SGPropertyNode* child = node->getNode( tokens[1].c_str() );
+ if ( child ) {
+ node = child;
+ path = node->getPath();
+ } else {
+ node_not_found_error( tokens[1] );
+ }
+ }
+ } else if ( command == "pwd" ) {
+ string pwd = node->getPath();
+ if (pwd.empty()) {
+ pwd = "/";
}
- if ( !globals->get_commands()
- ->execute( "reinit", &args) )
- {
- SG_LOG( SG_GENERAL, SG_ALERT,
- "Command " << tokens[1] << " failed.");
+
+ push( pwd.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 += "*failed*";
- push( tmp.c_str() );
- push( getTerminator() );
+ tmp = tokens[1];
+ tmp += " = '";
+ tmp += value;
+ tmp += "' (";
+ tmp += getValueTypeString(
+ node->getNode( tokens[1].c_str() ) );
+ tmp += ")";
+ } else {
+ tmp = value;
}
- } else {
+ push( tmp.c_str() );
+ push( getTerminator() );
+ }
+ } else if ( command == "set" ) {
+ if ( tokens.size() >= 2 ) {
+ string value, tmp;
+ for (unsigned int i = 2; i < tokens.size(); i++) {
+ if (i > 2)
+ value += " ";
+ value += tokens[i];
+ }
+ node->getNode( tokens[1].c_str(), true )
+ ->setStringValue(value.c_str());
+
if ( mode == PROMPT ) {
- tmp += "<completed>";
+ // now fetch and write out the new value as confirmation
+ // of the change
+ value = node->getStringValue ( tokens[1].c_str(), "" );
+ tmp = tokens[1] + " = '" + value + "' (";
+ tmp += getValueTypeString( node->getNode( tokens[1].c_str() ) );
+ tmp += ")";
push( tmp.c_str() );
push( getTerminator() );
}
}
- }
- } else if ( command == "run" ) {
- string tmp;
- if ( tokens.size() >= 2 ) {
- SGPropertyNode args;
- if ( tokens[1] == "reinit" ) {
- for ( unsigned int i = 2; i < tokens.size(); ++i ) {
- cout << "props: adding subsystem = " << tokens[i]
- << endl;
- SGPropertyNode *node
- = args.getNode("subsystem", i-2, true);
+ } else if ( command == "reinit" ) {
+ if ( tokens.size() == 2 ) {
+ string tmp;
+ SGPropertyNode args;
+ for ( unsigned int i = 1; i < tokens.size(); ++i ) {
+ cout << "props: adding subsystem = " << tokens[i] << endl;
+ SGPropertyNode *node = args.getNode("subsystem", i-1, true);
node->setStringValue( tokens[i].c_str() );
}
- } else if ( tokens[1] == "timeofday" ) {
- for ( unsigned int i = 2; i < tokens.size(); ++i ) {
- cout << "props: adding subsystem = " << tokens[i]
- << endl;
- SGPropertyNode *node
- = args.getNode("timeofday", i-2, true);
- node->setStringValue( tokens[i].c_str() );
+ if ( !globals->get_commands()
+ ->execute( "reinit", &args) )
+ {
+ SG_LOG( SG_GENERAL, SG_ALERT,
+ "Command " << tokens[1] << " failed.");
+ if ( mode == PROMPT ) {
+ tmp += "*failed*";
+ push( tmp.c_str() );
+ push( getTerminator() );
+ }
+ } else {
+ if ( mode == PROMPT ) {
+ tmp += "<completed>";
+ push( tmp.c_str() );
+ push( getTerminator() );
+ }
}
}
- if ( !globals->get_commands()
- ->execute(tokens[1].c_str(), &args) )
- {
- SG_LOG( SG_GENERAL, SG_ALERT,
- "Command " << tokens[1] << " failed.");
- if ( mode == PROMPT ) {
- tmp += "*failed*";
- push( tmp.c_str() );
- push( getTerminator() );
+ } else if ( command == "run" ) {
+ string tmp;
+ if ( tokens.size() >= 2 ) {
+ SGPropertyNode args;
+ if ( tokens[1] == "reinit" ) {
+ for ( unsigned int i = 2; i < tokens.size(); ++i ) {
+ cout << "props: adding subsystem = " << tokens[i]
+ << endl;
+ SGPropertyNode *node
+ = args.getNode("subsystem", i-2, true);
+ node->setStringValue( tokens[i].c_str() );
+ }
+ } else if ( tokens[1] == "set-sea-level-air-temp-degc" ) {
+ for ( unsigned int i = 2; i < tokens.size(); ++i ) {
+ cout << "props: set-sl command = " << tokens[i]
+ << endl;
+ SGPropertyNode *node
+ = args.getNode("temp-degc", i-2, true);
+ node->setStringValue( tokens[i].c_str() );
+ }
+ } else if ( tokens[1] == "set-outside-air-temp-degc" ) {
+ for ( unsigned int i = 2; i < tokens.size(); ++i ) {
+ cout << "props: set-oat command = " << tokens[i]
+ << endl;
+ SGPropertyNode *node
+ = args.getNode("temp-degc", i-2, true);
+ node->setStringValue( tokens[i].c_str() );
+ }
+ } else if ( tokens[1] == "timeofday" ) {
+ for ( unsigned int i = 2; i < tokens.size(); ++i ) {
+ cout << "props: time of day command = " << tokens[i]
+ << endl;
+ SGPropertyNode *node
+ = args.getNode("timeofday", i-2, true);
+ node->setStringValue( tokens[i].c_str() );
+ }
+ } else if ( tokens[1] == "play-audio-message" ) {
+ if ( tokens.size() == 4 ) {
+ cout << "props: play audio message = " << tokens[2]
+ << " " << tokens[3] << endl;
+ SGPropertyNode *node;
+ node = args.getNode("path", 0, true);
+ node->setStringValue( tokens[2].c_str() );
+ node = args.getNode("file", 0, true);
+ node->setStringValue( tokens[3].c_str() );
+ }
+ }
+ if ( !globals->get_commands()
+ ->execute(tokens[1].c_str(), &args) )
+ {
+ SG_LOG( SG_GENERAL, SG_ALERT,
+ "Command " << tokens[1] << " failed.");
+ if ( mode == PROMPT ) {
+ tmp += "*failed*";
+ push( tmp.c_str() );
+ push( getTerminator() );
+ }
+ } else {
+ if ( mode == PROMPT ) {
+ tmp += "<completed>";
+ push( tmp.c_str() );
+ push( getTerminator() );
+ }
}
} else {
if ( mode == PROMPT ) {
- tmp += "<completed>";
+ tmp += "no command specified";
push( tmp.c_str() );
push( getTerminator() );
}
}
- } else {
- if ( mode == PROMPT ) {
- tmp += "no command specified";
- 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 = "\
+ } else if ( command == "quit" || command == "exit" ) {
+ 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 <dir> cd to a directory, '..' to move back\r\n\
pwd display your current path\r\n\
quit terminate connection\r\n\
run <command> run built in command\r\n\
-set <var> <val> set <var> to a new <val>\r\n\
-show <var> synonym for get\r\n";
- push( msg );
- }
+set <var> <val> set <var> to a new <val>\r\n";
+ push( msg );
+ }
+ }
+
+ } catch ( const string& msg ) {
+ string error = "-ERR \"" + msg + "\"";
+ push( error.c_str() );
+ push( getTerminator() );
}
- prompt:
- if (mode == PROMPT) {
- string prompt = node->getPath();
- if (prompt.empty()) {
- prompt = "/";
- }
- prompt += "> ";
- push( prompt.c_str() );
+ if ( mode == PROMPT ) {
+ string prompt = node->getPath();
+ if (prompt.empty()) {
+ prompt = "/";
+ }
+ prompt += "> ";
+ push( prompt.c_str() );
}
buffer.remove();
}
/**
- *
+ *
*/
FGProps::FGProps( const vector<string>& tokens )
{
// props,port#
// props,medium,direction,hz,hostname,port#,style
if (tokens.size() == 2) {
- port = atoi( tokens[1].c_str() );
+ port = atoi( tokens[1].c_str() );
set_hz( 5 ); // default to processing requests @ 5Hz
} else if (tokens.size() == 7) {
char* endptr;
<< hz << " Hz");
set_hz( hz );
}
- port = atoi( tokens[5].c_str() );
+ port = atoi( tokens[5].c_str() );
} else {
- throw FGProtocolConfigError( "FGProps: incorrect number of configuration arguments" );
+ throw FGProtocolConfigError( "FGProps: incorrect number of configuration arguments" );
}
}
/**
- *
+ *
*/
FGProps::~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;
+ 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 );
+ simgear::NetChannel::open();
+ simgear::NetChannel::bind( "", port );
+ simgear::NetChannel::listen( 5 );
SG_LOG( SG_IO, SG_INFO, "Props server started on port " << port );
set_enabled( true );
}
/**
- *
+ *
*/
bool
FGProps::close()
{
+ SG_LOG( SG_IO, SG_INFO, "closing FGProps" );
return true;
}
/**
- *
+ *
*/
bool
FGProps::process()
{
- netChannel::poll();
+ simgear::NetChannel::poll();
return true;
}
/**
- *
+ *
*/
void
FGProps::handleAccept()
{
- netAddress addr;
+ simgear::IPAddress addr;
int handle = accept( &addr );
SG_LOG( SG_IO, SG_INFO, "Props server accepted connection from "
- << addr.getHost() << ":" << addr.getPort() );
+ << addr.getHost() << ":" << addr.getPort() );
PropsChannel* channel = new PropsChannel();
channel->setHandle( handle );
}