diff --git a/src/client.cpp b/src/client.cpp index ef34b4d..a79f0e6 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -468,8 +468,7 @@ Value buildCAMethod() } ContextImpl::ContextImpl(const Config& conf, const evbase& tcp_loop) - :canIPv6(evsocket::canIPv6()) - ,ifmap(IfaceMap::instance()) + :ifmap(IfaceMap::instance()) ,effective(conf) ,caMethod(buildCAMethod()) ,searchTx4(AF_INET, SOCK_DGRAM, 0) diff --git a/src/clientimpl.h b/src/clientimpl.h index d8b6476..63a7e09 100644 --- a/src/clientimpl.h +++ b/src/clientimpl.h @@ -226,7 +226,6 @@ private: struct ContextImpl : public std::enable_shared_from_this { SockAttach attach; - const bool canIPv6; IfaceMap& ifmap; // "const" after ctor diff --git a/src/evhelper.cpp b/src/evhelper.cpp index d319d46..b914f85 100644 --- a/src/evhelper.cpp +++ b/src/evhelper.cpp @@ -365,6 +365,8 @@ bool evbase::assertInRunningLoop() const throw std::logic_error("Not in running evbase worker"); } +bool evsocket::canIPv6; + evsocket::evsocket(int af, evutil_socket_t sock) :sock(sock) ,af(af) @@ -636,7 +638,7 @@ std::vector evsocket::broadcasts(const SockAddr* match) const # define EAFNOSUPPORT WSAESOCKTNOSUPPORT #endif -bool evsocket::canIPv6() +bool evsocket::init_canIPv6() { try { evsocket sock(AF_INET6, SOCK_DGRAM, 0); diff --git a/src/evhelper.h b/src/evhelper.h index 858a399..5f463df 100644 --- a/src/evhelper.h +++ b/src/evhelper.h @@ -248,7 +248,9 @@ struct PVXS_API evsocket std::vector broadcasts(const SockAddr* match=nullptr) const; static - bool canIPv6(); + bool canIPv6; + + static bool init_canIPv6(); }; struct PVXS_API IfaceMap { diff --git a/src/os/WIN32/osdSockExt.cpp b/src/os/WIN32/osdSockExt.cpp index e0d59a5..4c120be 100644 --- a/src/os/WIN32/osdSockExt.cpp +++ b/src/os/WIN32/osdSockExt.cpp @@ -46,6 +46,8 @@ void oseDoOnce(void*) } if(!WSARecvMsg) cantProceed("Unable to get &WSARecvMsg!!"); + + evsocket::canIPv6 = evsocket::init_canIPv6(); } void osiSockAttachExt() diff --git a/src/os/default/osdSockExt.cpp b/src/os/default/osdSockExt.cpp index d2c1216..8a68435 100644 --- a/src/os/default/osdSockExt.cpp +++ b/src/os/default/osdSockExt.cpp @@ -37,7 +37,19 @@ namespace pvxs { DEFINE_LOGGER(log, "pvxs.util"); DEFINE_LOGGER(logiface, "pvxs.iface"); -void osiSockAttachExt() {} +static +epicsThreadOnceId oseOnce = EPICS_THREAD_ONCE_INIT; + +static +void oseDoOnce(void*) +{ + evsocket::canIPv6 = evsocket::init_canIPv6(); +} + +void osiSockAttachExt() { + osiSockAttach(); + epicsThreadOnce(&oseOnce, &oseDoOnce, nullptr); +} void evsocket::enable_SO_RXQ_OVFL() const { diff --git a/src/server.cpp b/src/server.cpp index 4352b8a..894ba57 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -375,8 +375,7 @@ std::ostream& operator<<(std::ostream& strm, const Server& serv) } Server::Pvt::Pvt(const Config &conf) - :canIPv6(evsocket::canIPv6()) - ,effective(conf) + :effective(conf) ,beaconMsg(128) ,acceptor_loop("PVXTCP", epicsThreadPriorityCAServerLow-2) ,beaconSender4(AF_INET, SOCK_DGRAM, 0) diff --git a/src/serverconn.cpp b/src/serverconn.cpp index 6820d39..1de3180 100644 --- a/src/serverconn.cpp +++ b/src/serverconn.cpp @@ -387,7 +387,7 @@ ServIface::ServIface(const SockAddr &addr, server::Server::Pvt *server, bool fal auto orig_port = bind_addr.port(); #ifdef __linux__ - if(server->canIPv6 && bind_addr.family()==AF_INET && bind_addr.isAny()) { + if(evsocket::canIPv6 && bind_addr.family()==AF_INET && bind_addr.isAny()) { // Linux IP stack disallows binding both 0.0.0.0 and [::] for the same port. // so promote to IPv6 when possible bind_addr = SockAddr::any(AF_INET6, bind_addr.port()); diff --git a/src/serverconn.h b/src/serverconn.h index 0895792..6f668ae 100644 --- a/src/serverconn.h +++ b/src/serverconn.h @@ -200,7 +200,6 @@ using namespace impl; struct Server::Pvt { SockAttach attach; - const bool canIPv6; std::weak_ptr internal_self; diff --git a/test/testget.cpp b/test/testget.cpp index 8f43a8d..83af28e 100644 --- a/test/testget.cpp +++ b/test/testget.cpp @@ -502,7 +502,7 @@ MAIN(testget) testPlan(59); testSetup(); logger_config_env(); - bool canIPv6 = pvxs::impl::evsocket::canIPv6(); + const bool canIPv6 = pvxs::impl::evsocket::canIPv6; Tester().testConnector(); Tester().testWaiter(); Tester(AF_INET).loopback(); diff --git a/test/testsock.cpp b/test/testsock.cpp index 63e2e8e..28f2f9b 100644 --- a/test/testsock.cpp +++ b/test/testsock.cpp @@ -398,7 +398,7 @@ MAIN(testsock) testSetup(); // check for behavior when binding ipv4 and ipv6 to the same socket // as a function of socket type and order. - if(evsocket::canIPv6()) { + if(evsocket::canIPv6) { // IPv4 and v6 loopback addresses are entirely distinct, // so no problem binding to both w/ or w/o IPV6_V6ONLY test_bind46("127.0.0.1" , "::1" , SOCK_DGRAM , 0);