Merge branch 'next' of gitorious.org:fg/simgear into next

This commit is contained in:
Stuart Buchanan
2011-09-01 19:55:11 +01:00
18 changed files with 554 additions and 152 deletions

View File

@@ -32,6 +32,9 @@ AM_INIT_AUTOMAKE([dist-bzip2])
AC_ARG_ENABLE(headless,
AS_HELP_STRING([--enable-headless],[Enable only packages for headless build]))
AC_ARG_ENABLE(osgdebug,
AS_HELP_STRING([--enable-osgdebug],[Enable debug OSG libraries]))
AC_MSG_CHECKING([for headless mode])
AC_MSG_RESULT([$enable_headless])
@@ -437,6 +440,8 @@ AM_CONDITIONAL(EXTGL_NEEDED, test "x$ac_cv_header_windows_h" = "xyes")
CXXCPP="g++ -E"
AC_LANG_PUSH(C++)
LIBS="$base_LIBS"
# OpenSceneGraph
case "${host}" in
*-apple-darwin*)
@@ -497,6 +502,10 @@ if test "x$ac_cv_header_osg_Version" != "xyes" -o "x$ac_cv_lib_OpenThreads_OpenT
fi
fi
osg_LIBS="$LIBS"
AC_SUBST(osg_LIBS)
LIBS="$base_LIBS"
AC_CHECK_HEADER(boost/version.hpp)
if test "x$ac_cv_header_boost_version_hpp" != "xyes"; then
echo

View File

@@ -26,9 +26,6 @@ set(HLA_HEADERS
)
set(HLA_SOURCES
RTIObjectClass.cxx
RTIObjectInstance.cxx
RTIFederate.cxx
HLAArrayDataElement.cxx
HLAArrayDataType.cxx
HLABasicDataElement.cxx
@@ -51,15 +48,18 @@ set(HLA_SOURCES
simgear_component(hla hla "${HLA_SOURCES}" "${HLA_HEADERS}")
if(RTI_FOUND)
set(HLA13_HEADERS
HLA13Federate.hxx
)
set(HLA13_SOURCES
set(RTI13_SOURCES
RTI13ObjectClass.cxx
RTI13ObjectInstance.cxx
RTI13Federate.cxx
HLA13Federate.cxx
)
simgear_component(hla13 hla "${HLA13_SOURCES}" "${HLA13_HEADERS}")
set_property(TARGET sghla13 APPEND PROPERTY COMPILE_FLAGS "-I${RTI_INCLUDE_DIR}")
simgear_component(rti13 hla "${RTI13_SOURCES}" "")
set_property(TARGET sgrti13 APPEND PROPERTY COMPILE_FLAGS "-I${RTI_INCLUDE_DIR}")
endif()
set(RTI_SOURCES
RTIObjectClass.cxx
RTIObjectInstance.cxx
RTIFederate.cxx
)
simgear_component(rti hla "${RTI_SOURCES}" "")

View File

@@ -1,33 +0,0 @@
// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Library 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 "HLA13Federate.hxx"
#include "RTI13Federate.hxx"
namespace simgear {
HLA13Federate::HLA13Federate() :
HLAFederate(new RTI13Federate)
{
}
HLA13Federate::~HLA13Federate()
{
}
} // namespace simgear

View File

@@ -1,33 +0,0 @@
// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Library 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 HLA13Federate_hxx
#define HLA13Federate_hxx
#include "HLAFederate.hxx"
namespace simgear {
class HLA13Federate : public HLAFederate {
public:
HLA13Federate();
virtual ~HLA13Federate();
};
} // namespace simgear
#endif

View File

@@ -248,6 +248,43 @@ private:
SGVec2<T> _value;
};
template<typename T>
class HLAVec2Data {
public:
HLAVec2Data() :
_value(new HLAVec2DataElement<T>(0))
{ }
HLAVec2Data(const SGVec2<T>& value) :
_value(new HLAVec2DataElement<T>(0, value))
{ }
operator const SGVec2<T>&() const
{ return _value->getValue(); }
HLAVec2Data& operator=(const SGVec2<T>& value)
{ _value->setValue(value); return *this; }
const SGVec2<T>& getValue() const
{ return _value->getValue(); }
void setValue(const SGVec2<T>& value)
{ _value->setValue(value); }
const HLAVec2DataElement<T>* getDataElement() const
{ return _value.get(); }
HLAVec2DataElement<T>* getDataElement()
{ return _value.get(); }
const HLAArrayDataType* getDataType() const
{ return _value->getDataType(); }
void setDataType(const HLAArrayDataType* dataType)
{ _value->setDataType(dataType); }
private:
SGSharedPtr<HLAVec2DataElement<T> > _value;
};
typedef HLAVec2Data<float> HLAVec2fData;
typedef HLAVec2Data<double> HLAVec2dData;
template<typename T>
class HLAVec3DataElement : public HLAAbstractArrayDataElement {
public:
@@ -303,6 +340,43 @@ private:
SGVec3<T> _value;
};
template<typename T>
class HLAVec3Data {
public:
HLAVec3Data() :
_value(new HLAVec3DataElement<T>(0))
{ }
HLAVec3Data(const SGVec3<T>& value) :
_value(new HLAVec3DataElement<T>(0, value))
{ }
operator const SGVec3<T>&() const
{ return _value->getValue(); }
HLAVec3Data& operator=(const SGVec3<T>& value)
{ _value->setValue(value); return *this; }
const SGVec3<T>& getValue() const
{ return _value->getValue(); }
void setValue(const SGVec3<T>& value)
{ _value->setValue(value); }
const HLAVec3DataElement<T>* getDataElement() const
{ return _value.get(); }
HLAVec3DataElement<T>* getDataElement()
{ return _value.get(); }
const HLAArrayDataType* getDataType() const
{ return _value->getDataType(); }
void setDataType(const HLAArrayDataType* dataType)
{ _value->setDataType(dataType); }
private:
SGSharedPtr<HLAVec3DataElement<T> > _value;
};
typedef HLAVec3Data<float> HLAVec3fData;
typedef HLAVec3Data<double> HLAVec3dData;
template<typename T>
class HLAVec4DataElement : public HLAAbstractArrayDataElement {
public:
@@ -358,6 +432,43 @@ private:
SGVec4<T> _value;
};
template<typename T>
class HLAVec4Data {
public:
HLAVec4Data() :
_value(new HLAVec4DataElement<T>(0))
{ }
HLAVec4Data(const SGVec4<T>& value) :
_value(new HLAVec4DataElement<T>(0, value))
{ }
operator const SGVec4<T>&() const
{ return _value->getValue(); }
HLAVec4Data& operator=(const SGVec4<T>& value)
{ _value->setValue(value); return *this; }
const SGVec4<T>& getValue() const
{ return _value->getValue(); }
void setValue(const SGVec4<T>& value)
{ _value->setValue(value); }
const HLAVec4DataElement<T>* getDataElement() const
{ return _value.get(); }
HLAVec4DataElement<T>* getDataElement()
{ return _value.get(); }
const HLAArrayDataType* getDataType() const
{ return _value->getDataType(); }
void setDataType(const HLAArrayDataType* dataType)
{ _value->setDataType(dataType); }
private:
SGSharedPtr<HLAVec4DataElement<T> > _value;
};
typedef HLAVec4Data<float> HLAVec4fData;
typedef HLAVec4Data<double> HLAVec4dData;
template<typename T>
class HLAQuatDataElement : public HLAAbstractArrayDataElement {
public:

View File

@@ -17,6 +17,7 @@
#include "HLAFederate.hxx"
#include "RTI13Federate.hxx"
#include "RTIFederate.hxx"
#include "RTIInteractionClass.hxx"
#include "RTIObjectClass.hxx"
@@ -26,8 +27,7 @@
namespace simgear {
HLAFederate::HLAFederate(const SGSharedPtr<RTIFederate>& rtiFederate) :
_rtiFederate(rtiFederate)
HLAFederate::HLAFederate()
{
}
@@ -35,99 +35,209 @@ HLAFederate::~HLAFederate()
{
}
const std::string&
std::string
HLAFederate::getFederateType() const
{
if (!_rtiFederate.valid()) {
SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
return std::string();
}
return _rtiFederate->getFederateType();
}
const std::string&
std::string
HLAFederate::getFederationName() const
{
if (!_rtiFederate.valid()) {
SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
return std::string();
}
return _rtiFederate->getFederationName();
}
bool
HLAFederate::connect(Version version, const std::list<std::string>& stringList)
{
if (_rtiFederate.valid()) {
SG_LOG(SG_NETWORK, SG_WARN, "HLA: Trying to connect to already connected federate!");
return false;
}
switch (version) {
case RTI13:
_rtiFederate = new RTI13Federate(stringList);
break;
case RTI1516:
SG_LOG(SG_IO, SG_ALERT, "HLA version RTI1516 not yet(!?) supported.");
// _rtiFederate = new RTI1516Federate(stringList);
break;
case RTI1516E:
SG_LOG(SG_IO, SG_ALERT, "HLA version RTI1516E not yet(!?) supported.");
// _rtiFederate = new RTI1516eFederate(stringList);
break;
default:
SG_LOG(SG_NETWORK, SG_WARN, "HLA: Unknown rti version in connect!");
}
return _rtiFederate.valid();
}
bool
HLAFederate::disconnect()
{
if (!_rtiFederate.valid()) {
SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
return false;
}
_rtiFederate = 0;
return true;
}
bool
HLAFederate::createFederationExecution(const std::string& federation, const std::string& objectModel)
{
if (!_rtiFederate.valid()) {
SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
return false;
}
return _rtiFederate->createFederationExecution(federation, objectModel);
}
bool
HLAFederate::destroyFederationExecution(const std::string& federation)
{
if (!_rtiFederate.valid()) {
SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
return false;
}
return _rtiFederate->destroyFederationExecution(federation);
}
bool
HLAFederate::join(const std::string& federateType, const std::string& federation)
{
if (!_rtiFederate.valid()) {
SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
return false;
}
return _rtiFederate->join(federateType, federation);
}
bool
HLAFederate::resign()
{
if (!_rtiFederate.valid()) {
SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
return false;
}
return _rtiFederate->resign();
}
bool
HLAFederate::enableTimeConstrained()
{
if (!_rtiFederate.valid()) {
SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
return false;
}
return _rtiFederate->enableTimeConstrained();
}
bool
HLAFederate::disableTimeConstrained()
{
if (!_rtiFederate.valid()) {
SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
return false;
}
return _rtiFederate->disableTimeConstrained();
}
bool
HLAFederate::enableTimeRegulation(const SGTimeStamp& lookahead)
{
if (!_rtiFederate.valid()) {
SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
return false;
}
return _rtiFederate->enableTimeRegulation(lookahead);
}
bool
HLAFederate::disableTimeRegulation()
{
if (!_rtiFederate.valid()) {
SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
return false;
}
return _rtiFederate->disableTimeRegulation();
}
bool
HLAFederate::timeAdvanceRequestBy(const SGTimeStamp& dt)
{
if (!_rtiFederate.valid()) {
SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
return false;
}
return _rtiFederate->timeAdvanceRequestBy(dt);
}
bool
HLAFederate::timeAdvanceRequest(const SGTimeStamp& dt)
{
if (!_rtiFederate.valid()) {
SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
return false;
}
return _rtiFederate->timeAdvanceRequest(dt);
}
bool
HLAFederate::queryFederateTime(SGTimeStamp& timeStamp)
{
if (!_rtiFederate.valid()) {
SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
return false;
}
return _rtiFederate->queryFederateTime(timeStamp);
}
bool
HLAFederate::modifyLookahead(const SGTimeStamp& timeStamp)
{
if (!_rtiFederate.valid()) {
SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
return false;
}
return _rtiFederate->modifyLookahead(timeStamp);
}
bool
HLAFederate::queryLookahead(SGTimeStamp& timeStamp)
{
if (!_rtiFederate.valid()) {
SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
return false;
}
return _rtiFederate->queryLookahead(timeStamp);
}
bool
HLAFederate::tick()
{
if (!_rtiFederate.valid()) {
SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
return false;
}
return _rtiFederate->tick();
}
bool
HLAFederate::tick(const double& minimum, const double& maximum)
{
if (!_rtiFederate.valid()) {
SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
return false;
}
return _rtiFederate->tick(minimum, maximum);
}
@@ -136,8 +246,7 @@ HLAFederate::readObjectModelTemplate(const std::string& objectModel,
HLAFederate::ObjectModelFactory& objectModelFactory)
{
if (!_rtiFederate.valid()) {
SG_LOG(SG_IO, SG_ALERT, "Could not process HLA XML object model file: "
"No rti federate available!");
SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
return false;
}

View File

@@ -32,11 +32,22 @@ class RTIFederate;
class HLAFederate : public SGWeakReferenced {
public:
enum Version {
RTI13,
RTI1516,
RTI1516E
};
HLAFederate();
virtual ~HLAFederate();
/// connect to an rti
bool connect(Version version, const std::list<std::string>& stringList);
bool disconnect();
/// Get the name of the joined federate/federation
const std::string& getFederateType() const;
const std::string& getFederationName() const;
std::string getFederateType() const;
std::string getFederationName() const;
/// Create a federation execution
/// Semantically this methods should be static,
@@ -59,6 +70,7 @@ public:
bool timeAdvanceRequest(const SGTimeStamp& dt);
bool queryFederateTime(SGTimeStamp& timeStamp);
bool modifyLookahead(const SGTimeStamp& timeStamp);
bool queryLookahead(SGTimeStamp& timeStamp);
/// Process messages
@@ -93,9 +105,6 @@ public:
HLAInteractionClass* getInteractionClass(const std::string& name);
const HLAInteractionClass* getInteractionClass(const std::string& name) const;
protected:
HLAFederate(const SGSharedPtr<RTIFederate>& rtiFederate);
private:
SGSharedPtr<RTIFederate> _rtiFederate;

View File

@@ -29,9 +29,6 @@ libsghla_a_HEADERS = \
HLAVariantDataType.hxx
libsghla_a_SOURCES = \
RTIObjectClass.cxx \
RTIObjectInstance.cxx \
RTIFederate.cxx \
HLAArrayDataElement.cxx \
HLAArrayDataType.cxx \
HLABasicDataElement.cxx \
@@ -53,17 +50,23 @@ libsghla_a_SOURCES = \
if ENABLE_HLA13
lib_LIBRARIES += libsghla13.a
lib_LIBRARIES += libsgrti13.a
libsghla13_adir = @includedir@/hla
libsgrti13_adir = @includedir@/hla
libsghla13_a_HEADERS = \
HLA13Federate.hxx
libsghla13_a_SOURCES = \
libsgrti13_a_SOURCES = \
RTI13ObjectClass.cxx \
RTI13ObjectInstance.cxx \
RTI13Federate.cxx \
HLA13Federate.cxx
RTI13Federate.cxx
endif
lib_LIBRARIES += libsgrti.a
libsgrti_adir = @includedir@/hla
libsgrti_a_SOURCES = \
RTIObjectClass.cxx \
RTIObjectInstance.cxx \
RTIFederate.cxx

View File

@@ -387,6 +387,8 @@ public:
_rtiAmbassador.queryFederateTime(fedTime);
timeStamp = toTimeStamp(fedTime);
}
void modifyLookahead(const SGTimeStamp& timeStamp)
{ _rtiAmbassador.modifyLookahead(toFedTime(timeStamp)); }
void queryLookahead(SGTimeStamp& timeStamp)
{
RTIfedTime fedTime;

View File

@@ -21,10 +21,13 @@
namespace simgear {
RTI13Federate::RTI13Federate() :
RTI13Federate::RTI13Federate(const std::list<std::string>& stringList) :
_tickTimeout(10),
_ambassador(new RTI13Ambassador)
{
if (stringList.empty()) {
SG_LOG(SG_NETWORK, SG_WARN, "RTI: Ignoring non empty connect arguments while connecting to an RTI13 federation!");
}
}
RTI13Federate::~RTI13Federate()
@@ -480,6 +483,37 @@ RTI13Federate::queryFederateTime(SGTimeStamp& timeStamp)
return true;
}
bool
RTI13Federate::modifyLookahead(const SGTimeStamp& timeStamp)
{
if (!_ambassador.valid()) {
SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead.");
return false;
}
try {
_ambassador->modifyLookahead(timeStamp);
} catch (RTI::InvalidLookahead& e) {
SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead: " << e._name << " " << e._reason);
return false;
} catch (RTI::FederateNotExecutionMember& e) {
SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead: " << e._name << " " << e._reason);
return false;
} catch (RTI::ConcurrentAccessAttempted& e) {
SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead: " << e._name << " " << e._reason);
return false;
} catch (RTI::SaveInProgress& e) {
SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead: " << e._name << " " << e._reason);
return false;
} catch (RTI::RestoreInProgress& e) {
SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead: " << e._name << " " << e._reason);
return false;
} catch (RTI::RTIinternalError& e) {
SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not modify lookahead: " << e._name << " " << e._reason);
return false;
}
return true;
}
bool
RTI13Federate::queryLookahead(SGTimeStamp& timeStamp)
{

View File

@@ -34,7 +34,7 @@ class RTI13Ambassador;
class RTI13Federate : public RTIFederate {
public:
RTI13Federate();
RTI13Federate(const std::list<std::string>& stringList);
virtual ~RTI13Federate();
virtual bool createFederationExecution(const std::string& federation, const std::string& objectModel);
@@ -61,6 +61,7 @@ public:
virtual bool timeAdvanceRequest(const SGTimeStamp& fedTime);
virtual bool queryFederateTime(SGTimeStamp& timeStamp);
virtual bool modifyLookahead(const SGTimeStamp& timeStamp);
virtual bool queryLookahead(SGTimeStamp& timeStamp);
/// Process messages

View File

@@ -66,6 +66,7 @@ public:
virtual bool timeAdvanceRequest(const SGTimeStamp& fedTime) = 0;
virtual bool queryFederateTime(SGTimeStamp& timeStamp) = 0;
virtual bool modifyLookahead(const SGTimeStamp& timeStamp) = 0;
virtual bool queryLookahead(SGTimeStamp& timeStamp) = 0;
/// Process messages

View File

@@ -37,17 +37,19 @@ set(SOURCES
simgear_component(io io "${SOURCES}" "${HEADERS}")
add_executable(test_sock socktest.cxx)
target_link_libraries(test_sock sgio sgstructure sgdebug)
target_link_libraries(test_sock sgio sgstructure sgdebug ${OPENTHREADS_LIBRARY})
add_executable(test_http test_HTTP.cxx)
target_link_libraries(test_http
sgio sgstructure sgtiming sgmisc sgdebug
${RT_LIBRARY})
${RT_LIBRARY}
${OPENTHREADS_LIBRARY})
add_test(http ${EXECUTABLE_OUTPUT_PATH}/test_http)
add_executable(httpget httpget.cxx)
target_link_libraries(httpget
sgio sgstructure sgtiming sgmisc sgdebug
${RT_LIBRARY})
${RT_LIBRARY}
${OPENTHREADS_LIBRARY})

View File

@@ -46,6 +46,7 @@ tcp_server_LDADD = \
$(top_builddir)/simgear/misc/libsgmisc.a \
-lz \
$(network_LIBS) \
$(osg_LIBS) \
$(base_LIBS)
tcp_client_SOURCES = tcp_client.cxx
@@ -58,6 +59,7 @@ tcp_client_LDADD = \
$(top_builddir)/simgear/misc/libsgmisc.a \
-lz \
$(network_LIBS) \
$(osg_LIBS) \
$(base_LIBS)
socktest_SOURCES = socktest.cxx
@@ -70,6 +72,7 @@ socktest_LDADD = \
$(top_builddir)/simgear/misc/libsgmisc.a \
-lz \
$(network_LIBS) \
$(osg_LIBS) \
$(base_LIBS)
lowtest_SOURCES = lowtest.cxx
@@ -80,7 +83,7 @@ lowtest_LDADD = \
$(top_builddir)/simgear/debug/libsgdebug.a \
$(top_builddir)/simgear/bucket/libsgbucket.a \
$(top_builddir)/simgear/misc/libsgmisc.a \
$(base_LIBS) -lz
$(base_LIBS) -lz $(osg_LIBS)
decode_binobj_SOURCES = decode_binobj.cxx
@@ -89,4 +92,4 @@ decode_binobj_LDADD = \
$(top_builddir)/simgear/debug/libsgdebug.a \
$(top_builddir)/simgear/bucket/libsgbucket.a \
$(top_builddir)/simgear/misc/libsgmisc.a \
$(base_LIBS) -lz
$(base_LIBS) -lz $(osg_LIBS)

View File

@@ -57,9 +57,166 @@
#define socklen_t int
#endif
#include <map>
#include <simgear/debug/logstream.hxx>
#include <simgear/structure/exception.hxx>
#include <OpenThreads/Thread>
#include <OpenThreads/Mutex>
#include <OpenThreads/Condition>
namespace {
class Resolver : public OpenThreads::Thread
{
public:
static Resolver* instance()
{
if (!static_instance) {
OpenThreads::Thread::Init();
static_instance = new Resolver;
atexit(&Resolver::cleanup);
static_instance->start();
}
return static_instance;
}
static void cleanup()
{
static_instance->cancel();
}
Resolver()
{
// take the lock initially, thread will wait upon it once running
_lock.lock();
}
simgear::IPAddress* lookup(const string& host)
{
simgear::IPAddress* result = NULL;
_lock.lock();
AddressCache::iterator it = _cache.find(host);
if (it == _cache.end()) {
_cache[host] = NULL; // mark as needing looked up
_wait.signal(); // if the thread was sleeping, poke it
} else {
result = it->second;
}
_lock.unlock();
return result;
}
simgear::IPAddress* lookupSync(const string& host)
{
simgear::IPAddress* result = NULL;
_lock.lock();
AddressCache::iterator it = _cache.find(host);
if (it == _cache.end()) {
_lock.unlock();
result = new simgear::IPAddress;
bool ok = lookupHost(host.c_str(), *result);
_lock.lock();
if (ok) {
_cache[host] = result; // mark as needing looked up
} else {
delete result;
result = NULL;
}
} else { // found in cache, easy
result = it->second;
}
_lock.unlock();
return result;
}
protected:
/**
* run method waits on a condition (_wait), and when awoken,
* finds any unresolved entries in _cache, resolves them, and goes
* back to sleep.
*/
virtual void run()
{
while (true) {
_wait.wait(&_lock);
AddressCache::iterator it;
for (it = _cache.begin(); it != _cache.end(); ++it) {
if (it->second == NULL) {
string h = it->first;
_lock.unlock();
simgear::IPAddress* addr = new simgear::IPAddress;
// may take seconds or even minutes!
lookupHost(h.c_str(), *addr);
_lock.lock();
// cahce may have changed while we had the lock released -
// so iterators may be invalid: restart the traversal
it = _cache.begin();
_cache[h] = addr;
} // of found un-resolved entry
} // of un-resolved address iteration
} // of thread run loop
}
private:
static Resolver* static_instance;
/**
* The actual synchronous, blocking host lookup function
* do *not* call this with any locks (mutexs) held, since depending
* on local system configuration / network availability, it
* may block for seconds or minutes.
*/
bool lookupHost(const char* host, simgear::IPAddress& addr)
{
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET;
bool ok = false;
struct addrinfo* result0 = NULL;
int err = getaddrinfo(host, NULL, &hints, &result0);
if (err) {
SG_LOG(SG_IO, SG_WARN, "getaddrinfo failed for '" << host << "' : " << gai_strerror(err));
return false;
} else {
struct addrinfo* result;
for (result = result0; result != NULL; result = result->ai_next) {
if (result->ai_family != AF_INET) { // only accept IP4 for the moment
continue;
}
if (result->ai_addrlen != addr.getAddrLen()) {
SG_LOG(SG_IO, SG_ALERT, "mismatch in socket address sizes: got " <<
result->ai_addrlen << ", expected " << addr.getAddrLen());
continue;
}
memcpy(addr.getAddr(), result->ai_addr, result->ai_addrlen);
ok = true;
break;
} // of getaddrinfo results iteration
} // of getaddrinfo succeeded
freeaddrinfo(result0);
return ok;
}
OpenThreads::Mutex _lock;
OpenThreads::Condition _wait;
typedef std::map<string, simgear::IPAddress*> AddressCache;
AddressCache _cache;
};
Resolver* Resolver::static_instance = NULL;
} // of anonymous namespace
namespace simgear
{
@@ -115,33 +272,12 @@ void IPAddress::set ( const char* host, int port )
return;
}
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET;
// check the cache
IPAddress* cached = Resolver::instance()->lookupSync(host);
if (cached) {
memcpy(addr, cached->getAddr(), cached->getAddrLen());
}
struct addrinfo* result0 = NULL;
int err = getaddrinfo(host, NULL, &hints, &result0);
if (err) {
SG_LOG(SG_IO, SG_WARN, "getaddrinfo failed for '" << host << "' : " << gai_strerror(err));
} else {
struct addrinfo* result;
for (result = result0; result != NULL; result = result->ai_next) {
if (result->ai_family != AF_INET) { // only accept IP4 for the moment
continue;
}
if (result->ai_addrlen != getAddrLen()) {
SG_LOG(SG_IO, SG_ALERT, "mismatch in socket address sizes: got " <<
result->ai_addrlen << ", expected " << getAddrLen());
continue;
}
memcpy(addr, result->ai_addr, result->ai_addrlen);
break;
} // of getaddrinfo results iteration
} // of getaddrinfo succeeded
freeaddrinfo(result0);
addr->sin_port = htons (port); // fix up port after getaddrinfo
}
@@ -152,6 +288,17 @@ IPAddress::~IPAddress()
}
}
bool IPAddress::lookupNonblocking(const char* host, IPAddress& addr)
{
IPAddress* cached = Resolver::instance()->lookup(host);
if (!cached) {
return false;
}
addr = *cached;
return true;
}
/* Create a string object representing an IP address.
This is always a string of the form 'dd.dd.dd.dd' (with variable
size numbers). */
@@ -176,6 +323,11 @@ unsigned int IPAddress::getPort() const
return ntohs(addr->sin_port);
}
void IPAddress::setPort(int port)
{
addr->sin_port = htons(port);
}
unsigned int IPAddress::getFamily () const
{
return addr->sin_family;
@@ -215,6 +367,11 @@ unsigned int IPAddress::getAddrLen() const
struct sockaddr* IPAddress::getAddr() const
{
if (addr == NULL) {
addr = (struct sockaddr_in*) malloc(sizeof(struct sockaddr_in));
memset(addr, 0, sizeof(struct sockaddr_in));
}
return (struct sockaddr*) addr;
}

View File

@@ -40,18 +40,22 @@ namespace simgear
*/
class IPAddress
{
struct sockaddr_in* addr;
mutable struct sockaddr_in* addr;
public:
IPAddress () : addr(0) {}
IPAddress ( const char* host, int port ) ;
~IPAddress();
static bool lookupNonblocking(const char* host, IPAddress& addr);
IPAddress( const IPAddress& other );
const IPAddress& operator=(const IPAddress& other);
void set ( const char* host, int port ) ;
const char* getHost () const ;
unsigned int getPort() const ;
void setPort(int port);
unsigned int getIP () const ;
unsigned int getFamily () const ;
static const char* getLocalHost () ;
@@ -69,7 +73,7 @@ public:
class Socket
{
int handle ;
public:
Socket () ;

View File

@@ -38,6 +38,7 @@
#include <simgear/debug/logstream.hxx>
namespace simgear {
static NetChannel* channels = 0 ;
@@ -46,6 +47,7 @@ NetChannel::NetChannel ()
{
closed = true ;
connected = false ;
resolving_host = false;
accepting = false ;
write_blocked = false ;
should_delete = false ;
@@ -83,7 +85,6 @@ NetChannel::setHandle (int handle, bool is_connected)
close () ;
Socket::setHandle ( handle ) ;
connected = is_connected ;
//if ( connected ) this->handleConnect();
closed = false ;
}
@@ -107,21 +108,12 @@ NetChannel::listen ( int backlog )
}
int
NetChannel::connect ( const char* host, int port )
NetChannel::connect ( const char* h, int p )
{
int result = Socket::connect ( host, port ) ;
if (result == 0) {
connected = true ;
//this->handleConnect();
return 0;
} else if (isNonBlockingError ()) {
return 0;
} else {
// some other error condition
this->handleError (result);
close();
return -1;
}
host = h;
port = p;
resolving_host = true;
return handleResolve();
}
int
@@ -189,12 +181,10 @@ NetChannel::handleReadEvent (void)
if (accepting) {
if (!connected) {
connected = true ;
//this->handleConnect();
}
this->handleAccept();
} else if (!connected) {
connected = true ;
//this->handleConnect();
this->handleRead();
} else {
this->handleRead();
@@ -206,12 +196,35 @@ NetChannel::handleWriteEvent (void)
{
if (!connected) {
connected = true ;
//this->handleConnect();
}
write_blocked = false ;
this->handleWrite();
}
int
NetChannel::handleResolve()
{
IPAddress addr;
if (!IPAddress::lookupNonblocking(host.c_str(), addr)) {
return 0; // not looked up yet, wait longer
}
resolving_host = false;
addr.setPort(port);
int result = Socket::connect ( &addr ) ;
if (result == 0) {
connected = true ;
return 0;
} else if (isNonBlockingError ()) {
return 0;
} else {
// some other error condition
handleError (result);
close();
return -1;
}
}
bool
NetChannel::poll (unsigned int timeout)
{
@@ -236,6 +249,12 @@ NetChannel::poll (unsigned int timeout)
}
else if ( ! ch -> closed )
{
if (ch -> resolving_host )
{
ch -> handleResolve();
continue;
}
nopen++ ;
if (ch -> readable()) {
assert(nreads<MAX_SOCKETS);

View File

@@ -54,14 +54,17 @@
#define SG_NET_CHANNEL_H
#include <simgear/io/raw_socket.hxx>
#include <string>
namespace simgear
{
class NetChannel : public Socket
{
bool closed, connected, accepting, write_blocked, should_delete ;
bool closed, connected, accepting, write_blocked, should_delete, resolving_host ;
NetChannel* next_channel ;
std::string host;
int port;
friend bool netPoll (unsigned int timeout);
@@ -96,6 +99,7 @@ public:
void handleReadEvent (void);
void handleWriteEvent (void);
int handleResolve (void);
// These are meant to be overridden.
virtual void handleClose (void) {