From c8aa989ac776395a20229700e6b801ee510e4a7a Mon Sep 17 00:00:00 2001 From: Torsten Dreyer Date: Tue, 3 May 2016 12:11:38 +0200 Subject: [PATCH] Terrasync: implement HTTP service lookup via DNS Let terrasync use the http repository if /sim/terrasync/http-server == "automatic" resolve DNS NAPTR RR for terrasync.flightgear.org with service "ws20" and flags "U". Pick one of the returned entries with lowest order and preference. If more than one entry with the same order and preference is returned, pick a random entry of those returned. or if /sim/terrasync/http-server != "automatic" explicitly use the value of that property as the http server if /sim/terrasync/http-server is empty, fall back to the legacy SVN repository --- simgear/scene/tsync/terrasync.cxx | 66 ++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/simgear/scene/tsync/terrasync.cxx b/simgear/scene/tsync/terrasync.cxx index 6385b484..5edc591e 100644 --- a/simgear/scene/tsync/terrasync.cxx +++ b/simgear/scene/tsync/terrasync.cxx @@ -61,7 +61,9 @@ #include #include #include +#include #include +#include static const bool svn_built_in_available = true; @@ -507,7 +509,67 @@ void SGTerraSync::SvnThread::run() initCompletedTilesPersistentCache(); { - if (_svn_server.empty()) { + if (_httpServer == "automatic" ) { + + //TODO: make DN and service settable from properties + DNS::NAPTRRequest * naptrRequest = new DNS::NAPTRRequest("terrasync.flightgear.org"); + naptrRequest->qservice = "ws20"; + + naptrRequest->qflags = "U"; + DNS::Request_ptr r(naptrRequest); + + DNS::Client dnsClient; + dnsClient.makeRequest(r); + while( !r->isComplete() && !r->isTimeout() ) + dnsClient.update(0); + + if( naptrRequest->entries.empty() ) { + SG_LOG(SG_TERRASYNC, SG_ALERT, "ERROR: automatic terrasync http-server requested, but no DNS entry found."); + _httpServer = ""; + } else { + // walk through responses, they are ordered by 1. order and 2. preference + // For now, only take entries with lowest order + // TODO: try all available servers in the order given by preferenc and order + int order = naptrRequest->entries[0]->order; + + // get all servers with this order and the same (for now only lowest preference) + DNS::NAPTRRequest::NAPTR_list availableServers; + for( DNS::NAPTRRequest::NAPTR_list::const_iterator it = naptrRequest->entries.begin(); + it != naptrRequest->entries.end(); + ++it ) { + + if( (*it)->order != order ) + continue; + + string regex = (*it)->regexp; + if( false == simgear::strutils::starts_with( (*it)->regexp, "!^.*$!" ) ) { + SG_LOG(SG_TERRASYNC,SG_WARN, "ignoring unsupported regexp: " << (*it)->regexp ); + continue; + } + + if( false == simgear::strutils::ends_with( (*it)->regexp, "!" ) ) { + SG_LOG(SG_TERRASYNC,SG_WARN, "ignoring unsupported regexp: " << (*it)->regexp ); + continue; + } + + // always use first entry + if( availableServers.empty() || (*it)->preference == availableServers[0]->preference) { + SG_LOG(SG_TERRASYNC,SG_DEBUG, "available server regexp: " << (*it)->regexp ); + availableServers.push_back( *it ); + } + } + + // now pick a random entry from the available servers + DNS::NAPTRRequest::NAPTR_list::size_type idx = sg_random() * availableServers.size(); + _httpServer = availableServers[idx]->regexp; + _httpServer = _httpServer.substr( 6, _httpServer.length()-7 ); // strip search pattern and separators + + SG_LOG(SG_TERRASYNC,SG_INFO, "picking entry # " << idx << ", server is " << _httpServer ); + } + } + } + if( _httpServer.empty() ) { // don't resolve SVN server is HTTP server is set + if ( _svn_server.empty()) { SG_LOG(SG_TERRASYNC,SG_INFO, "Querying closest TerraSync server"); ServerSelectQuery* ssq = new ServerSelectQuery; HTTP::Request_ptr req = ssq; @@ -527,8 +589,10 @@ void SGTerraSync::SvnThread::run() } if (_svn_server.empty()) { +#if WE_HAVE_A_DEFAULT_SERVER_BUT_WE_DONT_THIS_URL_IS_NO_LONGER_VALID // default value _svn_server = "http://foxtrot.mgras.net:8080/terrascenery/trunk/data/Scenery"; +#endif } } -- 2.39.5