diff options
author | Benoit Foucher <benoit@zeroc.com> | 2017-03-01 19:42:52 +0100 |
---|---|---|
committer | Benoit Foucher <benoit@zeroc.com> | 2017-03-01 19:42:52 +0100 |
commit | 0a57f0b1841f51bc45ff2adc9ac19e114d695e43 (patch) | |
tree | 2ecab85164a70618fc0f861058f97194cb4e797e | |
parent | UWP build failure (diff) | |
download | ice-0a57f0b1841f51bc45ff2adc9ac19e114d695e43.tar.bz2 ice-0a57f0b1841f51bc45ff2adc9ac19e114d695e43.tar.xz ice-0a57f0b1841f51bc45ff2adc9ac19e114d695e43.zip |
Fixed ICE-7584 - discovery plugins now send multicast datagrams on all interfaces
52 files changed, 1720 insertions, 1170 deletions
diff --git a/config/PropertyNames.xml b/config/PropertyNames.xml index f0461a5fe1b..c12367fc58e 100644 --- a/config/PropertyNames.xml +++ b/config/PropertyNames.xml @@ -471,6 +471,7 @@ generated from the section label. <property name="Discovery.Interface" /> <property name="Discovery.Lookup" /> <property name="Discovery.Reply" class="objectadapter" /> + <property name="Discovery.Locator" class="objectadapter" /> <property name="Trace.Observers" /> <property name="Trace.SaveToRegistry" /> </section> diff --git a/cpp/src/Ice/Network.cpp b/cpp/src/Ice/Network.cpp index 05abc9528f9..b98ea329429 100755 --- a/cpp/src/Ice/Network.cpp +++ b/cpp/src/Ice/Network.cpp @@ -1664,9 +1664,8 @@ IceInternal::getHostsForEndpointExpand(const string& host, ProtocolSupport proto } vector<string> -IceInternal::getInterfacesForMulticast(const string& intf, const Address& mcastAddr) +IceInternal::getInterfacesForMulticast(const string& intf, ProtocolSupport protocolSupport) { - ProtocolSupport protocolSupport = getProtocolSupport(mcastAddr); vector<string> interfaces = getHostsForEndpointExpand(intf, protocolSupport, true); if(interfaces.empty()) { @@ -1700,9 +1699,8 @@ IceInternal::getHostsForEndpointExpand(const string& host, ProtocolSupport proto } vector<string> -IceInternal::getInterfacesForMulticast(const string& intf, const Address& mcastAddr) +IceInternal::getInterfacesForMulticast(const string& intf, ProtocolSupport protocolSupport) { - ProtocolSupport protocolSupport = getProtocolSupport(mcastAddr); vector<string> interfaces; bool ipv4Wildcard = false; if(isWildcard(intf, protocolSupport, ipv4Wildcard)) @@ -2069,7 +2067,7 @@ IceInternal::getRecvBufferSize(SOCKET fd) void IceInternal::setMcastGroup(SOCKET fd, const Address& group, const string& intf) { - vector<string> interfaces = getInterfacesForMulticast(intf, group); + vector<string> interfaces = getInterfacesForMulticast(intf, getProtocolSupport(group)); set<int> indexes; for(vector<string>::const_iterator p = interfaces.begin(); p != interfaces.end(); ++p) { @@ -3068,7 +3066,7 @@ IceInternal::isIpAddress(const string& name) #else in_addr addr; in6_addr addr6; - + return inet_pton(AF_INET, name.c_str(), &addr) > 0 || inet_pton(AF_INET6, name.c_str(), &addr6) > 0; #endif }
\ No newline at end of file diff --git a/cpp/src/Ice/Network.h b/cpp/src/Ice/Network.h index df07941f73d..38ae134437f 100755 --- a/cpp/src/Ice/Network.h +++ b/cpp/src/Ice/Network.h @@ -284,7 +284,7 @@ ICE_API std::string addressesToString(const Address&, const Address&, bool); ICE_API bool isAddressValid(const Address&); ICE_API std::vector<std::string> getHostsForEndpointExpand(const std::string&, ProtocolSupport, bool); -ICE_API std::vector<std::string> getInterfacesForMulticast(const std::string&, const Address&); +ICE_API std::vector<std::string> getInterfacesForMulticast(const std::string&, ProtocolSupport); ICE_API std::string inetAddrToString(const Address&); ICE_API int getPort(const Address&); diff --git a/cpp/src/Ice/PropertyNames.cpp b/cpp/src/Ice/PropertyNames.cpp index e78121014d3..02ee0f7ac2c 100644 --- a/cpp/src/Ice/PropertyNames.cpp +++ b/cpp/src/Ice/PropertyNames.cpp @@ -6,7 +6,7 @@ // ICE_LICENSE file included in this distribution. // // ********************************************************************** -// Generated by makeprops.py from file ..\config\PropertyNames.xml, Fri Feb 24 18:49:18 2017 +// Generated by makeprops.py from file ./config/PropertyNames.xml, Tue Feb 28 15:01:12 2017 // IMPORTANT: Do not edit this file -- any edits made here will be lost! @@ -520,6 +520,43 @@ const IceInternal::Property IceGridAdminPropsData[] = IceInternal::Property("IceGridAdmin.Discovery.Reply.ThreadPool.ThreadIdleTime", false, 0), IceInternal::Property("IceGridAdmin.Discovery.Reply.ThreadPool.ThreadPriority", false, 0), IceInternal::Property("IceGridAdmin.Discovery.Reply.MessageSizeMax", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.ACM.Timeout", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.ACM.Heartbeat", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.ACM.Close", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.ACM", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.AdapterId", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.Endpoints", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.Locator.EndpointSelection", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.Locator.ConnectionCached", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.Locator.PreferSecure", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.Locator.LocatorCacheTimeout", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.Locator.InvocationTimeout", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.Locator.Locator", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.Locator.Router", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.Locator.CollocationOptimized", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.Locator.Context.*", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.Locator", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.PublishedEndpoints", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.ReplicaGroupId", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.Router.EndpointSelection", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.Router.ConnectionCached", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.Router.PreferSecure", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.Router.LocatorCacheTimeout", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.Router.InvocationTimeout", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.Router.Locator", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.Router.Router", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.Router.CollocationOptimized", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.Router.Context.*", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.Router", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.ProxyOptions", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.ThreadPool.Size", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.ThreadPool.SizeMax", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.ThreadPool.SizeWarn", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.ThreadPool.StackSize", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.ThreadPool.Serialize", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.ThreadPool.ThreadIdleTime", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.ThreadPool.ThreadPriority", false, 0), + IceInternal::Property("IceGridAdmin.Discovery.Locator.MessageSizeMax", false, 0), IceInternal::Property("IceGridAdmin.Trace.Observers", false, 0), IceInternal::Property("IceGridAdmin.Trace.SaveToRegistry", false, 0), }; diff --git a/cpp/src/Ice/PropertyNames.h b/cpp/src/Ice/PropertyNames.h index 3479ab66c1e..171fa1bed8c 100644 --- a/cpp/src/Ice/PropertyNames.h +++ b/cpp/src/Ice/PropertyNames.h @@ -6,7 +6,7 @@ // ICE_LICENSE file included in this distribution. // // ********************************************************************** -// Generated by makeprops.py from file ..\config\PropertyNames.xml, Fri Feb 24 18:49:18 2017 +// Generated by makeprops.py from file ./config/PropertyNames.xml, Tue Feb 28 15:01:12 2017 // IMPORTANT: Do not edit this file -- any edits made here will be lost! diff --git a/cpp/src/Ice/UdpTransceiver.cpp b/cpp/src/Ice/UdpTransceiver.cpp index 0eeba8690e2..bcb78ed2373 100755 --- a/cpp/src/Ice/UdpTransceiver.cpp +++ b/cpp/src/Ice/UdpTransceiver.cpp @@ -774,7 +774,7 @@ IceInternal::UdpTransceiver::toDetailedString() const vector<string> intfs; if(isAddressValid(_mcastAddr)) { - intfs = getInterfacesForMulticast(_mcastInterface, _mcastAddr); + intfs = getInterfacesForMulticast(_mcastInterface, getProtocolSupport(_mcastAddr)); } else { diff --git a/cpp/src/IceDiscovery/LookupI.cpp b/cpp/src/IceDiscovery/LookupI.cpp index 0f554e397d8..76fb6525f03 100644 --- a/cpp/src/IceDiscovery/LookupI.cpp +++ b/cpp/src/IceDiscovery/LookupI.cpp @@ -56,24 +56,31 @@ AdapterRequest::response(const Ice::ObjectPrxPtr& proxy, bool isReplicaGroup) return true; } -#ifdef ICE_CPP11_MAPPING void -AdapterRequest::finished(const Ice::ObjectPrxPtr& proxy) +AdapterRequest::finished(const ObjectPrxPtr& proxy) { if(proxy || _proxies.empty()) { +#ifdef ICE_CPP11_MAPPING Request<string>::finished(proxy); +#else + RequestT<string, AMD_Locator_findAdapterByIdPtr>::finished(proxy); +#endif return; } else if(_proxies.size() == 1) { +#ifdef ICE_CPP11_MAPPING Request<string>::finished(_proxies[0]); +#else + RequestT<string, AMD_Locator_findAdapterByIdPtr>::finished(_proxies[0]); +#endif return; } EndpointSeq endpoints; - shared_ptr<ObjectPrx> prx; - for(vector<shared_ptr<ObjectPrx>>::const_iterator p = _proxies.begin(); p != _proxies.end(); ++p) + ObjectPrxPtr prx; + for(vector<ObjectPrxPtr>::const_iterator p = _proxies.begin(); p != _proxies.end(); ++p) { if(!prx) { @@ -82,37 +89,12 @@ AdapterRequest::finished(const Ice::ObjectPrxPtr& proxy) Ice::EndpointSeq endpts = (*p)->ice_getEndpoints(); copy(endpts.begin(), endpts.end(), back_inserter(endpoints)); } +#ifdef ICE_CPP11_MAPPING Request<string>::finished(prx->ice_endpoints(endpoints)); -} #else -void -AdapterRequest::finished(const Ice::ObjectPrxPtr& proxy) -{ - if(proxy || _proxies.empty()) - { - RequestT<std::string, Ice::AMD_Locator_findAdapterByIdPtr>::finished(proxy); - return; - } - else if(_proxies.size() == 1) - { - RequestT<std::string, Ice::AMD_Locator_findAdapterByIdPtr>::finished(_proxies[0]); - return; - } - - Ice::EndpointSeq endpoints; - Ice::ObjectPrxPtr prx; - for(vector<Ice::ObjectPrxPtr>::const_iterator p = _proxies.begin(); p != _proxies.end(); ++p) - { - if(!prx) - { - prx = *p; - } - Ice::EndpointSeq endpts = (*p)->ice_getEndpoints(); - copy(endpts.begin(), endpts.end(), back_inserter(endpoints)); - } - RequestT<std::string, Ice::AMD_Locator_findAdapterByIdPtr>::finished(prx->ice_endpoints(endpoints)); -} + RequestT<string, AMD_Locator_findAdapterByIdPtr>::finished(prx->ice_endpoints(endpoints)); #endif +} void AdapterRequest::runTimerTask() @@ -134,13 +116,52 @@ ObjectRequest::runTimerTask() LookupI::LookupI(const LocatorRegistryIPtr& registry, const LookupPrxPtr& lookup, const Ice::PropertiesPtr& properties) : _registry(registry), - _lookup(lookup), _timeout(IceUtil::Time::milliSeconds(properties->getPropertyAsIntWithDefault("IceDiscovery.Timeout", 300))), _retryCount(properties->getPropertyAsIntWithDefault("IceDiscovery.RetryCount", 3)), _latencyMultiplier(properties->getPropertyAsIntWithDefault("IceDiscovery.LatencyMultiplier", 1)), _domainId(properties->getProperty("IceDiscovery.DomainId")), _timer(IceInternal::getInstanceTimer(lookup->ice_getCommunicator())) { +#ifndef ICE_CPP11_MAPPING + __setNoDelete(true); +#endif + try + { + // Ensure we can establish a connection to the multicast proxy + lookup->ice_getConnection(); + } + catch(const Ice::LocalException& ex) + { + ostringstream os; + os << "IceDiscovery is unable to establish a multicast connection:\n"; + os << "proxy = " << lookup << '\n'; + os << ex; + throw Ice::PluginInitializationException(__FILE__, __LINE__, os.str()); + } + + // + // Create one lookup proxy per endpoint from the given proxy. We want to send a multicast + // datagram on each endpoint. + // + EndpointSeq endpoints = lookup->ice_getEndpoints(); + for(vector<EndpointPtr>::const_iterator p = endpoints.begin(); p != endpoints.end(); ++p) + { + try + { + EndpointSeq single; + single.push_back(*p); + LookupPrxPtr l = lookup->ice_endpoints(single); + l->ice_getConnection(); + _lookup.push_back(make_pair(l, LookupReplyPrxPtr())); + } + catch(const Ice::LocalException&) + { + } + } + assert(!_lookup.empty()); +#ifndef ICE_CPP11_MAPPING + __setNoDelete(false); +#endif } LookupI::~LookupI() @@ -168,7 +189,32 @@ LookupI::destroy() void LookupI::setLookupReply(const LookupReplyPrxPtr& lookupReply) { - _lookupReply = lookupReply; + // + // Use a lookup reply proxy whose adress matches the interface used to send multicast datagrams. + // + for(vector<pair<LookupPrxPtr, LookupReplyPrxPtr> >::iterator p = _lookup.begin(); p != _lookup.end(); ++p) + { + UDPEndpointInfoPtr info = ICE_DYNAMIC_CAST(UDPEndpointInfo, p->first->ice_getEndpoints()[0]->getInfo()); + if(info && !info->mcastInterface.empty()) + { + EndpointSeq endpts = lookupReply->ice_getEndpoints(); + for(EndpointSeq::const_iterator q = endpts.begin(); q != endpts.end(); ++q) + { + IPEndpointInfoPtr r = ICE_DYNAMIC_CAST(IPEndpointInfo, (*q)->getInfo()); + if(r && r->host == info->mcastInterface) + { + EndpointSeq single; + single.push_back(*q); + p->second = lookupReply->ice_endpoints(single); + } + } + } + + if(!p->second) + { + p->second = lookupReply; // Fallback: just use the given lookup reply proxy if no matching endpoint found. + } + } } void @@ -242,107 +288,85 @@ LookupI::findAdapterById(const string& domainId, const string& adapterId, const } } -#ifdef ICE_CPP11_MAPPING void -LookupI::findObject(function<void(const shared_ptr<Ice::ObjectPrx>&)> response, const Ice::Identity& id) -{ - Lock sync(*this); - map<Ice::Identity, ObjectRequestPtr>::iterator p = _objectRequests.find(id); - if(p == _objectRequests.end()) - { - p = _objectRequests.insert(make_pair(id, make_shared<ObjectRequest>(shared_from_this(), id, _retryCount))).first; - } - - if(p->second->addCallback(response)) - { - try - { - _lookup->findObjectByIdAsync(_domainId, id, _lookupReply); - _timer->schedule(p->second, _timeout); - } - catch(const Ice::LocalException&) - { - p->second->finished(nullptr); - _objectRequests.erase(p); - } - } -} - -void -LookupI::findAdapter(function<void(const shared_ptr<Ice::ObjectPrx>&)> response, const std::string& adapterId) -{ - Lock sync(*this); - map<string, AdapterRequestPtr>::iterator p = _adapterRequests.find(adapterId); - if(p == _adapterRequests.end()) - { - p = _adapterRequests.insert(make_pair(adapterId, make_shared<AdapterRequest>(shared_from_this(), adapterId, _retryCount))).first; - } - - if(p->second->addCallback(response)) - { - try - { - _lookup->findAdapterByIdAsync(_domainId, adapterId, _lookupReply); - _timer->schedule(p->second, _timeout); - } - catch(const Ice::LocalException&) - { - p->second->finished(0); - _adapterRequests.erase(p); - } - } -} +#ifdef ICE_CPP11_MAPPING +LookupI::findObject(function<void(const shared_ptr<Ice::ObjectPrx>&)> cb, const Ice::Identity& id) #else -void LookupI::findObject(const Ice::AMD_Locator_findObjectByIdPtr& cb, const Ice::Identity& id) +#endif { Lock sync(*this); map<Ice::Identity, ObjectRequestPtr>::iterator p = _objectRequests.find(id); if(p == _objectRequests.end()) { - p = _objectRequests.insert(make_pair(id, new ObjectRequest(this, id, _retryCount))).first; + p = _objectRequests.insert(make_pair(id, ICE_MAKE_SHARED(ObjectRequest, + ICE_SHARED_FROM_THIS, + id, + _retryCount))).first; } if(p->second->addCallback(cb)) { try { - _lookup->begin_findObjectById(_domainId, id, _lookupReply); + for(vector<pair<LookupPrxPtr, LookupReplyPrxPtr> >::const_iterator l = _lookup.begin(); l != _lookup.end(); + ++l) + { +#ifdef ICE_CPP11_MAPPING + l->first->findObjectByIdAsync(_domainId, id, l->second); +#else + l->first->begin_findObjectById(_domainId, id, l->second); +#endif + } _timer->schedule(p->second, _timeout); } catch(const Ice::LocalException&) { - p->second->finished(0); + p->second->finished(ICE_NULLPTR); _objectRequests.erase(p); } } } void +#ifdef ICE_CPP11_MAPPING +LookupI::findAdapter(function<void(const shared_ptr<Ice::ObjectPrx>&)> cb, const std::string& adapterId) +#else LookupI::findAdapter(const Ice::AMD_Locator_findAdapterByIdPtr& cb, const std::string& adapterId) +#endif { Lock sync(*this); map<string, AdapterRequestPtr>::iterator p = _adapterRequests.find(adapterId); if(p == _adapterRequests.end()) { - p = _adapterRequests.insert(make_pair(adapterId, new AdapterRequest(this, adapterId, _retryCount))).first; + p = _adapterRequests.insert(make_pair(adapterId, ICE_MAKE_SHARED(AdapterRequest, + ICE_SHARED_FROM_THIS, + adapterId, + _retryCount))).first; } if(p->second->addCallback(cb)) { try { - _lookup->begin_findAdapterById(_domainId, adapterId, _lookupReply); + for(vector<pair<LookupPrxPtr, LookupReplyPrxPtr> >::const_iterator l = _lookup.begin(); l != _lookup.end(); + ++l) + { +#ifdef ICE_CPP11_MAPPING + l->first->findAdapterByIdAsync(_domainId, adapterId, l->second); +#else + l->first->begin_findAdapterById(_domainId, adapterId, l->second); +#endif + } _timer->schedule(p->second, _timeout); } catch(const Ice::LocalException&) { - p->second->finished(0); + p->second->finished(ICE_NULLPTR); _adapterRequests.erase(p); } } } -#endif void LookupI::foundObject(const Ice::Identity& id, const Ice::ObjectPrxPtr& proxy) @@ -390,11 +414,15 @@ LookupI::objectRequestTimedOut(const ObjectRequestPtr& request) { try { + for(vector<pair<LookupPrxPtr, LookupReplyPrxPtr> >::const_iterator l = _lookup.begin(); l != _lookup.end(); + ++l) + { #ifdef ICE_CPP11_MAPPING - _lookup->findObjectByIdAsync(_domainId, request->getId(), _lookupReply); + l->first->findObjectByIdAsync(_domainId, request->getId(), l->second); #else - _lookup->begin_findObjectById(_domainId, request->getId(), _lookupReply); + l->first->begin_findObjectById(_domainId, request->getId(), l->second); #endif + } _timer->schedule(p->second, _timeout); return; } @@ -422,11 +450,15 @@ LookupI::adapterRequestTimedOut(const AdapterRequestPtr& request) { try { + for(vector<pair<LookupPrxPtr, LookupReplyPrxPtr> >::const_iterator l = _lookup.begin(); l != _lookup.end(); + ++l) + { #ifdef ICE_CPP11_MAPPING - _lookup->findAdapterByIdAsync(_domainId, request->getId(), _lookupReply); + l->first->findAdapterByIdAsync(_domainId, request->getId(), l->second); #else - _lookup->begin_findAdapterById(_domainId, request->getId(), _lookupReply); + l->first->begin_findAdapterById(_domainId, request->getId(), l->second); #endif + } _timer->schedule(p->second, _timeout); return; } diff --git a/cpp/src/IceDiscovery/LookupI.h b/cpp/src/IceDiscovery/LookupI.h index fed98927913..46f582d6118 100644 --- a/cpp/src/IceDiscovery/LookupI.h +++ b/cpp/src/IceDiscovery/LookupI.h @@ -255,8 +255,7 @@ public: private: LocatorRegistryIPtr _registry; - const LookupPrxPtr _lookup; - LookupReplyPrxPtr _lookupReply; + std::vector<std::pair<LookupPrxPtr, LookupReplyPrxPtr> > _lookup; const IceUtil::Time _timeout; const int _retryCount; const int _latencyMultiplier; diff --git a/cpp/src/IceDiscovery/PluginI.cpp b/cpp/src/IceDiscovery/PluginI.cpp index 2275459c04f..fa6e65bc5b2 100644 --- a/cpp/src/IceDiscovery/PluginI.cpp +++ b/cpp/src/IceDiscovery/PluginI.cpp @@ -9,6 +9,7 @@ #include <IceUtil/IceUtil.h> #include <Ice/Ice.h> +#include <Ice/Network.h> // For getInterfacesForMulticast #include <IceDiscovery/PluginI.h> #include <IceDiscovery/LocatorI.h> @@ -87,16 +88,33 @@ PluginI::initialize() } properties->setProperty("IceDiscovery.Multicast.Endpoints", os.str()); } - if(properties->getProperty("IceDiscovery.Reply.Endpoints").empty()) + + string lookupEndpoints = properties->getProperty("IceDiscovery.Lookup"); + if(lookupEndpoints.empty()) { - ostringstream os; - os << "udp"; - if(!intf.empty()) + // + // If no lookup endpoints are specified, we get all the network interfaces and create + // an endpoint for each of them. We'll send UDP multicast packages on each interface. + // + IceInternal::ProtocolSupport protocol = ipv4 && !preferIPv6 ? IceInternal::EnableIPv4 : IceInternal::EnableIPv6; + vector<string> interfaces = IceInternal::getInterfacesForMulticast(intf, protocol); + ostringstream lookup; + for(vector<string>::const_iterator p = interfaces.begin(); p != interfaces.end(); ++p) { - os << " -h \"" << intf << "\""; + if(p != interfaces.begin()) + { + lookup << ":"; + } + lookup << "udp -h \"" << address << "\" -p " << port << " --interface \"" << *p << "\""; } - properties->setProperty("IceDiscovery.Reply.Endpoints", os.str()); + lookupEndpoints = lookup.str(); } + + if(properties->getProperty("IceDiscovery.Reply.Endpoints").empty()) + { + properties->setProperty("IceDiscovery.Reply.Endpoints", "udp -h " + (intf.empty() ? "*" : "\"" + intf + "\"")); + } + if(properties->getProperty("IceDiscovery.Locator.Endpoints").empty()) { properties->setProperty("IceDiscovery.Locator.AdapterId", Ice::generateUUID()); @@ -113,42 +131,8 @@ PluginI::initialize() Ice::LocatorRegistryPrxPtr locatorRegistryPrx = ICE_UNCHECKED_CAST(Ice::LocatorRegistryPrx, _locatorAdapter->addWithUUID(locatorRegistry)); - string lookupEndpoints = properties->getProperty("IceDiscovery.Lookup"); - if(lookupEndpoints.empty()) - { - ostringstream os; - os << "udp -h \"" << address << "\" -p " << port; - if(!intf.empty()) - { - os << " --interface \"" << intf << "\""; - } - lookupEndpoints = os.str(); - } - Ice::ObjectPrxPtr lookupPrx = _communicator->stringToProxy("IceDiscovery/Lookup -d:" + lookupEndpoints); lookupPrx = lookupPrx->ice_collocationOptimized(false); // No collocation optimization for the multicast proxy! - try - { - // Ensure we can establish a connection to the multicast proxy - // but don't block. -#ifdef ICE_CPP11_MAPPING - lookupPrx->ice_getConnection(); -#else - Ice::AsyncResultPtr result = lookupPrx->begin_ice_getConnection(); - if(result->sentSynchronously()) - { - lookupPrx->end_ice_getConnection(result); - } -#endif - } - catch(const Ice::LocalException& ex) - { - ostringstream os; - os << "IceDiscovery is unable to establish a multicast connection:\n"; - os << "proxy = " << lookupPrx << '\n'; - os << ex; - throw Ice::PluginInitializationException(__FILE__, __LINE__, os.str()); - } // // Add lookup and lookup reply Ice objects diff --git a/cpp/src/IceGrid/Client.cpp b/cpp/src/IceGrid/Client.cpp index 35721f3cf74..3473bdb72ca 100644 --- a/cpp/src/IceGrid/Client.cpp +++ b/cpp/src/IceGrid/Client.cpp @@ -21,7 +21,7 @@ #include <IceGrid/Parser.h> #include <IceGrid/FileParserI.h> #include <IceGrid/Registry.h> -#include <IceGrid/IceLocatorDiscovery.h> +#include <IceLocatorDiscovery/Plugin.h> #include <Glacier2/Router.h> #include <fstream> @@ -68,74 +68,6 @@ public: Init init; -class LookupReplyI : public LookupReply, private IceUtil::Monitor<IceUtil::Mutex> -{ -public: - - virtual void - foundLocator(const Ice::LocatorPrx& locator, const Ice::Current&) - { - Lock sync(*this); - for(vector<Ice::LocatorPrx>::iterator p = _locators.begin(); p != _locators.end(); ++p) - { - if((*p)->ice_getIdentity() == locator->ice_getIdentity()) - { - Ice::EndpointSeq newEndpoints = (*p)->ice_getEndpoints(); - Ice::EndpointSeq endpts = locator->ice_getEndpoints(); - for(Ice::EndpointSeq::const_iterator r = endpts.begin(); r != endpts.end(); ++r) - { - // - // Only add unknown endpoints - // - bool found = false; - for(Ice::EndpointSeq::const_iterator q = newEndpoints.begin(); q != newEndpoints.end(); ++q) - { - if(*r == *q) - { - found = true; - break; - } - } - if(!found) - { - newEndpoints.push_back(*r); - } - } - *p = (*p)->ice_endpoints(newEndpoints); - return; - } - } - _locators.push_back(locator); - notify(); - } - - vector<Ice::LocatorPrx> - getLocators() - { - Lock sync(*this); - return _locators; - } - - bool - waitForLocator() - { - Lock sync(*this); - while(_locators.empty()) - { - if(!timedWait(IceUtil::Time::milliSeconds(300))) - { - return false; - } - } - return true; - } - -private: - - vector<Ice::LocatorPrx> _locators; -}; -typedef IceUtil::Handle<LookupReplyI> LookupReplyIPtr; - } class SessionKeepAliveThread : public IceUtil::Thread, public IceUtil::Monitor<IceUtil::Mutex> @@ -297,6 +229,8 @@ Client::usage() ; } +extern "C" ICE_LOCATOR_DISCOVERY_API Ice::Plugin* +createIceLocatorDiscovery(const Ice::CommunicatorPtr&, const string&, const Ice::StringSeq&); int Client::main(StringSeq& args) @@ -539,74 +473,17 @@ Client::run(StringSeq& originalArgs) } else { - bool ipv4 = properties->getPropertyAsIntWithDefault("Ice.IPv4", 1) > 0; - string address; - bool preferIPv6 = properties->getPropertyAsInt("Ice.PreferIPv6Address") > 0; - if(ipv4 && !preferIPv6) - { - address = properties->getPropertyWithDefault("IceGridAdmin.Discovery.Address", "239.255.0.1"); - } - else - { - address = properties->getPropertyWithDefault("IceGridAdmin.Discovery.Address", "ff15::1"); - } - - string interface = properties->getProperty("IceGridAdmin.Discovery.Interface"); - - string lookupEndpoints = properties->getProperty("IceGridAdmin.Discovery.Lookup"); - if(lookupEndpoints.empty()) - { - ostringstream os; - os << "udp -h \"" << address << "\" -p " << (port == 0 ? 4061 : port); - if(!interface.empty()) - { - os << " --interface \"" << interface << "\""; - } - lookupEndpoints = os.str(); - } - - ObjectPrx prx = communicator()->stringToProxy("IceLocatorDiscovery/Lookup -d:" + lookupEndpoints); - LookupPrx lookupPrx = LookupPrx::uncheckedCast(prx->ice_collocationOptimized(false)); - - if(properties->getProperty("IceGridAdmin.Discovery.Reply.Endpoints").empty()) - { - ostringstream os; - os << "udp"; - if(!interface.empty()) - { - os << " -h \"" << interface << "\""; - } - properties->setProperty("IceGridAdmin.Discovery.Reply.Endpoints", os.str()); - } - - Ice::ObjectAdapterPtr adapter = communicator()->createObjectAdapter("IceGridAdmin.Discovery.Reply"); - adapter->activate(); - LookupReplyIPtr reply = new LookupReplyI(); - LookupReplyPrx replyPrx = LookupReplyPrx::uncheckedCast(adapter->addWithUUID(reply)->ice_datagram()); - int retryCount = 3; // Send several findLocator queries. - try - { - while(--retryCount >= 0) - { - lookupPrx->findLocator(instanceName, replyPrx); - if(instanceName.empty()) - { - IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(300)); - } - else if(reply->waitForLocator()) - { - break; - } - } - } - catch(const Ice::LocalException& ex) - { - consoleErr << _appName << ": registry discovery failed:\n" << ex << endl; - return EXIT_FAILURE; - } - adapter->destroy(); + // + // NOTE: we don't configure the plugin with the Ice communicator on initialization + // because it would install a default locator. Instead, we create the plugin here + // to lookup for locator proxies. We destroy the plugin, once we have selected a + // locator. + // + Ice::PluginPtr p = createIceLocatorDiscovery(communicator(), "IceGridAdmin.Discovery", Ice::StringSeq()); + IceLocatorDiscovery::PluginPtr plugin = IceLocatorDiscovery::PluginPtr::dynamicCast(p); + plugin->initialize(); - vector<Ice::LocatorPrx> locators = reply->getLocators(); + vector<Ice::LocatorPrx> locators = plugin->getLocators(instanceName, IceUtil::Time::milliSeconds(300)); if(locators.size() > 1) { consoleOut << "found " << locators.size() << " Ice locators:" << endl; @@ -644,6 +521,15 @@ Client::run(StringSeq& originalArgs) consoleOut << "using discovered locator:\nproxy = `" << locators[0] << "'" << endl; communicator()->setDefaultLocator(locators[0]); } + else + { + communicator()->setDefaultLocator(0); + } + + // + // Destroy the plugin, we no longer need it. + // + plugin->destroy(); } } diff --git a/cpp/src/IceGrid/Makefile.mk b/cpp/src/IceGrid/Makefile.mk index 4e14f08b10b..c3ab9e190a2 100644 --- a/cpp/src/IceGrid/Makefile.mk +++ b/cpp/src/IceGrid/Makefile.mk @@ -78,9 +78,8 @@ icegridregistry_sources := $(addprefix $(currentdir)/,$(local_registry_srcs) I icegridregistry_dependencies := IceBox IceStormService IceStorm IceXML IceSSL IcePatch2 IceDB $(local_dependencies) icegridregistry_cppflags := $(if $(lmdb_includedir),-I$(lmdb_includedir)) -icegridadmin_dependencies := IcePatch2 IceBox IceXML -icegridadmin_sources := $(slicedir)/IceLocatorDiscovery/IceLocatorDiscovery.ice \ - $(addprefix $(currentdir)/,$(local_admin_srcs)) +icegridadmin_dependencies := IcePatch2 IceBox IceXML IceLocatorDiscovery +icegridadmin_sources := $(addprefix $(currentdir)/,$(local_admin_srcs)) projects += $(project) diff --git a/cpp/src/IceGrid/msbuild/icegridadmin/icegridadmin.vcxproj b/cpp/src/IceGrid/msbuild/icegridadmin/icegridadmin.vcxproj index bbc62f79b1c..65ef495834a 100644 --- a/cpp/src/IceGrid/msbuild/icegridadmin/icegridadmin.vcxproj +++ b/cpp/src/IceGrid/msbuild/icegridadmin/icegridadmin.vcxproj @@ -105,41 +105,21 @@ <ClCompile Include="..\..\Parser.cpp" /> <ClCompile Include="..\..\Scanner.cpp" /> <ClCompile Include="..\..\Util.cpp" /> - <ClCompile Include="Win32\Debug\IceLocatorDiscovery.cpp"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> - </ClCompile> <ClCompile Include="Win32\Debug\Internal.cpp"> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> </ClCompile> - <ClCompile Include="Win32\Release\IceLocatorDiscovery.cpp"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> - </ClCompile> <ClCompile Include="Win32\Release\Internal.cpp"> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> </ClCompile> - <ClCompile Include="x64\Debug\IceLocatorDiscovery.cpp"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> - </ClCompile> <ClCompile Include="x64\Debug\Internal.cpp"> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> </ClCompile> - <ClCompile Include="x64\Release\IceLocatorDiscovery.cpp"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> - </ClCompile> <ClCompile Include="x64\Release\Internal.cpp"> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> @@ -147,45 +127,24 @@ </ClCompile> </ItemGroup> <ItemGroup> - <IceBuilder Include="..\..\..\..\..\slice\IceLocatorDiscovery\IceLocatorDiscovery.ice" /> <IceBuilder Include="..\..\Internal.ice" /> </ItemGroup> <ItemGroup> - <ClInclude Include="Win32\Debug\IceGrid\IceLocatorDiscovery.h"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> - </ClInclude> <ClInclude Include="Win32\Debug\IceGrid\Internal.h"> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> </ClInclude> - <ClInclude Include="Win32\Release\IceGrid\IceLocatorDiscovery.h"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> - </ClInclude> <ClInclude Include="Win32\Release\IceGrid\Internal.h"> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> </ClInclude> - <ClInclude Include="x64\Debug\IceGrid\IceLocatorDiscovery.h"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> - </ClInclude> <ClInclude Include="x64\Debug\IceGrid\Internal.h"> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> </ClInclude> - <ClInclude Include="x64\Release\IceGrid\IceLocatorDiscovery.h"> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> - <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> - </ClInclude> <ClInclude Include="x64\Release\IceGrid\Internal.h"> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> diff --git a/cpp/src/IceGrid/msbuild/icegridadmin/icegridadmin.vcxproj.filters b/cpp/src/IceGrid/msbuild/icegridadmin/icegridadmin.vcxproj.filters index fc0cc2249bc..d63f7b210fc 100644 --- a/cpp/src/IceGrid/msbuild/icegridadmin/icegridadmin.vcxproj.filters +++ b/cpp/src/IceGrid/msbuild/icegridadmin/icegridadmin.vcxproj.filters @@ -82,61 +82,34 @@ <ClCompile Include="..\..\Util.cpp"> <Filter>Source Files</Filter> </ClCompile> - <ClCompile Include="Win32\Debug\IceLocatorDiscovery.cpp"> - <Filter>Source Files\Win32\Debug</Filter> - </ClCompile> <ClCompile Include="Win32\Debug\Internal.cpp"> <Filter>Source Files\Win32\Debug</Filter> </ClCompile> - <ClCompile Include="x64\Debug\IceLocatorDiscovery.cpp"> - <Filter>Source Files\x64\Debug</Filter> - </ClCompile> <ClCompile Include="x64\Debug\Internal.cpp"> <Filter>Source Files\x64\Debug</Filter> </ClCompile> - <ClCompile Include="Win32\Release\IceLocatorDiscovery.cpp"> - <Filter>Source Files\Win32\Release</Filter> - </ClCompile> <ClCompile Include="Win32\Release\Internal.cpp"> <Filter>Source Files\Win32\Release</Filter> </ClCompile> - <ClCompile Include="x64\Release\IceLocatorDiscovery.cpp"> - <Filter>Source Files\x64\Release</Filter> - </ClCompile> <ClCompile Include="x64\Release\Internal.cpp"> <Filter>Source Files\x64\Release</Filter> </ClCompile> </ItemGroup> <ItemGroup> - <IceBuilder Include="..\..\..\..\..\slice\IceLocatorDiscovery\IceLocatorDiscovery.ice"> - <Filter>Slice Files</Filter> - </IceBuilder> <IceBuilder Include="..\..\Internal.ice"> <Filter>Slice Files</Filter> </IceBuilder> </ItemGroup> <ItemGroup> - <ClInclude Include="Win32\Debug\IceGrid\IceLocatorDiscovery.h"> - <Filter>Header Files\Win32\Debug</Filter> - </ClInclude> <ClInclude Include="Win32\Debug\IceGrid\Internal.h"> <Filter>Header Files\Win32\Debug</Filter> </ClInclude> - <ClInclude Include="x64\Debug\IceGrid\IceLocatorDiscovery.h"> - <Filter>Header Files\x64\Debug</Filter> - </ClInclude> <ClInclude Include="x64\Debug\IceGrid\Internal.h"> <Filter>Header Files\x64\Debug</Filter> </ClInclude> - <ClInclude Include="Win32\Release\IceGrid\IceLocatorDiscovery.h"> - <Filter>Header Files\Win32\Release</Filter> - </ClInclude> <ClInclude Include="Win32\Release\IceGrid\Internal.h"> <Filter>Header Files\Win32\Release</Filter> </ClInclude> - <ClInclude Include="x64\Release\IceGrid\IceLocatorDiscovery.h"> - <Filter>Header Files\x64\Release</Filter> - </ClInclude> <ClInclude Include="x64\Release\IceGrid\Internal.h"> <Filter>Header Files\x64\Release</Filter> </ClInclude> diff --git a/cpp/src/IceLocatorDiscovery/Plugin.h b/cpp/src/IceLocatorDiscovery/Plugin.h new file mode 100644 index 00000000000..f9e02b1166a --- /dev/null +++ b/cpp/src/IceLocatorDiscovery/Plugin.h @@ -0,0 +1,52 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef LOCATOR_DISCOVERY_PLUGIN_I_H +#define LOCATOR_DISCOVERY_PLUGIN_I_H + +#include <Ice/Config.h> +#include <Ice/Plugin.h> +#include <Ice/Locator.h> +#include <IceUtil/Time.h> + +// +// Automatically link IceLocatorDiscovery[D|++11|++11D].lib with Visual C++ +// +#if !defined(ICE_BUILDING_ICE_LOCATOR_DISCOVERY) && defined(ICE_LOCATOR_DISCOVERY_API_EXPORTS) +# define ICE_BUILDING_ICE_LOCATOR_DISCOVERY +#endif + +#if defined(_MSC_VER) && !defined(ICE_BUILDING_ICE_LOCATOR_DISCOVERY) +# pragma comment(lib, ICE_LIBNAME("IceLocatorDiscovery")) +#endif + +#ifndef ICE_LOCATOR_DISCOVERY_API +# if defined(ICE_STATIC_LIBS) +# define ICE_LOCATOR_DISCOVERY_API /**/ +# elif defined(ICE_LOCATOR_DISCOVERY_API_EXPORTS) +# define ICE_LOCATOR_DISCOVERY_API ICE_DECLSPEC_EXPORT +# else +# define ICE_LOCATOR_DISCOVERY_API ICE_DECLSPEC_IMPORT +# endif +#endif + +namespace IceLocatorDiscovery +{ + +class ICE_LOCATOR_DISCOVERY_API Plugin : public Ice::Plugin +{ +public: + + virtual std::vector<Ice::LocatorPrxPtr> getLocators(const std::string&, const IceUtil::Time&) const = 0; +}; +ICE_DEFINE_PTR(PluginPtr, Plugin); + +}; + +#endif diff --git a/cpp/src/IceLocatorDiscovery/PluginI.cpp b/cpp/src/IceLocatorDiscovery/PluginI.cpp index d68d4eacf34..7948fa13870 100644 --- a/cpp/src/IceLocatorDiscovery/PluginI.cpp +++ b/cpp/src/IceLocatorDiscovery/PluginI.cpp @@ -9,50 +9,14 @@ #include <IceUtil/IceUtil.h> #include <Ice/Ice.h> +#include <Ice/Network.h> // For getInterfacesForMulticast -#include <IceLocatorDiscovery/PluginI.h> +#include <IceLocatorDiscovery/Plugin.h> #include <IceLocatorDiscovery/IceLocatorDiscovery.h> using namespace std; using namespace IceLocatorDiscovery; -#ifndef ICE_LOCATOR_DISCOVERY_API -# ifdef ICE_LOCATOR_DISCOVERY_API_EXPORTS -# define ICE_LOCATOR_DISCOVERY_API ICE_DECLSPEC_EXPORT -# else -# define ICE_LOCATOR_DISCOVERY_API /**/ -# endif -#endif - -// -// Plugin factory function. -// -extern "C" ICE_LOCATOR_DISCOVERY_API Ice::Plugin* -createIceLocatorDiscovery(const Ice::CommunicatorPtr& communicator, const string&, const Ice::StringSeq&) -{ - return new PluginI(communicator); -} - -namespace Ice -{ - -ICE_LOCATOR_DISCOVERY_API void -registerIceLocatorDiscovery(bool loadOnInitialize) -{ - Ice::registerPluginFactory("IceLocatorDiscovery", createIceLocatorDiscovery, loadOnInitialize); -} - -} - -// -// Objective-C function to allow Objective-C programs to register plugin. -// -extern "C" ICE_LOCATOR_DISCOVERY_API void -ICEregisterIceLocatorDiscovery(bool loadOnInitialize) -{ - Ice::registerIceLocatorDiscovery(loadOnInitialize); -} - namespace { @@ -136,7 +100,7 @@ class LocatorI : public Ice::BlobjectArrayAsync, { public: - LocatorI(const LookupPrxPtr&, const Ice::PropertiesPtr&, const string&, const Ice::LocatorPrxPtr&); + LocatorI(const string&, const LookupPrxPtr&, const Ice::PropertiesPtr&, const string&, const Ice::LocatorPrxPtr&); void setLookupReply(const LookupReplyPrxPtr&); #ifdef ICE_CPP11_MAPPING @@ -152,11 +116,13 @@ public: void foundLocator(const Ice::LocatorPrxPtr&); void invoke(const Ice::LocatorPrxPtr&, const RequestPtr&); + vector<Ice::LocatorPrxPtr> getLocators(const string&, const IceUtil::Time&); + private: virtual void runTimerTask(); - const LookupPrxPtr _lookup; + vector<pair<LookupPrxPtr, LookupReplyPrxPtr> > _lookup; const IceUtil::Time _timeout; const int _retryCount; const IceUtil::Time _retryDelay; @@ -164,8 +130,8 @@ private: string _instanceName; bool _warned; - LookupReplyPrxPtr _lookupReply; Ice::LocatorPrxPtr _locator; + map<string, Ice::LocatorPrxPtr> _locators; Ice::LocatorPrxPtr _voidLocator; IceUtil::Time _nextRetry; @@ -246,9 +212,58 @@ public: } }; +class PluginI : public Plugin +{ +public: + + PluginI(const std::string&, const Ice::CommunicatorPtr&); + + virtual void initialize(); + virtual void destroy(); + virtual vector<Ice::LocatorPrxPtr> getLocators(const string&, const IceUtil::Time&) const; + +private: + + const string _name; + const Ice::CommunicatorPtr _communicator; + Ice::ObjectAdapterPtr _locatorAdapter; + Ice::ObjectAdapterPtr _replyAdapter; + LocatorIPtr _locator; +}; + +} + +// +// Plugin factory function. +// +extern "C" ICE_LOCATOR_DISCOVERY_API Ice::Plugin* +createIceLocatorDiscovery(const Ice::CommunicatorPtr& communicator, const string& name, const Ice::StringSeq&) +{ + return new PluginI(name, communicator); +} + +namespace Ice +{ + +ICE_LOCATOR_DISCOVERY_API void +registerIceLocatorDiscovery(bool loadOnInitialize) +{ + Ice::registerPluginFactory("IceLocatorDiscovery", createIceLocatorDiscovery, loadOnInitialize); +} + } -PluginI::PluginI(const Ice::CommunicatorPtr& communicator) : _communicator(communicator) +// +// Objective-C function to allow Objective-C programs to register plugin. +// +extern "C" ICE_LOCATOR_DISCOVERY_API void +ICEregisterIceLocatorDiscovery(bool loadOnInitialize) +{ + Ice::registerIceLocatorDiscovery(loadOnInitialize); +} + +PluginI::PluginI(const string& name, const Ice::CommunicatorPtr& communicator) : + _name(name), _communicator(communicator) { } @@ -262,109 +277,80 @@ PluginI::initialize() string address; if(ipv4 && !preferIPv6) { - address = properties->getPropertyWithDefault("IceLocatorDiscovery.Address", "239.255.0.1"); + address = properties->getPropertyWithDefault(_name + ".Address", "239.255.0.1"); } else { - address = properties->getPropertyWithDefault("IceLocatorDiscovery.Address", "ff15::1"); + address = properties->getPropertyWithDefault(_name + ".Address", "ff15::1"); } - int port = properties->getPropertyAsIntWithDefault("IceLocatorDiscovery.Port", 4061); - string intf = properties->getProperty("IceLocatorDiscovery.Interface"); + int port = properties->getPropertyAsIntWithDefault(_name + ".Port", 4061); + string intf = properties->getProperty(_name + ".Interface"); - if(properties->getProperty("IceLocatorDiscovery.Reply.Endpoints").empty()) + string lookupEndpoints = properties->getProperty(_name + ".Lookup"); + if(lookupEndpoints.empty()) { - ostringstream os; - os << "udp"; - if(!intf.empty()) + // + // If no lookup endpoints are specified, we get all the network interfaces and create + // an endpoint for each of them. We'll send UDP multicast packages on each interface. + // + IceInternal::ProtocolSupport protocol = ipv4 && !preferIPv6 ? IceInternal::EnableIPv4 : IceInternal::EnableIPv6; + vector<string> interfaces = IceInternal::getInterfacesForMulticast(intf, protocol); + ostringstream lookup; + for(vector<string>::const_iterator p = interfaces.begin(); p != interfaces.end(); ++p) { - os << " -h \"" << intf << "\""; + if(p != interfaces.begin()) + { + lookup << ":"; + } + lookup << "udp -h \"" << address << "\" -p " << port << " --interface \"" << *p << "\""; } - properties->setProperty("IceLocatorDiscovery.Reply.Endpoints", os.str()); + lookupEndpoints = lookup.str(); + } + + if(properties->getProperty(_name + ".Reply.Endpoints").empty()) + { + properties->setProperty(_name + ".Reply.Endpoints", "udp -h " + (intf.empty() ? "*" : "\"" + intf + "\"")); } - if(properties->getProperty("IceLocatorDiscovery.Locator.Endpoints").empty()) + + if(properties->getProperty(_name + ".Locator.Endpoints").empty()) { - properties->setProperty("IceLocatorDiscovery.Locator.AdapterId", Ice::generateUUID()); // Collocated adapter + properties->setProperty(_name + ".Locator.AdapterId", Ice::generateUUID()); // Collocated adapter } - _replyAdapter = _communicator->createObjectAdapter("IceLocatorDiscovery.Reply"); - _locatorAdapter = _communicator->createObjectAdapter("IceLocatorDiscovery.Locator"); + _replyAdapter = _communicator->createObjectAdapter(_name + ".Reply"); + _locatorAdapter = _communicator->createObjectAdapter(_name + ".Locator"); // We don't want those adapters to be registered with the locator so clear their locator. _replyAdapter->setLocator(0); _locatorAdapter->setLocator(0); - string lookupEndpoints = properties->getProperty("IceLocatorDiscovery.Lookup"); - if(lookupEndpoints.empty()) - { - ostringstream os; - os << "udp -h \"" << address << "\" -p " << port; - if(!intf.empty()) - { - os << " --interface \"" << intf << "\""; - } - lookupEndpoints = os.str(); - } - Ice::ObjectPrxPtr lookupPrx = _communicator->stringToProxy("IceLocatorDiscovery/Lookup -d:" + lookupEndpoints); lookupPrx = lookupPrx->ice_collocationOptimized(false); // No collocation optimization for the multicast proxy! - try - { - // Ensure we can establish a connection to the multicast proxy - // but don't block. -#ifdef ICE_CPP11_MAPPING - promise<bool> sent; - promise<void> completed; - - lookupPrx->ice_getConnectionAsync( - [&](shared_ptr<Ice::Connection>) - { - completed.set_value(); - }, - [&](exception_ptr ex) - { - completed.set_exception(ex); - }, - [&](bool sentSynchronously) - { - sent.set_value(sentSynchronously); - }); - if(sent.get_future().get()) - { - completed.get_future().get(); - } -#else - Ice::AsyncResultPtr result = lookupPrx->begin_ice_getConnection(); - if(result->sentSynchronously()) - { - lookupPrx->end_ice_getConnection(result); - } -#endif - } - catch(const Ice::LocalException& ex) - { - ostringstream os; - os << "IceLocatorDiscovery is unable to establish a multicast connection:\n"; - os << "proxy = " << lookupPrx << '\n'; - os << ex; - throw Ice::PluginInitializationException(__FILE__, __LINE__, os.str()); - } - Ice::LocatorPrxPtr voidLocator = ICE_UNCHECKED_CAST(Ice::LocatorPrx, _locatorAdapter->addWithUUID(ICE_MAKE_SHARED(VoidLocatorI))); + Ice::LocatorPrxPtr voidLocator = ICE_UNCHECKED_CAST(Ice::LocatorPrx, + _locatorAdapter->addWithUUID(ICE_MAKE_SHARED(VoidLocatorI))); - string instanceName = properties->getProperty("IceLocatorDiscovery.InstanceName"); + string instanceName = properties->getProperty(_name + ".InstanceName"); Ice::Identity id; id.name = "Locator"; id.category = !instanceName.empty() ? instanceName : Ice::generateUUID(); - LocatorIPtr locator = ICE_MAKE_SHARED(LocatorI, ICE_UNCHECKED_CAST(LookupPrx, lookupPrx), properties, instanceName, voidLocator); - _communicator->setDefaultLocator(ICE_UNCHECKED_CAST(Ice::LocatorPrx, _locatorAdapter->add(locator, id))); + _locator = ICE_MAKE_SHARED(LocatorI, _name, ICE_UNCHECKED_CAST(LookupPrx, lookupPrx), properties, instanceName, + voidLocator); + _communicator->setDefaultLocator(ICE_UNCHECKED_CAST(Ice::LocatorPrx, _locatorAdapter->add(_locator, id))); - Ice::ObjectPrxPtr lookupReply = _replyAdapter->addWithUUID(ICE_MAKE_SHARED(LookupReplyI, locator))->ice_datagram(); - locator->setLookupReply(ICE_UNCHECKED_CAST(LookupReplyPrx, lookupReply)); + Ice::ObjectPrxPtr lookupReply = _replyAdapter->addWithUUID(ICE_MAKE_SHARED(LookupReplyI, _locator))->ice_datagram(); + _locator->setLookupReply(ICE_UNCHECKED_CAST(LookupReplyPrx, lookupReply)); _replyAdapter->activate(); _locatorAdapter->activate(); } +vector<Ice::LocatorPrxPtr> +PluginI::getLocators(const string& instanceName, const IceUtil::Time& waitTime) const +{ + return _locator->getLocators(instanceName, waitTime); +} + void PluginI::destroy() { @@ -545,14 +531,14 @@ Request::exception(const Ice::Exception& ex) #endif } -LocatorI::LocatorI(const LookupPrxPtr& lookup, +LocatorI::LocatorI(const string& name, + const LookupPrxPtr& lookup, const Ice::PropertiesPtr& p, const string& instanceName, const Ice::LocatorPrxPtr& voidLocator) : - _lookup(lookup), - _timeout(IceUtil::Time::milliSeconds(p->getPropertyAsIntWithDefault("IceLocatorDiscovery.Timeout", 300))), - _retryCount(p->getPropertyAsIntWithDefault("IceLocatorDiscovery.RetryCount", 3)), - _retryDelay(IceUtil::Time::milliSeconds(p->getPropertyAsIntWithDefault("IceLocatorDiscovery.RetryDelay", 2000))), + _timeout(IceUtil::Time::milliSeconds(p->getPropertyAsIntWithDefault(name + ".Timeout", 300))), + _retryCount(p->getPropertyAsIntWithDefault(name + ".RetryCount", 3)), + _retryDelay(IceUtil::Time::milliSeconds(p->getPropertyAsIntWithDefault(name + ".RetryDelay", 2000))), _timer(IceInternal::getInstanceTimer(lookup->ice_getCommunicator())), _instanceName(instanceName), _warned(false), @@ -560,12 +546,77 @@ LocatorI::LocatorI(const LookupPrxPtr& lookup, _voidLocator(voidLocator), _pendingRetryCount(0) { +#ifndef ICE_CPP11_MAPPING + __setNoDelete(true); +#endif + try + { + // Ensure we can establish a connection to the multicast proxy + lookup->ice_getConnection(); + } + catch(const Ice::LocalException& ex) + { + ostringstream os; + os << "IceLocatorDiscovery is unable to establish a multicast connection:\n"; + os << "proxy = " << lookup << '\n'; + os << ex; + throw Ice::PluginInitializationException(__FILE__, __LINE__, os.str()); + } + + // + // Create one lookup proxy per endpoint from the given proxy. We want to send a multicast + // datagram on each endpoint. + // + Ice::EndpointSeq endpoints = lookup->ice_getEndpoints(); + for(vector<Ice::EndpointPtr>::const_iterator p = endpoints.begin(); p != endpoints.end(); ++p) + { + try + { + Ice::EndpointSeq single; + single.push_back(*p); + LookupPrxPtr l = lookup->ice_endpoints(single); + l->ice_getConnection(); + _lookup.push_back(make_pair(l, LookupReplyPrxPtr())); + } + catch(const Ice::LocalException&) + { + } + } + assert(!_lookup.empty()); +#ifndef ICE_CPP11_MAPPING + __setNoDelete(false); +#endif } void LocatorI::setLookupReply(const LookupReplyPrxPtr& lookupReply) { - _lookupReply = lookupReply; + // + // Use a lookup reply proxy whose adress matches the interface used to send multicast datagrams. + // + for(vector<pair<LookupPrxPtr, LookupReplyPrxPtr> >::iterator p = _lookup.begin(); p != _lookup.end(); ++p) + { + Ice::UDPEndpointInfoPtr info = ICE_DYNAMIC_CAST(Ice::UDPEndpointInfo, p->first->ice_getEndpoints()[0]->getInfo()); + if(info && !info->mcastInterface.empty()) + { + Ice::EndpointSeq endpts = lookupReply->ice_getEndpoints(); + for(Ice::EndpointSeq::const_iterator q = endpts.begin(); q != endpts.end(); ++q) + { + Ice::IPEndpointInfoPtr r = ICE_DYNAMIC_CAST(Ice::IPEndpointInfo, (*q)->getInfo()); + if(r && r->host == info->mcastInterface) + { + Ice::EndpointSeq single; + single.push_back(*q); + p->second = lookupReply->ice_endpoints(single); + } + } + } + + if(!p->second) + { + p->second = lookupReply; // Fallback: just use the given lookup reply proxy if no matching endpoint found. + } + } } #ifdef ICE_CPP11_MAPPING @@ -588,6 +639,50 @@ LocatorI::ice_invoke_async(const Ice::AMD_Object_ice_invokePtr& amdCB, } #endif +vector<Ice::LocatorPrxPtr> +LocatorI::getLocators(const string& instanceName, const IceUtil::Time& waitTime) +{ + // + // Clear locators from previous search + // + { + Lock sync(*this); + _locators.clear(); + } + + // + // Find a locator + // + invoke(ICE_NULLPTR, ICE_NULLPTR); + + // + // Wait for responses + // + if(instanceName.empty()) + { + IceUtil::ThreadControl::sleep(waitTime); + } + else + { + Lock sync(*this); + while(_locators.find(instanceName) == _locators.end() && _pendingRetryCount > 0) + { + timedWait(waitTime); + } + } + + // + // Return found locators + // + Lock sync(*this); + vector<Ice::LocatorPrxPtr> locators; + for(map<string, Ice::LocatorPrxPtr>::const_iterator p = _locators.begin(); p != _locators.end(); ++p) + { + locators.push_back(p->second); + } + return locators; +} + void LocatorI::foundLocator(const Ice::LocatorPrxPtr& locator) { @@ -601,7 +696,8 @@ LocatorI::foundLocator(const Ice::LocatorPrxPtr& locator) // If we already have a locator assigned, ensure the given locator // has the same identity, otherwise ignore it. // - if(_locator && locator->ice_getIdentity().category != _locator->ice_getIdentity().category) + if(!_pendingRequests.empty() && + _locator && locator->ice_getIdentity().category != _locator->ice_getIdentity().category) { if(!_warned) { @@ -624,13 +720,14 @@ LocatorI::foundLocator(const Ice::LocatorPrxPtr& locator) _pendingRetryCount = 0; } - if(_locator) + Ice::LocatorPrxPtr l = _pendingRequests.empty() ? _locators[locator->ice_getIdentity().category] : _locator; + if(l) { // // We found another locator replica, append its endpoints to the // current locator proxy endpoints. // - Ice::EndpointSeq newEndpoints = _locator->ice_getEndpoints(); + Ice::EndpointSeq newEndpoints = l->ice_getEndpoints(); Ice::EndpointSeq endpts = locator->ice_getEndpoints(); for(Ice::EndpointSeq::const_iterator p = endpts.begin(); p != endpts.end(); ++p) { @@ -651,25 +748,35 @@ LocatorI::foundLocator(const Ice::LocatorPrxPtr& locator) newEndpoints.push_back(*p); } } - _locator = _locator->ice_endpoints(newEndpoints); + l = l->ice_endpoints(newEndpoints); + } + else + { + l = locator; + } + + if(_pendingRequests.empty()) + { + _locators[locator->ice_getIdentity().category] = l; + notify(); } else { - _locator = locator; + _locator = l; if(_instanceName.empty()) { _instanceName = _locator->ice_getIdentity().category; // Stick to the first discovered locator. } - } - // - // Send pending requests if any. - // - for(vector<RequestPtr>::const_iterator p = _pendingRequests.begin(); p != _pendingRequests.end(); ++p) - { - (*p)->invoke(_locator); + // + // Send pending requests if any. + // + for(vector<RequestPtr>::const_iterator p = _pendingRequests.begin(); p != _pendingRequests.end(); ++p) + { + (*p)->invoke(_locator); + } + _pendingRequests.clear(); } - _pendingRequests.clear(); } void @@ -678,28 +785,41 @@ LocatorI::invoke(const Ice::LocatorPrxPtr& locator, const RequestPtr& request) Lock sync(*this); if(_locator && _locator != locator) { - request->invoke(_locator); + if(request) + { + request->invoke(_locator); + } } else if(IceUtil::Time::now() < _nextRetry) { - request->invoke(_voidLocator); // Don't retry to find a locator before the retry delay expires + if(request) + { + request->invoke(_voidLocator); // Don't retry to find a locator before the retry delay expires + } } else { _locator = 0; - _pendingRequests.push_back(request); + if(request) + { + _pendingRequests.push_back(request); + } if(_pendingRetryCount == 0) // No request in progress { _pendingRetryCount = _retryCount; try { + for(vector<pair<LookupPrxPtr, LookupReplyPrxPtr> >::const_iterator l = _lookup.begin(); + l != _lookup.end(); ++l) + { #ifdef ICE_CPP11_MAPPING - _lookup->findLocatorAsync(_instanceName, _lookupReply); // Send multicast request. + l->first->findLocatorAsync(_instanceName, l->second); // Send multicast request. #else - _lookup->begin_findLocator(_instanceName, _lookupReply); // Send multicast request. + l->first->begin_findLocator(_instanceName, l->second); // Send multicast request. #endif + } _timer->schedule(ICE_SHARED_FROM_THIS, _timeout); } catch(const Ice::LocalException&) @@ -723,11 +843,15 @@ LocatorI::runTimerTask() { try { + for(vector<pair<LookupPrxPtr, LookupReplyPrxPtr> >::const_iterator l = _lookup.begin(); + l != _lookup.end(); ++l) + { #ifdef ICE_CPP11_MAPPING - _lookup->findLocatorAsync(_instanceName, _lookupReply); // Send multicast request. + l->first->findLocatorAsync(_instanceName, l->second); // Send multicast request. #else - _lookup->begin_findLocator(_instanceName, _lookupReply); // Send multicast request. + l->first->begin_findLocator(_instanceName, l->second); // Send multicast request. #endif + } _timer->schedule(ICE_SHARED_FROM_THIS, _timeout); return; } @@ -737,11 +861,18 @@ LocatorI::runTimerTask() _pendingRetryCount = 0; } - for(vector<RequestPtr>::const_iterator p = _pendingRequests.begin(); p != _pendingRequests.end(); ++p) + if(_pendingRequests.empty()) + { + notify(); + } + else { - (*p)->invoke(_voidLocator); // Send pending requests on void locator. + for(vector<RequestPtr>::const_iterator p = _pendingRequests.begin(); p != _pendingRequests.end(); ++p) + { + (*p)->invoke(_voidLocator); // Send pending requests on void locator. + } + _pendingRequests.clear(); } - _pendingRequests.clear(); _nextRetry = IceUtil::Time::now() + _retryDelay; // Only retry when the retry delay expires } diff --git a/cpp/src/IceLocatorDiscovery/PluginI.h b/cpp/src/IceLocatorDiscovery/PluginI.h deleted file mode 100644 index c87b6a9b438..00000000000 --- a/cpp/src/IceLocatorDiscovery/PluginI.h +++ /dev/null @@ -1,36 +0,0 @@ -// ********************************************************************** -// -// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. -// -// This copy of Ice is licensed to you under the terms described in the -// ICE_LICENSE file included in this distribution. -// -// ********************************************************************** - -#ifndef LOCATOR_DISCOVERY_PLUGIN_I_H -#define LOCATOR_DISCOVERY_PLUGIN_I_H - -#include <Ice/Plugin.h> - -namespace IceLocatorDiscovery -{ - -class PluginI : public Ice::Plugin -{ -public: - - PluginI(const Ice::CommunicatorPtr&); - - virtual void initialize(); - virtual void destroy(); - -private: - - const Ice::CommunicatorPtr _communicator; - Ice::ObjectAdapterPtr _locatorAdapter; - Ice::ObjectAdapterPtr _replyAdapter; -}; - -}; - -#endif diff --git a/cpp/test/IceGrid/simple/AllTests.cpp b/cpp/test/IceGrid/simple/AllTests.cpp index 67c4b41b1f5..fdfbf76ca7a 100644 --- a/cpp/test/IceGrid/simple/AllTests.cpp +++ b/cpp/test/IceGrid/simple/AllTests.cpp @@ -71,12 +71,6 @@ allTests(const Ice::CommunicatorPtr& communicator) initData.properties->setProperty("Ice.Default.Locator", ""); initData.properties->setProperty("Ice.Plugin.IceLocatorDiscovery", "IceLocatorDiscovery:createIceLocatorDiscovery"); -#ifdef __APPLE__ - if(initData.properties->getPropertyAsInt("Ice.PreferIPv6Address") > 0) - { - initData.properties->setProperty("IceLocatorDiscovery.Interface", "::1"); - } -#endif { ostringstream port; port << getTestPort(initData.properties, 99); diff --git a/csharp/src/Ice/Network.cs b/csharp/src/Ice/Network.cs index d9172aa086c..babefa65710 100644 --- a/csharp/src/Ice/Network.cs +++ b/csharp/src/Ice/Network.cs @@ -457,7 +457,7 @@ namespace IceInternal try { var indexes = new HashSet<int>(); - foreach(string intf in getInterfacesForMulticast(iface, group)) + foreach(string intf in getInterfacesForMulticast(iface, getProtocolSupport(group))) { int index = getInterfaceIndex(intf, group.AddressFamily); if(!indexes.Contains(index)) @@ -687,6 +687,11 @@ namespace IceInternal setBlock(fd, fd.Blocking); } + public static int getProtocolSupport(IPAddress addr) + { + return addr.AddressFamily == AddressFamily.InterNetwork ? EnableIPv4 : EnableIPv6; + } + public static EndPoint getAddressForServer(string host, int port, int protocol, bool preferIPv6) { if(host.Length == 0) @@ -951,11 +956,10 @@ namespace IceInternal return hosts; } - public static List<string> getInterfacesForMulticast(string intf, IPAddress group) + public static List<string> getInterfacesForMulticast(string intf, int protocol) { List<string> interfaces = new List<string>(); bool ipv4Wildcard = false; - int protocol = group.AddressFamily == AddressFamily.InterNetwork ? EnableIPv4 : EnableIPv6; if(isWildcard(intf, out ipv4Wildcard)) { IPAddress[] addrs = getLocalAddresses(ipv4Wildcard ? EnableIPv4 : protocol, true); diff --git a/csharp/src/Ice/PropertyNames.cs b/csharp/src/Ice/PropertyNames.cs index 5cfc6aaaab6..b5fa1fec421 100644 --- a/csharp/src/Ice/PropertyNames.cs +++ b/csharp/src/Ice/PropertyNames.cs @@ -6,7 +6,7 @@ // ICE_LICENSE file included in this distribution. // // ********************************************************************** -// Generated by makeprops.py from file ..\config\PropertyNames.xml, Fri Feb 24 18:49:18 2017 +// Generated by makeprops.py from file ./config/PropertyNames.xml, Tue Feb 28 15:01:12 2017 // IMPORTANT: Do not edit this file -- any edits made here will be lost! @@ -504,6 +504,43 @@ namespace IceInternal new Property(@"^IceGridAdmin\.Discovery\.Reply\.ThreadPool\.ThreadIdleTime$", false, null), new Property(@"^IceGridAdmin\.Discovery\.Reply\.ThreadPool\.ThreadPriority$", false, null), new Property(@"^IceGridAdmin\.Discovery\.Reply\.MessageSizeMax$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.ACM\.Timeout$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.ACM\.Heartbeat$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.ACM\.Close$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.ACM$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.AdapterId$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.Endpoints$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.Locator\.EndpointSelection$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.Locator\.ConnectionCached$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.Locator\.PreferSecure$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.Locator\.LocatorCacheTimeout$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.Locator\.InvocationTimeout$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.Locator\.Locator$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.Locator\.Router$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.Locator\.CollocationOptimized$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.Locator\.Context\.[^\s]+$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.Locator$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.PublishedEndpoints$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.ReplicaGroupId$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.Router\.EndpointSelection$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.Router\.ConnectionCached$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.Router\.PreferSecure$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.Router\.LocatorCacheTimeout$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.Router\.InvocationTimeout$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.Router\.Locator$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.Router\.Router$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.Router\.CollocationOptimized$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.Router\.Context\.[^\s]+$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.Router$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.ProxyOptions$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.ThreadPool\.Size$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.ThreadPool\.SizeMax$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.ThreadPool\.SizeWarn$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.ThreadPool\.StackSize$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.ThreadPool\.Serialize$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.ThreadPool\.ThreadIdleTime$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.ThreadPool\.ThreadPriority$", false, null), + new Property(@"^IceGridAdmin\.Discovery\.Locator\.MessageSizeMax$", false, null), new Property(@"^IceGridAdmin\.Trace\.Observers$", false, null), new Property(@"^IceGridAdmin\.Trace\.SaveToRegistry$", false, null), null diff --git a/csharp/src/Ice/UdpTransceiver.cs b/csharp/src/Ice/UdpTransceiver.cs index 0b469bba3ac..897ca80a9a6 100644 --- a/csharp/src/Ice/UdpTransceiver.cs +++ b/csharp/src/Ice/UdpTransceiver.cs @@ -586,11 +586,10 @@ namespace IceInternal info.remotePort = Network.endpointPort(remoteEndpoint); } } + info.rcvSize = Network.getRecvBufferSize(_fd); + info.sndSize = Network.getSendBufferSize(_fd); } - info.rcvSize = Network.getRecvBufferSize(_fd); - info.sndSize = Network.getSendBufferSize(_fd); - if(_mcastAddr != null) { info.mcastAddress = Network.endpointAddressToString(_mcastAddr); @@ -660,7 +659,8 @@ namespace IceInternal } else { - intfs = Network.getInterfacesForMulticast(_mcastInterface, _mcastAddr.Address); + intfs = Network.getInterfacesForMulticast(_mcastInterface, + Network.getProtocolSupport(_mcastAddr.Address)); } if(intfs.Count != 0) { diff --git a/csharp/src/IceDiscovery/LookupI.cs b/csharp/src/IceDiscovery/LookupI.cs index ee1775bb444..14dfbdd9f36 100644 --- a/csharp/src/IceDiscovery/LookupI.cs +++ b/csharp/src/IceDiscovery/LookupI.cs @@ -12,6 +12,8 @@ namespace IceDiscovery using System; using System.Collections.Generic; using System.Threading.Tasks; + using System.Text; + using System.Diagnostics; class Request<T> { @@ -154,17 +156,77 @@ namespace IceDiscovery public LookupI(LocatorRegistryI registry, LookupPrx lookup, Ice.Properties properties) { _registry = registry; - _lookup = lookup; _timeout = properties.getPropertyAsIntWithDefault("IceDiscovery.Timeout", 300); _retryCount = properties.getPropertyAsIntWithDefault("IceDiscovery.RetryCount", 3); _latencyMultiplier = properties.getPropertyAsIntWithDefault("IceDiscovery.LatencyMultiplier", 1); _domainId = properties.getProperty("IceDiscovery.DomainId"); _timer = IceInternal.Util.getInstance(lookup.ice_getCommunicator()).timer(); + + try + { + lookup.ice_getConnection(); + } + catch(Ice.LocalException ex) + { + StringBuilder b = new StringBuilder(); + b.Append("IceDiscovery is unable to establish a multicast connection:\n"); + b.Append("proxy = "); + b.Append(lookup.ToString()); + b.Append('\n'); + b.Append(ex.ToString()); + throw new Ice.PluginInitializationException(b.ToString()); + } + + // + // Create one lookup proxy per endpoint from the given proxy. We want to send a multicast + // datagram on each endpoint. + // + var single = new Ice.Endpoint[1]; + foreach(var endpt in lookup.ice_getEndpoints()) + { + try + { + single[0] = endpt; + LookupPrx l = (LookupPrx)lookup.ice_endpoints(single); + l.ice_getConnection(); + _lookup[(LookupPrx)lookup.ice_endpoints(single)] = null; + } + catch(Ice.LocalException) + { + // Ignore + } + } + Debug.Assert(_lookup.Count > 0); } public void setLookupReply(LookupReplyPrx lookupReply) { - _lookupReply = lookupReply; + // + // Use a lookup reply proxy whose adress matches the interface used to send multicast datagrams. + // + var single = new Ice.Endpoint[1]; + foreach(var key in new List<LookupPrx>(_lookup.Keys)) + { + var info = (Ice.UDPEndpointInfo)key.ice_getEndpoints()[0].getInfo(); + if(info.mcastInterface.Length > 0) + { + foreach(var q in lookupReply.ice_getEndpoints()) + { + var r = q.getInfo(); + if(r is Ice.IPEndpointInfo && ((Ice.IPEndpointInfo)r).host.Equals(info.mcastInterface)) + { + single[0] = q; + _lookup[key] = (LookupReplyPrx)lookupReply.ice_endpoints(single); + } + } + } + + if(_lookup[key] == null) + { + // Fallback: just use the given lookup reply proxy if no matching endpoint found. + _lookup[key] = lookupReply; + } + } } public override void findObjectById(string domainId, Ice.Identity id, LookupReplyPrx reply, @@ -234,7 +296,10 @@ namespace IceDiscovery { try { - _lookup.findObjectByIdAsync(_domainId, id, _lookupReply); + foreach(var l in _lookup) + { + l.Key.findObjectByIdAsync(_domainId, id, l.Value); + } _timer.schedule(request, _timeout); } catch(Ice.LocalException) @@ -263,7 +328,10 @@ namespace IceDiscovery { try { - _lookup.findAdapterByIdAsync(_domainId, adapterId, _lookupReply); + foreach(var l in _lookup) + { + l.Key.findAdapterByIdAsync(_domainId, adapterId, l.Value); + } _timer.schedule(request, _timeout); } catch(Ice.LocalException) @@ -323,7 +391,10 @@ namespace IceDiscovery { try { - _lookup.findObjectByIdAsync(_domainId, request.getId(), _lookupReply); + foreach(var l in _lookup) + { + l.Key.findObjectByIdAsync(_domainId, request.getId(), l.Value); + } _timer.schedule(request, _timeout); return; } @@ -352,7 +423,10 @@ namespace IceDiscovery { try { - _lookup.findAdapterByIdAsync(_domainId, request.getId(), _lookupReply); + foreach(var l in _lookup) + { + l.Key.findAdapterByIdAsync(_domainId, request.getId(), l.Value); + } _timer.schedule(request, _timeout); return; } @@ -378,8 +452,7 @@ namespace IceDiscovery } private LocatorRegistryI _registry; - private readonly LookupPrx _lookup; - private LookupReplyPrx _lookupReply; + private Dictionary<LookupPrx, LookupReplyPrx> _lookup = new Dictionary<LookupPrx, LookupReplyPrx>(); private readonly int _timeout; private readonly int _retryCount; private readonly int _latencyMultiplier; diff --git a/csharp/src/IceDiscovery/PluginI.cs b/csharp/src/IceDiscovery/PluginI.cs index 5883dabeaf5..f633d3a7f2d 100644 --- a/csharp/src/IceDiscovery/PluginI.cs +++ b/csharp/src/IceDiscovery/PluginI.cs @@ -57,16 +57,28 @@ namespace IceDiscovery } properties.setProperty("IceDiscovery.Multicast.Endpoints", s.ToString()); } - if(properties.getProperty("IceDiscovery.Reply.Endpoints").Length == 0) + + string lookupEndpoints = properties.getProperty("IceDiscovery.Lookup"); + if(lookupEndpoints.Length == 0) { - StringBuilder s = new StringBuilder(); - s.Append("udp"); - if(intf.Length != 0) + int protocol = ipv4 && !preferIPv6 ? IceInternal.Network.EnableIPv4 : IceInternal.Network.EnableIPv6; + var interfaces = IceInternal.Network.getInterfacesForMulticast(intf, protocol); + foreach(string p in interfaces) { - s.Append(" -h \"").Append(intf).Append("\""); + if(p != interfaces[0]) + { + lookupEndpoints += ":"; + } + lookupEndpoints += "udp -h \"" + address + "\" -p " + port + " --interface \"" + p + "\""; } - properties.setProperty("IceDiscovery.Reply.Endpoints", s.ToString()); } + + if(properties.getProperty("IceDiscovery.Reply.Endpoints").Length == 0) + { + properties.setProperty("IceDiscovery.Reply.Endpoints", + "udp -h " + (intf.Length == 0 ? "*" : "\"" + intf + "\"")); + } + if(properties.getProperty("IceDiscovery.Locator.Endpoints").Length == 0) { properties.setProperty("IceDiscovery.Locator.AdapterId", Guid.NewGuid().ToString()); @@ -83,32 +95,8 @@ namespace IceDiscovery Ice.LocatorRegistryPrx locatorRegistryPrx = Ice.LocatorRegistryPrxHelper.uncheckedCast( _locatorAdapter.addWithUUID(locatorRegistry)); - string lookupEndpoints = properties.getProperty("IceDiscovery.Lookup"); - if(lookupEndpoints.Length == 0) - { - lookupEndpoints = "udp -h \"" + address + "\" -p " + port; - if(intf.Length > 0) - { - lookupEndpoints += " --interface \"" + intf + "\""; - } - } - Ice.ObjectPrx lookupPrx = _communicator.stringToProxy("IceDiscovery/Lookup -d:" + lookupEndpoints); lookupPrx = lookupPrx.ice_collocationOptimized(false); - try - { - lookupPrx.ice_getConnection(); - } - catch(Ice.LocalException ex) - { - StringBuilder b = new StringBuilder(); - b.Append("IceDiscovery is unable to establish a multicast connection:\n"); - b.Append("proxy = "); - b.Append(lookupPrx.ToString()); - b.Append('\n'); - b.Append(ex.ToString()); - throw new Ice.PluginInitializationException(b.ToString()); - } // // Add lookup and lookup reply Ice objects diff --git a/csharp/src/IceLocatorDiscovery/PluginI.cs b/csharp/src/IceLocatorDiscovery/PluginI.cs index 7e728d4b2e8..a3a32cb3c7f 100644 --- a/csharp/src/IceLocatorDiscovery/PluginI.cs +++ b/csharp/src/IceLocatorDiscovery/PluginI.cs @@ -12,17 +12,24 @@ namespace IceLocatorDiscovery using System; using System.Collections.Generic; using System.Diagnostics; + using System.Threading; using System.Threading.Tasks; + using System.Text; public sealed class PluginFactory : Ice.PluginFactory { public Ice.Plugin create(Ice.Communicator communicator, string name, string[] args) { - return new PluginI(communicator); + return new PluginI(name, communicator); } } + public interface Plugin : Ice.Plugin + { + List<Ice.LocatorPrx> getLocators(string instanceName, int waitTime); + } + internal class Request : TaskCompletionSource<Ice.Object_Ice_invokeResult> { public Request(LocatorI locator, @@ -132,24 +139,85 @@ namespace IceLocatorDiscovery internal class LocatorI : Ice.BlobjectAsync, IceInternal.TimerTask { public - LocatorI(LookupPrx lookup, Ice.Properties properties, string instanceName, Ice.LocatorPrx voidLocator) + LocatorI(string name, LookupPrx lookup, Ice.Properties properties, string instanceName, + Ice.LocatorPrx voidLocator) { - _lookup = lookup; - _timeout = properties.getPropertyAsIntWithDefault("IceLocatorDiscovery.Timeout", 300); - _retryCount = properties.getPropertyAsIntWithDefault("IceLocatorDiscovery.RetryCount", 3); - _retryDelay = properties.getPropertyAsIntWithDefault("IceLocatorDiscovery.RetryDelay", 2000); + _timeout = properties.getPropertyAsIntWithDefault(name + ".Timeout", 300); + _retryCount = properties.getPropertyAsIntWithDefault(name + ".RetryCount", 3); + _retryDelay = properties.getPropertyAsIntWithDefault(name + ".RetryDelay", 2000); _timer = IceInternal.Util.getInstance(lookup.ice_getCommunicator()).timer(); _instanceName = instanceName; _warned = false; _locator = lookup.ice_getCommunicator().getDefaultLocator(); _voidLocator = voidLocator; _pendingRetryCount = 0; + + try + { + lookup.ice_getConnection(); + } + catch(Ice.LocalException ex) + { + StringBuilder b = new StringBuilder(); + b.Append("IceLocatorDiscovery is unable to establish a multicast connection:\n"); + b.Append("proxy = "); + b.Append(lookup.ToString()); + b.Append('\n'); + b.Append(ex.ToString()); + throw new Ice.PluginInitializationException(b.ToString()); + } + + // + // Create one lookup proxy per endpoint from the given proxy. We want to send a multicast + // datagram on each endpoint. + // + var single = new Ice.Endpoint[1]; + foreach(var endpt in lookup.ice_getEndpoints()) + { + try + { + single[0] = endpt; + LookupPrx l = (LookupPrx)lookup.ice_endpoints(single); + l.ice_getConnection(); + _lookup[(LookupPrx)lookup.ice_endpoints(single)] = null; + } + catch(Ice.LocalException) + { + // Ignore + } + } + Debug.Assert(_lookup.Count > 0); } public void setLookupReply(LookupReplyPrx lookupReply) { - _lookupReply = lookupReply; + // + // Use a lookup reply proxy whose adress matches the interface used to send multicast datagrams. + // + var single = new Ice.Endpoint[1]; + foreach(var key in new List<LookupPrx>(_lookup.Keys)) + { + var info = (Ice.UDPEndpointInfo)key.ice_getEndpoints()[0].getInfo(); + if(info.mcastInterface.Length > 0) + { + foreach(var q in lookupReply.ice_getEndpoints()) + { + var r = q.getInfo(); + if(r is Ice.IPEndpointInfo && ((Ice.IPEndpointInfo)r).host.Equals(info.mcastInterface)) + { + single[0] = q; + _lookup[key] = (LookupReplyPrx)lookupReply.ice_endpoints(single); + } + } + } + + if(_lookup[key] == null) + { + // Fallback: just use the given lookup reply proxy if no matching endpoint found. + _lookup[key] = lookupReply; + } + } } public override Task<Ice.Object_Ice_invokeResult> @@ -163,6 +231,49 @@ namespace IceLocatorDiscovery } } + public List<Ice.LocatorPrx> + getLocators(String instanceName, int waitTime) + { + // + // Clear locators from previous search. + // + lock(this) + { + _locators.Clear(); + } + + // + // Find a locator + // + invoke(null, null); + + // + // Wait for responses + // + if(instanceName.Length == 0) + { + Thread.Sleep(waitTime); + } + else + { + lock(this) + { + while(!_locators.ContainsKey(instanceName) && _pendingRetryCount > 0) + { + Monitor.Wait(this, waitTime); + } + } + } + + // + // Return found locators + // + lock(this) + { + return new List<Ice.LocatorPrx>(_locators.Values); + } + } + public void foundLocator(Ice.LocatorPrx locator) { @@ -178,7 +289,8 @@ namespace IceLocatorDiscovery // If we already have a locator assigned, ensure the given locator // has the same identity, otherwise ignore it. // - if(_locator != null && !locator.ice_getIdentity().category.Equals(_locator.ice_getIdentity().category)) + if(_pendingRequests.Count > 0 && + _locator != null && !locator.ice_getIdentity().category.Equals(_locator.ice_getIdentity().category)) { if(!_warned) { @@ -202,13 +314,22 @@ namespace IceLocatorDiscovery _pendingRetryCount = 0; } - if(_locator != null) + Ice.LocatorPrx l = null; + if(_pendingRequests.Count == 0) + { + _locators.TryGetValue(locator.ice_getIdentity().category, out _locator); + } + else + { + l = _locator; + } + if(l != null) { // // We found another locator replica, append its endpoints to the // current locator proxy endpoints. // - List<Ice.Endpoint> newEndpoints = new List<Ice.Endpoint>(_locator.ice_getEndpoints()); + List<Ice.Endpoint> newEndpoints = new List<Ice.Endpoint>(l.ice_getEndpoints()); foreach(Ice.Endpoint p in locator.ice_getEndpoints()) { // @@ -228,25 +349,35 @@ namespace IceLocatorDiscovery newEndpoints.Add(p); } } - _locator = (Ice.LocatorPrx) _locator.ice_endpoints(newEndpoints.ToArray()); + l = (Ice.LocatorPrx)l.ice_endpoints(newEndpoints.ToArray()); } else { - _locator = locator; + l = locator; + } + + if(_pendingRequests.Count == 0) + { + _locators[locator.ice_getIdentity().category] = l; + Monitor.Pulse(this); + } + else + { + _locator = l; if(_instanceName.Length == 0) { _instanceName = _locator.ice_getIdentity().category; // Stick to the first locator } - } - // - // Send pending requests if any. - // - foreach(Request req in _pendingRequests) - { - req.invoke(_locator); + // + // Send pending requests if any. + // + foreach(Request req in _pendingRequests) + { + req.invoke(_locator); + } + _pendingRequests.Clear(); } - _pendingRequests.Clear(); } } @@ -257,24 +388,36 @@ namespace IceLocatorDiscovery { if(_locator != null && _locator != locator) { - request.invoke(_locator); + if(request != null) + { + request.invoke(_locator); + } } else if(IceInternal.Time.currentMonotonicTimeMillis() < _nextRetry) { - request.invoke(_voidLocator); // Don't retry to find a locator before the retry delay expires + if(request != null) + { + request.invoke(_voidLocator); // Don't retry to find a locator before the retry delay expires + } } else { _locator = null; - _pendingRequests.Add(request); + if(request != null) + { + _pendingRequests.Add(request); + } if(_pendingRetryCount == 0) // No request in progress { _pendingRetryCount = _retryCount; try { - _lookup.findLocatorAsync(_instanceName, _lookupReply); // Send multicast request. + foreach(var l in _lookup) + { + l.Key.findLocatorAsync(_instanceName, l.Value); // Send multicast request. + } _timer.schedule(this, _timeout); } catch(Ice.LocalException) @@ -300,7 +443,10 @@ namespace IceLocatorDiscovery { try { - _lookup.findLocatorAsync(_instanceName, _lookupReply); // Send multicast request + foreach(var l in _lookup) + { + l.Key.findLocatorAsync(_instanceName, l.Value); // Send multicast request + } _timer.schedule(this, _timeout); return; } @@ -319,7 +465,7 @@ namespace IceLocatorDiscovery } } - private LookupPrx _lookup; + private Dictionary<LookupPrx, LookupReplyPrx> _lookup = new Dictionary<LookupPrx, LookupReplyPrx>(); private int _timeout; private IceInternal.Timer _timer; private int _retryCount; @@ -327,9 +473,9 @@ namespace IceLocatorDiscovery private string _instanceName; private bool _warned; - private LookupReplyPrx _lookupReply; private Ice.LocatorPrx _locator; private Ice.LocatorPrx _voidLocator; + private Dictionary<string, Ice.LocatorPrx> _locators = new Dictionary<string, Ice.LocatorPrx>(); private int _pendingRetryCount; private List<Request> _pendingRequests = new List<Request>(); @@ -352,11 +498,12 @@ namespace IceLocatorDiscovery private LocatorI _locator; } - class PluginI : Ice.Plugin + internal class PluginI : Ice.Plugin { public - PluginI(Ice.Communicator communicator) + PluginI(string name, Ice.Communicator communicator) { + _name = name; _communicator = communicator; } @@ -370,85 +517,63 @@ namespace IceLocatorDiscovery string address; if(ipv4 && !preferIPv6) { - address = properties.getPropertyWithDefault("IceLocatorDiscovery.Address", "239.255.0.1"); + address = properties.getPropertyWithDefault(_name + ".Address", "239.255.0.1"); } else { - address = properties.getPropertyWithDefault("IceLocatorDiscovery.Address", "ff15::1"); + address = properties.getPropertyWithDefault(_name + ".Address", "ff15::1"); } - int port = properties.getPropertyAsIntWithDefault("IceLocatorDiscovery.Port", 4061); - string intf = properties.getProperty("IceLocatorDiscovery.Interface"); + int port = properties.getPropertyAsIntWithDefault(_name + ".Port", 4061); + string intf = properties.getProperty(_name + ".Interface"); - if(properties.getProperty("IceLocatorDiscovery.Reply.Endpoints").Length == 0) + string lookupEndpoints = properties.getProperty(_name + ".Lookup"); + if(lookupEndpoints.Length == 0) { - System.Text.StringBuilder s = new System.Text.StringBuilder(); - s.Append("udp"); - if(intf.Length > 0) + int protocol = ipv4 && !preferIPv6 ? IceInternal.Network.EnableIPv4 : IceInternal.Network.EnableIPv6; + var interfaces = IceInternal.Network.getInterfacesForMulticast(intf, protocol); + foreach(string p in interfaces) { - s.Append(" -h \""); - s.Append(intf); - s.Append("\""); + if(p != interfaces[0]) + { + lookupEndpoints += ":"; + } + lookupEndpoints += "udp -h \"" + address + "\" -p " + port + " --interface \"" + p + "\""; } - properties.setProperty("IceLocatorDiscovery.Reply.Endpoints", s.ToString()); } - if(properties.getProperty("IceLocatorDiscovery.Locator.Endpoints").Length == 0) + + if(properties.getProperty(_name + ".Reply.Endpoints").Length == 0) { - properties.setProperty("IceLocatorDiscovery.Locator.AdapterId", Guid.NewGuid().ToString()); + properties.setProperty(_name + ".Reply.Endpoints", + "udp -h " + (intf.Length == 0 ? "*" : "\"" + intf + "\"")); } - _replyAdapter = _communicator.createObjectAdapter("IceLocatorDiscovery.Reply"); - _locatorAdapter = _communicator.createObjectAdapter("IceLocatorDiscovery.Locator"); + if(properties.getProperty(_name + ".Locator.Endpoints").Length == 0) + { + properties.setProperty(_name + ".Locator.AdapterId", Guid.NewGuid().ToString()); + } + + _replyAdapter = _communicator.createObjectAdapter(_name + ".Reply"); + _locatorAdapter = _communicator.createObjectAdapter(_name + ".Locator"); // We don't want those adapters to be registered with the locator so clear their locator. _replyAdapter.setLocator(null); _locatorAdapter.setLocator(null); - string lookupEndpoints = properties.getProperty("IceLocatorDiscovery.Lookup"); - if(lookupEndpoints.Length == 0) - { - System.Text.StringBuilder s = new System.Text.StringBuilder(); - s.Append("udp -h \""); - s.Append(address); - s.Append("\" -p "); - s.Append(port); - if(intf.Length > 0) - { - s.Append(" --interface \""); - s.Append(intf); - s.Append("\""); - } - lookupEndpoints = s.ToString(); - } - Ice.ObjectPrx lookupPrx = _communicator.stringToProxy("IceLocatorDiscovery/Lookup -d:" + lookupEndpoints); lookupPrx = lookupPrx.ice_collocationOptimized(false); // No colloc optimization for the multicast proxy! - try - { - lookupPrx.ice_getConnection(); // Ensure we can establish a connection to the multicast proxy - } - catch (Ice.LocalException ex) - { - System.Text.StringBuilder s = new System.Text.StringBuilder(); - s.Append("IceLocatorDiscovery is unable to establish a multicast connection:\n"); - s.Append("proxy = "); - s.Append(lookupPrx.ToString()); - s.Append("\n"); - s.Append(ex); - throw new Ice.PluginInitializationException(s.ToString()); - } Ice.LocatorPrx voidLo = Ice.LocatorPrxHelper.uncheckedCast(_locatorAdapter.addWithUUID(new VoidLocatorI())); - string instanceName = properties.getProperty("IceLocatorDiscovery.InstanceName"); + string instanceName = properties.getProperty(_name + ".InstanceName"); Ice.Identity id = new Ice.Identity(); id.name = "Locator"; id.category = instanceName.Length > 0 ? instanceName : Guid.NewGuid().ToString(); - LocatorI locator = new LocatorI(LookupPrxHelper.uncheckedCast(lookupPrx), properties, instanceName, voidLo); - _communicator.setDefaultLocator(Ice.LocatorPrxHelper.uncheckedCast(_locatorAdapter.addWithUUID(locator))); + _locator = new LocatorI(_name, LookupPrxHelper.uncheckedCast(lookupPrx), properties, instanceName, voidLo); + _communicator.setDefaultLocator(Ice.LocatorPrxHelper.uncheckedCast(_locatorAdapter.addWithUUID(_locator))); - Ice.ObjectPrx lookupReply = _replyAdapter.addWithUUID(new LookupReplyI(locator)).ice_datagram(); - locator.setLookupReply(LookupReplyPrxHelper.uncheckedCast(lookupReply)); + Ice.ObjectPrx lookupReply = _replyAdapter.addWithUUID(new LookupReplyI(_locator)).ice_datagram(); + _locator.setLookupReply(LookupReplyPrxHelper.uncheckedCast(lookupReply)); _replyAdapter.activate(); _locatorAdapter.activate(); @@ -461,8 +586,16 @@ namespace IceLocatorDiscovery _locatorAdapter.destroy(); } + List<Ice.LocatorPrx> + getLocators(string instanceName, int waitTime) + { + return _locator.getLocators(instanceName, waitTime); + } + + private string _name; private Ice.Communicator _communicator; private Ice.ObjectAdapter _locatorAdapter; private Ice.ObjectAdapter _replyAdapter; + private LocatorI _locator; } } diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Network.java b/java-compat/src/Ice/src/main/java/IceInternal/Network.java index 6e22f1484ec..14c50c52e40 100644 --- a/java-compat/src/Ice/src/main/java/IceInternal/Network.java +++ b/java-compat/src/Ice/src/main/java/IceInternal/Network.java @@ -298,7 +298,7 @@ public final class Network try { java.util.Set<java.net.NetworkInterface> interfaces = new java.util.HashSet<>(); - for(String address : getInterfacesForMulticast(intf, group)) + for(String address : getInterfacesForMulticast(intf, getProtocolSupport(group))) { java.net.NetworkInterface intf2 = getInterface(address); if(!interfaces.contains(intf2)) @@ -320,7 +320,7 @@ public final class Network try { java.util.Set<java.net.NetworkInterface> interfaces = new java.util.HashSet<>(); - for(String address : getInterfacesForMulticast(intf, group)) + for(String address : getInterfacesForMulticast(intf, getProtocolSupport(group))) { java.net.NetworkInterface intf2 = getInterface(address); if(!interfaces.contains(intf2)) @@ -1076,10 +1076,9 @@ public final class Network return hosts; } - public static java.util.ArrayList<String> - getInterfacesForMulticast(String intf, java.net.InetSocketAddress mcastAddr) + public static java.util.List<String> + getInterfacesForMulticast(String intf, int protocolSupport) { - int protocolSupport = getProtocolSupport(mcastAddr); java.util.ArrayList<String> interfaces = new java.util.ArrayList<>(); if(isWildcard(intf)) { diff --git a/java-compat/src/Ice/src/main/java/IceInternal/PropertyNames.java b/java-compat/src/Ice/src/main/java/IceInternal/PropertyNames.java index e925bf7d217..1b2db0f1030 100644 --- a/java-compat/src/Ice/src/main/java/IceInternal/PropertyNames.java +++ b/java-compat/src/Ice/src/main/java/IceInternal/PropertyNames.java @@ -6,7 +6,7 @@ // ICE_LICENSE file included in this distribution. // // ********************************************************************** -// Generated by makeprops.py from file ..\config\PropertyNames.xml, Fri Feb 24 18:49:18 2017 +// Generated by makeprops.py from file ./config/PropertyNames.xml, Tue Feb 28 15:01:12 2017 // IMPORTANT: Do not edit this file -- any edits made here will be lost! @@ -504,6 +504,43 @@ public final class PropertyNames new Property("IceGridAdmin\\.Discovery\\.Reply\\.ThreadPool\\.ThreadIdleTime", false, null), new Property("IceGridAdmin\\.Discovery\\.Reply\\.ThreadPool\\.ThreadPriority", false, null), new Property("IceGridAdmin\\.Discovery\\.Reply\\.MessageSizeMax", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ACM\\.Timeout", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ACM\\.Heartbeat", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ACM\\.Close", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ACM", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.AdapterId", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Endpoints", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Locator\\.EndpointSelection", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Locator\\.ConnectionCached", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Locator\\.PreferSecure", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Locator\\.LocatorCacheTimeout", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Locator\\.InvocationTimeout", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Locator\\.Locator", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Locator\\.Router", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Locator\\.CollocationOptimized", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Locator\\.Context\\.[^\\s]+", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Locator", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.PublishedEndpoints", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ReplicaGroupId", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Router\\.EndpointSelection", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Router\\.ConnectionCached", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Router\\.PreferSecure", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Router\\.LocatorCacheTimeout", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Router\\.InvocationTimeout", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Router\\.Locator", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Router\\.Router", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Router\\.CollocationOptimized", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Router\\.Context\\.[^\\s]+", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Router", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ProxyOptions", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ThreadPool\\.Size", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ThreadPool\\.SizeMax", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ThreadPool\\.SizeWarn", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ThreadPool\\.StackSize", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ThreadPool\\.Serialize", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ThreadPool\\.ThreadIdleTime", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ThreadPool\\.ThreadPriority", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.MessageSizeMax", false, null), new Property("IceGridAdmin\\.Trace\\.Observers", false, null), new Property("IceGridAdmin\\.Trace\\.SaveToRegistry", false, null), null diff --git a/java-compat/src/Ice/src/main/java/IceInternal/UdpMulticastClientTransceiver.java b/java-compat/src/Ice/src/main/java/IceInternal/UdpMulticastClientTransceiver.java index d92f362395d..ce5da6173ff 100644 --- a/java-compat/src/Ice/src/main/java/IceInternal/UdpMulticastClientTransceiver.java +++ b/java-compat/src/Ice/src/main/java/IceInternal/UdpMulticastClientTransceiver.java @@ -161,7 +161,8 @@ final class UdpMulticastClientTransceiver implements Transceiver public String toDetailedString() { StringBuilder s = new StringBuilder(toString()); - java.util.List<String> intfs = Network.getInterfacesForMulticast(_mcastInterface, _addr); + java.util.List<String> intfs = Network.getInterfacesForMulticast(_mcastInterface, + Network.getProtocolSupport(_addr)); if(!intfs.isEmpty()) { s.append("\nlocal interfaces = "); diff --git a/java-compat/src/Ice/src/main/java/IceInternal/UdpMulticastServerTransceiver.java b/java-compat/src/Ice/src/main/java/IceInternal/UdpMulticastServerTransceiver.java index e6d44880908..4ae7b4c08a3 100644 --- a/java-compat/src/Ice/src/main/java/IceInternal/UdpMulticastServerTransceiver.java +++ b/java-compat/src/Ice/src/main/java/IceInternal/UdpMulticastServerTransceiver.java @@ -169,7 +169,8 @@ final class UdpMulticastServerTransceiver implements Transceiver public String toDetailedString() { StringBuilder s = new StringBuilder(toString()); - java.util.List<String> intfs = Network.getInterfacesForMulticast(_mcastInterface, _addr); + java.util.List<String> intfs = Network.getInterfacesForMulticast(_mcastInterface, + Network.getProtocolSupport(_addr)); if(!intfs.isEmpty()) { s.append("\nlocal interfaces = "); diff --git a/java-compat/src/Ice/src/main/java/IceInternal/UdpTransceiver.java b/java-compat/src/Ice/src/main/java/IceInternal/UdpTransceiver.java index 9c8261732e0..288af7da40d 100644 --- a/java-compat/src/Ice/src/main/java/IceInternal/UdpTransceiver.java +++ b/java-compat/src/Ice/src/main/java/IceInternal/UdpTransceiver.java @@ -290,7 +290,7 @@ final class UdpTransceiver implements Transceiver } else { - intfs = Network.getInterfacesForMulticast(_mcastInterface, _mcastAddr); + intfs = Network.getInterfacesForMulticast(_mcastInterface, Network.getProtocolSupport(_mcastAddr)); } if(!intfs.isEmpty()) { diff --git a/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/LookupI.java b/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/LookupI.java index 7f805891f56..fcf1f3acf23 100644 --- a/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/LookupI.java +++ b/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/LookupI.java @@ -184,18 +184,77 @@ class LookupI extends _LookupDisp public LookupI(LocatorRegistryI registry, LookupPrx lookup, Ice.Properties properties) { _registry = registry; - _lookup = lookup; _timeout = properties.getPropertyAsIntWithDefault("IceDiscovery.Timeout", 300); _retryCount = properties.getPropertyAsIntWithDefault("IceDiscovery.RetryCount", 3); _latencyMultiplier = properties.getPropertyAsIntWithDefault("IceDiscovery.LatencyMultiplier", 1); _domainId = properties.getProperty("IceDiscovery.DomainId"); _timer = IceInternal.Util.getInstance(lookup.ice_getCommunicator()).timer(); + + try + { + lookup.ice_getConnection(); + } + catch(Ice.LocalException ex) + { + StringBuilder b = new StringBuilder(); + b.append("IceDiscovery is unable to establish a multicast connection:\n"); + b.append("proxy = "); + b.append(lookup.toString()); + b.append('\n'); + b.append(ex.toString()); + throw new Ice.PluginInitializationException(b.toString()); + } + + // + // Create one lookup proxy per endpoint from the given proxy. We want to send a multicast + // datagram on each endpoint. + // + Ice.Endpoint[] single = new Ice.Endpoint[1]; + for(Ice.Endpoint endpt : lookup.ice_getEndpoints()) + { + try + { + single[0] = endpt; + LookupPrx l = (LookupPrx)lookup.ice_endpoints(single); + l.ice_getConnection(); + _lookup.put(l, null); + } + catch(Ice.LocalException ex) + { + } + } + assert(!_lookup.isEmpty()); } void setLookupReply(LookupReplyPrx lookupReply) { - _lookupReply = lookupReply; + // + // Use a lookup reply proxy whose adress matches the interface used to send multicast datagrams. + // + Ice.Endpoint[] single = new Ice.Endpoint[1]; + for(Map.Entry<LookupPrx, LookupReplyPrx> entry : _lookup.entrySet()) + { + Ice.UDPEndpointInfo info = (Ice.UDPEndpointInfo)entry.getKey().ice_getEndpoints()[0].getInfo(); + if(!info.mcastInterface.isEmpty()) + { + for(Ice.Endpoint q : lookupReply.ice_getEndpoints()) + { + Ice.EndpointInfo r = q.getInfo(); + if(r instanceof Ice.IPEndpointInfo && ((Ice.IPEndpointInfo)r).host.equals(info.mcastInterface)) + { + single[0] = q; + entry.setValue((LookupReplyPrx)lookupReply.ice_endpoints(single)); + } + } + } + + if(entry.getValue() == null) + { + // Fallback: just use the given lookup reply proxy if no matching endpoint found. + entry.setValue(lookupReply); + } + } } @Override @@ -265,7 +324,10 @@ class LookupI extends _LookupDisp { try { - _lookup.begin_findObjectById(_domainId, id, _lookupReply); + for(Map.Entry<LookupPrx, LookupReplyPrx> entry : _lookup.entrySet()) + { + entry.getKey().begin_findObjectById(_domainId, id, entry.getValue()); + } request.scheduleTimer(_timeout); } catch(Ice.LocalException ex) @@ -290,7 +352,10 @@ class LookupI extends _LookupDisp { try { - _lookup.begin_findAdapterById(_domainId, adapterId, _lookupReply); + for(Map.Entry<LookupPrx, LookupReplyPrx> entry : _lookup.entrySet()) + { + entry.getKey().begin_findAdapterById(_domainId, adapterId, entry.getValue()); + } request.scheduleTimer(_timeout); } catch(Ice.LocalException ex) @@ -344,7 +409,10 @@ class LookupI extends _LookupDisp { try { - _lookup.begin_findObjectById(_domainId, request.getId(), _lookupReply); + for(Map.Entry<LookupPrx, LookupReplyPrx> entry : _lookup.entrySet()) + { + entry.getKey().begin_findObjectById(_domainId, request.getId(), entry.getValue()); + } request.scheduleTimer(_timeout); return; } @@ -370,7 +438,10 @@ class LookupI extends _LookupDisp { try { - _lookup.begin_findAdapterById(_domainId, request.getId(), _lookupReply); + for(Map.Entry<LookupPrx, LookupReplyPrx> entry : _lookup.entrySet()) + { + entry.getKey().begin_findAdapterById(_domainId, request.getId(), entry.getValue()); + } request.scheduleTimer(_timeout); return; } @@ -384,8 +455,7 @@ class LookupI extends _LookupDisp } private LocatorRegistryI _registry; - private final LookupPrx _lookup; - private LookupReplyPrx _lookupReply; + private java.util.Map<LookupPrx, LookupReplyPrx> _lookup = new java.util.HashMap<>(); private final int _timeout; private final int _retryCount; private final int _latencyMultiplier; diff --git a/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/PluginI.java b/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/PluginI.java index bc36a6cc7f6..1e2074a65a2 100644 --- a/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/PluginI.java +++ b/java-compat/src/IceDiscovery/src/main/java/IceDiscovery/PluginI.java @@ -47,16 +47,28 @@ public class PluginI implements Ice.Plugin } properties.setProperty("IceDiscovery.Multicast.Endpoints", s.toString()); } - if(properties.getProperty("IceDiscovery.Reply.Endpoints").isEmpty()) + + String lookupEndpoints = properties.getProperty("IceDiscovery.Lookup"); + if(lookupEndpoints.isEmpty()) { - StringBuilder s = new StringBuilder(); - s.append("udp"); - if(!intf.isEmpty()) + int protocol = ipv4 && !preferIPv6 ? IceInternal.Network.EnableIPv4 : IceInternal.Network.EnableIPv6; + java.util.List<String> interfaces = IceInternal.Network.getInterfacesForMulticast(intf, protocol); + for(String p : interfaces) { - s.append(" -h \"").append(intf).append("\""); + if(p != interfaces.get(0)) + { + lookupEndpoints += ":"; + } + lookupEndpoints += "udp -h \"" + address + "\" -p " + port + " --interface \"" + p + "\""; } - properties.setProperty("IceDiscovery.Reply.Endpoints", s.toString()); } + + if(properties.getProperty("IceDiscovery.Reply.Endpoints").isEmpty()) + { + properties.setProperty("IceDiscovery.Reply.Endpoints", + "udp -h " + (intf.isEmpty() ? "*" : "\"" + intf + "\"")); + } + if(properties.getProperty("IceDiscovery.Locator.Endpoints").isEmpty()) { properties.setProperty("IceDiscovery.Locator.AdapterId", java.util.UUID.randomUUID().toString()); @@ -73,34 +85,8 @@ public class PluginI implements Ice.Plugin Ice.LocatorRegistryPrx locatorRegistryPrx = Ice.LocatorRegistryPrxHelper.uncheckedCast( _locatorAdapter.addWithUUID(locatorRegistry)); - String lookupEndpoints = properties.getProperty("IceDiscovery.Lookup"); - if(lookupEndpoints.isEmpty()) - { - StringBuilder s = new StringBuilder(); - s.append("udp -h \"").append(address).append("\" -p ").append(port); - if(!intf.isEmpty()) - { - s.append(" --interface \"").append(intf).append("\""); - } - lookupEndpoints = s.toString(); - } - Ice.ObjectPrx lookupPrx = _communicator.stringToProxy("IceDiscovery/Lookup -d:" + lookupEndpoints); lookupPrx = lookupPrx.ice_collocationOptimized(false); // No collocation optimization for the multicast proxy! - try - { - lookupPrx.ice_getConnection(); - } - catch(Ice.LocalException ex) - { - StringBuilder b = new StringBuilder(); - b.append("IceDiscovery is unable to establish a multicast connection:\n"); - b.append("proxy = "); - b.append(lookupPrx.toString()); - b.append('\n'); - b.append(ex.toString()); - throw new Ice.PluginInitializationException(b.toString()); - } // // Add lookup and lookup reply Ice objects diff --git a/java-compat/src/IceLocatorDiscovery/src/main/java/IceLocatorDiscovery/Plugin.java b/java-compat/src/IceLocatorDiscovery/src/main/java/IceLocatorDiscovery/Plugin.java new file mode 100644 index 00000000000..a7fbd1eaf0f --- /dev/null +++ b/java-compat/src/IceLocatorDiscovery/src/main/java/IceLocatorDiscovery/Plugin.java @@ -0,0 +1,17 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +package IceLocatorDiscovery; + +import java.util.List; + +interface Plugin extends Ice.Plugin +{ + List<Ice.LocatorPrx> getLocators(String instanceName, int waitTime); +} diff --git a/java-compat/src/IceLocatorDiscovery/src/main/java/IceLocatorDiscovery/PluginFactory.java b/java-compat/src/IceLocatorDiscovery/src/main/java/IceLocatorDiscovery/PluginFactory.java index 9701f75571a..38ec505eb76 100644 --- a/java-compat/src/IceLocatorDiscovery/src/main/java/IceLocatorDiscovery/PluginFactory.java +++ b/java-compat/src/IceLocatorDiscovery/src/main/java/IceLocatorDiscovery/PluginFactory.java @@ -15,6 +15,6 @@ public class PluginFactory implements Ice.PluginFactory public Ice.Plugin create(Ice.Communicator communicator, String name, String[] args) { - return new PluginI(communicator); + return new PluginI(name, communicator); } } diff --git a/java-compat/src/IceLocatorDiscovery/src/main/java/IceLocatorDiscovery/PluginI.java b/java-compat/src/IceLocatorDiscovery/src/main/java/IceLocatorDiscovery/PluginI.java index d95ea460ad5..c93137b7bee 100644 --- a/java-compat/src/IceLocatorDiscovery/src/main/java/IceLocatorDiscovery/PluginI.java +++ b/java-compat/src/IceLocatorDiscovery/src/main/java/IceLocatorDiscovery/PluginI.java @@ -12,8 +12,9 @@ package IceLocatorDiscovery; import java.util.List; import java.util.Arrays; import java.util.ArrayList; +import java.util.Map; -class PluginI implements Ice.Plugin +class PluginI implements Plugin { private static class Request { @@ -141,24 +142,84 @@ class PluginI implements Ice.Plugin private static class LocatorI extends Ice.BlobjectAsync { - LocatorI(LookupPrx lookup, Ice.Properties properties, String instanceName, Ice.LocatorPrx voidLocator) + LocatorI(String name, LookupPrx lookup, Ice.Properties properties, String instanceName, + Ice.LocatorPrx voidLocator) { - _lookup = lookup; - _timeout = properties.getPropertyAsIntWithDefault("IceLocatorDiscovery.Timeout", 300); - _retryCount = properties.getPropertyAsIntWithDefault("IceLocatorDiscovery.RetryCount", 3); - _retryDelay = properties.getPropertyAsIntWithDefault("IceLocatorDiscovery.RetryDelay", 2000); + _timeout = properties.getPropertyAsIntWithDefault(name + ".Timeout", 300); + _retryCount = properties.getPropertyAsIntWithDefault(name + ".RetryCount", 3); + _retryDelay = properties.getPropertyAsIntWithDefault(name + ".RetryDelay", 2000); _timer = IceInternal.Util.getInstance(lookup.ice_getCommunicator()).timer(); _instanceName = instanceName; _warned = false; _locator = lookup.ice_getCommunicator().getDefaultLocator(); _voidLocator = voidLocator; _pendingRetryCount = 0; + + try + { + lookup.ice_getConnection(); + } + catch(Ice.LocalException ex) + { + StringBuilder b = new StringBuilder(); + b.append("IceDiscovery is unable to establish a multicast connection:\n"); + b.append("proxy = "); + b.append(lookup.toString()); + b.append('\n'); + b.append(ex.toString()); + throw new Ice.PluginInitializationException(b.toString()); + } + + // + // Create one lookup proxy per endpoint from the given proxy. We want to send a multicast + // datagram on each endpoint. + // + Ice.Endpoint[] single = new Ice.Endpoint[1]; + for(Ice.Endpoint endpt : lookup.ice_getEndpoints()) + { + try + { + single[0] = endpt; + LookupPrx l = (LookupPrx)lookup.ice_endpoints(single); + l.ice_getConnection(); + _lookup.put(l, null); + } + catch(Ice.LocalException ex) + { + } + } + assert(!_lookup.isEmpty()); } public void setLookupReply(LookupReplyPrx lookupReply) { - _lookupReply = lookupReply; + // + // Use a lookup reply proxy whose adress matches the interface used to send multicast datagrams. + // + Ice.Endpoint[] single = new Ice.Endpoint[1]; + for(Map.Entry<LookupPrx, LookupReplyPrx> entry : _lookup.entrySet()) + { + Ice.UDPEndpointInfo info = (Ice.UDPEndpointInfo)entry.getKey().ice_getEndpoints()[0].getInfo(); + if(!info.mcastInterface.isEmpty()) + { + for(Ice.Endpoint q : lookupReply.ice_getEndpoints()) + { + Ice.EndpointInfo r = q.getInfo(); + if(r instanceof Ice.IPEndpointInfo && ((Ice.IPEndpointInfo)r).host.equals(info.mcastInterface)) + { + single[0] = q; + entry.setValue((LookupReplyPrx)lookupReply.ice_endpoints(single)); + } + } + } + + if(entry.getValue() == null) + { + // Fallback: just use the given lookup reply proxy if no matching endpoint found. + entry.setValue(lookupReply); + } + } } @Override @@ -168,6 +229,56 @@ class PluginI implements Ice.Plugin invoke(null, new Request(this, current.operation, current.mode, inParams, current.ctx, amdCB)); } + public List<Ice.LocatorPrx> + getLocators(String instanceName, int waitTime) + { + // + // Clear locators from previous search. + // + synchronized(this) + { + _locators.clear(); + } + + // + // Find a locator + // + invoke(null, null); + + // + // Wait for responses + // + try + { + if(instanceName.isEmpty()) + { + Thread.sleep(waitTime); + } + else + { + synchronized(this) + { + while(!_locators.containsKey(instanceName) && _pendingRetryCount > 0) + { + wait(waitTime); + } + } + } + } + catch(java.lang.InterruptedException ex) + { + throw new Ice.OperationInterruptedException(); + } + + // + // Return found locators + // + synchronized(this) + { + return new ArrayList<>(_locators.values()); + } + } + public synchronized void foundLocator(Ice.LocatorPrx locator) { @@ -181,7 +292,8 @@ class PluginI implements Ice.Plugin // If we already have a locator assigned, ensure the given locator // has the same identity, otherwise ignore it. // - if(_locator != null && !locator.ice_getIdentity().category.equals(_locator.ice_getIdentity().category)) + if(!_pendingRequests.isEmpty() && + _locator != null && !locator.ice_getIdentity().category.equals(_locator.ice_getIdentity().category)) { if(!_warned) { @@ -206,14 +318,15 @@ class PluginI implements Ice.Plugin _pendingRetryCount = 0; } - if(_locator != null) + Ice.LocatorPrx l = + _pendingRequests.isEmpty() ? _locators.get(locator.ice_getIdentity().category) : _locator; + if(l != null) { // // We found another locator replica, append its endpoints to the // current locator proxy endpoints. // - List<Ice.Endpoint> newEndpoints = new ArrayList<Ice.Endpoint>( - Arrays.asList(_locator.ice_getEndpoints())); + List<Ice.Endpoint> newEndpoints = new ArrayList<Ice.Endpoint>(Arrays.asList(l.ice_getEndpoints())); for(Ice.Endpoint p : locator.ice_getEndpoints()) { // @@ -234,26 +347,35 @@ class PluginI implements Ice.Plugin } } - _locator = (Ice.LocatorPrx)_locator.ice_endpoints( - newEndpoints.toArray(new Ice.Endpoint[newEndpoints.size()])); + l = (Ice.LocatorPrx)l.ice_endpoints(newEndpoints.toArray(new Ice.Endpoint[newEndpoints.size()])); + } + else + { + l = locator; + } + + if(_pendingRequests.isEmpty()) + { + _locators.put(locator.ice_getIdentity().category, l); + notify(); } else { - _locator = locator; + _locator = l; if(_instanceName.isEmpty()) { _instanceName = _locator.ice_getIdentity().category; // Stick to the first locator } - } - // - // Send pending requests if any. - // - for(Request req : _pendingRequests) - { - req.invoke(_locator); + // + // Send pending requests if any. + // + for(Request req : _pendingRequests) + { + req.invoke(_locator); + } + _pendingRequests.clear(); } - _pendingRequests.clear(); } public synchronized void @@ -261,24 +383,36 @@ class PluginI implements Ice.Plugin { if(_locator != null && _locator != locator) { - request.invoke(_locator); + if(request != null) + { + request.invoke(_locator); + } } else if(IceInternal.Time.currentMonotonicTimeMillis() < _nextRetry) { - request.invoke(_voidLocator); // Don't retry to find a locator before the retry delay expires + if(request != null) + { + request.invoke(_voidLocator); // Don't retry to find a locator before the retry delay expires + } } else { _locator = null; - _pendingRequests.add(request); + if(request != null) + { + _pendingRequests.add(request); + } if(_pendingRetryCount == 0) // No request in progress { _pendingRetryCount = _retryCount; try { - _lookup.begin_findLocator(_instanceName, _lookupReply); // Send multicast request. + for(Map.Entry<LookupPrx, LookupReplyPrx> entry : _lookup.entrySet()) + { + entry.getKey().begin_findLocator(_instanceName, entry.getValue()); // Send multicast request + } _future = _timer.schedule(_retryTask, _timeout, java.util.concurrent.TimeUnit.MILLISECONDS); } catch(Ice.LocalException ex) @@ -305,7 +439,10 @@ class PluginI implements Ice.Plugin { try { - _lookup.begin_findLocator(_instanceName, _lookupReply); // Send multicast request. + for(Map.Entry<LookupPrx, LookupReplyPrx> entry : _lookup.entrySet()) + { + entry.getKey().begin_findLocator(_instanceName, entry.getValue()); // Send multicast request + } _future = _timer.schedule(_retryTask, _timeout, java.util.concurrent.TimeUnit.MILLISECONDS); return; } @@ -326,7 +463,7 @@ class PluginI implements Ice.Plugin } }; - private final LookupPrx _lookup; + private final java.util.Map<LookupPrx, LookupReplyPrx> _lookup = new java.util.HashMap<>(); private final int _timeout; private java.util.concurrent.Future<?> _future; private final java.util.concurrent.ScheduledExecutorService _timer; @@ -335,9 +472,9 @@ class PluginI implements Ice.Plugin private String _instanceName; private boolean _warned; - private LookupReplyPrx _lookupReply; private Ice.LocatorPrx _locator; private Ice.LocatorPrx _voidLocator; + private Map<String, Ice.LocatorPrx> _locators = new java.util.HashMap<>(); private int _pendingRetryCount; private List<Request> _pendingRequests = new ArrayList<Request>(); @@ -362,8 +499,9 @@ class PluginI implements Ice.Plugin }; public - PluginI(Ice.Communicator communicator) + PluginI(String name, Ice.Communicator communicator) { + _name = name; _communicator = communicator; } @@ -378,74 +516,61 @@ class PluginI implements Ice.Plugin String address; if(ipv4 && !preferIPv6) { - address = properties.getPropertyWithDefault("IceLocatorDiscovery.Address", "239.255.0.1"); + address = properties.getPropertyWithDefault(_name + ".Address", "239.255.0.1"); } else { - address = properties.getPropertyWithDefault("IceLocatorDiscovery.Address", "ff15::1"); + address = properties.getPropertyWithDefault(_name + ".Address", "ff15::1"); } - int port = properties.getPropertyAsIntWithDefault("IceLocatorDiscovery.Port", 4061); - String intf = properties.getProperty("IceLocatorDiscovery.Interface"); + int port = properties.getPropertyAsIntWithDefault(_name + ".Port", 4061); + String intf = properties.getProperty(_name + ".Interface"); - if(properties.getProperty("IceLocatorDiscovery.Reply.Endpoints").isEmpty()) + String lookupEndpoints = properties.getProperty(_name + ".Lookup"); + if(lookupEndpoints.isEmpty()) { - StringBuilder s = new StringBuilder(); - s.append("udp"); - if(!intf.isEmpty()) + int protocol = ipv4 && !preferIPv6 ? IceInternal.Network.EnableIPv4 : IceInternal.Network.EnableIPv6; + java.util.List<String> interfaces = IceInternal.Network.getInterfacesForMulticast(intf, protocol); + for(String p : interfaces) { - s.append(" -h \"").append(intf).append("\""); + if(p != interfaces.get(0)) + { + lookupEndpoints += ":"; + } + lookupEndpoints += "udp -h \"" + address + "\" -p " + port + " --interface \"" + p + "\""; } - properties.setProperty("IceLocatorDiscovery.Reply.Endpoints", s.toString()); } - if(properties.getProperty("IceLocatorDiscovery.Locator.Endpoints").isEmpty()) + + if(properties.getProperty(_name + ".Reply.Endpoints").isEmpty()) + { + properties.setProperty(_name + ".Reply.Endpoints", "udp -h " + (intf.isEmpty() ? "*" : "\"" + intf + "\"")); + } + + if(properties.getProperty(_name + ".Locator.Endpoints").isEmpty()) { - properties.setProperty("IceLocatorDiscovery.Locator.AdapterId", java.util.UUID.randomUUID().toString()); + properties.setProperty(_name + ".Locator.AdapterId", java.util.UUID.randomUUID().toString()); } - _replyAdapter = _communicator.createObjectAdapter("IceLocatorDiscovery.Reply"); - _locatorAdapter = _communicator.createObjectAdapter("IceLocatorDiscovery.Locator"); + _replyAdapter = _communicator.createObjectAdapter(_name + ".Reply"); + _locatorAdapter = _communicator.createObjectAdapter(_name + ".Locator"); // We don't want those adapters to be registered with the locator so clear their locator. _replyAdapter.setLocator(null); _locatorAdapter.setLocator(null); - String lookupEndpoints = properties.getProperty("IceLocatorDiscovery.Lookup"); - if(lookupEndpoints.isEmpty()) - { - StringBuilder s = new StringBuilder(); - s.append("udp -h \"").append(address).append("\" -p ").append(port); - if(!intf.isEmpty()) - { - s.append(" --interface \"").append(intf).append("\""); - } - lookupEndpoints = s.toString(); - } - Ice.ObjectPrx lookupPrx = _communicator.stringToProxy("IceLocatorDiscovery/Lookup -d:" + lookupEndpoints); lookupPrx = lookupPrx.ice_collocationOptimized(false); // No collocation optimization for the multicast proxy! - try - { - lookupPrx.ice_getConnection(); // Ensure we can establish a connection to the multicast proxy - } - catch(Ice.LocalException ex) - { - StringBuilder s = new StringBuilder(); - s.append("IceLocatorDiscovery is unable to establish a multicast connection:\n"); - s.append("proxy = ").append(lookupPrx.toString()).append("\n").append(ex); - throw new Ice.PluginInitializationException(s.toString()); - } Ice.LocatorPrx voidLoc = Ice.LocatorPrxHelper.uncheckedCast(_locatorAdapter.addWithUUID(new VoidLocatorI())); - String instanceName = properties.getProperty("IceLocatorDiscovery.InstanceName"); + String instanceName = properties.getProperty(_name + ".InstanceName"); Ice.Identity id = new Ice.Identity(); id.name = "Locator"; id.category = !instanceName.isEmpty() ? instanceName : java.util.UUID.randomUUID().toString(); - LocatorI locator = new LocatorI(LookupPrxHelper.uncheckedCast(lookupPrx), properties, instanceName, voidLoc); - _communicator.setDefaultLocator(Ice.LocatorPrxHelper.uncheckedCast(_locatorAdapter.addWithUUID(locator))); + _locator = new LocatorI(_name, LookupPrxHelper.uncheckedCast(lookupPrx), properties, instanceName, voidLoc); + _communicator.setDefaultLocator(Ice.LocatorPrxHelper.uncheckedCast(_locatorAdapter.addWithUUID(_locator))); - Ice.ObjectPrx lookupReply = _replyAdapter.addWithUUID(new LookupReplyI(locator)).ice_datagram(); - locator.setLookupReply(LookupReplyPrxHelper.uncheckedCast(lookupReply)); + Ice.ObjectPrx lookupReply = _replyAdapter.addWithUUID(new LookupReplyI(_locator)).ice_datagram(); + _locator.setLookupReply(LookupReplyPrxHelper.uncheckedCast(lookupReply)); _replyAdapter.activate(); _locatorAdapter.activate(); @@ -459,7 +584,16 @@ class PluginI implements Ice.Plugin _locatorAdapter.destroy(); } + @Override + public List<Ice.LocatorPrx> + getLocators(String instanceName, int waitTime) + { + return _locator.getLocators(instanceName, waitTime); + } + + private String _name; private Ice.Communicator _communicator; private Ice.ObjectAdapter _locatorAdapter; private Ice.ObjectAdapter _replyAdapter; + private LocatorI _locator; } diff --git a/java-compat/test/src/main/java/test/IceGrid/simple/AllTests.java b/java-compat/test/src/main/java/test/IceGrid/simple/AllTests.java index 79dcf805dd0..95b173016e5 100644 --- a/java-compat/test/src/main/java/test/IceGrid/simple/AllTests.java +++ b/java-compat/test/src/main/java/test/IceGrid/simple/AllTests.java @@ -91,11 +91,6 @@ public class AllTests initData.properties.setProperty("Ice.Default.Locator", ""); initData.properties.setProperty("Ice.Plugin.IceLocatorDiscovery", "IceLocatorDiscovery:IceLocatorDiscovery.PluginFactory"); - if(System.getProperty("os.name").contains("OS X") && - initData.properties.getPropertyAsInt("Ice.PreferIPv6Address") > 0) - { - initData.properties.setProperty("IceLocatorDiscovery.Interface", "::1"); - } initData.properties.setProperty("IceLocatorDiscovery.Port", Integer.toString(app.getTestPort(99))); initData.properties.setProperty("AdapterForDiscoveryTest.AdapterId", "discoveryAdapter"); initData.properties.setProperty("AdapterForDiscoveryTest.Endpoints", "default"); diff --git a/java/src/Ice/src/main/java/com/zeroc/IceInternal/Network.java b/java/src/Ice/src/main/java/com/zeroc/IceInternal/Network.java index 7e29515406d..cb56f0bb9e1 100644 --- a/java/src/Ice/src/main/java/com/zeroc/IceInternal/Network.java +++ b/java/src/Ice/src/main/java/com/zeroc/IceInternal/Network.java @@ -303,7 +303,7 @@ public final class Network try { java.util.Set<java.net.NetworkInterface> interfaces = new java.util.HashSet<>(); - for(String address : getInterfacesForMulticast(intf, group)) + for(String address : getInterfacesForMulticast(intf, getProtocolSupport(group))) { java.net.NetworkInterface intf2 = getInterface(address); if(!interfaces.contains(intf2)) @@ -325,7 +325,7 @@ public final class Network try { java.util.Set<java.net.NetworkInterface> interfaces = new java.util.HashSet<>(); - for(String address : getInterfacesForMulticast(intf, group)) + for(String address : getInterfacesForMulticast(intf, getProtocolSupport(group))) { java.net.NetworkInterface intf2 = getInterface(address); if(!interfaces.contains(intf2)) @@ -1081,10 +1081,9 @@ public final class Network return hosts; } - public static java.util.ArrayList<String> - getInterfacesForMulticast(String intf, java.net.InetSocketAddress mcastAddr) + public static java.util.List<String> + getInterfacesForMulticast(String intf, int protocolSupport) { - int protocolSupport = getProtocolSupport(mcastAddr); java.util.ArrayList<String> interfaces = new java.util.ArrayList<>(); if(isWildcard(intf)) { diff --git a/java/src/Ice/src/main/java/com/zeroc/IceInternal/PropertyNames.java b/java/src/Ice/src/main/java/com/zeroc/IceInternal/PropertyNames.java index 6d1273b8793..eb3319e9b46 100644 --- a/java/src/Ice/src/main/java/com/zeroc/IceInternal/PropertyNames.java +++ b/java/src/Ice/src/main/java/com/zeroc/IceInternal/PropertyNames.java @@ -6,7 +6,7 @@ // ICE_LICENSE file included in this distribution. // // ********************************************************************** -// Generated by makeprops.py from file ..\config\PropertyNames.xml, Fri Feb 24 18:49:18 2017 +// Generated by makeprops.py from file ./config/PropertyNames.xml, Tue Feb 28 15:01:12 2017 // IMPORTANT: Do not edit this file -- any edits made here will be lost! @@ -504,6 +504,43 @@ public final class PropertyNames new Property("IceGridAdmin\\.Discovery\\.Reply\\.ThreadPool\\.ThreadIdleTime", false, null), new Property("IceGridAdmin\\.Discovery\\.Reply\\.ThreadPool\\.ThreadPriority", false, null), new Property("IceGridAdmin\\.Discovery\\.Reply\\.MessageSizeMax", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ACM\\.Timeout", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ACM\\.Heartbeat", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ACM\\.Close", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ACM", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.AdapterId", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Endpoints", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Locator\\.EndpointSelection", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Locator\\.ConnectionCached", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Locator\\.PreferSecure", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Locator\\.LocatorCacheTimeout", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Locator\\.InvocationTimeout", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Locator\\.Locator", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Locator\\.Router", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Locator\\.CollocationOptimized", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Locator\\.Context\\.[^\\s]+", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Locator", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.PublishedEndpoints", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ReplicaGroupId", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Router\\.EndpointSelection", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Router\\.ConnectionCached", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Router\\.PreferSecure", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Router\\.LocatorCacheTimeout", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Router\\.InvocationTimeout", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Router\\.Locator", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Router\\.Router", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Router\\.CollocationOptimized", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Router\\.Context\\.[^\\s]+", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.Router", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ProxyOptions", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ThreadPool\\.Size", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ThreadPool\\.SizeMax", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ThreadPool\\.SizeWarn", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ThreadPool\\.StackSize", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ThreadPool\\.Serialize", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ThreadPool\\.ThreadIdleTime", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.ThreadPool\\.ThreadPriority", false, null), + new Property("IceGridAdmin\\.Discovery\\.Locator\\.MessageSizeMax", false, null), new Property("IceGridAdmin\\.Trace\\.Observers", false, null), new Property("IceGridAdmin\\.Trace\\.SaveToRegistry", false, null), null diff --git a/java/src/Ice/src/main/java/com/zeroc/IceInternal/UdpMulticastClientTransceiver.java b/java/src/Ice/src/main/java/com/zeroc/IceInternal/UdpMulticastClientTransceiver.java index e3edc69d4b5..2390cea50a1 100644 --- a/java/src/Ice/src/main/java/com/zeroc/IceInternal/UdpMulticastClientTransceiver.java +++ b/java/src/Ice/src/main/java/com/zeroc/IceInternal/UdpMulticastClientTransceiver.java @@ -161,7 +161,8 @@ final class UdpMulticastClientTransceiver implements Transceiver public String toDetailedString() { StringBuilder s = new StringBuilder(toString()); - java.util.List<String> intfs = Network.getInterfacesForMulticast(_mcastInterface, _addr); + java.util.List<String> intfs = Network.getInterfacesForMulticast(_mcastInterface, + Network.getProtocolSupport(_addr)); if(!intfs.isEmpty()) { s.append("\nlocal interfaces = "); diff --git a/java/src/Ice/src/main/java/com/zeroc/IceInternal/UdpMulticastServerTransceiver.java b/java/src/Ice/src/main/java/com/zeroc/IceInternal/UdpMulticastServerTransceiver.java index 8c7b462e89e..bfcc1c11060 100644 --- a/java/src/Ice/src/main/java/com/zeroc/IceInternal/UdpMulticastServerTransceiver.java +++ b/java/src/Ice/src/main/java/com/zeroc/IceInternal/UdpMulticastServerTransceiver.java @@ -169,7 +169,8 @@ final class UdpMulticastServerTransceiver implements Transceiver public String toDetailedString() { StringBuilder s = new StringBuilder(toString()); - java.util.List<String> intfs = Network.getInterfacesForMulticast(_mcastInterface, _addr); + java.util.List<String> intfs = Network.getInterfacesForMulticast(_mcastInterface, + Network.getProtocolSupport(_addr)); if(!intfs.isEmpty()) { s.append("\nlocal interfaces = "); diff --git a/java/src/Ice/src/main/java/com/zeroc/IceInternal/UdpTransceiver.java b/java/src/Ice/src/main/java/com/zeroc/IceInternal/UdpTransceiver.java index 491e6c0b7ee..8f6d5683251 100644 --- a/java/src/Ice/src/main/java/com/zeroc/IceInternal/UdpTransceiver.java +++ b/java/src/Ice/src/main/java/com/zeroc/IceInternal/UdpTransceiver.java @@ -290,7 +290,7 @@ final class UdpTransceiver implements Transceiver } else { - intfs = Network.getInterfacesForMulticast(_mcastInterface, _mcastAddr); + intfs = Network.getInterfacesForMulticast(_mcastInterface, Network.getProtocolSupport(_mcastAddr)); } if(!intfs.isEmpty()) { diff --git a/java/src/IceDiscovery/src/main/java/com/zeroc/IceDiscovery/LookupI.java b/java/src/IceDiscovery/src/main/java/com/zeroc/IceDiscovery/LookupI.java index 5e3910d4aef..ac99857d3ae 100644 --- a/java/src/IceDiscovery/src/main/java/com/zeroc/IceDiscovery/LookupI.java +++ b/java/src/IceDiscovery/src/main/java/com/zeroc/IceDiscovery/LookupI.java @@ -172,17 +172,78 @@ class LookupI implements Lookup public LookupI(LocatorRegistryI registry, LookupPrx lookup, com.zeroc.Ice.Properties properties) { _registry = registry; - _lookup = lookup; _timeout = properties.getPropertyAsIntWithDefault("IceDiscovery.Timeout", 300); _retryCount = properties.getPropertyAsIntWithDefault("IceDiscovery.RetryCount", 3); _latencyMultiplier = properties.getPropertyAsIntWithDefault("IceDiscovery.LatencyMultiplier", 1); _domainId = properties.getProperty("IceDiscovery.DomainId"); _timer = com.zeroc.IceInternal.Util.getInstance(lookup.ice_getCommunicator()).timer(); + + try + { + lookup.ice_getConnection(); + } + catch(com.zeroc.Ice.LocalException ex) + { + StringBuilder b = new StringBuilder(); + b.append("IceDiscovery is unable to establish a multicast connection:\n"); + b.append("proxy = "); + b.append(lookup.toString()); + b.append('\n'); + b.append(ex.toString()); + throw new com.zeroc.Ice.PluginInitializationException(b.toString()); + } + + // + // Create one lookup proxy per endpoint from the given proxy. We want to send a multicast + // datagram on each endpoint. + // + com.zeroc.Ice.Endpoint[] single = new com.zeroc.Ice.Endpoint[1]; + for(com.zeroc.Ice.Endpoint endpt : lookup.ice_getEndpoints()) + { + try + { + single[0] = endpt; + LookupPrx l = (LookupPrx)lookup.ice_endpoints(single); + l.ice_getConnection(); + _lookup.put(l, null); + } + catch(com.zeroc.Ice.LocalException ex) + { + } + } + assert(!_lookup.isEmpty()); } void setLookupReply(LookupReplyPrx lookupReply) { - _lookupReply = lookupReply; + // + // Use a lookup reply proxy whose adress matches the interface used to send multicast datagrams. + // + com.zeroc.Ice.Endpoint[] single = new com.zeroc.Ice.Endpoint[1]; + for(Map.Entry<LookupPrx, LookupReplyPrx> entry : _lookup.entrySet()) + { + com.zeroc.Ice.UDPEndpointInfo info = + (com.zeroc.Ice.UDPEndpointInfo)entry.getKey().ice_getEndpoints()[0].getInfo(); + if(!info.mcastInterface.isEmpty()) + { + for(com.zeroc.Ice.Endpoint q : lookupReply.ice_getEndpoints()) + { + com.zeroc.Ice.EndpointInfo r = q.getInfo(); + if(r instanceof com.zeroc.Ice.IPEndpointInfo && + ((com.zeroc.Ice.IPEndpointInfo)r).host.equals(info.mcastInterface)) + { + single[0] = q; + entry.setValue((LookupReplyPrx)lookupReply.ice_endpoints(single)); + } + } + } + + if(entry.getValue() == null) + { + // Fallback: just use the given lookup reply proxy if no matching endpoint found. + entry.setValue(lookupReply); + } + } } @Override @@ -250,7 +311,10 @@ class LookupI implements Lookup { try { - _lookup.findObjectByIdAsync(_domainId, id, _lookupReply); + for(Map.Entry<LookupPrx, LookupReplyPrx> entry : _lookup.entrySet()) + { + entry.getKey().findObjectByIdAsync(_domainId, id, entry.getValue()); + } request.scheduleTimer(_timeout); } catch(com.zeroc.Ice.LocalException ex) @@ -274,7 +338,10 @@ class LookupI implements Lookup { try { - _lookup.findAdapterByIdAsync(_domainId, adapterId, _lookupReply); + for(Map.Entry<LookupPrx, LookupReplyPrx> entry : _lookup.entrySet()) + { + entry.getKey().findAdapterByIdAsync(_domainId, adapterId, entry.getValue()); + } request.scheduleTimer(_timeout); } catch(com.zeroc.Ice.LocalException ex) @@ -325,7 +392,10 @@ class LookupI implements Lookup { try { - _lookup.findObjectByIdAsync(_domainId, request.getId(), _lookupReply); + for(Map.Entry<LookupPrx, LookupReplyPrx> entry : _lookup.entrySet()) + { + entry.getKey().findObjectByIdAsync(_domainId, request.getId(), entry.getValue()); + } request.scheduleTimer(_timeout); return; } @@ -350,7 +420,10 @@ class LookupI implements Lookup { try { - _lookup.findAdapterByIdAsync(_domainId, request.getId(), _lookupReply); + for(Map.Entry<LookupPrx, LookupReplyPrx> entry : _lookup.entrySet()) + { + entry.getKey().findAdapterByIdAsync(_domainId, request.getId(), entry.getValue()); + } request.scheduleTimer(_timeout); return; } @@ -364,8 +437,7 @@ class LookupI implements Lookup } private LocatorRegistryI _registry; - private final LookupPrx _lookup; - private LookupReplyPrx _lookupReply; + private java.util.Map<LookupPrx, LookupReplyPrx> _lookup = new java.util.HashMap<>(); private final int _timeout; private final int _retryCount; private final int _latencyMultiplier; diff --git a/java/src/IceDiscovery/src/main/java/com/zeroc/IceDiscovery/PluginI.java b/java/src/IceDiscovery/src/main/java/com/zeroc/IceDiscovery/PluginI.java index 9b52edf963b..46bed9f0ee8 100644 --- a/java/src/IceDiscovery/src/main/java/com/zeroc/IceDiscovery/PluginI.java +++ b/java/src/IceDiscovery/src/main/java/com/zeroc/IceDiscovery/PluginI.java @@ -9,6 +9,8 @@ package com.zeroc.IceDiscovery; +import com.zeroc.IceInternal.Network; + public class PluginI implements com.zeroc.Ice.Plugin { public PluginI(com.zeroc.Ice.Communicator communicator) @@ -45,16 +47,28 @@ public class PluginI implements com.zeroc.Ice.Plugin } properties.setProperty("IceDiscovery.Multicast.Endpoints", s.toString()); } - if(properties.getProperty("IceDiscovery.Reply.Endpoints").isEmpty()) + + String lookupEndpoints = properties.getProperty("IceDiscovery.Lookup"); + if(lookupEndpoints.isEmpty()) { - StringBuilder s = new StringBuilder(); - s.append("udp"); - if(!intf.isEmpty()) + int protocol = ipv4 && !preferIPv6 ? Network.EnableIPv4 : Network.EnableIPv6; + java.util.List<String> interfaces = Network.getInterfacesForMulticast(intf, protocol); + for(String p : interfaces) { - s.append(" -h \"").append(intf).append("\""); + if(p != interfaces.get(0)) + { + lookupEndpoints += ":"; + } + lookupEndpoints += "udp -h \"" + address + "\" -p " + port + " --interface \"" + p + "\""; } - properties.setProperty("IceDiscovery.Reply.Endpoints", s.toString()); } + + if(properties.getProperty("IceDiscovery.Reply.Endpoints").isEmpty()) + { + properties.setProperty("IceDiscovery.Reply.Endpoints", + "udp -h " + (intf.isEmpty() ? "*" : "\"" + intf + "\"")); + } + if(properties.getProperty("IceDiscovery.Locator.Endpoints").isEmpty()) { properties.setProperty("IceDiscovery.Locator.AdapterId", java.util.UUID.randomUUID().toString()); @@ -71,34 +85,8 @@ public class PluginI implements com.zeroc.Ice.Plugin com.zeroc.Ice.LocatorRegistryPrx locatorRegistryPrx = com.zeroc.Ice.LocatorRegistryPrx.uncheckedCast( _locatorAdapter.addWithUUID(locatorRegistry)); - String lookupEndpoints = properties.getProperty("IceDiscovery.Lookup"); - if(lookupEndpoints.isEmpty()) - { - StringBuilder s = new StringBuilder(); - s.append("udp -h \"").append(address).append("\" -p ").append(port); - if(!intf.isEmpty()) - { - s.append(" --interface \"").append(intf).append("\""); - } - lookupEndpoints = s.toString(); - } - com.zeroc.Ice.ObjectPrx lookupPrx = _communicator.stringToProxy("IceDiscovery/Lookup -d:" + lookupEndpoints); lookupPrx = lookupPrx.ice_collocationOptimized(false); // No collocation optimization for the multicast proxy! - try - { - lookupPrx.ice_getConnection(); - } - catch(com.zeroc.Ice.LocalException ex) - { - StringBuilder b = new StringBuilder(); - b.append("IceDiscovery is unable to establish a multicast connection:\n"); - b.append("proxy = "); - b.append(lookupPrx.toString()); - b.append('\n'); - b.append(ex.toString()); - throw new com.zeroc.Ice.PluginInitializationException(b.toString()); - } // // Add lookup and lookup reply Ice objects diff --git a/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/SessionKeeper.java b/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/SessionKeeper.java index a12122ea4cf..9aeb8315872 100644 --- a/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/SessionKeeper.java +++ b/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/SessionKeeper.java @@ -62,9 +62,8 @@ import javax.naming.ldap.Rdn; import java.net.NetworkInterface; import java.net.InetAddress; -import com.zeroc.IceLocatorDiscovery.LookupPrx; -import com.zeroc.IceLocatorDiscovery.LookupReplyPrx; -import com.zeroc.IceLocatorDiscovery.LookupReply; +import com.zeroc.IceLocatorDiscovery.Plugin; +import com.zeroc.IceLocatorDiscovery.PluginFactory; import com.zeroc.IceGrid.*; @@ -1075,175 +1074,67 @@ public class SessionKeeper _nextButton.requestFocusInWindow(); } - public void destroyDiscoveryAdapter() - { - synchronized(SessionKeeper.this) - { - if(_discoveryAdapter != null) - { - SwingUtilities.invokeLater(() -> - { - if(_directDiscoveryEndpointModel.size() > 0) - { - _discoveryStatus.setText(""); - } - else - { - _discoveryStatus.setText("No registries found"); - } - }); - _discoveryAdapter.destroy(); - _discoveryAdapter = null; - } - } - } - - public void refreshDiscoveryEndpoints() + public void refreshDiscoveryLocators() { final com.zeroc.Ice.Communicator communicator = _coordinator.getCommunicator(); - if(_discoveryLookupReply == null) - { - _discoveryLookupReply = new LookupReply() - { - @Override - public void foundLocator(final com.zeroc.Ice.LocatorPrx locator, com.zeroc.Ice.Current curr) - { - SwingUtilities.invokeLater(() -> - { - if(_directDiscoveryEndpointModel.indexOf(locator) == -1) - { - _directDiscoveryEndpointModel.addElement(locator); - } - - if(_directDiscoveryEndpointModel.size() > 0 && - _directDiscoveryEndpointList.getSelectedIndex() == -1) - { - _directDiscoveryEndpointList.setSelectedIndex(0); - } - }); - } - }; - } - _discoveryStatus.setText("Searching for registries..."); - - // - // If there isn't any search in progress clear the endpoint list. - // - synchronized(SessionKeeper.this) - { - if(_discoveryAdapter == null) - { - _directDiscoveryEndpointModel.clear(); - } - } - - final com.zeroc.Ice.Properties properties = communicator.getProperties(); - final String intf = _discoveryInterfaces.getSelectedItem().toString(); - - String lookupEndpoints = properties.getProperty("IceGridAdmin.Discovery.Lookup"); - String address; - if(properties.getPropertyAsIntWithDefault("Ice.IPv4", 1) > 0 && - properties.getPropertyAsInt("Ice.PreferIPv6Address") <= 0) - { - address = "239.255.0.1"; - } - else - { - address = "ff15::1"; - } - if(lookupEndpoints.isEmpty()) - { - StringBuilder s = new StringBuilder(); - s.append("udp -h \""); - s.append(properties.getPropertyWithDefault("IceGridAdmin.Discovery.Address", address)); - s.append("\" -p "); - s.append(4061); - if(!intf.isEmpty()) - { - s.append(" --interface \"").append(intf).append("\""); - } - lookupEndpoints = s.toString(); - } - try { - final LookupPrx lookupPrx = LookupPrx.uncheckedCast( - communicator.stringToProxy("IceLocatorDiscovery/Lookup -d:" + - lookupEndpoints).ice_collocationOptimized(false).ice_router(null)); - new Thread(() -> { synchronized(SessionKeeper.this) { - // - // If search is in progress when refresh is hit, cancel the - // finish task we will schedule a new one with this new - // search. - // - if(_discoveryFinishTask != null) - { - _discoveryFinishTask.cancel(); - } - - if(properties.getProperty("IceGridAdmin.Discovery.Reply.Endpoints").isEmpty()) + try { - StringBuilder s = new StringBuilder(); - s.append("udp"); - if(!intf.isEmpty()) + if(_discoveryPlugin == null) { - s.append(" -h \"").append(intf).append("\""); + PluginFactory f = new PluginFactory(); + _discoveryPlugin = (Plugin)f.create(communicator, "IceGridAdmin.Discovery", null); + _discoveryPlugin.initialize(); } - properties.setProperty("IceGridAdmin.Discovery.Reply.Endpoints", s.toString()); - } - try - { - if(_discoveryAdapter == null) + final List<com.zeroc.Ice.LocatorPrx> locators = _discoveryPlugin.getLocators("", 1000); + SwingUtilities.invokeLater(() -> { - _discoveryAdapter = communicator.createObjectAdapter( - "IceGridAdmin.Discovery.Reply"); - _discoveryAdapter.activate(); - _discoveryReplyPrx = LookupReplyPrx.uncheckedCast( - _discoveryAdapter.addWithUUID(_discoveryLookupReply).ice_datagram()); - } + _directDiscoveryLocatorModel.clear(); + for(com.zeroc.Ice.LocatorPrx locator : locators) + { + _directDiscoveryLocatorModel.addElement(locator); + } + if(_directDiscoveryLocatorModel.size() > 0 && + _directDiscoveryLocatorList.getSelectedIndex() == -1) + { + _directDiscoveryLocatorList.setSelectedIndex(0); + } - lookupPrx.findLocator("", _discoveryReplyPrx); + if(_directDiscoveryLocatorModel.size() > 0) + { + _discoveryStatus.setText(""); + } + else + { + _discoveryStatus.setText("No registries found"); + } + }); } catch(final com.zeroc.Ice.LocalException ex) { - ex.printStackTrace(); - destroyDiscoveryAdapter(); SwingUtilities.invokeLater(() -> { + _discoveryStatus.setText("No registries found"); JOptionPane.showMessageDialog(ConnectionWizardDialog.this, ex.toString(), - "Error while looking up locator endpoints", + "Error while looking up registries", JOptionPane.ERROR_MESSAGE); }); } - - // - // We schedule a timer task to destroy the discovery adapter after 2 - // seconds, the user doesn't need to wait, discovered proxies are - // added as they are found. - // - _discoveryFinishTask = new java.util.TimerTask() - { - @Override - public void run() - { - destroyDiscoveryAdapter(); - } - }; - new java.util.Timer().schedule(_discoveryFinishTask, 2000); } }).start(); } catch(com.zeroc.Ice.LocalException ex) { JOptionPane.showMessageDialog(ConnectionWizardDialog.this, ex.toString(), - "Error while looking up locator endpoints", JOptionPane.ERROR_MESSAGE); + "Error while looking up registries", JOptionPane.ERROR_MESSAGE); } } @@ -1298,69 +1189,11 @@ public class SessionKeeper builder.append(new JLabel("Connect to an IceGrid registry through a Glacier2 router.")); _cardPanel.add(builder.getPanel(), WizardStep.ConnectionTypeStep.toString()); } - - JPanel discoveryInterface; - { - FormLayout layout = new FormLayout("pref, 2dlu, pref:grow", "pref"); - DefaultFormBuilder builder = new DefaultFormBuilder(layout); - _discoveryInterfaces = new JComboBox(); - - builder.append("Discovery Interface:", _discoveryInterfaces); - - List<String> addresses = new ArrayList<String>(); - try - { - Enumeration<NetworkInterface> p = NetworkInterface.getNetworkInterfaces(); - - while(p != null && p.hasMoreElements()) - { - NetworkInterface intf = p.nextElement(); - if(intf.isUp()) - { - Enumeration<InetAddress> q = intf.getInetAddresses(); - while(q != null && q.hasMoreElements()) - { - InetAddress address = q.nextElement(); - if(!address.isAnyLocalAddress()) - { - addresses.add(address.getHostAddress()); - } - } - } - } - } - catch(java.net.SocketException ex) - { - JOptionPane.showMessageDialog(ConnectionWizardDialog.this, - ex.toString(), - "Error retrieving network interfaces", - JOptionPane.ERROR_MESSAGE); - } - - final com.zeroc.Ice.Properties properties = _coordinator.getCommunicator().getProperties(); - String selected = properties.getPropertyWithDefault("IceGridAdmin.Discovery.Interface", "127.0.0.1"); - if(!addresses.contains(selected)) - { - addresses.add(selected); - } - - _discoveryInterfaces.setModel(new DefaultComboBoxModel(addresses.toArray())); - _discoveryInterfaces.setSelectedItem(selected); - _discoveryInterfaces.addActionListener(new ActionListener () - { - @Override - public void actionPerformed(ActionEvent e) - { - refreshDiscoveryEndpoints(); - } - }); - discoveryInterface = builder.getPanel(); - } - // Direct Discovery Endpoint List + // Direct Discovery Locator List { - _directDiscoveryEndpointModel = new DefaultListModel<>(); - _directDiscoveryEndpointList = new JList(_directDiscoveryEndpointModel) + _directDiscoveryLocatorModel = new DefaultListModel<>(); + _directDiscoveryLocatorList = new JList(_directDiscoveryLocatorModel) { @Override public String getToolTipText(MouseEvent evt) @@ -1378,9 +1211,9 @@ public class SessionKeeper return null; } }; - _directDiscoveryEndpointList.setVisibleRowCount(7); - _directDiscoveryEndpointList.setFixedCellWidth(500); - _directDiscoveryEndpointList.addMouseListener( + _directDiscoveryLocatorList.setVisibleRowCount(7); + _directDiscoveryLocatorList.setFixedCellWidth(500); + _directDiscoveryLocatorList.addMouseListener( new MouseAdapter() { @Override @@ -1388,8 +1221,8 @@ public class SessionKeeper { if(e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1) { - Object obj = _directDiscoveryEndpointModel.getElementAt( - _directDiscoveryEndpointList.locationToIndex(e.getPoint())); + Object obj = _directDiscoveryLocatorModel.getElementAt( + _directDiscoveryLocatorList.locationToIndex(e.getPoint())); if(obj != null && obj instanceof com.zeroc.Ice.LocatorPrx) { _nextButton.doClick(0); @@ -1397,9 +1230,9 @@ public class SessionKeeper } } }); - - _directDiscoveryEndpointList.addListSelectionListener(new ListSelectionListener() + + _directDiscoveryLocatorList.addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent event) @@ -1409,20 +1242,20 @@ public class SessionKeeper }); ButtonGroup group = new ButtonGroup(); - _directDiscoveryDiscoveredEndpoint = new JRadioButton(new AbstractAction("Discovered Endpoints") + _directDiscoveryDiscoveredLocators = new JRadioButton(new AbstractAction("Discovered Registries") { @Override public void actionPerformed(ActionEvent e) { - _directDiscoveryEndpointList.setEnabled(true); + _directDiscoveryLocatorList.setEnabled(true); _discoveryStatus.setEnabled(true); _discoveryRefresh.setEnabled(true); validatePanel(); - refreshDiscoveryEndpoints(); + refreshDiscoveryLocators(); } }); - _directDiscoveryDiscoveredEndpoint.setSelected(true); - group.add(_directDiscoveryDiscoveredEndpoint); + _directDiscoveryDiscoveredLocators.setSelected(true); + group.add(_directDiscoveryDiscoveredLocators); JPanel discoveryStatus; { @@ -1435,7 +1268,7 @@ public class SessionKeeper @Override public void actionPerformed(ActionEvent e) { - refreshDiscoveryEndpoints(); + refreshDiscoveryLocators(); } }); @@ -1449,8 +1282,7 @@ public class SessionKeeper @Override public void actionPerformed(ActionEvent e) { - destroyDiscoveryAdapter(); - _directDiscoveryEndpointList.setEnabled(false); + _directDiscoveryLocatorList.setEnabled(false); _discoveryStatus.setEnabled(false); _discoveryRefresh.setEnabled(false); validatePanel(); @@ -1463,9 +1295,8 @@ public class SessionKeeper DefaultFormBuilder builder = new DefaultFormBuilder(layout); builder.border(Borders.DIALOG); builder.rowGroupingEnabled(false); - builder.append(_directDiscoveryDiscoveredEndpoint); - builder.append(discoveryInterface); - builder.append(createStrippedScrollPane(_directDiscoveryEndpointList)); + builder.append(_directDiscoveryDiscoveredLocators); + builder.append(createStrippedScrollPane(_directDiscoveryLocatorList)); builder.append(discoveryStatus); builder.append(_directDiscoveryManualEndpoint); _cardPanel.add(builder.getPanel(), WizardStep.DirectDiscoveryChooseStep.toString()); @@ -2170,9 +2001,9 @@ public class SessionKeeper { _cardLayout.show(_cardPanel, WizardStep.DirectDiscoveryChooseStep.toString()); _wizardSteps.push(WizardStep.DirectDiscoveryChooseStep); - if(_directDiscoveryDiscoveredEndpoint.isSelected()) + if(_directDiscoveryDiscoveredLocators.isSelected()) { - refreshDiscoveryEndpoints(); + refreshDiscoveryLocators(); } break; } @@ -2186,9 +2017,9 @@ public class SessionKeeper } else { - com.zeroc.Ice.LocatorPrx locator = _directDiscoveryEndpointList.getSelectedValue(); + com.zeroc.Ice.LocatorPrx locator = _directDiscoveryLocatorList.getSelectedValue(); _directInstanceName.setText(locator.ice_getIdentity().category); - + String endpoints = null; for(com.zeroc.Ice.Endpoint endpoint : locator.ice_getEndpoints()) { @@ -2496,7 +2327,8 @@ public class SessionKeeper @Override public void actionPerformed(ActionEvent e) { - destroyDiscoveryAdapter(); + _discoveryPlugin.destroy(); + _discoveryPlugin = null; ConnectionInfo inf = getConfiguration(); if(inf == null) @@ -2670,7 +2502,8 @@ public class SessionKeeper @Override public void actionPerformed(ActionEvent e) { - destroyDiscoveryAdapter(); + _discoveryPlugin.destroy(); + _discoveryPlugin = null; dispose(); } }; @@ -2707,7 +2540,7 @@ public class SessionKeeper } else { - _directDiscoveryEndpointList.requestFocusInWindow(); + _directDiscoveryLocatorList.requestFocusInWindow(); } break; } @@ -2851,7 +2684,7 @@ public class SessionKeeper } else { - validated = _directDiscoveryEndpointList.getSelectedValue() != null; + validated = _directDiscoveryLocatorList.getSelectedValue() != null; } break; } @@ -3247,17 +3080,13 @@ public class SessionKeeper private JCheckBox _directConnectToMaster; // Direct Discovery Endpoints - private JComboBox _discoveryInterfaces; - private JList<com.zeroc.Ice.LocatorPrx> _directDiscoveryEndpointList; - private DefaultListModel<com.zeroc.Ice.LocatorPrx> _directDiscoveryEndpointModel; - private JRadioButton _directDiscoveryDiscoveredEndpoint; + private JList<com.zeroc.Ice.LocatorPrx> _directDiscoveryLocatorList; + private DefaultListModel<com.zeroc.Ice.LocatorPrx> _directDiscoveryLocatorModel; + private JRadioButton _directDiscoveryDiscoveredLocators; private JLabel _discoveryStatus; private JButton _discoveryRefresh; - private java.util.TimerTask _discoveryFinishTask; - private com.zeroc.Ice.ObjectAdapter _discoveryAdapter; - private LookupReplyPrx _discoveryReplyPrx; - private LookupReply _discoveryLookupReply; + private Plugin _discoveryPlugin; private JRadioButton _directDiscoveryManualEndpoint; // Direct Endpoints panel components diff --git a/java/src/IceLocatorDiscovery/src/main/java/com/zeroc/IceLocatorDiscovery/Plugin.java b/java/src/IceLocatorDiscovery/src/main/java/com/zeroc/IceLocatorDiscovery/Plugin.java new file mode 100644 index 00000000000..b050046aab7 --- /dev/null +++ b/java/src/IceLocatorDiscovery/src/main/java/com/zeroc/IceLocatorDiscovery/Plugin.java @@ -0,0 +1,17 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +package com.zeroc.IceLocatorDiscovery; + +import java.util.List; + +public interface Plugin extends com.zeroc.Ice.Plugin +{ + List<com.zeroc.Ice.LocatorPrx> getLocators(String instanceName, int waitTime); +} diff --git a/java/src/IceLocatorDiscovery/src/main/java/com/zeroc/IceLocatorDiscovery/PluginFactory.java b/java/src/IceLocatorDiscovery/src/main/java/com/zeroc/IceLocatorDiscovery/PluginFactory.java index 6c6b82f4fac..cec8ddf78b3 100644 --- a/java/src/IceLocatorDiscovery/src/main/java/com/zeroc/IceLocatorDiscovery/PluginFactory.java +++ b/java/src/IceLocatorDiscovery/src/main/java/com/zeroc/IceLocatorDiscovery/PluginFactory.java @@ -14,6 +14,6 @@ public class PluginFactory implements com.zeroc.Ice.PluginFactory @Override public com.zeroc.Ice.Plugin create(com.zeroc.Ice.Communicator communicator, String name, String[] args) { - return new PluginI(communicator); + return new PluginI(name, communicator); } } diff --git a/java/src/IceLocatorDiscovery/src/main/java/com/zeroc/IceLocatorDiscovery/PluginI.java b/java/src/IceLocatorDiscovery/src/main/java/com/zeroc/IceLocatorDiscovery/PluginI.java index 5cdf0d781ff..3a50fd6c79b 100644 --- a/java/src/IceLocatorDiscovery/src/main/java/com/zeroc/IceLocatorDiscovery/PluginI.java +++ b/java/src/IceLocatorDiscovery/src/main/java/com/zeroc/IceLocatorDiscovery/PluginI.java @@ -9,13 +9,16 @@ package com.zeroc.IceLocatorDiscovery; +import com.zeroc.IceInternal.Network; import java.util.List; import java.util.Arrays; import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; -class PluginI implements com.zeroc.Ice.Plugin +class PluginI implements Plugin { private static class Request { @@ -135,24 +138,85 @@ class PluginI implements com.zeroc.Ice.Plugin private static class LocatorI implements com.zeroc.Ice.BlobjectAsync { - LocatorI(LookupPrx lookup, com.zeroc.Ice.Properties properties, String instanceName, + LocatorI(String name, LookupPrx lookup, com.zeroc.Ice.Properties properties, String instanceName, com.zeroc.Ice.LocatorPrx voidLocator) { - _lookup = lookup; - _timeout = properties.getPropertyAsIntWithDefault("IceLocatorDiscovery.Timeout", 300); - _retryCount = properties.getPropertyAsIntWithDefault("IceLocatorDiscovery.RetryCount", 3); - _retryDelay = properties.getPropertyAsIntWithDefault("IceLocatorDiscovery.RetryDelay", 2000); + _timeout = properties.getPropertyAsIntWithDefault(name + ".Timeout", 300); + _retryCount = properties.getPropertyAsIntWithDefault(name + ".RetryCount", 3); + _retryDelay = properties.getPropertyAsIntWithDefault(name + ".RetryDelay", 2000); _timer = com.zeroc.IceInternal.Util.getInstance(lookup.ice_getCommunicator()).timer(); _instanceName = instanceName; _warned = false; _locator = lookup.ice_getCommunicator().getDefaultLocator(); _voidLocator = voidLocator; _pendingRetryCount = 0; + + try + { + lookup.ice_getConnection(); + } + catch(com.zeroc.Ice.LocalException ex) + { + StringBuilder b = new StringBuilder(); + b.append("IceDiscovery is unable to establish a multicast connection:\n"); + b.append("proxy = "); + b.append(lookup.toString()); + b.append('\n'); + b.append(ex.toString()); + throw new com.zeroc.Ice.PluginInitializationException(b.toString()); + } + + // + // Create one lookup proxy per endpoint from the given proxy. We want to send a multicast + // datagram on each endpoint. + // + com.zeroc.Ice.Endpoint[] single = new com.zeroc.Ice.Endpoint[1]; + for(com.zeroc.Ice.Endpoint endpt : lookup.ice_getEndpoints()) + { + try + { + single[0] = endpt; + LookupPrx l = (LookupPrx)lookup.ice_endpoints(single); + l.ice_getConnection(); + _lookup.put(l, null); + } + catch(com.zeroc.Ice.LocalException ex) + { + } + } + assert(!_lookup.isEmpty()); } public void setLookupReply(LookupReplyPrx lookupReply) { - _lookupReply = lookupReply; + // + // Use a lookup reply proxy whose adress matches the interface used to send multicast datagrams. + // + com.zeroc.Ice.Endpoint[] single = new com.zeroc.Ice.Endpoint[1]; + for(Map.Entry<LookupPrx, LookupReplyPrx> entry : _lookup.entrySet()) + { + com.zeroc.Ice.UDPEndpointInfo info = + (com.zeroc.Ice.UDPEndpointInfo)entry.getKey().ice_getEndpoints()[0].getInfo(); + if(!info.mcastInterface.isEmpty()) + { + for(com.zeroc.Ice.Endpoint q : lookupReply.ice_getEndpoints()) + { + com.zeroc.Ice.EndpointInfo r = q.getInfo(); + if(r instanceof com.zeroc.Ice.IPEndpointInfo && + ((com.zeroc.Ice.IPEndpointInfo)r).host.equals(info.mcastInterface)) + { + single[0] = q; + entry.setValue((LookupReplyPrx)lookupReply.ice_endpoints(single)); + } + } + } + + if(entry.getValue() == null) + { + // Fallback: just use the given lookup reply proxy if no matching endpoint found. + entry.setValue(lookupReply); + } + } } @Override @@ -164,6 +228,56 @@ class PluginI implements com.zeroc.Ice.Plugin return f; } + public List<com.zeroc.Ice.LocatorPrx> + getLocators(String instanceName, int waitTime) + { + // + // Clear locators from previous search. + // + synchronized(this) + { + _locators.clear(); + } + + // + // Find a locator + // + invoke(null, null); + + // + // Wait for responses + // + try + { + if(instanceName.isEmpty()) + { + Thread.sleep(waitTime); + } + else + { + synchronized(this) + { + while(!_locators.containsKey(instanceName) && _pendingRetryCount > 0) + { + wait(waitTime); + } + } + } + } + catch(java.lang.InterruptedException ex) + { + throw new com.zeroc.Ice.OperationInterruptedException(); + } + + // + // Return found locators + // + synchronized(this) + { + return new ArrayList<>(_locators.values()); + } + } + public synchronized void foundLocator(com.zeroc.Ice.LocatorPrx locator) { if(locator == null || @@ -176,7 +290,8 @@ class PluginI implements com.zeroc.Ice.Plugin // If we already have a locator assigned, ensure the given locator // has the same identity, otherwise ignore it. // - if(_locator != null && !locator.ice_getIdentity().category.equals(_locator.ice_getIdentity().category)) + if(!_pendingRequests.isEmpty() && + _locator != null && !locator.ice_getIdentity().category.equals(_locator.ice_getIdentity().category)) { if(!_warned) { @@ -201,14 +316,15 @@ class PluginI implements com.zeroc.Ice.Plugin _pendingRetryCount = 0; } - if(_locator != null) + com.zeroc.Ice.LocatorPrx l = + _pendingRequests.isEmpty() ? _locators.get(locator.ice_getIdentity().category) : _locator; + if(l != null) { // // We found another locator replica, append its endpoints to the // current locator proxy endpoints. // - List<com.zeroc.Ice.Endpoint> newEndpoints = new ArrayList<>( - Arrays.asList(_locator.ice_getEndpoints())); + List<com.zeroc.Ice.Endpoint> newEndpoints = new ArrayList<>(Arrays.asList(l.ice_getEndpoints())); for(com.zeroc.Ice.Endpoint p : locator.ice_getEndpoints()) { // @@ -229,50 +345,72 @@ class PluginI implements com.zeroc.Ice.Plugin } } - _locator = (com.zeroc.Ice.LocatorPrx)_locator.ice_endpoints( + l = (com.zeroc.Ice.LocatorPrx)l.ice_endpoints( newEndpoints.toArray(new com.zeroc.Ice.Endpoint[newEndpoints.size()])); } else { - _locator = locator; + l = locator; + } + + if(_pendingRequests.isEmpty()) + { + _locators.put(locator.ice_getIdentity().category, l); + notify(); + } + else + { + _locator = l; if(_instanceName.isEmpty()) { _instanceName = _locator.ice_getIdentity().category; // Stick to the first locator } - } - // - // Send pending requests if any. - // - for(Request req : _pendingRequests) - { - req.invoke(_locator); + // + // Send pending requests if any. + // + for(Request req : _pendingRequests) + { + req.invoke(_locator); + } + _pendingRequests.clear(); } - _pendingRequests.clear(); } public synchronized void invoke(com.zeroc.Ice.LocatorPrx locator, Request request) { if(_locator != null && _locator != locator) { - request.invoke(_locator); + if(request != null) + { + request.invoke(_locator); + } } else if(com.zeroc.IceInternal.Time.currentMonotonicTimeMillis() < _nextRetry) { - request.invoke(_voidLocator); // Don't retry to find a locator before the retry delay expires + if(request != null) + { + request.invoke(_voidLocator); // Don't retry to find a locator before the retry delay expires + } } else { _locator = null; - _pendingRequests.add(request); + if(request != null) + { + _pendingRequests.add(request); + } if(_pendingRetryCount == 0) // No request in progress { _pendingRetryCount = _retryCount; try { - _lookup.findLocatorAsync(_instanceName, _lookupReply); // Send multicast request. + for(Map.Entry<LookupPrx, LookupReplyPrx> entry : _lookup.entrySet()) + { + entry.getKey().findLocatorAsync(_instanceName, entry.getValue()); // Send multicast request. + } _future = _timer.schedule(_retryTask, _timeout, java.util.concurrent.TimeUnit.MILLISECONDS); } catch(com.zeroc.Ice.LocalException ex) @@ -299,7 +437,10 @@ class PluginI implements com.zeroc.Ice.Plugin { try { - _lookup.findLocatorAsync(_instanceName, _lookupReply); // Send multicast request. + for(Map.Entry<LookupPrx, LookupReplyPrx> entry : _lookup.entrySet()) + { + entry.getKey().findLocatorAsync(_instanceName, entry.getValue()); // Send multicast request + } _future = _timer.schedule(_retryTask, _timeout, java.util.concurrent.TimeUnit.MILLISECONDS); return; } @@ -320,7 +461,7 @@ class PluginI implements com.zeroc.Ice.Plugin } }; - private final LookupPrx _lookup; + private final Map<LookupPrx, LookupReplyPrx> _lookup = new java.util.HashMap<>(); private final int _timeout; private java.util.concurrent.Future<?> _future; private final java.util.concurrent.ScheduledExecutorService _timer; @@ -329,9 +470,9 @@ class PluginI implements com.zeroc.Ice.Plugin private String _instanceName; private boolean _warned; - private LookupReplyPrx _lookupReply; private com.zeroc.Ice.LocatorPrx _locator; private com.zeroc.Ice.LocatorPrx _voidLocator; + private Map<String, com.zeroc.Ice.LocatorPrx> _locators = new HashMap<>(); private int _pendingRetryCount; private List<Request> _pendingRequests = new ArrayList<>(); @@ -354,8 +495,9 @@ class PluginI implements com.zeroc.Ice.Plugin private final LocatorI _locator; } - public PluginI(com.zeroc.Ice.Communicator communicator) + public PluginI(String name, com.zeroc.Ice.Communicator communicator) { + _name = name; _communicator = communicator; } @@ -369,76 +511,63 @@ class PluginI implements com.zeroc.Ice.Plugin String address; if(ipv4 && !preferIPv6) { - address = properties.getPropertyWithDefault("IceLocatorDiscovery.Address", "239.255.0.1"); + address = properties.getPropertyWithDefault(_name + ".Address", "239.255.0.1"); } else { - address = properties.getPropertyWithDefault("IceLocatorDiscovery.Address", "ff15::1"); + address = properties.getPropertyWithDefault(_name + ".Address", "ff15::1"); } - int port = properties.getPropertyAsIntWithDefault("IceLocatorDiscovery.Port", 4061); - String intf = properties.getProperty("IceLocatorDiscovery.Interface"); + int port = properties.getPropertyAsIntWithDefault(_name + ".Port", 4061); + String intf = properties.getProperty(_name + ".Interface"); - if(properties.getProperty("IceLocatorDiscovery.Reply.Endpoints").isEmpty()) + String lookupEndpoints = properties.getProperty(_name + ".Lookup"); + if(lookupEndpoints.isEmpty()) { - StringBuilder s = new StringBuilder(); - s.append("udp"); - if(!intf.isEmpty()) + int protocol = ipv4 && !preferIPv6 ? Network.EnableIPv4 : Network.EnableIPv6; + java.util.List<String> interfaces = Network.getInterfacesForMulticast(intf, protocol); + for(String p : interfaces) { - s.append(" -h \"").append(intf).append("\""); + if(p != interfaces.get(0)) + { + lookupEndpoints += ":"; + } + lookupEndpoints += "udp -h \"" + address + "\" -p " + port + " --interface \"" + p + "\""; } - properties.setProperty("IceLocatorDiscovery.Reply.Endpoints", s.toString()); } - if(properties.getProperty("IceLocatorDiscovery.Locator.Endpoints").isEmpty()) + + if(properties.getProperty(_name + ".Reply.Endpoints").isEmpty()) + { + properties.setProperty(_name + ".Reply.Endpoints", "udp -h " + (intf.isEmpty() ? "*" : "\"" + intf + "\"")); + } + + if(properties.getProperty(_name + ".Locator.Endpoints").isEmpty()) { - properties.setProperty("IceLocatorDiscovery.Locator.AdapterId", java.util.UUID.randomUUID().toString()); + properties.setProperty(_name + ".Locator.AdapterId", java.util.UUID.randomUUID().toString()); } - _replyAdapter = _communicator.createObjectAdapter("IceLocatorDiscovery.Reply"); - _locatorAdapter = _communicator.createObjectAdapter("IceLocatorDiscovery.Locator"); + _replyAdapter = _communicator.createObjectAdapter(_name + ".Reply"); + _locatorAdapter = _communicator.createObjectAdapter(_name + ".Locator"); // We don't want those adapters to be registered with the locator so clear their locator. _replyAdapter.setLocator(null); _locatorAdapter.setLocator(null); - String lookupEndpoints = properties.getProperty("IceLocatorDiscovery.Lookup"); - if(lookupEndpoints.isEmpty()) - { - StringBuilder s = new StringBuilder(); - s.append("udp -h \"").append(address).append("\" -p ").append(port); - if(!intf.isEmpty()) - { - s.append(" --interface \"").append(intf).append("\""); - } - lookupEndpoints = s.toString(); - } - com.zeroc.Ice.ObjectPrx lookupPrx = _communicator.stringToProxy("IceLocatorDiscovery/Lookup -d:" + lookupEndpoints); lookupPrx = lookupPrx.ice_collocationOptimized(false); // No collocation optimization for the multicast proxy! - try - { - lookupPrx.ice_getConnection(); // Ensure we can establish a connection to the multicast proxy - } - catch(com.zeroc.Ice.LocalException ex) - { - StringBuilder s = new StringBuilder(); - s.append("IceLocatorDiscovery is unable to establish a multicast connection:\n"); - s.append("proxy = ").append(lookupPrx.toString()).append("\n").append(ex); - throw new com.zeroc.Ice.PluginInitializationException(s.toString()); - } com.zeroc.Ice.LocatorPrx voidLoc = com.zeroc.Ice.LocatorPrx.uncheckedCast(_locatorAdapter.addWithUUID(new VoidLocatorI())); - String instanceName = properties.getProperty("IceLocatorDiscovery.InstanceName"); + String instanceName = properties.getProperty(_name + ".InstanceName"); com.zeroc.Ice.Identity id = new com.zeroc.Ice.Identity(); id.name = "Locator"; id.category = !instanceName.isEmpty() ? instanceName : java.util.UUID.randomUUID().toString(); - LocatorI locator = new LocatorI(LookupPrx.uncheckedCast(lookupPrx), properties, instanceName, voidLoc); - _communicator.setDefaultLocator(com.zeroc.Ice.LocatorPrx.uncheckedCast(_locatorAdapter.addWithUUID(locator))); + _locator = new LocatorI(_name, LookupPrx.uncheckedCast(lookupPrx), properties, instanceName, voidLoc); + _communicator.setDefaultLocator(com.zeroc.Ice.LocatorPrx.uncheckedCast(_locatorAdapter.addWithUUID(_locator))); - com.zeroc.Ice.ObjectPrx lookupReply = _replyAdapter.addWithUUID(new LookupReplyI(locator)).ice_datagram(); - locator.setLookupReply(LookupReplyPrx.uncheckedCast(lookupReply)); + com.zeroc.Ice.ObjectPrx lookupReply = _replyAdapter.addWithUUID(new LookupReplyI(_locator)).ice_datagram(); + _locator.setLookupReply(LookupReplyPrx.uncheckedCast(lookupReply)); _replyAdapter.activate(); _locatorAdapter.activate(); @@ -451,7 +580,15 @@ class PluginI implements com.zeroc.Ice.Plugin _locatorAdapter.destroy(); } + public List<com.zeroc.Ice.LocatorPrx> + getLocators(String instanceName, int waitTime) + { + return _locator.getLocators(instanceName, waitTime); + } + + private String _name; private com.zeroc.Ice.Communicator _communicator; private com.zeroc.Ice.ObjectAdapter _locatorAdapter; private com.zeroc.Ice.ObjectAdapter _replyAdapter; + private LocatorI _locator; } diff --git a/java/test/src/main/java/test/IceGrid/simple/AllTests.java b/java/test/src/main/java/test/IceGrid/simple/AllTests.java index f5f8cb46f8c..1c9e28cccc2 100644 --- a/java/test/src/main/java/test/IceGrid/simple/AllTests.java +++ b/java/test/src/main/java/test/IceGrid/simple/AllTests.java @@ -88,11 +88,6 @@ public class AllTests initData.properties.setProperty("Ice.Default.Locator", ""); initData.properties.setProperty("Ice.Plugin.IceLocatorDiscovery", "IceLocatorDiscovery:com.zeroc.IceLocatorDiscovery.PluginFactory"); - if(System.getProperty("os.name").contains("OS X") && - initData.properties.getPropertyAsInt("Ice.PreferIPv6Address") > 0) - { - initData.properties.setProperty("IceLocatorDiscovery.Interface", "::1"); - } initData.properties.setProperty("IceLocatorDiscovery.Port", Integer.toString(app.getTestPort(99))); initData.properties.setProperty("AdapterForDiscoveryTest.AdapterId", "discoveryAdapter"); initData.properties.setProperty("AdapterForDiscoveryTest.Endpoints", "default"); diff --git a/js/src/Ice/PropertyNames.js b/js/src/Ice/PropertyNames.js index 9aa03b29979..835a981434d 100644 --- a/js/src/Ice/PropertyNames.js +++ b/js/src/Ice/PropertyNames.js @@ -6,7 +6,7 @@ // ICE_LICENSE file included in this distribution. // // ********************************************************************** -// Generated by makeprops.py from file ..\config\PropertyNames.xml, Fri Feb 24 18:49:18 2017 +// Generated by makeprops.py from file ./config/PropertyNames.xml, Tue Feb 28 15:01:12 2017 // IMPORTANT: Do not edit this file -- any edits made here will be lost! diff --git a/scripts/Expect.py b/scripts/Expect.py index aacaf80258e..a3bf1962724 100755 --- a/scripts/Expect.py +++ b/scripts/Expect.py @@ -655,7 +655,7 @@ class Expect (object): raise RuntimeError("unexpected exit status: expected: %d, got %d\n" % (expected, result)) self.wait(timeout) - if self.mapping == "java": + if self.mapping in ["java", "java-compat"]: if self.killed is not None: if win32: test(self.exitstatus, -self.killed) @@ -674,6 +674,6 @@ class Expect (object): def hasInterruptSupport(self): """Return True if the application gracefully terminated, False otherwise.""" - if win32 and self.mapping == "java": + if win32 and self.mapping in ["java", "java-compat"]: return False return True diff --git a/scripts/IceGridUtil.py b/scripts/IceGridUtil.py index a60de105794..296d92a8e56 100644 --- a/scripts/IceGridUtil.py +++ b/scripts/IceGridUtil.py @@ -158,10 +158,6 @@ class IceGridRegistry(ProcessFromBinDir, Server): 'IceGrid.Registry.DefaultTemplates' : '"' + os.path.abspath(os.path.join(toplevel, "cpp", "config", "templates.xml")) + '"' } - - if current.config.ipv6 and not isinstance(platform, Linux): - props['IceGrid.Registry.Discovery.Interface'] = '::1' - return props def getEndpoints(self, current): diff --git a/scripts/Util.py b/scripts/Util.py index 4df40f78e0e..3b968a2c553 100644 --- a/scripts/Util.py +++ b/scripts/Util.py @@ -2071,7 +2071,6 @@ class BrowserProcessController(RemoteProcessController): def __init__(self, current): RemoteProcessController.__init__(self, current, "ws -h 127.0.0.1 -p 15002:wss -h 127.0.0.1 -p 15003") self.httpServer = None - self.safariDriver = None try: from selenium import webdriver if not hasattr(webdriver, current.config.browser): @@ -2136,10 +2135,6 @@ class BrowserProcessController(RemoteProcessController): self.httpServer.terminate() self.httpServer = None - if self.safariDriver: - self.safariDriver.terminate() - self.safariDriver = None - try: self.driver.quit() except: diff --git a/scripts/tests/IceDiscovery/simple.py b/scripts/tests/IceDiscovery/simple.py index d04aea87985..40c8a00b2a0 100644 --- a/scripts/tests/IceDiscovery/simple.py +++ b/scripts/tests/IceDiscovery/simple.py @@ -17,7 +17,6 @@ props = lambda process, current: { "IceDiscovery.Timeout": 50, "IceDiscovery.RetryCount": 5, - "IceDiscovery.Interface": '::1' if current.config.ipv6 and not isinstance(platform, Linux) else "", "Ice.Plugin.IceDiscovery": current.getPluginEntryPoint("IceDiscovery", process) } diff --git a/slice/IceLocatorDiscovery/IceLocatorDiscovery.ice b/slice/IceLocatorDiscovery/IceLocatorDiscovery.ice index b0c0db983e7..68eb3c31c45 100644 --- a/slice/IceLocatorDiscovery/IceLocatorDiscovery.ice +++ b/slice/IceLocatorDiscovery/IceLocatorDiscovery.ice @@ -8,7 +8,7 @@ // ********************************************************************** #pragma once -[["ice-prefix", "cpp:header-ext:h", "objc:header-dir:objc"]] +[["ice-prefix", "cpp:dll-export:ICE_LOCATOR_DISCOVERY_API", "cpp:header-ext:h", "objc:header-dir:objc"]] #include <Ice/Locator.ice> |