From: Stuart Buchanan Date: Thu, 1 Sep 2011 18:55:11 +0000 (+0100) Subject: Merge branch 'next' of gitorious.org:fg/simgear into next X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=becea84955bf1d553f0bb6b721ace64b9880fa93;hp=05272d10703f040cbd3a0d972e05a9bc0ee46e14;p=simgear.git Merge branch 'next' of gitorious.org:fg/simgear into next --- diff --git a/configure.ac b/configure.ac index 28e846cd..81bae41e 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/simgear/hla/CMakeLists.txt b/simgear/hla/CMakeLists.txt index bae6eb73..207210ab 100644 --- a/simgear/hla/CMakeLists.txt +++ b/simgear/hla/CMakeLists.txt @@ -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}" "") diff --git a/simgear/hla/HLA13Federate.cxx b/simgear/hla/HLA13Federate.cxx deleted file mode 100644 index 4f78344c..00000000 --- a/simgear/hla/HLA13Federate.cxx +++ /dev/null @@ -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 diff --git a/simgear/hla/HLA13Federate.hxx b/simgear/hla/HLA13Federate.hxx deleted file mode 100644 index dc3fa0b6..00000000 --- a/simgear/hla/HLA13Federate.hxx +++ /dev/null @@ -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 diff --git a/simgear/hla/HLAArrayDataElement.hxx b/simgear/hla/HLAArrayDataElement.hxx index f1acf8ef..b7c9c1e3 100644 --- a/simgear/hla/HLAArrayDataElement.hxx +++ b/simgear/hla/HLAArrayDataElement.hxx @@ -248,6 +248,43 @@ private: SGVec2 _value; }; +template +class HLAVec2Data { +public: + HLAVec2Data() : + _value(new HLAVec2DataElement(0)) + { } + HLAVec2Data(const SGVec2& value) : + _value(new HLAVec2DataElement(0, value)) + { } + + operator const SGVec2&() const + { return _value->getValue(); } + HLAVec2Data& operator=(const SGVec2& value) + { _value->setValue(value); return *this; } + + const SGVec2& getValue() const + { return _value->getValue(); } + void setValue(const SGVec2& value) + { _value->setValue(value); } + + const HLAVec2DataElement* getDataElement() const + { return _value.get(); } + HLAVec2DataElement* getDataElement() + { return _value.get(); } + + const HLAArrayDataType* getDataType() const + { return _value->getDataType(); } + void setDataType(const HLAArrayDataType* dataType) + { _value->setDataType(dataType); } + +private: + SGSharedPtr > _value; +}; + +typedef HLAVec2Data HLAVec2fData; +typedef HLAVec2Data HLAVec2dData; + template class HLAVec3DataElement : public HLAAbstractArrayDataElement { public: @@ -303,6 +340,43 @@ private: SGVec3 _value; }; +template +class HLAVec3Data { +public: + HLAVec3Data() : + _value(new HLAVec3DataElement(0)) + { } + HLAVec3Data(const SGVec3& value) : + _value(new HLAVec3DataElement(0, value)) + { } + + operator const SGVec3&() const + { return _value->getValue(); } + HLAVec3Data& operator=(const SGVec3& value) + { _value->setValue(value); return *this; } + + const SGVec3& getValue() const + { return _value->getValue(); } + void setValue(const SGVec3& value) + { _value->setValue(value); } + + const HLAVec3DataElement* getDataElement() const + { return _value.get(); } + HLAVec3DataElement* getDataElement() + { return _value.get(); } + + const HLAArrayDataType* getDataType() const + { return _value->getDataType(); } + void setDataType(const HLAArrayDataType* dataType) + { _value->setDataType(dataType); } + +private: + SGSharedPtr > _value; +}; + +typedef HLAVec3Data HLAVec3fData; +typedef HLAVec3Data HLAVec3dData; + template class HLAVec4DataElement : public HLAAbstractArrayDataElement { public: @@ -358,6 +432,43 @@ private: SGVec4 _value; }; +template +class HLAVec4Data { +public: + HLAVec4Data() : + _value(new HLAVec4DataElement(0)) + { } + HLAVec4Data(const SGVec4& value) : + _value(new HLAVec4DataElement(0, value)) + { } + + operator const SGVec4&() const + { return _value->getValue(); } + HLAVec4Data& operator=(const SGVec4& value) + { _value->setValue(value); return *this; } + + const SGVec4& getValue() const + { return _value->getValue(); } + void setValue(const SGVec4& value) + { _value->setValue(value); } + + const HLAVec4DataElement* getDataElement() const + { return _value.get(); } + HLAVec4DataElement* getDataElement() + { return _value.get(); } + + const HLAArrayDataType* getDataType() const + { return _value->getDataType(); } + void setDataType(const HLAArrayDataType* dataType) + { _value->setDataType(dataType); } + +private: + SGSharedPtr > _value; +}; + +typedef HLAVec4Data HLAVec4fData; +typedef HLAVec4Data HLAVec4dData; + template class HLAQuatDataElement : public HLAAbstractArrayDataElement { public: diff --git a/simgear/hla/HLAFederate.cxx b/simgear/hla/HLAFederate.cxx index 96e31fc3..59a5f4b0 100644 --- a/simgear/hla/HLAFederate.cxx +++ b/simgear/hla/HLAFederate.cxx @@ -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) +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& 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; } diff --git a/simgear/hla/HLAFederate.hxx b/simgear/hla/HLAFederate.hxx index 241f6093..5af83396 100644 --- a/simgear/hla/HLAFederate.hxx +++ b/simgear/hla/HLAFederate.hxx @@ -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& 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); - private: SGSharedPtr _rtiFederate; diff --git a/simgear/hla/Makefile.am b/simgear/hla/Makefile.am index e4af1531..67542ddb 100644 --- a/simgear/hla/Makefile.am +++ b/simgear/hla/Makefile.am @@ -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 - -libsghla13_adir = @includedir@/hla +lib_LIBRARIES += libsgrti13.a -libsghla13_a_HEADERS = \ - HLA13Federate.hxx +libsgrti13_adir = @includedir@/hla -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 + diff --git a/simgear/hla/RTI13Ambassador.hxx b/simgear/hla/RTI13Ambassador.hxx index 502a39f7..5446f858 100644 --- a/simgear/hla/RTI13Ambassador.hxx +++ b/simgear/hla/RTI13Ambassador.hxx @@ -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; diff --git a/simgear/hla/RTI13Federate.cxx b/simgear/hla/RTI13Federate.cxx index d3f9eebc..a77fbaea 100644 --- a/simgear/hla/RTI13Federate.cxx +++ b/simgear/hla/RTI13Federate.cxx @@ -21,10 +21,13 @@ namespace simgear { -RTI13Federate::RTI13Federate() : +RTI13Federate::RTI13Federate(const std::list& 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) { diff --git a/simgear/hla/RTI13Federate.hxx b/simgear/hla/RTI13Federate.hxx index acad0fce..839e7d50 100644 --- a/simgear/hla/RTI13Federate.hxx +++ b/simgear/hla/RTI13Federate.hxx @@ -34,7 +34,7 @@ class RTI13Ambassador; class RTI13Federate : public RTIFederate { public: - RTI13Federate(); + RTI13Federate(const std::list& 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 diff --git a/simgear/hla/RTIFederate.hxx b/simgear/hla/RTIFederate.hxx index bdb68faa..c997704f 100644 --- a/simgear/hla/RTIFederate.hxx +++ b/simgear/hla/RTIFederate.hxx @@ -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 diff --git a/simgear/io/CMakeLists.txt b/simgear/io/CMakeLists.txt index a2638e1b..2cdb1d5a 100644 --- a/simgear/io/CMakeLists.txt +++ b/simgear/io/CMakeLists.txt @@ -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}) \ No newline at end of file diff --git a/simgear/io/Makefile.am b/simgear/io/Makefile.am index 760676a3..e0086d86 100644 --- a/simgear/io/Makefile.am +++ b/simgear/io/Makefile.am @@ -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) diff --git a/simgear/io/raw_socket.cxx b/simgear/io/raw_socket.cxx index d972c145..b849bddc 100644 --- a/simgear/io/raw_socket.cxx +++ b/simgear/io/raw_socket.cxx @@ -57,9 +57,166 @@ #define socklen_t int #endif +#include + #include #include +#include +#include +#include + +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 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; } diff --git a/simgear/io/raw_socket.hxx b/simgear/io/raw_socket.hxx index 2b5031f3..9450e9eb 100644 --- a/simgear/io/raw_socket.hxx +++ b/simgear/io/raw_socket.hxx @@ -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 () ; diff --git a/simgear/io/sg_netChannel.cxx b/simgear/io/sg_netChannel.cxx index c3644b6c..86839e71 100644 --- a/simgear/io/sg_netChannel.cxx +++ b/simgear/io/sg_netChannel.cxx @@ -38,6 +38,7 @@ #include + 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 +#include 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) {