Support loading PropertyList data remotely, as part of #450. Along the way, centralise the HTTPClient object so it can be used beyond the METAR download engine.
This commit is contained in:
parent
7d3195aaa6
commit
2218a44ed7
6 changed files with 192 additions and 37 deletions
src
Environment
Main
Network
|
@ -25,42 +25,25 @@
|
|||
#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));
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------------- */
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
50
src/Network/HTTPClient.cxx
Normal file
50
src/Network/HTTPClient.cxx
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
37
src/Network/HTTPClient.hxx
Normal file
37
src/Network/HTTPClient.hxx
Normal file
|
@ -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
|
||||
|
||||
|
Loading…
Add table
Reference in a new issue