diff --git a/src/Network/httpd.cxx b/src/Network/httpd.cxx new file mode 100644 index 000000000..f2c237fff --- /dev/null +++ b/src/Network/httpd.cxx @@ -0,0 +1,237 @@ +// httpd.hxx -- FGFS http property manager interface / external script +// and control class +// +// Written by Curtis Olson, started June 2001. +// +// Copyright (C) 2001 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$ + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include +#include +#include +#include + +#include // atoi() atof() + +#include STL_STRING +#include STL_STRSTREAM + +#include
+#include
+ +#include "httpd.hxx" + +SG_USING_STD(string); +#if !defined(SG_HAVE_NATIVE_SGI_COMPILERS) +SG_USING_STD(cout); +SG_USING_STD(istrstream); +#endif + + +bool FGHttpd::open() { + if ( is_enabled() ) { + SG_LOG( SG_IO, SG_ALERT, "This shouldn't happen, but the channel " + << "is already in use, ignoring" ); + return false; + } + + server = new HttpdServer( port ); + + set_hz( 5 ); // default to processing requests @ 5Hz + set_enabled( true ); + + return true; +} + + +bool FGHttpd::process() { + netChannel::poll(); + + return true; +} + + +bool FGHttpd::close() { + delete server; + + return true; +} + + +// Handle http GET requests +void HttpdChannel::foundTerminator (void) { + const string s = buffer.getData(); + + if ( s.find( "GET " ) == 0 ) { + printf("echo: %s\n", s.c_str()); + + string rest = s.substr(4); + string request; + string tmp; + + unsigned int pos = rest.find( " " ); + if ( pos != string::npos ) { + request = rest.substr( 0, pos ); + } else { + request = "/"; + } + + SGPropertyNode *node = NULL; + pos = request.find( "?" ); + if ( pos != string::npos ) { + // request to update property value + string args = request.substr( pos + 1 ); + request = request.substr( 0, pos ); + printf("'%s' '%s'\n", request.c_str(), args.c_str()); + + // parse args looking for "value=" + bool done = false; + while ( ! done ) { + string arg; + pos = args.find("&"); + if ( pos != string::npos ) { + arg = args.substr( 0, pos ); + args = args.substr( pos + 1 ); + } else { + arg = args; + done = true; + } + + printf(" arg = %s\n", arg.c_str() ); + unsigned int apos = arg.find("="); + if ( apos != string::npos ) { + string a = arg.substr( 0, apos ); + string b = arg.substr( apos + 1 ); + printf(" a = %s b = %s\n", a.c_str(), b.c_str() ); + if ( a == "value" ) { + fgSetString( request, b ); + } + } + } + } + + node = globals->get_props()->getNode(request); + + string response = ""; + response += ""; + response += getTerminator(); + + response += ""; + response += getTerminator(); + + response += "HUD - "; + response += request; + response += ""; + response += getTerminator(); + + response += ""; + response += getTerminator(); + + response += ""; + response += getTerminator(); + + if ( node->nChildren() > 0 ) { + // request is a path with children + response += "

Contents of \""; + response += request; + response += "\"

"; + response += getTerminator(); + + for (int i = 0; i < node->nChildren(); i++) { + SGPropertyNode *child = node->getChild(i); + string name = child->getName(); + string line = ""; + if ( child->nChildren() > 0 ) { + line += ""; + line += name; + line += ""; + line += "/
"; + } else { + string value = node->getStringValue ( name, "" ); + line += ""; + line += name; + line += " ("; + line += value; + line += ")
"; + } + response += line; + response += getTerminator(); + } + } else { + // request for an individual data member + string value = node->getStringValue(); + + response += "
"; + response += ""; + response += request; + response += " = "; + response += ""; + response += ""; + response += ""; + response += "
"; + } + response += ""; + response += getTerminator(); + + response += ""; + response += getTerminator(); + + push( "HTTP/1.1 200 OK" ); + push( getTerminator() ); + + printf("size = %d\n", response.length()); + char ctmp[256]; + sprintf(ctmp, "Content-Length: %d", response.length()); + push( ctmp ); + push( getTerminator() ); + + push( "Connection: close" ); + push( getTerminator() ); + + push( "Content-Type: text/html" ); + push( getTerminator() ); + push( getTerminator() ); + + push( response.c_str() ); + } + + buffer.remove(); +} diff --git a/src/Network/httpd.hxx b/src/Network/httpd.hxx new file mode 100644 index 000000000..56bdbedef --- /dev/null +++ b/src/Network/httpd.hxx @@ -0,0 +1,102 @@ +// httpd.hxx -- FGFS http property manager interface / external script +// and control class +// +// Written by Curtis Olson, started June 2001. +// +// Copyright (C) 2001 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 _FG_HTTPD_HXX +#define _FG_HTTPD_HXX + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "protocol.hxx" + + +/* simple httpd server that makes an hasty stab at following the http + 1.1 rfc. */ + +class HttpdChannel : public netChat +{ + + netBuffer buffer ; + +public: + + HttpdChannel() : buffer(512) { setTerminator("\r\n"); } + + virtual void collectIncomingData (const char* s, int n) { + buffer.append(s,n); + } + + // Handle the actual http request + virtual void foundTerminator (void); +} ; + + +class HttpdServer : private netChannel +{ + virtual bool writable (void) { return false ; } + + virtual void handleAccept (void) { + netAddress addr ; + int handle = accept ( &addr ) ; + printf("Client %s:%d connected\n", addr.getHost(), addr.getPort()); + + HttpdChannel *hc = new HttpdChannel; + hc->setHandle ( handle ) ; + } + +public: + + HttpdServer ( int port ) { + open () ; + bind ("", port) ; + listen (5) ; + + printf ( "Httpd server started on port %d\n", port ) ; + } +}; + + +class FGHttpd : public FGProtocol { + + int port; + HttpdServer *server; + +public: + + inline FGHttpd( int p ) { port = p; } + + inline ~FGHttpd() { } + + bool open(); + + bool process(); + + bool close(); +}; + + +#endif // _FG_HTTPD_HXX