From a5775cdb944ed529eb97f4fa819b779d3441eaa7 Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Tue, 30 Aug 2011 07:27:24 +0200 Subject: [PATCH 1/6] Add SGVec* convinience hla data elements. --- simgear/hla/HLAArrayDataElement.hxx | 111 ++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) 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: From 959791ffde7bed820a319fbe228dcafddf7cb645 Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Tue, 30 Aug 2011 07:28:13 +0200 Subject: [PATCH 2/6] Add modifyLookahead to the rti abstraction. --- simgear/hla/HLAFederate.cxx | 6 ++++++ simgear/hla/HLAFederate.hxx | 1 + simgear/hla/RTI13Ambassador.hxx | 2 ++ simgear/hla/RTI13Federate.cxx | 31 +++++++++++++++++++++++++++++++ simgear/hla/RTI13Federate.hxx | 1 + simgear/hla/RTIFederate.hxx | 1 + 6 files changed, 42 insertions(+) diff --git a/simgear/hla/HLAFederate.cxx b/simgear/hla/HLAFederate.cxx index 96e31fc3..d16494c9 100644 --- a/simgear/hla/HLAFederate.cxx +++ b/simgear/hla/HLAFederate.cxx @@ -113,6 +113,12 @@ HLAFederate::queryFederateTime(SGTimeStamp& timeStamp) return _rtiFederate->queryFederateTime(timeStamp); } +bool +HLAFederate::modifyLookahead(const SGTimeStamp& timeStamp) +{ + return _rtiFederate->modifyLookahead(timeStamp); +} + bool HLAFederate::queryLookahead(SGTimeStamp& timeStamp) { diff --git a/simgear/hla/HLAFederate.hxx b/simgear/hla/HLAFederate.hxx index 241f6093..7376540e 100644 --- a/simgear/hla/HLAFederate.hxx +++ b/simgear/hla/HLAFederate.hxx @@ -59,6 +59,7 @@ public: bool timeAdvanceRequest(const SGTimeStamp& dt); bool queryFederateTime(SGTimeStamp& timeStamp); + bool modifyLookahead(const SGTimeStamp& timeStamp); bool queryLookahead(SGTimeStamp& timeStamp); /// Process messages 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..649a9f58 100644 --- a/simgear/hla/RTI13Federate.cxx +++ b/simgear/hla/RTI13Federate.cxx @@ -480,6 +480,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..8ace9e58 100644 --- a/simgear/hla/RTI13Federate.hxx +++ b/simgear/hla/RTI13Federate.hxx @@ -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 From 1cb9a79fd48ce6151f6a2cf8d07ef23e002a81b1 Mon Sep 17 00:00:00 2001 From: James Turner Date: Tue, 30 Aug 2011 12:51:03 +0100 Subject: [PATCH 3/6] Asynchronous host lookups+caching, attempt #2 --- simgear/io/CMakeLists.txt | 6 +- simgear/io/Makefile.am | 5 + simgear/io/raw_socket.cxx | 205 ++++++++++++++++++++++++++++++----- simgear/io/raw_socket.hxx | 8 +- simgear/io/sg_netChannel.cxx | 55 +++++++--- simgear/io/sg_netChannel.hxx | 6 +- 6 files changed, 235 insertions(+), 50 deletions(-) diff --git a/simgear/io/CMakeLists.txt b/simgear/io/CMakeLists.txt index a2638e1b..b3af0663 100644 --- a/simgear/io/CMakeLists.txt +++ b/simgear/io/CMakeLists.txt @@ -37,17 +37,17 @@ 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 sgthreads) add_executable(test_http test_HTTP.cxx) target_link_libraries(test_http - sgio sgstructure sgtiming sgmisc sgdebug + sgio sgstructure sgtiming sgmisc sgdebug sgthreads ${RT_LIBRARY}) add_test(http ${EXECUTABLE_OUTPUT_PATH}/test_http) add_executable(httpget httpget.cxx) target_link_libraries(httpget - sgio sgstructure sgtiming sgmisc sgdebug + sgio sgstructure sgtiming sgmisc sgdebug sgthreads ${RT_LIBRARY}) \ No newline at end of file diff --git a/simgear/io/Makefile.am b/simgear/io/Makefile.am index 760676a3..05d05a03 100644 --- a/simgear/io/Makefile.am +++ b/simgear/io/Makefile.am @@ -44,6 +44,7 @@ tcp_server_LDADD = \ $(top_builddir)/simgear/debug/libsgdebug.a \ $(top_builddir)/simgear/bucket/libsgbucket.a \ $(top_builddir)/simgear/misc/libsgmisc.a \ + $(top_builddir)/simgear/threads/libsgthreads.a \ -lz \ $(network_LIBS) \ $(base_LIBS) @@ -56,6 +57,7 @@ tcp_client_LDADD = \ $(top_builddir)/simgear/debug/libsgdebug.a \ $(top_builddir)/simgear/bucket/libsgbucket.a \ $(top_builddir)/simgear/misc/libsgmisc.a \ + $(top_builddir)/simgear/threads/libsgthreads.a \ -lz \ $(network_LIBS) \ $(base_LIBS) @@ -68,6 +70,7 @@ socktest_LDADD = \ $(top_builddir)/simgear/debug/libsgdebug.a \ $(top_builddir)/simgear/bucket/libsgbucket.a \ $(top_builddir)/simgear/misc/libsgmisc.a \ + $(top_builddir)/simgear/threads/libsgthreads.a \ -lz \ $(network_LIBS) \ $(base_LIBS) @@ -80,6 +83,7 @@ lowtest_LDADD = \ $(top_builddir)/simgear/debug/libsgdebug.a \ $(top_builddir)/simgear/bucket/libsgbucket.a \ $(top_builddir)/simgear/misc/libsgmisc.a \ + $(top_builddir)/simgear/threads/libsgthreads.a \ $(base_LIBS) -lz decode_binobj_SOURCES = decode_binobj.cxx @@ -89,4 +93,5 @@ decode_binobj_LDADD = \ $(top_builddir)/simgear/debug/libsgdebug.a \ $(top_builddir)/simgear/bucket/libsgbucket.a \ $(top_builddir)/simgear/misc/libsgmisc.a \ + $(top_builddir)/simgear/threads/libsgthreads.a \ $(base_LIBS) -lz diff --git a/simgear/io/raw_socket.cxx b/simgear/io/raw_socket.cxx index d972c145..2ef5d4c4 100644 --- a/simgear/io/raw_socket.cxx +++ b/simgear/io/raw_socket.cxx @@ -57,8 +57,161 @@ #define socklen_t int #endif +#include + #include #include +#include + +namespace { + + + +class Resolver : public SGThread +{ +public: + static Resolver* instance() + { + if (!static_instance) { + 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; + } + + SGMutex _lock; + SGPthreadCond _wait; + typedef std::map AddressCache; + AddressCache _cache; +}; + +Resolver* Resolver::static_instance = NULL; + +} // of anonymous namespace namespace simgear { @@ -115,33 +268,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 +284,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 +319,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 +363,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) { From eafea282664cbbf3316a068ce6683990cb1d5486 Mon Sep 17 00:00:00 2001 From: James Turner Date: Tue, 30 Aug 2011 13:41:06 +0100 Subject: [PATCH 4/6] Revert "Asynchronous host lookups+caching, attempt #2" Bah, SGThread is a pain, need to switch to OpenThreads This reverts commit 1cb9a79fd48ce6151f6a2cf8d07ef23e002a81b1. --- simgear/io/CMakeLists.txt | 6 +- simgear/io/Makefile.am | 5 - simgear/io/raw_socket.cxx | 205 +++++------------------------------ simgear/io/raw_socket.hxx | 8 +- simgear/io/sg_netChannel.cxx | 55 +++------- simgear/io/sg_netChannel.hxx | 6 +- 6 files changed, 50 insertions(+), 235 deletions(-) diff --git a/simgear/io/CMakeLists.txt b/simgear/io/CMakeLists.txt index b3af0663..a2638e1b 100644 --- a/simgear/io/CMakeLists.txt +++ b/simgear/io/CMakeLists.txt @@ -37,17 +37,17 @@ set(SOURCES simgear_component(io io "${SOURCES}" "${HEADERS}") add_executable(test_sock socktest.cxx) -target_link_libraries(test_sock sgio sgstructure sgdebug sgthreads) +target_link_libraries(test_sock sgio sgstructure sgdebug) add_executable(test_http test_HTTP.cxx) target_link_libraries(test_http - sgio sgstructure sgtiming sgmisc sgdebug sgthreads + sgio sgstructure sgtiming sgmisc sgdebug ${RT_LIBRARY}) add_test(http ${EXECUTABLE_OUTPUT_PATH}/test_http) add_executable(httpget httpget.cxx) target_link_libraries(httpget - sgio sgstructure sgtiming sgmisc sgdebug sgthreads + sgio sgstructure sgtiming sgmisc sgdebug ${RT_LIBRARY}) \ No newline at end of file diff --git a/simgear/io/Makefile.am b/simgear/io/Makefile.am index 05d05a03..760676a3 100644 --- a/simgear/io/Makefile.am +++ b/simgear/io/Makefile.am @@ -44,7 +44,6 @@ tcp_server_LDADD = \ $(top_builddir)/simgear/debug/libsgdebug.a \ $(top_builddir)/simgear/bucket/libsgbucket.a \ $(top_builddir)/simgear/misc/libsgmisc.a \ - $(top_builddir)/simgear/threads/libsgthreads.a \ -lz \ $(network_LIBS) \ $(base_LIBS) @@ -57,7 +56,6 @@ tcp_client_LDADD = \ $(top_builddir)/simgear/debug/libsgdebug.a \ $(top_builddir)/simgear/bucket/libsgbucket.a \ $(top_builddir)/simgear/misc/libsgmisc.a \ - $(top_builddir)/simgear/threads/libsgthreads.a \ -lz \ $(network_LIBS) \ $(base_LIBS) @@ -70,7 +68,6 @@ socktest_LDADD = \ $(top_builddir)/simgear/debug/libsgdebug.a \ $(top_builddir)/simgear/bucket/libsgbucket.a \ $(top_builddir)/simgear/misc/libsgmisc.a \ - $(top_builddir)/simgear/threads/libsgthreads.a \ -lz \ $(network_LIBS) \ $(base_LIBS) @@ -83,7 +80,6 @@ lowtest_LDADD = \ $(top_builddir)/simgear/debug/libsgdebug.a \ $(top_builddir)/simgear/bucket/libsgbucket.a \ $(top_builddir)/simgear/misc/libsgmisc.a \ - $(top_builddir)/simgear/threads/libsgthreads.a \ $(base_LIBS) -lz decode_binobj_SOURCES = decode_binobj.cxx @@ -93,5 +89,4 @@ decode_binobj_LDADD = \ $(top_builddir)/simgear/debug/libsgdebug.a \ $(top_builddir)/simgear/bucket/libsgbucket.a \ $(top_builddir)/simgear/misc/libsgmisc.a \ - $(top_builddir)/simgear/threads/libsgthreads.a \ $(base_LIBS) -lz diff --git a/simgear/io/raw_socket.cxx b/simgear/io/raw_socket.cxx index 2ef5d4c4..d972c145 100644 --- a/simgear/io/raw_socket.cxx +++ b/simgear/io/raw_socket.cxx @@ -57,161 +57,8 @@ #define socklen_t int #endif -#include - #include #include -#include - -namespace { - - - -class Resolver : public SGThread -{ -public: - static Resolver* instance() - { - if (!static_instance) { - 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; - } - - SGMutex _lock; - SGPthreadCond _wait; - typedef std::map AddressCache; - AddressCache _cache; -}; - -Resolver* Resolver::static_instance = NULL; - -} // of anonymous namespace namespace simgear { @@ -268,12 +115,33 @@ void IPAddress::set ( const char* host, int port ) return; } -// check the cache - IPAddress* cached = Resolver::instance()->lookupSync(host); - if (cached) { - memcpy(addr, cached->getAddr(), cached->getAddrLen()); - } + struct addrinfo hints; + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_INET; + 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 } @@ -284,17 +152,6 @@ 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). */ @@ -319,11 +176,6 @@ 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; @@ -363,11 +215,6 @@ 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 9450e9eb..2b5031f3 100644 --- a/simgear/io/raw_socket.hxx +++ b/simgear/io/raw_socket.hxx @@ -40,22 +40,18 @@ namespace simgear */ class IPAddress { - mutable struct sockaddr_in* addr; + 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 () ; @@ -73,7 +69,7 @@ public: class Socket { int handle ; - + public: Socket () ; diff --git a/simgear/io/sg_netChannel.cxx b/simgear/io/sg_netChannel.cxx index 86839e71..c3644b6c 100644 --- a/simgear/io/sg_netChannel.cxx +++ b/simgear/io/sg_netChannel.cxx @@ -38,7 +38,6 @@ #include - namespace simgear { static NetChannel* channels = 0 ; @@ -47,7 +46,6 @@ NetChannel::NetChannel () { closed = true ; connected = false ; - resolving_host = false; accepting = false ; write_blocked = false ; should_delete = false ; @@ -85,6 +83,7 @@ NetChannel::setHandle (int handle, bool is_connected) close () ; Socket::setHandle ( handle ) ; connected = is_connected ; + //if ( connected ) this->handleConnect(); closed = false ; } @@ -108,12 +107,21 @@ NetChannel::listen ( int backlog ) } int -NetChannel::connect ( const char* h, int p ) +NetChannel::connect ( const char* host, int port ) { - host = h; - port = p; - resolving_host = true; - return handleResolve(); + 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; + } } int @@ -181,10 +189,12 @@ 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(); @@ -196,35 +206,12 @@ 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) { @@ -249,12 +236,6 @@ 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, resolving_host ; + bool closed, connected, accepting, write_blocked, should_delete ; NetChannel* next_channel ; - std::string host; - int port; friend bool netPoll (unsigned int timeout); @@ -99,7 +96,6 @@ public: void handleReadEvent (void); void handleWriteEvent (void); - int handleResolve (void); // These are meant to be overridden. virtual void handleClose (void) { From 427d6c3316e59aa86bbf4d3e51f522e0aba9c4fd Mon Sep 17 00:00:00 2001 From: James Turner Date: Tue, 30 Aug 2011 15:14:14 +0100 Subject: [PATCH 5/6] Async lookup attempt #3 - use OpenThreads instead - I'm going to kill off SGThread imminently. --- configure.ac | 9 ++ simgear/io/CMakeLists.txt | 8 +- simgear/io/Makefile.am | 7 +- simgear/io/raw_socket.cxx | 209 ++++++++++++++++++++++++++++++----- simgear/io/raw_socket.hxx | 8 +- simgear/io/sg_netChannel.cxx | 55 ++++++--- simgear/io/sg_netChannel.hxx | 6 +- 7 files changed, 250 insertions(+), 52 deletions(-) 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/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) { From 29faf13afda0032b7f70bdde6092158c067c5da4 Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Tue, 30 Aug 2011 21:52:40 +0200 Subject: [PATCH 6/6] Move the decision which rti to use into HLAFederate. --- simgear/hla/CMakeLists.txt | 20 +++--- simgear/hla/HLA13Federate.cxx | 33 ---------- simgear/hla/HLA13Federate.hxx | 33 ---------- simgear/hla/HLAFederate.cxx | 115 ++++++++++++++++++++++++++++++++-- simgear/hla/HLAFederate.hxx | 18 ++++-- simgear/hla/Makefile.am | 25 ++++---- simgear/hla/RTI13Federate.cxx | 5 +- simgear/hla/RTI13Federate.hxx | 2 +- 8 files changed, 151 insertions(+), 100 deletions(-) delete mode 100644 simgear/hla/HLA13Federate.cxx delete mode 100644 simgear/hla/HLA13Federate.hxx 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/HLAFederate.cxx b/simgear/hla/HLAFederate.cxx index d16494c9..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,105 +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); } @@ -142,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 7376540e..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, @@ -94,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 +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 + diff --git a/simgear/hla/RTI13Federate.cxx b/simgear/hla/RTI13Federate.cxx index 649a9f58..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() diff --git a/simgear/hla/RTI13Federate.hxx b/simgear/hla/RTI13Federate.hxx index 8ace9e58..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);