X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FNetwork%2Fhttpd.cxx;h=206b553d62373875627eb96e006dc2f0845d4f9c;hb=a1031b052dd40ca3a4ea68dcd7f572b7d9e4bb24;hp=7a567a61a53d3884e1b5a6dfd20e005a53e636e6;hpb=463f8bcb5033cf6dacda2137cd18b077623ca9bd;p=flightgear.git diff --git a/src/Network/httpd.cxx b/src/Network/httpd.cxx index 7a567a61a..206b553d6 100644 --- a/src/Network/httpd.cxx +++ b/src/Network/httpd.cxx @@ -1,12 +1,9 @@ -// httpd.hxx -- FGFS http property manager interface / external script +// httpd.cxx -- 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 -// -// Jpeg Image Support added August 2001 -// by Norman Vine - nhv@cape.com +// Copyright (C) 2001 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 @@ -20,7 +17,7 @@ // // 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$ @@ -31,38 +28,122 @@ #include -#include // atoi() atof() - -#include STL_STRING -#include STL_STRSTREAM +#include // sort() +#include // atoi() atof() +#include +#include #include +#include #include #include -#include +#include +#include #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 +using std::string; + +/* simple httpd server that makes an hasty stab at following the http + 1.1 rfc. */ + +////////////////////////////////////////////////////////////// +// class HttpdChannel +////////////////////////////////////////////////////////////// + +class HttpdChannel : public simgear::NetChat +{ + simgear::NetBuffer buffer; + + string urlEncode(string); + string urlDecode(string); + +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 +////////////////////////////////////////////////////////////// + +class HttpdServer : private simgear::NetChannel +{ + virtual bool writable (void) { return false; } + + virtual void handleAccept (void) { + simgear::IPAddress addr; + int handle = accept ( &addr ); + SG_LOG( SG_IO, SG_INFO, "Client " << addr.getHost() << ":" << addr.getPort() << " connected" ); + + HttpdChannel *hc = new HttpdChannel; + hc->setHandle ( handle ); + } + +public: + + HttpdServer ( int port ); +}; + +HttpdServer::HttpdServer(int port) +{ + if (!open()) + { + SG_LOG( SG_IO, SG_ALERT, "Failed to open HTTP port."); + return; + } + + if (0 != bind( "", port )) + { + SG_LOG( SG_IO, SG_ALERT, "Failed to bind HTTP port."); + return; + } + + if (0 != listen( 5 )) + { + SG_LOG( SG_IO, SG_ALERT, "Failed to listen on HTTP port."); + return; + } + + SG_LOG(SG_IO, SG_ALERT, "Httpd server started on port " << port); +} + +////////////////////////////////////////////////////////////// +// class FGHttpd +////////////////////////////////////////////////////////////// + +FGHttpd::FGHttpd(int p) : + port(p), + server(NULL) +{ +} + +FGHttpd::~FGHttpd() +{ + delete server; +} + 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; + 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_hz( 15 ); // default to processing requests @ 15Hz set_enabled( true ); return true; @@ -70,19 +151,35 @@ bool FGHttpd::open() { bool FGHttpd::process() { - netChannel::poll(); + simgear::NetChannel::poll(); return true; } bool FGHttpd::close() { + if (!server) + return true; + + SG_LOG( SG_IO, SG_INFO, "closing FGHttpd" ); + delete server; + server = NULL; + set_enabled( false ); return true; } +class CompareNodes { +public: + bool operator() (const SGPropertyNode *a, const SGPropertyNode *b) const { + int r = strcmp(a->getName(), b->getName()); + return r ? r < 0 : a->getIndex() < b->getIndex(); + } +}; + + // Handle http GET requests void HttpdChannel::foundTerminator (void) { @@ -91,16 +188,15 @@ void HttpdChannel::foundTerminator (void) { const string s = buffer.getData(); if ( s.find( "GET " ) == 0 ) { - printf("echo: %s\n", s.c_str()); + SG_LOG( SG_IO, SG_INFO, "echo: " << s ); string rest = s.substr(4); string request; string tmp; - unsigned int pos = rest.find( " " ); + string::size_type pos = rest.find( " " ); if ( pos != string::npos ) { request = rest.substr( 0, pos ); - request = urlDecode(request); } else { request = "/"; } @@ -111,7 +207,8 @@ void HttpdChannel::foundTerminator (void) { // 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()); + SG_LOG( SG_IO, SG_INFO, "'" << request << "' '" << args << "'" ); + request = urlDecode(request); // parse args looking for "value=" bool done = false; @@ -126,20 +223,39 @@ void HttpdChannel::foundTerminator (void) { done = true; } - printf(" arg = %s\n", arg.c_str() ); - unsigned int apos = arg.find("="); + SG_LOG( SG_IO, SG_INFO, " arg = " << arg ); + string::size_type 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 ); - } + SG_LOG( SG_IO, SG_INFO, " a = " << a << " b = " << b ); + if ( request == "/run.cgi" ) { + // execute a command + if ( a == "value" ) { + SGPropertyNode args; + if ( !globals->get_commands() + ->execute(urlDecode(b).c_str(), &args) ) + { + SG_LOG( SG_NETWORK, SG_ALERT, + "Command " << urlDecode(b) + << " failed."); + } + + } + } else { + if ( a == "value" ) { + // update a property value + fgSetString( request.c_str(), + urlDecode(b).c_str() ); + } + } } } - } + } else { + request = urlDecode(request); + } - node = globals->get_props()->getNode(request); + node = globals->get_props()->getNode(request.c_str()); string response = ""; response += ""; @@ -174,19 +290,21 @@ void HttpdChannel::foundTerminator (void) { response += "\""; response += getTerminator(); - for (int i = 0; i < node->nChildren(); i++) { - SGPropertyNode *child = node->getChild(i); - string name = child->getName(); - if ( node->getChild(name, 1) ) { - char buf[16]; - sprintf(buf, "[%d]", child->getIndex()); - name += buf; - } + + vector children; + for (int i = 0; i < node->nChildren(); i++) + children.push_back(node->getChild(i)); + std::sort(children.begin(), children.end(), CompareNodes()); + + vector::iterator it, end = children.end(); + for (it = children.begin(); it != end; ++it) { + SGPropertyNode *child = *it; + string name = child->getDisplayName(true); string line = ""; if ( child->nChildren() > 0 ) { line += "getStringValue ( name, "" ); + string value = node->getStringValue ( name.c_str(), "" ); line += ""; line += name; line += " "; response += ""; - response += "
"; - response += "
"; + response += "
"; } response += ""; response += getTerminator(); @@ -237,9 +354,9 @@ void HttpdChannel::foundTerminator (void) { push( "HTTP/1.1 200 OK" ); push( getTerminator() ); - printf("size = %d\n", response.length()); + SG_LOG( SG_IO, SG_INFO, "size = " << response.length() ); char ctmp[256]; - sprintf(ctmp, "Content-Length: %d", response.length()); + sprintf(ctmp, "Content-Length: %u", (unsigned)response.length()); push( ctmp ); push( getTerminator() ); @@ -257,7 +374,7 @@ void HttpdChannel::foundTerminator (void) { } -// encode everything but "a-zA-Z0-9_.-/" +// encode everything but "a-zA-Z0-9_.-/" (see RFC2396) string HttpdChannel::urlEncode(string s) { string r = "";