diff options
author | Benoit Foucher <benoit@zeroc.com> | 2017-01-20 16:52:33 +0100 |
---|---|---|
committer | Benoit Foucher <benoit@zeroc.com> | 2017-01-20 16:52:33 +0100 |
commit | 10d9e3aae20e55d9824b632e77d8f14fd67b122f (patch) | |
tree | e38f0c77e423d9c1a8a5faf4abfccdfa63a905b3 /cpp/src/Ice | |
parent | java:UserException metadata for both local and remote operations (diff) | |
download | ice-10d9e3aae20e55d9824b632e77d8f14fd67b122f.tar.bz2 ice-10d9e3aae20e55d9824b632e77d8f14fd67b122f.tar.xz ice-10d9e3aae20e55d9824b632e77d8f14fd67b122f.zip |
Fixed ICE-6708 - the UDP transport now join the multicast group on all interfaces by default
Diffstat (limited to 'cpp/src/Ice')
-rwxr-xr-x | cpp/src/Ice/Network.cpp | 122 | ||||
-rwxr-xr-x | cpp/src/Ice/Network.h | 2 | ||||
-rwxr-xr-x | cpp/src/Ice/TcpAcceptor.cpp | 2 | ||||
-rw-r--r-- | cpp/src/Ice/UdpEndpointI.cpp | 20 | ||||
-rw-r--r-- | cpp/src/Ice/UdpEndpointI.h | 2 | ||||
-rwxr-xr-x | cpp/src/Ice/UdpTransceiver.cpp | 11 | ||||
-rw-r--r-- | cpp/src/Ice/ios/StreamAcceptor.cpp | 2 |
7 files changed, 100 insertions, 61 deletions
diff --git a/cpp/src/Ice/Network.cpp b/cpp/src/Ice/Network.cpp index c89bc020c2a..e98aa790f22 100755 --- a/cpp/src/Ice/Network.cpp +++ b/cpp/src/Ice/Network.cpp @@ -477,11 +477,11 @@ getLocalAddresses(ProtocolSupport protocol, bool includeLoopback) bool isLinklocal(const Address& addr) { - if (addr.saStorage.ss_family == AF_INET6) + if(addr.saStorage.ss_family == AF_INET6) { return IN6_IS_ADDR_LINKLOCAL(&addr.saIn6.sin6_addr); } - else if (addr.saStorage.ss_family == AF_INET) + else if(addr.saStorage.ss_family == AF_INET) { // Check for 169.254.X.X in network order return (addr.saIn.sin_addr.s_addr & 0xFF) == 169 && ((addr.saIn.sin_addr.s_addr & 0xFF00)>>8) == 254; @@ -492,28 +492,22 @@ isLinklocal(const Address& addr) bool isWildcard(const string& host, ProtocolSupport protocol, bool& ipv4) { - try + Address addr = getAddressForServer(host, 0, protocol, true, false); + if(addr.saStorage.ss_family == AF_INET) { - Address addr = getAddressForServer(host, 0, protocol, true); - if(addr.saStorage.ss_family == AF_INET) + if(addr.saIn.sin_addr.s_addr == INADDR_ANY) { - if(addr.saIn.sin_addr.s_addr == INADDR_ANY) - { - ipv4 = true; - return true; - } - } - else if(addr.saStorage.ss_family) - { - if(IN6_IS_ADDR_UNSPECIFIED(&addr.saIn6.sin6_addr)) - { - ipv4 = false; - return true; - } + ipv4 = true; + return true; } } - catch(const DNSException&) + else if(addr.saStorage.ss_family == AF_INET6) { + if(IN6_IS_ADDR_UNSPECIFIED(&addr.saIn6.sin6_addr)) + { + ipv4 = false; + return true; + } } return false; } @@ -526,7 +520,7 @@ getInterfaceIndex(const string& name) return 0; } - int index = 0; + int index = -1; // // First check if index @@ -595,6 +589,10 @@ getInterfaceIndex(const string& name) } delete[] buf; } + if(index < 0) // interface not found + { + throw Ice::SocketException(__FILE__, __LINE__, WSAEINVAL); + } #elif !defined(__hpux) // @@ -692,6 +690,11 @@ getInterfaceIndex(const string& name) { index = if_nametoindex(name.c_str()); } + if(index <= 0) + { + // index == 0 if if_nametoindex returned 0, < 0 if name wasn't found + throw Ice::SocketException(__FILE__, __LINE__, index == 0 ? getSocketErrno() : ENXIO); + } #endif return index; @@ -733,14 +736,15 @@ getInterfaceAddress(const string& name) struct sockaddr_in addrin; memcpy(&addrin, paddrs->FirstUnicastAddress->Address.lpSockaddr, paddrs->FirstUnicastAddress->Address.iSockaddrLength); - addr = addrin.sin_addr; - break; + delete[] buf; + return addrin.sin_addr; } paddrs = paddrs->Next; } } delete[] buf; } + throw Ice::SocketException(__FILE__, __LINE__, WSAEINVAL); #else ifreq if_address; strcpy(if_address.ifr_name, name.c_str()); @@ -748,14 +752,12 @@ getInterfaceAddress(const string& name) SOCKET fd = createSocketImpl(false, AF_INET); int rc = ioctl(fd, SIOCGIFADDR, &if_address); closeSocketNoThrow(fd); - - if(rc != SOCKET_ERROR) + if(rc == SOCKET_ERROR) { - addr = reinterpret_cast<struct sockaddr_in*>(&if_address.ifr_addr)->sin_addr; + throw Ice::SocketException(__FILE__, __LINE__, getSocketErrno()); } + return reinterpret_cast<struct sockaddr_in*>(&if_address.ifr_addr)->sin_addr; #endif - - return addr; } int @@ -1025,7 +1027,7 @@ IceInternal::getAddresses(const string& host, int port, ProtocolSupport, Ice::En #else vector<Address> IceInternal::getAddresses(const string& host, int port, ProtocolSupport protocol, Ice::EndpointSelectionType selType, - bool preferIPv6, bool blocking) + bool preferIPv6, bool canBlock) { vector<Address> result; Address addr; @@ -1073,7 +1075,7 @@ IceInternal::getAddresses(const string& host, int port, ProtocolSupport protocol hints.ai_family = PF_UNSPEC; } - if(!blocking) + if(!canBlock) { hints.ai_flags = AI_NUMERICHOST; } @@ -1090,12 +1092,12 @@ IceInternal::getAddresses(const string& host, int port, ProtocolSupport protocol // address. However on some platforms (e.g. OS X 10.4.x) // EAI_NODATA is also returned so we also check for it. # ifdef EAI_NODATA - if(!blocking && (rs == EAI_NONAME || rs == EAI_NODATA)) + if(!canBlock && (rs == EAI_NONAME || rs == EAI_NODATA)) # else - if(!blocking && rs == EAI_NONAME) + if(!canBlock && rs == EAI_NONAME) # endif { - return result; // Empty result indicates that a blocking lookup is necessary. + return result; // Empty result indicates that a canBlock lookup is necessary. } else if(rs != 0) { @@ -1161,7 +1163,7 @@ IceInternal::getProtocolSupport(const Address& addr) #endif Address -IceInternal::getAddressForServer(const string& host, int port, ProtocolSupport protocol, bool preferIPv6) +IceInternal::getAddressForServer(const string& host, int port, ProtocolSupport protocol, bool preferIPv6, bool canBlock) { // // We don't use getaddrinfo when host is empty as it's not portable (some old Linux @@ -1196,7 +1198,8 @@ IceInternal::getAddressForServer(const string& host, int port, ProtocolSupport p #endif return addr; } - return getAddresses(host, port, protocol, Ice::Ordered, preferIPv6, true)[0]; + vector<Address> addrs = getAddresses(host, port, protocol, Ice::Ordered, preferIPv6, canBlock); + return addrs.empty() ? Address() : addrs[0]; } int @@ -2016,32 +2019,41 @@ IceInternal::getRecvBufferSize(SOCKET fd) void IceInternal::setMcastGroup(SOCKET fd, const Address& group, const string& intf) { - int rc; - if(group.saStorage.ss_family == AF_INET) + vector<string> interfaces = getHostsForEndpointExpand(intf, getProtocolSupport(group), true); + if(interfaces.empty()) { - struct ip_mreq mreq; - mreq.imr_multiaddr = group.saIn.sin_addr; - mreq.imr_interface = getInterfaceAddress(intf); - rc = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, reinterpret_cast<char*>(&mreq), int(sizeof(mreq))); + interfaces.push_back(intf); } - else - { - struct ipv6_mreq mreq; - mreq.ipv6mr_multiaddr = group.saIn6.sin6_addr; - mreq.ipv6mr_interface = getInterfaceIndex(intf); - rc = setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, reinterpret_cast<char*>(&mreq), int(sizeof(mreq))); - } - if(rc == SOCKET_ERROR) + + for(vector<string>::const_iterator p = interfaces.begin(); p != interfaces.end(); ++p) { - closeSocketNoThrow(fd); - SocketException ex(__FILE__, __LINE__); - ex.error = getSocketErrno(); - throw ex; + int rc; + if(group.saStorage.ss_family == AF_INET) + { + struct ip_mreq mreq; + mreq.imr_multiaddr = group.saIn.sin_addr; + mreq.imr_interface = getInterfaceAddress(*p); + rc = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, reinterpret_cast<char*>(&mreq), int(sizeof(mreq))); + } + else + { + struct ipv6_mreq mreq; + mreq.ipv6mr_multiaddr = group.saIn6.sin6_addr; + mreq.ipv6mr_interface = getInterfaceIndex(*p); + rc = setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, reinterpret_cast<char*>(&mreq), int(sizeof(mreq))); + } + if(rc == SOCKET_ERROR) + { + closeSocketNoThrow(fd); + SocketException ex(__FILE__, __LINE__); + ex.error = getSocketErrno(); + throw ex; + } } } #else void -IceInternal::setMcastGroup(SOCKET fd, const Address& group, const string&) +IceInternal::setMcastGroup(SOCKET fd, const Address& group, const string&, int) { try { @@ -2051,7 +2063,7 @@ IceInternal::setMcastGroup(SOCKET fd, const Address& group, const string&) safe_cast<DatagramSocket^>(fd)->JoinMulticastGroup(group.host); // - // BUGFIX DatagramSocket will not recive any messages from a multicast group if the + // BUGFIX DatagramSocket will not recive any messages from a multicast group if the // messages originate in the same host until the socket is used to send at least one // message. We send a valiate connection message that the peers will ignore to workaround // the issue. @@ -2179,7 +2191,7 @@ checkResultAndWait(IAsyncAction^ action) { p.set_value(status != Windows::Foundation::AsyncStatus::Completed ? action->ErrorCode.Value : 0); }); - + HRESULT result = p.get_future().get(); if(result) { diff --git a/cpp/src/Ice/Network.h b/cpp/src/Ice/Network.h index 3f0c8cf2da7..788470f2708 100755 --- a/cpp/src/Ice/Network.h +++ b/cpp/src/Ice/Network.h @@ -264,7 +264,7 @@ ICE_API std::string errorToStringDNS(int); ICE_API std::vector<Address> getAddresses(const std::string&, int, ProtocolSupport, Ice::EndpointSelectionType, bool, bool); ICE_API ProtocolSupport getProtocolSupport(const Address&); -ICE_API Address getAddressForServer(const std::string&, int, ProtocolSupport, bool); +ICE_API Address getAddressForServer(const std::string&, int, ProtocolSupport, bool, bool); ICE_API int compareAddress(const Address&, const Address&); ICE_API bool isIPv6Supported(); diff --git a/cpp/src/Ice/TcpAcceptor.cpp b/cpp/src/Ice/TcpAcceptor.cpp index 14f03096cc2..769b9cbbb2c 100755 --- a/cpp/src/Ice/TcpAcceptor.cpp +++ b/cpp/src/Ice/TcpAcceptor.cpp @@ -290,7 +290,7 @@ IceInternal::TcpAcceptor::TcpAcceptor(const TcpEndpointIPtr& endpoint, int port) : _endpoint(endpoint), _instance(instance), - _addr(getAddressForServer(host, port, _instance->protocolSupport(), instance->preferIPv6())) + _addr(getAddressForServer(host, port, _instance->protocolSupport(), instance->preferIPv6(), true)) #ifdef ICE_USE_IOCP , _acceptFd(INVALID_SOCKET), _info(SocketOperationRead) #endif diff --git a/cpp/src/Ice/UdpEndpointI.cpp b/cpp/src/Ice/UdpEndpointI.cpp index 25a47b955d9..a631b4ae16d 100644 --- a/cpp/src/Ice/UdpEndpointI.cpp +++ b/cpp/src/Ice/UdpEndpointI.cpp @@ -156,6 +156,26 @@ IceInternal::UdpEndpointI::endpoint(const UdpTransceiverPtr& transceiver) const _mcastTtl, _connect, _connectionId, _compress); } +void +IceInternal::UdpEndpointI::initWithOptions(vector<string>& args, bool oaEndpoint) +{ + IPEndpointI::initWithOptions(args, oaEndpoint); + + if(_mcastInterface == "*") + { + if(oaEndpoint) + { + const_cast<string&>(_mcastInterface) = string(); + } + else + { + Ice::EndpointParseException ex(__FILE__, __LINE__); + ex.str = "`--interface *' not valid for proxy endpoint `" + toString() + "'"; + throw ex; + } + } +} + string IceInternal::UdpEndpointI::options() const { diff --git a/cpp/src/Ice/UdpEndpointI.h b/cpp/src/Ice/UdpEndpointI.h index 883b725e688..6cb0c412e36 100644 --- a/cpp/src/Ice/UdpEndpointI.h +++ b/cpp/src/Ice/UdpEndpointI.h @@ -53,6 +53,8 @@ public: using IPEndpointI::connectionId; + virtual void initWithOptions(std::vector<std::string>&, bool); + protected: virtual void hashInit(Ice::Int&) const; diff --git a/cpp/src/Ice/UdpTransceiver.cpp b/cpp/src/Ice/UdpTransceiver.cpp index 6f3ee3540c9..b4f5520c184 100755 --- a/cpp/src/Ice/UdpTransceiver.cpp +++ b/cpp/src/Ice/UdpTransceiver.cpp @@ -139,7 +139,7 @@ IceInternal::UdpTransceiver::bind() // address won't be the multicast address and the client will // therefore reject the datagram. // - const_cast<Address&>(_addr) = getAddressForServer("", _port, getProtocolSupport(_addr), false); + const_cast<Address&>(_addr) = getAddressForServer("", _port, getProtocolSupport(_addr), false, false); #endif const_cast<Address&>(_addr) = doBind(_fd, _addr, _mcastInterface); @@ -771,7 +771,12 @@ IceInternal::UdpTransceiver::toDetailedString() const { ostringstream os; os << toString(); - vector<string> intfs = getHostsForEndpointExpand(inetAddrToString(_addr), _instance->protocolSupport(), true); + string addr = isAddressValid(_mcastAddr) ? _mcastInterface : inetAddrToString(_addr); + vector<string> intfs = getHostsForEndpointExpand(addr, _instance->protocolSupport(), true); + if(isAddressValid(_mcastAddr) && intfs.empty()) + { + intfs.push_back(_mcastInterface); + } if(!intfs.empty()) { os << "\nlocal interfaces = "; @@ -952,7 +957,7 @@ IceInternal::UdpTransceiver::UdpTransceiver(const UdpEndpointIPtr& endpoint, con _instance(instance), _incoming(true), _bound(false), - _addr(getAddressForServer(host, port, instance->protocolSupport(), instance->preferIPv6())), + _addr(getAddressForServer(host, port, instance->protocolSupport(), instance->preferIPv6(), true)), _mcastInterface(mcastInterface), _port(port), _state(connect ? StateNeedConnect : StateNotConnected) diff --git a/cpp/src/Ice/ios/StreamAcceptor.cpp b/cpp/src/Ice/ios/StreamAcceptor.cpp index 2bf115390fe..bdc85306044 100644 --- a/cpp/src/Ice/ios/StreamAcceptor.cpp +++ b/cpp/src/Ice/ios/StreamAcceptor.cpp @@ -125,7 +125,7 @@ IceObjC::StreamAcceptor::StreamAcceptor(const StreamEndpointIPtr& endpoint, int port) : _endpoint(endpoint), _instance(instance), - _addr(getAddressForServer(host, port, instance->protocolSupport(), instance->preferIPv6())) + _addr(getAddressForServer(host, port, instance->protocolSupport(), instance->preferIPv6(), true)) { #ifdef SOMAXCONN _backlog = instance->properties()->getPropertyAsIntWithDefault("Ice.TCP.Backlog", SOMAXCONN); |