summaryrefslogtreecommitdiff
path: root/cpp/src/Ice
diff options
context:
space:
mode:
authorBenoit Foucher <benoit@zeroc.com>2017-01-20 16:52:33 +0100
committerBenoit Foucher <benoit@zeroc.com>2017-01-20 16:52:33 +0100
commit10d9e3aae20e55d9824b632e77d8f14fd67b122f (patch)
treee38f0c77e423d9c1a8a5faf4abfccdfa63a905b3 /cpp/src/Ice
parentjava:UserException metadata for both local and remote operations (diff)
downloadice-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-xcpp/src/Ice/Network.cpp122
-rwxr-xr-xcpp/src/Ice/Network.h2
-rwxr-xr-xcpp/src/Ice/TcpAcceptor.cpp2
-rw-r--r--cpp/src/Ice/UdpEndpointI.cpp20
-rw-r--r--cpp/src/Ice/UdpEndpointI.h2
-rwxr-xr-xcpp/src/Ice/UdpTransceiver.cpp11
-rw-r--r--cpp/src/Ice/ios/StreamAcceptor.cpp2
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);