1
0
Fork 0

Support loading PropertyList data remotely, as part of . Along the way, centralise the HTTPClient object so it can be used beyond the METAR download engine.

This commit is contained in:
James Turner 2012-04-18 10:25:27 +01:00
parent 7d3195aaa6
commit 2218a44ed7
6 changed files with 192 additions and 37 deletions

View file

@ -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));
}
/* -------------------------------------------------------------------------------- */

View 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 },

View 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

View 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

View 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);
}
}

View 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