]> git.mxchange.org Git - flightgear.git/commitdiff
Support loading PropertyList data remotely, as part of #450. Along the way, centralis...
authorJames Turner <zakalawe@mac.com>
Wed, 18 Apr 2012 09:25:27 +0000 (10:25 +0100)
committerJames Turner <zakalawe@mac.com>
Wed, 18 Apr 2012 09:25:27 +0000 (10:25 +0100)
src/Environment/realwx_ctrl.cxx
src/Main/fg_commands.cxx
src/Main/fg_io.cxx
src/Network/CMakeLists.txt
src/Network/HTTPClient.cxx [new file with mode: 0644]
src/Network/HTTPClient.hxx [new file with mode: 0644]

index b93316490aad54313e2f2391d7ac317d6b66f294..0e38d9355d3d6fcf8c5b7cbf295bcc8b897bf49b 100644 (file)
 #endif
 
 #include "realwx_ctrl.hxx"
-#include "metarproperties.hxx"
-#include "metarairportfilter.hxx"
-#include "fgmetar.hxx"
-
-#include <Main/fg_props.hxx>
 
+#include <algorithm>
 #include <boost/foreach.hpp>
 
 #include <simgear/structure/exception.hxx>
 #include <simgear/misc/strutils.hxx>
 #include <simgear/props/tiedpropertylist.hxx>
-#include <simgear/io/HTTPClient.hxx>
 #include <simgear/io/HTTPRequest.hxx>
 #include <simgear/timing/sg_time.hxx>
 #include <simgear/structure/event_mgr.hxx>
 
-#include <algorithm>
+#include "metarproperties.hxx"
+#include "metarairportfilter.hxx"
+#include "fgmetar.hxx"
+#include <Network/HTTPClient.hxx>
+#include <Main/fg_props.hxx>
 
 namespace Environment {
-/* -------------------------------------------------------------------------------- */
 
-class FGHTTPClient : public simgear::HTTP::Client {
-public:
-    FGHTTPClient();
-};
-
-FGHTTPClient::FGHTTPClient()
-{
-    string proxyHost(fgGetString("/sim/presets/proxy/host"));
-    int proxyPort(fgGetInt("/sim/presets/proxy/port"));
-    string proxyAuth(fgGetString("/sim/presets/proxy/auth"));
-    
-    if (!proxyHost.empty()) {
-        setProxy(proxyHost, proxyPort, proxyAuth);
-    }
-}
 
 /* -------------------------------------------------------------------------------- */
 
@@ -295,14 +278,12 @@ void BasicRealWxController::checkNearbyMetar()
 class NoaaMetarRealWxController : public BasicRealWxController, MetarRequester {
 public:
     NoaaMetarRealWxController( SGPropertyNode_ptr rootNode );
-    virtual ~NoaaMetarRealWxController();
-    virtual void update( double dt );
 
     // implementation of MetarRequester
     virtual void requestMetar( MetarDataHandler * metarDataHandler, const std::string & id );
 
 private:
-    FGHTTPClient _http;
+    
 };
 
 NoaaMetarRealWxController::NoaaMetarRealWxController( SGPropertyNode_ptr rootNode ) :
@@ -310,16 +291,6 @@ NoaaMetarRealWxController::NoaaMetarRealWxController( SGPropertyNode_ptr rootNod
 {
 }
 
-NoaaMetarRealWxController::~NoaaMetarRealWxController()
-{
-}
-
-void NoaaMetarRealWxController::update( double dt )
-{
-    _http.update();
-    BasicRealWxController::update( dt );
-}
-
 void NoaaMetarRealWxController::requestMetar( MetarDataHandler * metarDataHandler, const std::string & id )
 {
     class NoaaMetarGetRequest : public simgear::HTTP::Request
@@ -384,7 +355,7 @@ void NoaaMetarRealWxController::requestMetar( MetarDataHandler * metarDataHandle
 
     SG_LOG(SG_ENVIRONMENT, SG_INFO, 
         "NoaaMetarRealWxController::update(): spawning load request for station-id '" << id << "'" );
-    _http.makeRequest(new NoaaMetarGetRequest(metarDataHandler, id));
+    FGHTTPClient::instance()->makeRequest(new NoaaMetarGetRequest(metarDataHandler, id));
 }
 
 /* -------------------------------------------------------------------------------- */
index bf7bbdedeedf502217e85d3c39855f4062be7c77..cf36a7777cecedc9bb7f6f5f5e94efc2844e015d 100644 (file)
@@ -24,6 +24,7 @@
 #include <simgear/sound/soundmgr_openal.hxx>
 #include <simgear/timing/sg_time.hxx>
 #include <simgear/misc/interpolator.hxx>
+#include <simgear/io/HTTPRequest.hxx>
 
 #include <Cockpit/panel.hxx>
 #include <Cockpit/panel_io.hxx>
@@ -39,6 +40,7 @@
 #include <ATC/CommStation.hxx>
 #include <Navaids/navrecord.hxx>
 #include <Navaids/navlist.hxx>
+#include <Network/HTTPClient.hxx>
 
 #include "fg_init.hxx"
 #include "fg_io.hxx"
@@ -1316,6 +1318,93 @@ do_load_xml_to_proptree(const SGPropertyNode * arg)
     return true;
 }
 
+class RemoteXMLRequest : public simgear::HTTP::Request
+{
+public:
+    SGPropertyNode_ptr _complete;
+    SGPropertyNode_ptr _status;
+    SGPropertyNode_ptr _failed;
+    SGPropertyNode_ptr _target;
+    string propsData;
+    
+    RemoteXMLRequest(const std::string& url, SGPropertyNode* targetNode) : 
+        simgear::HTTP::Request(url),
+        _target(targetNode)
+    {
+    }
+    
+    void setCompletionProp(SGPropertyNode_ptr p)
+    {
+        _complete = p;
+    }
+    
+    void setStatusProp(SGPropertyNode_ptr p)
+    {
+        _status = p;
+    }
+    
+    void setFailedProp(SGPropertyNode_ptr p)
+    {
+        _failed = p;
+    }
+protected:
+    virtual void gotBodyData(const char* s, int n)
+    {
+        propsData += string(s, n);
+    }
+    
+    virtual void responseComplete()
+    {
+        int response = responseCode();
+        bool failed = false;
+        if (response == 200) {
+            try {
+                const char* buffer = propsData.c_str();
+                readProperties(buffer, propsData.size(), _target, true);
+            } catch (const sg_exception &e) {
+                SG_LOG(SG_IO, SG_WARN, "parsing XML from remote, failed: " << e.getFormattedMessage());
+                failed = true;
+                response = 406; // 'not acceptable', anything better?
+            }
+        } else {
+            failed = true;
+        }
+    // now the response data is output, signal Nasal / listeners
+        if (_complete) _complete->setBoolValue(true);
+        if (_status) _status->setIntValue(response);
+        if (_failed) _failed->setBoolValue(failed);
+    }
+};
+
+
+static bool
+do_load_xml_from_url(const SGPropertyNode * arg)
+{
+    std::string url(arg->getStringValue("url"));
+    if (url.empty())
+        return false;
+        
+    SGPropertyNode *targetnode;
+    if (arg->hasValue("targetnode"))
+        targetnode = fgGetNode(arg->getStringValue("targetnode"), true);
+    else
+        targetnode = const_cast<SGPropertyNode *>(arg)->getNode("data", true);
+    
+    RemoteXMLRequest* req = new RemoteXMLRequest(url, targetnode);
+    
+// connect up optional reporting properties
+    if (arg->hasValue("complete")) 
+        req->setCompletionProp(fgGetNode(arg->getStringValue("complete"), true));
+    if (arg->hasValue("failure")) 
+        req->setFailedProp(fgGetNode(arg->getStringValue("failure"), true));
+    if (arg->hasValue("status")) 
+        req->setStatusProp(fgGetNode(arg->getStringValue("status"), true));
+        
+    FGHTTPClient::instance()->makeRequest(req);
+    
+    return true;
+}
+
 
 /**
  * An fgcommand to allow saving of xml files via nasal,
@@ -1531,6 +1620,7 @@ static struct {
     */
     { "loadxml", do_load_xml_to_proptree},
     { "savexml", do_save_xml_from_proptree },
+    { "xmlhttprequest", do_load_xml_from_url },
     { "press-cockpit-button", do_press_cockpit_button },
     { "release-cockpit-button", do_release_cockpit_button },
     { "dump-scenegraph", do_dump_scene_graph },
index 7c5f6965245aa59ce693b35472769ec25dc16e38..2014212b5faeea942061604d8a30bafc5987e263 100644 (file)
@@ -65,6 +65,7 @@
 #include <Network/ray.hxx>
 #include <Network/rul.hxx>
 #include <Network/generic.hxx>
+#include <Network/HTTPClient.hxx>
 
 #ifdef FG_HAVE_HLA
 #include <Network/HLA/hla.hxx>
@@ -382,6 +383,10 @@ FGIO::reinit()
 void
 FGIO::update( double /* delta_time_sec */ )
 {
+    if (FGHTTPClient::haveInstance()) {
+        FGHTTPClient::instance()->update();
+    }
+    
   // use wall-clock, not simulation, delta time, so that network
   // protocols update when the simulation is paused
   // see http://code.google.com/p/flightgear-bugs/issues/detail?id=125
index f7947495d4a77fe7708cc60e73ca108253abad0d..2d2bc2c5b11201afbe57e258792ba7e83a177947 100644 (file)
@@ -11,6 +11,7 @@ set(SOURCES
        garmin.cxx
        generic.cxx
        httpd.cxx
+       HTTPClient.cxx
        joyclient.cxx
        jsclient.cxx
        lfsglass.cxx
@@ -38,6 +39,7 @@ set(HEADERS
        garmin.hxx
        generic.hxx
        httpd.hxx
+       HTTPClient.hxx
        joyclient.hxx
        jsclient.hxx
        lfsglass.hxx
diff --git a/src/Network/HTTPClient.cxx b/src/Network/HTTPClient.cxx
new file mode 100644 (file)
index 0000000..ca293d8
--- /dev/null
@@ -0,0 +1,50 @@
+// HTTPClient.cxx -- Singleton HTTP client object
+//
+// Written by James Turner, started April 2012.
+//
+// Copyright (C) 2012  James Turner
+//
+// 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+#include "HTTPClient.hxx"
+
+#include <Main/fg_props.hxx>
+
+static FGHTTPClient* static_instance = NULL;
+
+FGHTTPClient* FGHTTPClient::instance()
+{
+       if (!static_instance) {
+               static_instance = new FGHTTPClient;
+       }
+       
+       return static_instance;
+}
+
+bool FGHTTPClient::haveInstance()
+{
+    return (static_instance != NULL);
+}
+
+FGHTTPClient::FGHTTPClient()
+{
+    std::string proxyHost(fgGetString("/sim/presets/proxy/host"));
+    int proxyPort(fgGetInt("/sim/presets/proxy/port"));
+    std::string proxyAuth(fgGetString("/sim/presets/proxy/auth"));
+    
+    if (!proxyHost.empty()) {
+        setProxy(proxyHost, proxyPort, proxyAuth);
+    }
+}
diff --git a/src/Network/HTTPClient.hxx b/src/Network/HTTPClient.hxx
new file mode 100644 (file)
index 0000000..b36027e
--- /dev/null
@@ -0,0 +1,37 @@
+// HTTPClient.hxx -- Singleton HTTP client object
+//
+// Written by James Turner, started April 2012.
+//
+// Copyright (C) 2012  James Turner
+//
+// 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+#ifndef FG_HTTP_CLIENT_HXX
+#define FG_HTTP_CLIENT_HXX
+
+#include <simgear/io/HTTPClient.hxx>
+
+class FGHTTPClient : public simgear::HTTP::Client {
+public:
+       static FGHTTPClient* instance();
+
+    static bool haveInstance();
+private:
+    FGHTTPClient();
+};
+
+#endif // FG_HTTP_CLIENT_HXX
+
+