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
|
#endif
|
||||||
|
|
||||||
#include "realwx_ctrl.hxx"
|
#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 <boost/foreach.hpp>
|
||||||
|
|
||||||
#include <simgear/structure/exception.hxx>
|
#include <simgear/structure/exception.hxx>
|
||||||
#include <simgear/misc/strutils.hxx>
|
#include <simgear/misc/strutils.hxx>
|
||||||
#include <simgear/props/tiedpropertylist.hxx>
|
#include <simgear/props/tiedpropertylist.hxx>
|
||||||
#include <simgear/io/HTTPClient.hxx>
|
|
||||||
#include <simgear/io/HTTPRequest.hxx>
|
#include <simgear/io/HTTPRequest.hxx>
|
||||||
#include <simgear/timing/sg_time.hxx>
|
#include <simgear/timing/sg_time.hxx>
|
||||||
#include <simgear/structure/event_mgr.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 {
|
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 {
|
class NoaaMetarRealWxController : public BasicRealWxController, MetarRequester {
|
||||||
public:
|
public:
|
||||||
NoaaMetarRealWxController( SGPropertyNode_ptr rootNode );
|
NoaaMetarRealWxController( SGPropertyNode_ptr rootNode );
|
||||||
virtual ~NoaaMetarRealWxController();
|
|
||||||
virtual void update( double dt );
|
|
||||||
|
|
||||||
// implementation of MetarRequester
|
// implementation of MetarRequester
|
||||||
virtual void requestMetar( MetarDataHandler * metarDataHandler, const std::string & id );
|
virtual void requestMetar( MetarDataHandler * metarDataHandler, const std::string & id );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FGHTTPClient _http;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
NoaaMetarRealWxController::NoaaMetarRealWxController( SGPropertyNode_ptr rootNode ) :
|
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 )
|
void NoaaMetarRealWxController::requestMetar( MetarDataHandler * metarDataHandler, const std::string & id )
|
||||||
{
|
{
|
||||||
class NoaaMetarGetRequest : public simgear::HTTP::Request
|
class NoaaMetarGetRequest : public simgear::HTTP::Request
|
||||||
|
@ -384,7 +355,7 @@ void NoaaMetarRealWxController::requestMetar( MetarDataHandler * metarDataHandle
|
||||||
|
|
||||||
SG_LOG(SG_ENVIRONMENT, SG_INFO,
|
SG_LOG(SG_ENVIRONMENT, SG_INFO,
|
||||||
"NoaaMetarRealWxController::update(): spawning load request for station-id '" << id << "'" );
|
"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/sound/soundmgr_openal.hxx>
|
||||||
#include <simgear/timing/sg_time.hxx>
|
#include <simgear/timing/sg_time.hxx>
|
||||||
#include <simgear/misc/interpolator.hxx>
|
#include <simgear/misc/interpolator.hxx>
|
||||||
|
#include <simgear/io/HTTPRequest.hxx>
|
||||||
|
|
||||||
#include <Cockpit/panel.hxx>
|
#include <Cockpit/panel.hxx>
|
||||||
#include <Cockpit/panel_io.hxx>
|
#include <Cockpit/panel_io.hxx>
|
||||||
|
@ -39,6 +40,7 @@
|
||||||
#include <ATC/CommStation.hxx>
|
#include <ATC/CommStation.hxx>
|
||||||
#include <Navaids/navrecord.hxx>
|
#include <Navaids/navrecord.hxx>
|
||||||
#include <Navaids/navlist.hxx>
|
#include <Navaids/navlist.hxx>
|
||||||
|
#include <Network/HTTPClient.hxx>
|
||||||
|
|
||||||
#include "fg_init.hxx"
|
#include "fg_init.hxx"
|
||||||
#include "fg_io.hxx"
|
#include "fg_io.hxx"
|
||||||
|
@ -1316,6 +1318,93 @@ do_load_xml_to_proptree(const SGPropertyNode * arg)
|
||||||
return true;
|
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,
|
* An fgcommand to allow saving of xml files via nasal,
|
||||||
|
@ -1531,6 +1620,7 @@ static struct {
|
||||||
*/
|
*/
|
||||||
{ "loadxml", do_load_xml_to_proptree},
|
{ "loadxml", do_load_xml_to_proptree},
|
||||||
{ "savexml", do_save_xml_from_proptree },
|
{ "savexml", do_save_xml_from_proptree },
|
||||||
|
{ "xmlhttprequest", do_load_xml_from_url },
|
||||||
{ "press-cockpit-button", do_press_cockpit_button },
|
{ "press-cockpit-button", do_press_cockpit_button },
|
||||||
{ "release-cockpit-button", do_release_cockpit_button },
|
{ "release-cockpit-button", do_release_cockpit_button },
|
||||||
{ "dump-scenegraph", do_dump_scene_graph },
|
{ "dump-scenegraph", do_dump_scene_graph },
|
||||||
|
|
|
@ -65,6 +65,7 @@
|
||||||
#include <Network/ray.hxx>
|
#include <Network/ray.hxx>
|
||||||
#include <Network/rul.hxx>
|
#include <Network/rul.hxx>
|
||||||
#include <Network/generic.hxx>
|
#include <Network/generic.hxx>
|
||||||
|
#include <Network/HTTPClient.hxx>
|
||||||
|
|
||||||
#ifdef FG_HAVE_HLA
|
#ifdef FG_HAVE_HLA
|
||||||
#include <Network/HLA/hla.hxx>
|
#include <Network/HLA/hla.hxx>
|
||||||
|
@ -382,6 +383,10 @@ FGIO::reinit()
|
||||||
void
|
void
|
||||||
FGIO::update( double /* delta_time_sec */ )
|
FGIO::update( double /* delta_time_sec */ )
|
||||||
{
|
{
|
||||||
|
if (FGHTTPClient::haveInstance()) {
|
||||||
|
FGHTTPClient::instance()->update();
|
||||||
|
}
|
||||||
|
|
||||||
// use wall-clock, not simulation, delta time, so that network
|
// use wall-clock, not simulation, delta time, so that network
|
||||||
// protocols update when the simulation is paused
|
// protocols update when the simulation is paused
|
||||||
// see http://code.google.com/p/flightgear-bugs/issues/detail?id=125
|
// see http://code.google.com/p/flightgear-bugs/issues/detail?id=125
|
||||||
|
|
|
@ -11,6 +11,7 @@ set(SOURCES
|
||||||
garmin.cxx
|
garmin.cxx
|
||||||
generic.cxx
|
generic.cxx
|
||||||
httpd.cxx
|
httpd.cxx
|
||||||
|
HTTPClient.cxx
|
||||||
joyclient.cxx
|
joyclient.cxx
|
||||||
jsclient.cxx
|
jsclient.cxx
|
||||||
lfsglass.cxx
|
lfsglass.cxx
|
||||||
|
@ -38,6 +39,7 @@ set(HEADERS
|
||||||
garmin.hxx
|
garmin.hxx
|
||||||
generic.hxx
|
generic.hxx
|
||||||
httpd.hxx
|
httpd.hxx
|
||||||
|
HTTPClient.hxx
|
||||||
joyclient.hxx
|
joyclient.hxx
|
||||||
jsclient.hxx
|
jsclient.hxx
|
||||||
lfsglass.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