diff options
author | Benoit Foucher <benoit@zeroc.com> | 2007-12-19 22:06:38 +0100 |
---|---|---|
committer | Benoit Foucher <benoit@zeroc.com> | 2007-12-19 22:06:38 +0100 |
commit | f6121ea342641eb36f7cd67c7c877a1c70ec3055 (patch) | |
tree | b545f3a2548b81fd8dd56a87a58f98b992c0066b /cpp/src | |
parent | Merge branch 'master' of ssh://cvs.zeroc.com/home/git/ice (diff) | |
download | ice-f6121ea342641eb36f7cd67c7c877a1c70ec3055.tar.bz2 ice-f6121ea342641eb36f7cd67c7c877a1c70ec3055.tar.xz ice-f6121ea342641eb36f7cd67c7c877a1c70ec3055.zip |
- Merge IPv6 support from Dwayne's branch.
- Reviewed and fixed IPv6 bugs.
- Fixed bug in the outgoing connection factory where an assert could be
triggered if the proxy contained identical endpoints
Diffstat (limited to 'cpp/src')
40 files changed, 1046 insertions, 546 deletions
diff --git a/cpp/src/Glacier2/SessionRouterI.cpp b/cpp/src/Glacier2/SessionRouterI.cpp index 9e05665ce3c..830bb978243 100644 --- a/cpp/src/Glacier2/SessionRouterI.cpp +++ b/cpp/src/Glacier2/SessionRouterI.cpp @@ -778,10 +778,10 @@ Glacier2::SessionRouterI::createSessionFromSecureConnection_async( try { IceSSL::ConnectionInfo info = IceSSL::getConnectionInfo(current.con); - sslinfo.remotePort = ntohs(info.remoteAddr.sin_port); - sslinfo.remoteHost = IceInternal::inetAddrToString(info.remoteAddr.sin_addr); - sslinfo.localPort = ntohs(info.localAddr.sin_port); - sslinfo.localHost = IceInternal::inetAddrToString(info.localAddr.sin_addr); + sslinfo.remotePort = IceInternal::getPort(info.remoteAddr); + sslinfo.remoteHost = IceInternal::inetAddrToString(info.remoteAddr); + sslinfo.localPort = IceInternal::getPort(info.localAddr); + sslinfo.localHost = IceInternal::inetAddrToString(info.localAddr); sslinfo.cipher = info.cipher; @@ -804,7 +804,7 @@ Glacier2::SessionRouterI::createSessionFromSecureConnection_async( sslCtx["SSL.Remote.Port"] = os.str(); sslCtx["SSL.Remote.Host"] = sslinfo.remoteHost; os.str(""); - os << ntohs(info.localAddr.sin_port); + os << sslinfo.localPort; sslCtx["SSL.Local.Port"] = os.str(); sslCtx["SSL.Local.Host"] = sslinfo.localHost; if(info.certs.size() > 0) diff --git a/cpp/src/Ice/Application.cpp b/cpp/src/Ice/Application.cpp index 5bf86ba46a2..e9752a9eb86 100644 --- a/cpp/src/Ice/Application.cpp +++ b/cpp/src/Ice/Application.cpp @@ -651,7 +651,7 @@ Ice::Application::mainInternal(int argc, char* argv[], const InitializationData& } catch(const std::exception& ex) { - cerr << _appName << ex.what() << endl; + cerr << _appName << ": " << ex.what() << endl; status = EXIT_FAILURE; } catch(...) diff --git a/cpp/src/Ice/ConnectionFactory.cpp b/cpp/src/Ice/ConnectionFactory.cpp index 835c75c6912..97f5ddc8940 100644 --- a/cpp/src/Ice/ConnectionFactory.cpp +++ b/cpp/src/Ice/ConnectionFactory.cpp @@ -679,7 +679,7 @@ IceInternal::OutgoingConnectionFactory::getConnection(const vector<ConnectorInfo } } } - + if(_destroyed) { throw Ice::CommunicatorDestroyedException(__FILE__, __LINE__); @@ -688,12 +688,14 @@ IceInternal::OutgoingConnectionFactory::getConnection(const vector<ConnectorInfo // // No connection to any of our endpoints exists yet; we add the given connectors to // the _pending set to indicate that we're attempting connection establishment to - // these connectors. + // these connectors. We might attempt to connect to the same connector multiple times. // for(vector<ConnectorInfo>::const_iterator r = connectors.begin(); r != connectors.end(); ++r) { - assert(_pending.find(*r) == _pending.end()); - _pending.insert(pair<ConnectorInfo, set<ConnectCallbackPtr> >(*r, set<ConnectCallbackPtr>())); + if(_pending.find(*r) == _pending.end()) + { + _pending.insert(pair<ConnectorInfo, set<ConnectCallbackPtr> >(*r, set<ConnectCallbackPtr>())); + } } } @@ -769,9 +771,11 @@ IceInternal::OutgoingConnectionFactory::finishGetConnection(const vector<Connect for(vector<ConnectorInfo>::const_iterator p = connectors.begin(); p != connectors.end(); ++p) { map<ConnectorInfo, set<ConnectCallbackPtr> >::iterator q = _pending.find(*p); - assert(q != _pending.end()); - callbacks.insert(q->second.begin(), q->second.end()); - _pending.erase(q); + if(q != _pending.end()) + { + callbacks.insert(q->second.begin(), q->second.end()); + _pending.erase(q); + } } notifyAll(); diff --git a/cpp/src/Ice/EndpointFactoryManager.cpp b/cpp/src/Ice/EndpointFactoryManager.cpp index 9b1a126a1d6..b47686f19b7 100644 --- a/cpp/src/Ice/EndpointFactoryManager.cpp +++ b/cpp/src/Ice/EndpointFactoryManager.cpp @@ -111,7 +111,7 @@ IceInternal::EndpointFactoryManager::create(const string& str, bool oaEndpoint) return factory->create(str.substr(end), oaEndpoint); #else // Code below left in place for debugging. - + EndpointIPtr e = factory->create(str.substr(end), oaEndpoint); BasicStream bs(_instance.get()); e->streamWrite(&bs); diff --git a/cpp/src/Ice/EndpointFactoryManager.h b/cpp/src/Ice/EndpointFactoryManager.h index c2e5671020a..9dd5611a4f1 100644 --- a/cpp/src/Ice/EndpointFactoryManager.h +++ b/cpp/src/Ice/EndpointFactoryManager.h @@ -16,6 +16,7 @@ #include <Ice/EndpointIF.h> #include <Ice/EndpointFactoryF.h> #include <Ice/EndpointFactoryManagerF.h> +#include <Ice/Protocol.h> namespace IceInternal { diff --git a/cpp/src/Ice/EndpointI.cpp b/cpp/src/Ice/EndpointI.cpp index 2ae93da7362..8edb81f99a1 100644 --- a/cpp/src/Ice/EndpointI.cpp +++ b/cpp/src/Ice/EndpointI.cpp @@ -19,7 +19,7 @@ Ice::LocalObject* IceInternal::upCast(EndpointI* p) { return p; } IceUtil::Shared* IceInternal::upCast(EndpointHostResolver* p) { return p; } vector<ConnectorPtr> -IceInternal::EndpointI::connectors(const vector<struct sockaddr_in>& addrs) const +IceInternal::EndpointI::connectors(const vector<struct sockaddr_storage>& addrs) const { // // This method must be extended by endpoints which use the EndpointHostResolver to create @@ -37,7 +37,7 @@ IceInternal::EndpointHostResolver::EndpointHostResolver(const InstancePtr& insta } void -IceInternal::EndpointHostResolver::resolve(const string& host, int port, const EndpointIPtr& endpoint, +IceInternal::EndpointHostResolver::resolve(const string& host, int port, const EndpointIPtr& endpoint, const EndpointI_connectorsPtr& callback) { // @@ -46,7 +46,7 @@ IceInternal::EndpointHostResolver::resolve(const string& host, int port, const E // try { - vector<struct sockaddr_in> addrs = getAddresses(host, port, false); + vector<struct sockaddr_storage> addrs = getAddresses(host, port, _instance->protocolSupport(), false); if(!addrs.empty()) { callback->connectors(endpoint->connectors(addrs)); @@ -109,7 +109,9 @@ IceInternal::EndpointHostResolver::run() _queue.pop_front(); } - resolve.callback->connectors(resolve.endpoint->connectors(getAddresses(resolve.host, resolve.port))); + resolve.callback->connectors( + resolve.endpoint->connectors( + getAddresses(resolve.host, resolve.port, _instance->protocolSupport(), true))); } for(deque<ResolveEntry>::const_iterator p = _queue.begin(); p != _queue.end(); ++p) diff --git a/cpp/src/Ice/EndpointI.h b/cpp/src/Ice/EndpointI.h index 1d5eff2df76..63f8c18abf3 100644 --- a/cpp/src/Ice/EndpointI.h +++ b/cpp/src/Ice/EndpointI.h @@ -19,6 +19,7 @@ #include <Ice/TransceiverF.h> #include <Ice/ConnectorF.h> #include <Ice/AcceptorF.h> +#include <Ice/Protocol.h> #ifdef _WIN32 # include <winsock2.h> @@ -131,7 +132,7 @@ public: // // Expand endpoint out in to separate endpoints for each local - // host if listening on INADDR_ANY. + // host if listening on INADDR_ANY on server side. // virtual std::vector<EndpointIPtr> expand() const = 0; @@ -149,7 +150,7 @@ public: private: - virtual std::vector<ConnectorPtr> connectors(const std::vector<struct sockaddr_in>&) const; + virtual std::vector<ConnectorPtr> connectors(const std::vector<struct sockaddr_storage>&) const; friend class EndpointHostResolver; #if defined(__SUNPRO_CC) || defined(__HP_aCC) diff --git a/cpp/src/Ice/Instance.cpp b/cpp/src/Ice/Instance.cpp index 9349990bb63..de7a679739b 100644 --- a/cpp/src/Ice/Instance.cpp +++ b/cpp/src/Ice/Instance.cpp @@ -199,6 +199,19 @@ IceInternal::Instance::objectAdapterFactory() const return _objectAdapterFactory; } +ProtocolSupport +IceInternal::Instance::protocolSupport() const +{ + IceUtil::RecMutex::Lock sync(*this); + + if(_state == StateDestroyed) + { + throw CommunicatorDestroyedException(__FILE__, __LINE__); + } + + return _protocolSupport; +} + ThreadPoolPtr IceInternal::Instance::clientThreadPool() { @@ -623,7 +636,8 @@ IceInternal::Instance::getAdmin() } catch(const ServerNotFoundException&) { - throw InitializationException(__FILE__, __LINE__, "Locator knows nothing about server '" + serverId + "'"); + throw InitializationException(__FILE__, __LINE__, "Locator knows nothing about server '" + + serverId + "'"); } } @@ -890,6 +904,24 @@ IceInternal::Instance::Instance(const CommunicatorPtr& communicator, const Initi _proxyFactory = new ProxyFactory(this); + bool ipv4 = _initData.properties->getPropertyAsIntWithDefault("Ice.IPv4", 1) > 0; + bool ipv6 = _initData.properties->getPropertyAsIntWithDefault("Ice.IPv6", 0) > 0; + if(!ipv4 && !ipv6) + { + throw InitializationException(__FILE__, __LINE__, "Both IPV4 and IPv6 support cannot be disabled."); + } + else if(ipv4 && ipv6) + { + _protocolSupport = EnableBoth; + } + else if(ipv4) + { + _protocolSupport = EnableIPv4; + } + else + { + _protocolSupport = EnableIPv6; + } _endpointFactoryManager = new EndpointFactoryManager(this); EndpointFactoryPtr tcpEndpointFactory = new TcpEndpointFactory(this); _endpointFactoryManager->add(tcpEndpointFactory); diff --git a/cpp/src/Ice/Instance.h b/cpp/src/Ice/Instance.h index cbf6ad36ecf..2c840985fe6 100644 --- a/cpp/src/Ice/Instance.h +++ b/cpp/src/Ice/Instance.h @@ -66,6 +66,7 @@ public: ConnectionMonitorPtr connectionMonitor() const; ObjectFactoryManagerPtr servantFactoryManager() const; ObjectAdapterFactoryPtr objectAdapterFactory() const; + ProtocolSupport protocolSupport() const; ThreadPoolPtr clientThreadPool(); ThreadPoolPtr serverThreadPool(); SelectorThreadPtr selectorThread(); @@ -123,6 +124,7 @@ private: ConnectionMonitorPtr _connectionMonitor; ObjectFactoryManagerPtr _servantFactoryManager; ObjectAdapterFactoryPtr _objectAdapterFactory; + ProtocolSupport _protocolSupport; ThreadPoolPtr _clientThreadPool; ThreadPoolPtr _serverThreadPool; SelectorThreadPtr _selectorThread; diff --git a/cpp/src/Ice/Network.cpp b/cpp/src/Ice/Network.cpp index 0bd0fa8bd4a..db66ebc4441 100644 --- a/cpp/src/Ice/Network.cpp +++ b/cpp/src/Ice/Network.cpp @@ -28,6 +28,7 @@ # include <ws2tcpip.h> #elif defined(__linux) || defined(__APPLE__) || defined(__FreeBSD__) # include <ifaddrs.h> +# include <net/if.h> #else # include <sys/ioctl.h> # include <net/if.h> @@ -44,17 +45,350 @@ using namespace IceInternal; # define INADDR_NONE (in_addr_t)0xffffffff #endif -static IceUtil::StaticMutex inetMutex = ICE_STATIC_MUTEX_INITIALIZER; +namespace +{ -string -IceInternal::inetAddrToString(const struct in_addr& in) +vector<struct sockaddr_storage> +getLocalAddresses(ProtocolSupport protocol) +{ + vector<struct sockaddr_storage> result; + +#if defined(_WIN32) + try + { + for(int i = 0; i < 2; i++) + { + if((i == 0 && protocol == EnableIPv6) || (i == 1 && protocol == EnableIPv4)) + { + continue; + } + + SOCKET fd = createSocket(false, i == 0 ? AF_INET : AF_INET6); + + vector<unsigned char> buffer; + buffer.resize(1024); + unsigned long len = 0; + DWORD rs = WSAIoctl(fd, SIO_ADDRESS_LIST_QUERY, 0, 0, + &buffer[0], static_cast<DWORD>(buffer.size()), + &len, 0, 0); + if(rs == SOCKET_ERROR) + { + // + // If the buffer wasn't big enough, resize it to the + // required length and try again. + // + if(getSocketErrno() == WSAEFAULT) + { + buffer.resize(len); + rs = WSAIoctl(fd, SIO_ADDRESS_LIST_QUERY, 0, 0, + &buffer[0], static_cast<DWORD>(buffer.size()), + &len, 0, 0); + } + + if(rs == SOCKET_ERROR) + { + closeSocketNoThrow(fd); + SocketException ex(__FILE__, __LINE__); + ex.error = getSocketErrno(); + throw ex; + } + } + + // + // Add the local interface addresses. + // + SOCKET_ADDRESS_LIST* addrs = reinterpret_cast<SOCKET_ADDRESS_LIST*>(&buffer[0]); + for (int i = 0; i < addrs->iAddressCount; ++i) + { + sockaddr_storage addr; + memcpy(&addr, addrs->Address[i].lpSockaddr, addrs->Address[i].iSockaddrLength); + if(addr.ss_family == AF_INET && protocol != EnableIPv6) + { + if(reinterpret_cast<struct sockaddr_in*>(&addr)->sin_addr.s_addr != 0) + { + result.push_back(addr); + } + } + else if(addr.ss_family == AF_INET6 && protocol != EnableIPv4) + { + struct in6_addr* inaddr6 = &reinterpret_cast<struct sockaddr_in6*>(&addr)->sin6_addr; + if(!IN6_IS_ADDR_UNSPECIFIED(inaddr6) && !IN6_IS_ADDR_LOOPBACK(inaddr6)) + { + result.push_back(addr); + } + } + } + + closeSocket(fd); + } + } + catch(const Ice::LocalException&) + { + // + // TODO: Warning? + // + } +#elif defined(__linux) || defined(__APPLE__) || defined(__FreeBSD__) + struct ifaddrs* ifap; + if(::getifaddrs(&ifap) == SOCKET_ERROR) + { + SocketException ex(__FILE__, __LINE__); + ex.error = getSocketErrno(); + throw ex; + } + + struct ifaddrs* curr = ifap; + while(curr != 0) + { + if(curr->ifa_addr && !(curr->ifa_flags & IFF_LOOPBACK)) // Don't include loopback interface addresses + { + if(curr->ifa_addr->sa_family == AF_INET && protocol != EnableIPv6) + { + sockaddr_storage addr; + memcpy(&addr, curr->ifa_addr, sizeof(sockaddr_in)); + if(reinterpret_cast<struct sockaddr_in*>(&addr)->sin_addr.s_addr != 0) + { + result.push_back(addr); + } + } + else if(curr->ifa_addr->sa_family == AF_INET6 && protocol != EnableIPv4) + { + sockaddr_storage addr; + memcpy(&addr, curr->ifa_addr, sizeof(sockaddr_in6)); + if(!IN6_IS_ADDR_UNSPECIFIED(&reinterpret_cast<struct sockaddr_in6*>(&addr)->sin6_addr)) + { + result.push_back(*reinterpret_cast<struct sockaddr_storage*>(curr->ifa_addr)); + } + } + } + + curr = curr->ifa_next; + } + + ::freeifaddrs(ifap); +#else + for(int i = 0; i < 2; i++) + { + if((i == 0 && protocol == EnableIPv6) || (i == 1 && protocol == EnableIPv4)) + { + continue; + } + SOCKET fd = createSocket(false, i == 0 ? AF_INET : AF_INET6); + +#ifdef _AIX + int cmd = CSIOCGIFCONF; +#else + int cmd = SIOCGIFCONF; +#endif + struct ifconf ifc; + int numaddrs = 10; + int old_ifc_len = 0; + + // + // Need to call ioctl multiple times since we do not know up front + // how many addresses there will be, and thus how large a buffer we need. + // We keep increasing the buffer size until subsequent calls return + // the same length, meaning we have all the addresses. + // + while(true) + { + int bufsize = numaddrs * static_cast<int>(sizeof(struct ifreq)); + ifc.ifc_len = bufsize; + ifc.ifc_buf = (char*)malloc(bufsize); + + int rs = ioctl(fd, cmd, &ifc); + if(rs == SOCKET_ERROR) + { + free(ifc.ifc_buf); + closeSocketNoThrow(fd); + SocketException ex(__FILE__, __LINE__); + ex.error = getSocketErrno(); + throw ex; + } + else if(ifc.ifc_len == old_ifc_len) + { + // + // Returned same length twice in a row, finished. + // + break; + } + else + { + old_ifc_len = ifc.ifc_len; + } + + numaddrs += 10; + free(ifc.ifc_buf); + } + closeSocket(fd); + + numaddrs = ifc.ifc_len / static_cast<int>(sizeof(struct ifreq)); + struct ifreq* ifr = ifc.ifc_req; + for(int i = 0; i < numaddrs; ++i) + { + if(!(ifr[i].ifr_flags & IFF_LOOPBACK)) // Don't include loopback interface addresses + { + if(ifr[i].ifr_addr.sa_family == AF_INET && protocol != EnableIPv6) + { + sockaddr_storage addr; + memcpy(&addr, &ifr[i].ifr_addr, sizeof(sockaddr_in)); + if(reinterpret_cast<struct sockaddr_in*>(&addr)->sin_addr.s_addr != 0) + { + result.push_back(addr); + } + } + else if(ifr[i].ifr_addr.sa_family == AF_INET6 && protocol != EnableIPv4) + { + sockaddr_storage addr; + memcpy(&addr, &ifr[i].ifr_addr, sizeof(sockaddr_in6)); + if(!IN6_IS_ADDR_UNSPECIFIED(&reinterpret_cast<struct sockaddr_in6*>(&addr)->sin6_addr)) + { + result.push_back(*reinterpret_cast<struct sockaddr_storage*>(curr->ifa_addr)); + } + } + } + } + free(ifc.ifc_buf); + } +#endif + + return result; +} + +void +getAddressImpl(const string& host, int port, struct sockaddr_storage& addr, ProtocolSupport protocol, bool server) { // - // inet_ntoa uses static memory on some platforms so we protect - // access and make a copy. + // We now use getaddrinfo() on Windows. // - IceUtil::StaticMutex::Lock lock(inetMutex); - return string(inet_ntoa(in)); +// #ifdef _WIN32 + +// // +// // Windows XP has getaddrinfo(), but we don't want to require XP to run Ice. +// // + +// // +// // gethostbyname() is thread safe on Windows, with a separate hostent per thread +// // +// struct hostent* entry; +// int retry = 5; +// do +// { +// entry = gethostbyname(host.c_str()); +// } +// while(entry == 0 && WSAGetLastError() == WSATRY_AGAIN && --retry >= 0); + +// if(entry == 0) +// { +// DNSException ex(__FILE__, __LINE__); + +// ex.error = WSAGetLastError(); +// ex.host = host; +// throw ex; +// } +// memcpy(&addr.sin_addr, entry->h_addr, entry->h_length); + +// #else + + memset(&addr, 0, sizeof(struct sockaddr_storage)); + struct addrinfo* info = 0; + int retry = 5; + + struct addrinfo hints = { 0 }; + + if(server) + { + // + // If host is empty, getaddrinfo will return the wildcard + // address instead of the loopack address. + // + hints.ai_flags |= AI_PASSIVE; + } + + if(protocol == EnableIPv4) + { + hints.ai_family = PF_INET; + } + else if(protocol == EnableIPv6) + { + hints.ai_family = PF_INET6; + } + else + { + hints.ai_family = PF_UNSPEC; + } + + int rs = 0; + do + { + if(host.empty()) + { + rs = getaddrinfo(0, "0", &hints, &info); + } + else + { + rs = getaddrinfo(host.c_str(), 0, &hints, &info); + } + } + while(info == 0 && rs == EAI_AGAIN && --retry >= 0); + + if(rs != 0) + { + DNSException ex(__FILE__, __LINE__); + ex.error = rs; + ex.host = host; + throw ex; + } + + memcpy(&addr, info->ai_addr, info->ai_addrlen); + if(info->ai_family != PF_INET) + { + reinterpret_cast<sockaddr_in*>(&addr)->sin_port = htons(port); + } + else if(info->ai_family != AF_INET6) + { + reinterpret_cast<sockaddr_in6*>(&addr)->sin6_port = htons(port); + } + else // Unknown address family. + { + freeaddrinfo(info); + DNSException ex(__FILE__, __LINE__); + ex.host = host; + throw ex; + } + freeaddrinfo(info); +} + +bool +isWildcard(const string& host, ProtocolSupport protocol) +{ + try + { + sockaddr_storage addr; + getAddressImpl(host, 0, addr, protocol, false); + if(addr.ss_family == AF_INET) + { + struct sockaddr_in* addrin = reinterpret_cast<sockaddr_in*>(&addr); + if(addrin->sin_addr.s_addr == INADDR_ANY) + { + return true; + } + } + else if(addr.ss_family) + { + struct sockaddr_in6* addrin6 = reinterpret_cast<sockaddr_in6*>(&addr); + if(IN6_IS_ADDR_UNSPECIFIED(&addrin6->sin6_addr)) + { + return true; + } + } + } + catch(const DNSException&) + { + } + return false; +} + } int @@ -209,17 +543,17 @@ IceInternal::recvTruncated() } SOCKET -IceInternal::createSocket(bool udp) +IceInternal::createSocket(bool udp, int family) { SOCKET fd; if(udp) { - fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + fd = socket(family, SOCK_DGRAM, IPPROTO_UDP); } else { - fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + fd = socket(family, SOCK_STREAM, IPPROTO_TCP); } if(fd == INVALID_SOCKET) @@ -533,9 +867,19 @@ IceInternal::setReuseAddress(SOCKET fd, bool reuse) } void -IceInternal::doBind(SOCKET fd, struct sockaddr_in& addr) +IceInternal::doBind(SOCKET fd, struct sockaddr_storage& addr) { - if(bind(fd, reinterpret_cast<struct sockaddr*>(&addr), int(sizeof(addr))) == SOCKET_ERROR) + int size; + if(addr.ss_family == AF_INET) + { + size = sizeof(sockaddr_in); + } + else if(addr.ss_family == AF_INET6) + { + size = sizeof(sockaddr_in6); + } + + if(bind(fd, reinterpret_cast<struct sockaddr*>(&addr), size) == SOCKET_ERROR) { closeSocketNoThrow(fd); SocketException ex(__FILE__, __LINE__); @@ -571,10 +915,20 @@ repeatListen: } bool -IceInternal::doConnect(SOCKET fd, struct sockaddr_in& addr, int timeout) +IceInternal::doConnect(SOCKET fd, struct sockaddr_storage& addr, int timeout) { repeatConnect: - if(::connect(fd, reinterpret_cast<struct sockaddr*>(&addr), int(sizeof(addr))) == SOCKET_ERROR) + int size; + if(addr.ss_family == AF_INET) + { + size = sizeof(sockaddr_in); + } + else if(addr.ss_family == AF_INET6) + { + size = sizeof(sockaddr_in6); + } + + if(::connect(fd, reinterpret_cast<struct sockaddr*>(&addr), size) == SOCKET_ERROR) { if(interrupted()) { @@ -627,7 +981,7 @@ repeatConnect: // a server which was just deactivated if the client socket re-uses the same ephemeral // port as the server). // - struct sockaddr_in localAddr; + struct sockaddr_storage localAddr; fdToLocalAddress(fd, localAddr); if(compareAddress(addr, localAddr) == 0) { @@ -744,9 +1098,9 @@ IceInternal::doFinishConnect(SOCKET fd, int timeout) // a server which was just deactivated if the client socket re-uses the same ephemeral // port as the server). // - struct sockaddr_in localAddr; + struct sockaddr_storage localAddr; fdToLocalAddress(fd, localAddr); - struct sockaddr_in remoteAddr; + struct sockaddr_storage remoteAddr; if(fdToRemoteAddress(fd, remoteAddr) && compareAddress(remoteAddr, localAddr) == 0) { ConnectionRefusedException ex(__FILE__, __LINE__); @@ -830,20 +1184,24 @@ repeatAccept: } void -IceInternal::getAddress(const string& host, int port, struct sockaddr_in& addr) +IceInternal::getAddressForServer(const string& host, int port, struct sockaddr_storage& addr, ProtocolSupport protocol) { - memset(&addr, 0, sizeof(struct sockaddr_in)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = inet_addr(host.c_str()); + getAddressImpl(host, port, addr, protocol, true); +} - if(addr.sin_addr.s_addr == INADDR_NONE) - { - // - // We now use getaddrinfo() on Windows. - // -// #ifdef _WIN32 +void +IceInternal::getAddress(const string& host, int port, struct sockaddr_storage& addr, ProtocolSupport protocol) +{ + getAddressImpl(host, port, addr, protocol, false); +} +vector<struct sockaddr_storage> +IceInternal::getAddresses(const string& host, int port, ProtocolSupport protocol, bool blocking) +{ + // + // We now use getaddrinfo() on Windows. + // +// #ifdef _WIN32 // // // // Windows XP has getaddrinfo(), but we don't want to require XP to run Ice. // // @@ -851,83 +1209,185 @@ IceInternal::getAddress(const string& host, int port, struct sockaddr_in& addr) // // // // gethostbyname() is thread safe on Windows, with a separate hostent per thread // // -// struct hostent* entry; +// struct hostent* entry = 0; // int retry = 5; + // do // { // entry = gethostbyname(host.c_str()); // } -// while(entry == 0 && WSAGetLastError() == WSATRY_AGAIN && --retry >= 0); - +// while(entry == 0 && h_errno == TRY_AGAIN && --retry >= 0); + // if(entry == 0) // { // DNSException ex(__FILE__, __LINE__); - -// ex.error = WSAGetLastError(); +// ex.error = h_errno; // ex.host = host; // throw ex; // } -// memcpy(&addr.sin_addr, entry->h_addr, entry->h_length); + +// char** p = entry->h_addr_list; +// while(*p) +// { +// memcpy(&addr.sin_addr, *p, entry->h_length); +// result.push_back(addr); +// p++; +// } // #else - struct addrinfo* info = 0; - int retry = 5; + vector<struct sockaddr_storage> result; + struct sockaddr_storage addr; + memset(&addr, 0, sizeof(struct sockaddr_storage)); + + struct addrinfo* info = 0; + int retry = 5; - struct addrinfo hints = { 0 }; + struct addrinfo hints = { 0 }; + if(protocol == EnableIPv4) + { hints.ai_family = PF_INET; + } + else if(protocol == EnableIPv6) + { + hints.ai_family = PF_INET6; + } + else + { + hints.ai_family = PF_UNSPEC; + } - int rs = 0; - do + if(!blocking) + { + hints.ai_flags = AI_NUMERICHOST; + } + + int rs = 0; + do + { + if(host.empty()) { - rs = getaddrinfo(host.c_str(), 0, &hints, &info); + rs = getaddrinfo(0, "0", &hints, &info); // Get the address of the loopback interface } - while(info == 0 && rs == EAI_AGAIN && --retry >= 0); - - if(rs != 0) + else { - DNSException ex(__FILE__, __LINE__); - ex.error = rs; - ex.host = host; - throw ex; + rs = getaddrinfo(host.c_str(), 0, &hints, &info); } + } + while(info == 0 && rs == EAI_AGAIN && --retry >= 0); - assert(info->ai_family == PF_INET); - struct sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(info->ai_addr); + if(!blocking && rs == EAI_NONAME) + { + return result; // Empty result indicates that a blocking lookup is necessary. + } + else if(rs != 0) + { + DNSException ex(__FILE__, __LINE__); + ex.error = rs; + ex.host = host; + throw ex; + } - addr.sin_addr.s_addr = sin->sin_addr.s_addr; - freeaddrinfo(info); + struct addrinfo* p; + for(p = info; p != NULL; p = p->ai_next) + { + memcpy(&addr, p->ai_addr, p->ai_addrlen); + if(p->ai_family == PF_INET) + { + struct sockaddr_in* addrin = reinterpret_cast<sockaddr_in*>(&addr); + addrin->sin_port = htons(port); + if(addrin->sin_addr.s_addr == 0) + { + continue; + } + } + else if(p->ai_family == PF_INET6) + { + struct sockaddr_in6* addrin6 = reinterpret_cast<sockaddr_in6*>(&addr); + addrin6->sin6_port = htons(port); + if(IN6_IS_ADDR_UNSPECIFIED(&addrin6->sin6_addr)) + { + continue; + } + } + + bool found = false; + for(unsigned int i = 0; i < result.size(); ++i) + { + if(compareAddress(result[i], addr) == 0) + { + found = true; + break; + } + } + if(!found) + { + result.push_back(addr); + } } + + freeaddrinfo(info); + return result; } int -IceInternal::compareAddress(const struct sockaddr_in& addr1, const struct sockaddr_in& addr2) +IceInternal::compareAddress(const struct sockaddr_storage& addr1, const struct sockaddr_storage& addr2) { - if(addr1.sin_family < addr2.sin_family) + if(addr1.ss_family < addr2.ss_family) { return -1; } - else if(addr2.sin_family < addr1.sin_family) + else if(addr2.ss_family < addr1.ss_family) { return 1; } - if(addr1.sin_port < addr2.sin_port) + if(addr1.ss_family == AF_INET) { - return -1; - } - else if(addr2.sin_port < addr1.sin_port) - { - return 1; - } + const struct sockaddr_in* addr1in = reinterpret_cast<const sockaddr_in*>(&addr1); + const struct sockaddr_in* addr2in = reinterpret_cast<const sockaddr_in*>(&addr2); - if(addr1.sin_addr.s_addr < addr2.sin_addr.s_addr) - { - return -1; + if(addr1in->sin_port < addr2in->sin_port) + { + return -1; + } + else if(addr2in->sin_port < addr1in->sin_port) + { + return 1; + } + + if(addr1in->sin_addr.s_addr < addr2in->sin_addr.s_addr) + { + return -1; + } + else if(addr2in->sin_addr.s_addr < addr1in->sin_addr.s_addr) + { + return 1; + } } - else if(addr2.sin_addr.s_addr < addr1.sin_addr.s_addr) + else { - return 1; + const struct sockaddr_in6* addr1in = reinterpret_cast<const sockaddr_in6*>(&addr1); + const struct sockaddr_in6* addr2in = reinterpret_cast<const sockaddr_in6*>(&addr2); + + if(addr1in->sin6_port < addr2in->sin6_port) + { + return -1; + } + else if(addr2in->sin6_port < addr1in->sin6_port) + { + return 1; + } + + int res = memcmp(&addr1in->sin6_addr, &addr2in->sin6_addr, sizeof(struct in6_addr)); + if(res < 0) + { + return -1; + } + else if(res > 0) + { + return 1; + } } return 0; @@ -938,21 +1398,23 @@ IceInternal::createPipe(SOCKET fds[2]) { #ifdef _WIN32 - SOCKET fd = createSocket(false); + SOCKET fd = createSocket(false, AF_INET); setBlock(fd, true); - struct sockaddr_in addr; + struct sockaddr_storage addr; memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(0); - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + struct sockaddr_in* addrin = reinterpret_cast<struct sockaddr_in*>(&addr); + addrin->sin_family = AF_INET; + addrin->sin_port = htons(0); + addrin->sin_addr.s_addr = htonl(INADDR_LOOPBACK); doBind(fd, addr); doListen(fd, 1); try { - fds[0] = createSocket(false); + fds[0] = createSocket(false, AF_INET); } catch(...) { @@ -1268,17 +1730,17 @@ IceInternal::fdToString(SOCKET fd) return "<closed>"; } - struct sockaddr_in localAddr; + struct sockaddr_storage localAddr; fdToLocalAddress(fd, localAddr); - struct sockaddr_in remoteAddr; + struct sockaddr_storage remoteAddr; bool peerConnected = fdToRemoteAddress(fd, remoteAddr); return addressesToString(localAddr, remoteAddr, peerConnected); }; std::string -IceInternal::addressesToString(const struct sockaddr_in& localAddr, const struct sockaddr_in& remoteAddr, +IceInternal::addressesToString(const struct sockaddr_storage& localAddr, const struct sockaddr_storage& remoteAddr, bool peerConnected) { ostringstream s; @@ -1295,9 +1757,9 @@ IceInternal::addressesToString(const struct sockaddr_in& localAddr, const struct } void -IceInternal::fdToLocalAddress(SOCKET fd, struct sockaddr_in& addr) +IceInternal::fdToLocalAddress(SOCKET fd, struct sockaddr_storage& addr) { - socklen_t len = static_cast<socklen_t>(sizeof(struct sockaddr_in)); + socklen_t len = static_cast<socklen_t>(sizeof(struct sockaddr_storage)); if(getsockname(fd, reinterpret_cast<struct sockaddr*>(&addr), &len) == SOCKET_ERROR) { closeSocketNoThrow(fd); @@ -1308,9 +1770,9 @@ IceInternal::fdToLocalAddress(SOCKET fd, struct sockaddr_in& addr) } bool -IceInternal::fdToRemoteAddress(SOCKET fd, struct sockaddr_in& addr) +IceInternal::fdToRemoteAddress(SOCKET fd, struct sockaddr_storage& addr) { - socklen_t len = static_cast<socklen_t>(sizeof(struct sockaddr_in)); + socklen_t len = static_cast<socklen_t>(sizeof(struct sockaddr_storage)); if(getpeername(fd, reinterpret_cast<struct sockaddr*>(&addr), &len) == SOCKET_ERROR) { if(notConnected()) @@ -1330,296 +1792,89 @@ IceInternal::fdToRemoteAddress(SOCKET fd, struct sockaddr_in& addr) } string -IceInternal::addrToString(const struct sockaddr_in& addr) +IceInternal::inetAddrToString(const struct sockaddr_storage& ss) +{ + int size; + if(ss.ss_family == AF_INET) + { + size = sizeof(sockaddr_in); + } + else if(ss.ss_family == AF_INET6) + { + size = sizeof(sockaddr_in6); + } + + char namebuf[1024]; + namebuf[0] = '\0'; + getnameinfo(reinterpret_cast<const struct sockaddr *>(&ss), size, namebuf, sizeof(namebuf), 0, 0, NI_NUMERICHOST); + return string(namebuf); +} + +string +IceInternal::addrToString(const struct sockaddr_storage& addr) { ostringstream s; - s << inetAddrToString(addr.sin_addr) << ':' << ntohs(addr.sin_port); + string port; + s << inetAddrToString(addr) << ':'; + if(addr.ss_family == AF_INET) + { + const struct sockaddr_in* addrin = reinterpret_cast<const sockaddr_in*>(&addr); + s << ntohs(addrin->sin_port); + } + else + { + const struct sockaddr_in6* addrin = reinterpret_cast<const sockaddr_in6*>(&addr); + s << ntohs(addrin->sin6_port); + } return s.str(); } -vector<struct sockaddr_in> -IceInternal::getAddresses(const string& host, int port, bool blocking) +int +IceInternal::getPort(const struct sockaddr_storage& addr) { - vector<struct sockaddr_in> result; - - if(host == "0.0.0.0") + if(addr.ss_family == AF_INET) { - vector<string> hosts = getLocalHosts(); - for(unsigned int i = 0; i < hosts.size(); ++i) - { - struct sockaddr_in addr; - getAddress(hosts[i], port, addr); - result.push_back(addr); - } + return ntohs(reinterpret_cast<const sockaddr_in*>(&addr)->sin_port); } else { - struct sockaddr_in addr; - memset(&addr, 0, sizeof(struct sockaddr_in)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - - // - // We now use getaddrinfo() on Windows. - // -// #ifdef _WIN32 - -// // -// // Windows XP has getaddrinfo(), but we don't want to require XP to run Ice. -// // - -// // -// // gethostbyname() is thread safe on Windows, with a separate hostent per thread -// // -// struct hostent* entry = 0; -// int retry = 5; - -// do -// { -// entry = gethostbyname(host.c_str()); -// } -// while(entry == 0 && h_errno == TRY_AGAIN && --retry >= 0); - -// if(entry == 0) -// { -// DNSException ex(__FILE__, __LINE__); -// ex.error = h_errno; -// ex.host = host; -// throw ex; -// } - -// char** p = entry->h_addr_list; -// while(*p) -// { -// memcpy(&addr.sin_addr, *p, entry->h_length); -// result.push_back(addr); -// p++; -// } - -// #else - - struct addrinfo* info = 0; - int retry = 5; - - struct addrinfo hints = { 0 }; - hints.ai_family = PF_INET; - if(!blocking) - { - hints.ai_flags = AI_NUMERICHOST; - } - - int rs = 0; - do - { - rs = getaddrinfo(host.c_str(), 0, &hints, &info); - } - while(info == 0 && rs == EAI_AGAIN && --retry >= 0); - - if(!blocking && rs == EAI_NONAME) - { - return result; // Empty result indicates that a blocking lookup is necessary. - } - else if(rs != 0) - { - DNSException ex(__FILE__, __LINE__); - ex.error = rs; - ex.host = host; - throw ex; - } - - struct addrinfo* p; - for(p = info; p != NULL; p = p->ai_next) - { - assert(p->ai_family == PF_INET); - struct sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(p->ai_addr); - if(sin->sin_addr.s_addr != 0) - { - addr.sin_addr.s_addr = sin->sin_addr.s_addr; - - bool found = false; - for(unsigned int i = 0; i < result.size(); ++i) - { - if(compareAddress(result[i], addr) == 0) - { - found = true; - break; - } - } - if(!found) - { - result.push_back(addr); - } - } - } - - freeaddrinfo(info); - -//#endif + return ntohs(reinterpret_cast<const sockaddr_in6*>(&addr)->sin6_port); } - - return result; } vector<string> -IceInternal::getLocalHosts() +IceInternal::getHostsForEndpointExpand(const string& host, ProtocolSupport protocolSupport) { - vector<string> result; - -#if defined(_WIN32) - try + vector<string> hosts; + if(host.empty() || isWildcard(host, protocolSupport)) { - SOCKET fd = createSocket(false); - - vector<unsigned char> buffer; - buffer.resize(1024); - unsigned long len = 0; - DWORD rs = WSAIoctl(fd, SIO_ADDRESS_LIST_QUERY, 0, 0, - &buffer[0], static_cast<DWORD>(buffer.size()), - &len, 0, 0); - if(rs == SOCKET_ERROR) + vector<struct sockaddr_storage> addrs = getLocalAddresses(protocolSupport); + for(vector<struct sockaddr_storage>::const_iterator p = addrs.begin(); p != addrs.end(); ++p) { // - // If the buffer wasn't big enough, resize it to the - // required length and try again. + // NOTE: We don't publish link-local IPv6 addresses as these addresses can only + // be accessed in general with a scope-id. // - if(getSocketErrno() == WSAEFAULT) + if(p->ss_family != AF_INET6 || + !IN6_IS_ADDR_LINKLOCAL(&reinterpret_cast<const struct sockaddr_in6*>(&(*p))->sin6_addr)) { - buffer.resize(len); - rs = WSAIoctl(fd, SIO_ADDRESS_LIST_QUERY, 0, 0, - &buffer[0], static_cast<DWORD>(buffer.size()), - &len, 0, 0); + hosts.push_back(inetAddrToString(*p)); } - - if(rs == SOCKET_ERROR) - { - closeSocketNoThrow(fd); - SocketException ex(__FILE__, __LINE__); - ex.error = getSocketErrno(); - throw ex; - } - } - - // - // Add the local interface addresses. - // - SOCKET_ADDRESS_LIST* addrs = reinterpret_cast<SOCKET_ADDRESS_LIST*>(&buffer[0]); - for (int i = 0; i < addrs->iAddressCount; ++i) - { - result.push_back( - inetAddrToString(reinterpret_cast<struct sockaddr_in*>(addrs->Address[i].lpSockaddr)->sin_addr)); } - // - // Add the loopback interface address. - // - struct sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(0); - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - result.push_back(inetAddrToString(addr.sin_addr)); - - closeSocket(fd); - } - catch(const Ice::LocalException&) - { - // - // TODO: Warning? - // - } -#elif defined(__linux) || defined(__APPLE__) || defined(__FreeBSD__) - struct ifaddrs* ifap; - if(::getifaddrs(&ifap) == SOCKET_ERROR) - { - SocketException ex(__FILE__, __LINE__); - ex.error = getSocketErrno(); - throw ex; - } - - struct ifaddrs* curr = ifap; - while(curr != 0) - { - if(curr->ifa_addr && curr->ifa_addr->sa_family == AF_INET) + if(hosts.empty()) { - struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(curr->ifa_addr); - if(addr->sin_addr.s_addr != 0) + if(protocolSupport != EnableIPv6) { - result.push_back(inetAddrToString((*addr).sin_addr)); + hosts.push_back("127.0.0.1"); } - } - - curr = curr->ifa_next; - } - - ::freeifaddrs(ifap); -#else - SOCKET fd = createSocket(false); - -#ifdef _AIX - int cmd = CSIOCGIFCONF; -#else - int cmd = SIOCGIFCONF; -#endif - struct ifconf ifc; - int numaddrs = 10; - int old_ifc_len = 0; - - // - // Need to call ioctl multiple times since we do not know up front - // how many addresses there will be, and thus how large a buffer we need. - // We keep increasing the buffer size until subsequent calls return - // the same length, meaning we have all the addresses. - // - while(true) - { - int bufsize = numaddrs * static_cast<int>(sizeof(struct ifreq)); - ifc.ifc_len = bufsize; - ifc.ifc_buf = (char*)malloc(bufsize); - - int rs = ioctl(fd, cmd, &ifc); - if(rs == SOCKET_ERROR) - { - free(ifc.ifc_buf); - closeSocketNoThrow(fd); - SocketException ex(__FILE__, __LINE__); - ex.error = getSocketErrno(); - throw ex; - } - else if(ifc.ifc_len == old_ifc_len) - { - // - // Returned same length twice in a row, finished. - // - break; - } - else - { - old_ifc_len = ifc.ifc_len; - } - - numaddrs += 10; - free(ifc.ifc_buf); - } - - numaddrs = ifc.ifc_len / static_cast<int>(sizeof(struct ifreq)); - struct ifreq* ifr = ifc.ifc_req; - for(int i = 0; i < numaddrs; ++i) - { - if(ifr[i].ifr_addr.sa_family == AF_INET) - { - struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(&ifr[i].ifr_addr); - if(addr->sin_addr.s_addr != 0) + if(protocolSupport != EnableIPv4) { - result.push_back(inetAddrToString((*addr).sin_addr)); + hosts.push_back("0:0:0:0:0:0:0:1"); } } } - - free(ifc.ifc_buf); - closeSocket(fd); -#endif - - return result; + return hosts; // An empty host list indicates to just use the given host. } void diff --git a/cpp/src/Ice/Network.h b/cpp/src/Ice/Network.h index 5936a2cd2c0..d5ba13de419 100644 --- a/cpp/src/Ice/Network.h +++ b/cpp/src/Ice/Network.h @@ -17,9 +17,11 @@ #include <Ice/Config.h> #include <Ice/PropertiesF.h> // For setTcpBufSize #include <Ice/LoggerF.h> // For setTcpBufSize +#include <Ice/Protocol.h> #ifdef _WIN32 # include <winsock2.h> +# include <ws2tcpip.h> typedef int ssize_t; #else # include <unistd.h> @@ -76,7 +78,7 @@ ICE_API bool connectionLost(); ICE_API bool notConnected(); ICE_API bool recvTruncated(); -ICE_API SOCKET createSocket(bool); +ICE_API SOCKET createSocket(bool, int); ICE_API void closeSocket(SOCKET); ICE_API void closeSocketNoThrow(SOCKET); ICE_API void shutdownSocketWrite(SOCKET); @@ -94,14 +96,18 @@ ICE_API void setMcastInterface(SOCKET, const struct in_addr&); ICE_API void setMcastTtl(SOCKET, int); ICE_API void setReuseAddress(SOCKET, bool); -ICE_API void doBind(SOCKET, struct sockaddr_in&); +ICE_API void doBind(SOCKET, struct sockaddr_storage&); ICE_API void doListen(SOCKET, int); -ICE_API bool doConnect(SOCKET, struct sockaddr_in&, int); +ICE_API bool doConnect(SOCKET, struct sockaddr_storage&, int); ICE_API void doFinishConnect(SOCKET, int); ICE_API SOCKET doAccept(SOCKET, int); -ICE_API void getAddress(const std::string&, int, struct sockaddr_in&); -ICE_API int compareAddress(const struct sockaddr_in&, const struct sockaddr_in&); +ICE_API void getAddressForServer(const std::string&, int, struct sockaddr_storage&, ProtocolSupport); +ICE_API void getAddress(const std::string&, int, struct sockaddr_storage&, ProtocolSupport); +ICE_API std::vector<struct sockaddr_storage> getAddresses(const std::string&, int, ProtocolSupport, bool); + + +ICE_API int compareAddress(const struct sockaddr_storage&, const struct sockaddr_storage&); ICE_API void createPipe(SOCKET fds[2]); @@ -110,16 +116,17 @@ ICE_API std::string errorToStringDNS(int); ICE_API std::string lastErrorToString(); ICE_API std::string fdToString(SOCKET); -ICE_API std::string addressesToString(const struct sockaddr_in&, const struct sockaddr_in&, bool); -ICE_API void fdToLocalAddress(SOCKET, struct sockaddr_in&); -ICE_API bool fdToRemoteAddress(SOCKET, struct sockaddr_in&); -ICE_API std::string addrToString(const struct sockaddr_in&); - -ICE_API std::vector<struct sockaddr_in> getAddresses(const std::string&, int, bool = true); -ICE_API std::vector<std::string> getLocalHosts(); +ICE_API std::string addressesToString(const struct sockaddr_storage&, const struct sockaddr_storage&, bool); +ICE_API void fdToLocalAddress(SOCKET, struct sockaddr_storage&); +ICE_API bool fdToRemoteAddress(SOCKET, struct sockaddr_storage&); +ICE_API std::string inetAddrToString(const struct sockaddr_storage&); +ICE_API std::string addrToString(const struct sockaddr_storage&); +ICE_API int getPort(const struct sockaddr_storage&); + +ICE_API std::vector<std::string> getHostsForEndpointExpand(const std::string&, ProtocolSupport); ICE_API void setTcpBufSize(SOCKET, const Ice::PropertiesPtr&, const Ice::LoggerPtr&); + ICE_API int getSocketErrno(); -ICE_API std::string inetAddrToString(const struct in_addr&); } diff --git a/cpp/src/Ice/ObjectAdapterI.cpp b/cpp/src/Ice/ObjectAdapterI.cpp index ccd571147ec..b89200fa601 100644 --- a/cpp/src/Ice/ObjectAdapterI.cpp +++ b/cpp/src/Ice/ObjectAdapterI.cpp @@ -932,17 +932,19 @@ Ice::ObjectAdapterI::ObjectAdapterI(const InstancePtr& instance, const Communica vector<EndpointIPtr> endpoints; if(endpointInfo.empty()) { - endpoints = parseEndpoints(properties->getProperty(_name + ".Endpoints")); + endpoints = parseEndpoints(properties->getProperty(_name + ".Endpoints"), true); } else { - endpoints = parseEndpoints(endpointInfo); + endpoints = parseEndpoints(endpointInfo, true); } + for(vector<EndpointIPtr>::iterator p = endpoints.begin(); p != endpoints.end(); ++p) { IncomingConnectionFactoryPtr factory = new IncomingConnectionFactory(instance, *p, this, _name); _incomingConnectionFactories.push_back(factory); } + if(endpoints.empty()) { TraceLevelsPtr tl = _instance->traceLevels(); @@ -1083,7 +1085,7 @@ Ice::ObjectAdapterI::checkIdentity(const Identity& ident) } vector<EndpointIPtr> -Ice::ObjectAdapterI::parseEndpoints(const string& endpts) const +Ice::ObjectAdapterI::parseEndpoints(const string& endpts, bool oaEndpoints) const { string::size_type beg; string::size_type end = 0; @@ -1099,10 +1101,47 @@ Ice::ObjectAdapterI::parseEndpoints(const string& endpts) const break; } - end = endpts.find(':', beg); - if(end == string::npos) + end = beg; + while(true) { - end = endpts.length(); + end = endpts.find(':', end); + if(end == string::npos) + { + end = endpts.length(); + break; + } + else + { + bool quoted = false; + string::size_type quote = beg; + while(true) + { + quote = endpts.find('\"', quote); + if(quote == string::npos || end < quote) + { + break; + } + else + { + quote = endpts.find('\"', ++quote); + if(quote == string::npos) + { + break; + } + else if(end < quote) + { + quoted = true; + break; + } + ++quote; + } + } + if(!quoted) + { + break; + } + ++end; + } } if(end == beg) @@ -1112,7 +1151,7 @@ Ice::ObjectAdapterI::parseEndpoints(const string& endpts) const } string s = endpts.substr(beg, end - beg); - EndpointIPtr endp = _instance->endpointFactoryManager()->create(s, true); + EndpointIPtr endp = _instance->endpointFactoryManager()->create(s, oaEndpoints); if(endp == 0) { EndpointParseException ex(__FILE__, __LINE__); @@ -1135,16 +1174,22 @@ ObjectAdapterI::parsePublishedEndpoints() // instead of the connection factory endpoints. // string endpts = _communicator->getProperties()->getProperty(_name + ".PublishedEndpoints"); - vector<EndpointIPtr> endpoints = parseEndpoints(endpts); - if(endpoints.empty()) + vector<EndpointIPtr> endpoints = parseEndpoints(endpts, false); + if(!endpoints.empty()) { - transform(_incomingConnectionFactories.begin(), _incomingConnectionFactories.end(), - back_inserter(endpoints), Ice::constMemFun(&IncomingConnectionFactory::endpoint)); + return endpoints; } // - // Expand any endpoints that may be listening on INADDR_ANY to - // include actual addresses in the published endpoints. + // If the PublishedEndpoints property isn't set, we compute the published enpdoints + // from the OA endpoints. + // + transform(_incomingConnectionFactories.begin(), _incomingConnectionFactories.end(), + back_inserter(endpoints), Ice::constMemFun(&IncomingConnectionFactory::endpoint)); + + // + // Expand any endpoints that may be listening on INADDR_ANY to include actual + // addresses in the published endpoints. // vector<EndpointIPtr> expandedEndpoints; for(unsigned int i = 0; i < endpoints.size(); ++i) diff --git a/cpp/src/Ice/ObjectAdapterI.h b/cpp/src/Ice/ObjectAdapterI.h index 84322f3a495..973e01ebc8e 100644 --- a/cpp/src/Ice/ObjectAdapterI.h +++ b/cpp/src/Ice/ObjectAdapterI.h @@ -100,7 +100,7 @@ private: ObjectPrx newIndirectProxy(const Identity&, const std::string&, const std::string&) const; void checkForDeactivation() const; static void checkIdentity(const Identity&); - std::vector<IceInternal::EndpointIPtr> parseEndpoints(const std::string&) const; + std::vector<IceInternal::EndpointIPtr> parseEndpoints(const std::string&, bool) const; std::vector<IceInternal::EndpointIPtr> parsePublishedEndpoints(); void updateLocatorRegistry(const IceInternal::LocatorInfoPtr&, const Ice::ObjectPrx&, bool); bool filterProperties(Ice::StringSeq&); diff --git a/cpp/src/Ice/PropertyNames.cpp b/cpp/src/Ice/PropertyNames.cpp index 4cd655a1d55..00636a8f1e3 100644 --- a/cpp/src/Ice/PropertyNames.cpp +++ b/cpp/src/Ice/PropertyNames.cpp @@ -66,6 +66,8 @@ const IceInternal::Property IcePropsData[] = IceInternal::Property("Ice.Default.Router.CollocationOptimized", false, 0), IceInternal::Property("Ice.Default.Router.ThreadPerConnection", false, 0), IceInternal::Property("Ice.Default.Router", false, 0), + IceInternal::Property("Ice.IPv4", false, 0), + IceInternal::Property("Ice.IPv6", false, 0), IceInternal::Property("Ice.EventLog.Source", false, 0), IceInternal::Property("Ice.GC.Interval", false, 0), IceInternal::Property("Ice.ImplicitContext", false, 0), diff --git a/cpp/src/Ice/ProtocolPluginFacade.cpp b/cpp/src/Ice/ProtocolPluginFacade.cpp index 2134bdd6ec1..25e9b157d68 100644 --- a/cpp/src/Ice/ProtocolPluginFacade.cpp +++ b/cpp/src/Ice/ProtocolPluginFacade.cpp @@ -56,6 +56,12 @@ IceInternal::ProtocolPluginFacade::getEndpointHostResolver() const return _instance->endpointHostResolver(); } +ProtocolSupport +IceInternal::ProtocolPluginFacade::getProtocolSupport() const +{ + return _instance->protocolSupport(); +} + void IceInternal::ProtocolPluginFacade::addEndpointFactory(const EndpointFactoryPtr& factory) const { diff --git a/cpp/src/Ice/ReferenceFactory.cpp b/cpp/src/Ice/ReferenceFactory.cpp index 0e894056597..ac8ebec8c10 100644 --- a/cpp/src/Ice/ReferenceFactory.cpp +++ b/cpp/src/Ice/ReferenceFactory.cpp @@ -450,10 +450,47 @@ IceInternal::ReferenceFactory::create(const string& str) { beg = end + 1; - end = s.find(':', beg); - if(end == string::npos) + end = beg; + while(true) { - end = s.length(); + end = s.find(':', end); + if(end == string::npos) + { + end = s.length(); + break; + } + else + { + bool quoted = false; + string::size_type quote = beg; + while(true) + { + quote = s.find('\"', quote); + if(quote == string::npos || end < quote) + { + break; + } + else + { + quote = s.find('\"', ++quote); + if(quote == string::npos) + { + break; + } + else if(end < quote) + { + quoted = true; + break; + } + ++quote; + } + } + if(!quoted) + { + break; + } + ++end; + } } string es = s.substr(beg, end - beg); diff --git a/cpp/src/Ice/TcpAcceptor.cpp b/cpp/src/Ice/TcpAcceptor.cpp index baa93aa594a..23378e54139 100644 --- a/cpp/src/Ice/TcpAcceptor.cpp +++ b/cpp/src/Ice/TcpAcceptor.cpp @@ -78,7 +78,7 @@ IceInternal::TcpAcceptor::accept(int timeout) void IceInternal::TcpAcceptor::connectToSelf() { - SOCKET fd = createSocket(false); + SOCKET fd = createSocket(false, _addr.ss_family); setBlock(fd, false); doConnect(fd, _addr, -1); closeSocket(fd); @@ -91,9 +91,9 @@ IceInternal::TcpAcceptor::toString() const } int -IceInternal::TcpAcceptor::effectivePort() +IceInternal::TcpAcceptor::effectivePort() const { - return ntohs(_addr.sin_port); + return getPort(_addr); } IceInternal::TcpAcceptor::TcpAcceptor(const InstancePtr& instance, const string& host, int port) : @@ -109,9 +109,9 @@ IceInternal::TcpAcceptor::TcpAcceptor(const InstancePtr& instance, const string& try { - _fd = createSocket(false); + getAddressForServer(host, port, _addr, _instance->protocolSupport()); + _fd = createSocket(false, _addr.ss_family); setBlock(_fd, false); - getAddress(host, port, _addr); setTcpBufSize(_fd, _instance->initializationData().properties, _logger); #ifndef _WIN32 // diff --git a/cpp/src/Ice/TcpAcceptor.h b/cpp/src/Ice/TcpAcceptor.h index ed2634a74ef..9d2526914f4 100644 --- a/cpp/src/Ice/TcpAcceptor.h +++ b/cpp/src/Ice/TcpAcceptor.h @@ -17,7 +17,7 @@ #include <Ice/Acceptor.h> #ifndef _WIN32 -# include <netinet/in.h> // For struct sockaddr_in +# include <netinet/in.h> // For struct sockaddr_storage #endif namespace IceInternal @@ -36,7 +36,7 @@ public: virtual void connectToSelf(); virtual std::string toString() const; - int effectivePort(); + int effectivePort() const; private: @@ -49,7 +49,7 @@ private: ::Ice::LoggerPtr _logger; SOCKET _fd; int _backlog; - struct sockaddr_in _addr; + struct sockaddr_storage _addr; }; } diff --git a/cpp/src/Ice/TcpConnector.cpp b/cpp/src/Ice/TcpConnector.cpp index a4394598ba9..eadb705f8e8 100644 --- a/cpp/src/Ice/TcpConnector.cpp +++ b/cpp/src/Ice/TcpConnector.cpp @@ -29,7 +29,7 @@ IceInternal::TcpConnector::connect(int timeout) out << "trying to establish tcp connection to " << toString(); } - SOCKET fd = createSocket(false); + SOCKET fd = createSocket(false, _addr.ss_family); setBlock(fd, false); setTcpBufSize(fd, _instance->initializationData().properties, _logger); bool connected = doConnect(fd, _addr, timeout); @@ -115,12 +115,11 @@ IceInternal::TcpConnector::operator<(const Connector& r) const { return false; } - return compareAddress(_addr, p->_addr) == -1; } -IceInternal::TcpConnector::TcpConnector(const InstancePtr& instance, const struct sockaddr_in& addr, Ice::Int timeout, - const string& connectionId) : +IceInternal::TcpConnector::TcpConnector(const InstancePtr& instance, const struct sockaddr_storage& addr, + Ice::Int timeout, const string& connectionId) : _instance(instance), _traceLevels(instance->traceLevels()), _logger(instance->initializationData().logger), diff --git a/cpp/src/Ice/TcpConnector.h b/cpp/src/Ice/TcpConnector.h index 2147f30cccc..28c42c064b8 100644 --- a/cpp/src/Ice/TcpConnector.h +++ b/cpp/src/Ice/TcpConnector.h @@ -19,7 +19,7 @@ #ifdef _WIN32 # include <winsock2.h> #else -# include <netinet/in.h> // For struct sockaddr_in +# include <netinet/in.h> // For struct sockaddr_storage #endif namespace IceInternal @@ -40,14 +40,14 @@ public: private: - TcpConnector(const InstancePtr&, const struct sockaddr_in&, Ice::Int, const std::string&); + TcpConnector(const InstancePtr&, const struct sockaddr_storage&, Ice::Int, const std::string&); virtual ~TcpConnector(); friend class TcpEndpointI; const InstancePtr _instance; const TraceLevelsPtr _traceLevels; const ::Ice::LoggerPtr _logger; - struct sockaddr_in _addr; + struct sockaddr_storage _addr; const Ice::Int _timeout; const std::string _connectionId; }; diff --git a/cpp/src/Ice/TcpEndpointI.cpp b/cpp/src/Ice/TcpEndpointI.cpp index 0cab29774ad..2568b5aeb2f 100644 --- a/cpp/src/Ice/TcpEndpointI.cpp +++ b/cpp/src/Ice/TcpEndpointI.cpp @@ -32,7 +32,7 @@ IceInternal::TcpEndpointI::TcpEndpointI(const InstancePtr& instance, const strin { } -IceInternal::TcpEndpointI::TcpEndpointI(const InstancePtr& instance, const string& str, bool server) : +IceInternal::TcpEndpointI::TcpEndpointI(const InstancePtr& instance, const string& str, bool oaEndpoint) : _instance(instance), _port(0), _timeout(-1), @@ -76,6 +76,10 @@ IceInternal::TcpEndpointI::TcpEndpointI(const InstancePtr& instance, const strin end = str.length(); } argument = str.substr(beg, end - beg); + if(argument[0] == '\"' && argument[argument.size() - 1] == '\"') + { + argument = argument.substr(1, argument.size() - 2); + } } switch(option[1]) @@ -140,21 +144,19 @@ IceInternal::TcpEndpointI::TcpEndpointI(const InstancePtr& instance, const strin if(_host.empty()) { const_cast<string&>(_host) = _instance->defaultsAndOverrides()->defaultHost; - if(_host.empty()) - { - if(server) - { - const_cast<string&>(_host) = "0.0.0.0"; - } - else - { - const_cast<string&>(_host) = "127.0.0.1"; - } - } } else if(_host == "*") { - const_cast<string&>(_host) = "0.0.0.0"; + if(oaEndpoint) + { + const_cast<string&>(_host) = string(); + } + else + { + EndpointParseException ex(__FILE__, __LINE__); + ex.str = "tcp " + str; + throw ex; + } } } @@ -195,7 +197,24 @@ IceInternal::TcpEndpointI::toString() const // format of proxyToString() before changing this and related code. // ostringstream s; - s << "tcp -h " << _host << " -p " << _port; + s << "tcp"; + + if(!_host.empty()) + { + s << " -h "; + bool addQuote = _host.find(':') != string::npos; + if(addQuote) + { + s << "\""; + } + s << _host; + if(addQuote) + { + s << "\""; + } + } + + s << " -p " << _port; if(_timeout != -1) { s << " -t " << _timeout; @@ -292,7 +311,7 @@ IceInternal::TcpEndpointI::transceiver(EndpointIPtr& endp) const vector<ConnectorPtr> IceInternal::TcpEndpointI::connectors() const { - return connectors(getAddresses(_host, _port)); + return connectors(getAddresses(_host, _port, _instance->protocolSupport(), true)); } void @@ -314,21 +333,18 @@ vector<EndpointIPtr> IceInternal::TcpEndpointI::expand() const { vector<EndpointIPtr> endps; - if(_host == "0.0.0.0") + vector<string> hosts = getHostsForEndpointExpand(_host, _instance->protocolSupport()); + if(hosts.empty()) { - vector<string> hosts = getLocalHosts(); - for(unsigned int i = 0; i < hosts.size(); ++i) - { - if(hosts.size() == 1 || hosts[i] != "127.0.0.1") - { - endps.push_back(new TcpEndpointI(_instance, hosts[i], _port, _timeout, _connectionId, _compress)); - } - } + endps.push_back(const_cast<TcpEndpointI*>(this)); } else { - endps.push_back(const_cast<TcpEndpointI*>(this)); - } + for(vector<string>::const_iterator p = hosts.begin(); p != hosts.end(); ++p) + { + endps.push_back(new TcpEndpointI(_instance, *p, _port, _timeout, _connectionId, _compress)); + } + } return endps; } @@ -454,7 +470,7 @@ IceInternal::TcpEndpointI::operator<(const EndpointI& r) const } vector<ConnectorPtr> -IceInternal::TcpEndpointI::connectors(const vector<struct sockaddr_in>& addresses) const +IceInternal::TcpEndpointI::connectors(const vector<struct sockaddr_storage>& addresses) const { vector<ConnectorPtr> connectors; for(unsigned int i = 0; i < addresses.size(); ++i) @@ -486,9 +502,9 @@ IceInternal::TcpEndpointFactory::protocol() const } EndpointIPtr -IceInternal::TcpEndpointFactory::create(const std::string& str, bool server) const +IceInternal::TcpEndpointFactory::create(const std::string& str, bool oaEndpoint) const { - return new TcpEndpointI(_instance, str, server); + return new TcpEndpointI(_instance, str, oaEndpoint); } EndpointIPtr diff --git a/cpp/src/Ice/TcpEndpointI.h b/cpp/src/Ice/TcpEndpointI.h index 361d7150de8..a2df26f15dc 100644 --- a/cpp/src/Ice/TcpEndpointI.h +++ b/cpp/src/Ice/TcpEndpointI.h @@ -50,7 +50,7 @@ public: private: - virtual std::vector<ConnectorPtr> connectors(const std::vector<struct sockaddr_in>&) const; + virtual std::vector<ConnectorPtr> connectors(const std::vector<struct sockaddr_storage>&) const; #if defined(__SUNPRO_CC) // diff --git a/cpp/src/Ice/ThreadPool.cpp b/cpp/src/Ice/ThreadPool.cpp index f18134ca2a5..61b01e42c48 100644 --- a/cpp/src/Ice/ThreadPool.cpp +++ b/cpp/src/Ice/ThreadPool.cpp @@ -126,7 +126,6 @@ IceInternal::ThreadPool::destroy() IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*this); assert(!_destroyed); assert(_handlerMap.empty()); - assert(_workItems.empty()); _destroyed = true; _selector.setInterrupt(); } diff --git a/cpp/src/Ice/UdpConnector.cpp b/cpp/src/Ice/UdpConnector.cpp index 05c202a8310..96019514ca1 100644 --- a/cpp/src/Ice/UdpConnector.cpp +++ b/cpp/src/Ice/UdpConnector.cpp @@ -168,7 +168,8 @@ IceInternal::UdpConnector::operator<(const Connector& r) const return compareAddress(_addr, p->_addr) == -1; } -IceInternal::UdpConnector::UdpConnector(const InstancePtr& instance, const struct sockaddr_in& addr, + +IceInternal::UdpConnector::UdpConnector(const InstancePtr& instance, const struct sockaddr_storage& addr, const string& mcastInterface, int mcastTtl, Ice::Byte protocolMajor, Ice::Byte protocolMinor, Ice::Byte encodingMajor, Ice::Byte encodingMinor, const std::string& connectionId) : diff --git a/cpp/src/Ice/UdpConnector.h b/cpp/src/Ice/UdpConnector.h index 77d73bba277..b6ca621cfb9 100644 --- a/cpp/src/Ice/UdpConnector.h +++ b/cpp/src/Ice/UdpConnector.h @@ -13,11 +13,12 @@ #include <Ice/TransceiverF.h> #include <Ice/InstanceF.h> #include <Ice/Connector.h> +#include <Ice/Protocol.h> #ifdef _WIN32 # include <winsock2.h> #else -# include <netinet/in.h> // For struct sockaddr_in +# include <netinet/in.h> // For struct sockaddr_storage #endif namespace IceInternal @@ -38,13 +39,13 @@ public: private: - UdpConnector(const InstancePtr&, const struct sockaddr_in&, const std::string&, int, Ice::Byte, Ice::Byte, + UdpConnector(const InstancePtr&, const struct sockaddr_storage&, const std::string&, int, Ice::Byte, Ice::Byte, Ice::Byte, Ice::Byte, const std::string&); virtual ~UdpConnector(); friend class UdpEndpointI; const InstancePtr _instance; - struct sockaddr_in _addr; + struct sockaddr_storage _addr; const std::string _mcastInterface; const int _mcastTtl; const Ice::Byte _protocolMajor; diff --git a/cpp/src/Ice/UdpEndpointI.cpp b/cpp/src/Ice/UdpEndpointI.cpp index b5f4588714c..217f9625528 100644 --- a/cpp/src/Ice/UdpEndpointI.cpp +++ b/cpp/src/Ice/UdpEndpointI.cpp @@ -39,7 +39,7 @@ IceInternal::UdpEndpointI::UdpEndpointI(const InstancePtr& instance, const strin { } -IceInternal::UdpEndpointI::UdpEndpointI(const InstancePtr& instance, const string& str, bool server) : +IceInternal::UdpEndpointI::UdpEndpointI(const InstancePtr& instance, const string& str, bool oaEndpoint) : _instance(instance), _port(0), _mcastTtl(-1), @@ -88,6 +88,10 @@ IceInternal::UdpEndpointI::UdpEndpointI(const InstancePtr& instance, const strin end = str.length(); } argument = str.substr(beg, end - beg); + if(argument[0] == '\"' && argument[argument.size() - 1] == '\"') + { + argument = argument.substr(1, argument.size() - 2); + } } if(option == "-v") @@ -267,21 +271,19 @@ IceInternal::UdpEndpointI::UdpEndpointI(const InstancePtr& instance, const strin if(_host.empty()) { const_cast<string&>(_host) = _instance->defaultsAndOverrides()->defaultHost; - if(_host.empty()) - { - if(server) - { - const_cast<string&>(_host) = "0.0.0.0"; - } - else - { - const_cast<string&>(_host) = "127.0.0.1"; - } - } } else if(_host == "*") { - const_cast<string&>(_host) = "0.0.0.0"; + if(oaEndpoint) + { + const_cast<string&>(_host) = string(); + } + else + { + EndpointParseException ex(__FILE__, __LINE__); + ex.str = "udp " + str; + throw ex; + } } } @@ -372,7 +374,22 @@ IceInternal::UdpEndpointI::toString() const << static_cast<unsigned>(static_cast<unsigned char>(_encodingMinor)); } - s << " -h " << _host << " -p " << _port; + if(!_host.empty()) + { + s << " -h "; + bool addQuote = _host.find(':') != string::npos; + if(addQuote) + { + s << "\""; + } + s << _host; + if(addQuote) + { + s << "\""; + } + } + + s << " -p " << _port; if(_mcastInterface.length() > 0) { @@ -480,7 +497,7 @@ IceInternal::UdpEndpointI::transceiver(EndpointIPtr& endp) const vector<ConnectorPtr> IceInternal::UdpEndpointI::connectors() const { - return connectors(getAddresses(_host, _port)); + return connectors(getAddresses(_host, _port, _instance->protocolSupport(), true)); } void @@ -500,22 +517,19 @@ vector<EndpointIPtr> IceInternal::UdpEndpointI::expand() const { vector<EndpointIPtr> endps; - if(_host == "0.0.0.0") + vector<string> hosts = getHostsForEndpointExpand(_host, _instance->protocolSupport()); + if(hosts.empty()) { - vector<string> hosts = getLocalHosts(); - for(unsigned int i = 0; i < hosts.size(); ++i) - { - if(hosts.size() == 1 || hosts[i] != "127.0.0.1") - { - endps.push_back(new UdpEndpointI(_instance, hosts[i], _port, _mcastInterface, _mcastTtl, _protocolMajor, - _protocolMinor, _encodingMajor, _encodingMinor, _connect, - _connectionId, _compress)); - } - } + endps.push_back(const_cast<UdpEndpointI*>(this)); } else { - endps.push_back(const_cast<UdpEndpointI*>(this)); + for(vector<string>::const_iterator p = hosts.begin(); p != hosts.end(); ++p) + { + endps.push_back(new UdpEndpointI(_instance, *p, _port, _mcastInterface, _mcastTtl, _protocolMajor, + _protocolMinor, _encodingMajor, _encodingMinor, _connect, + _connectionId, _compress)); + } } return endps; } @@ -726,7 +740,7 @@ IceInternal::UdpEndpointI::operator<(const EndpointI& r) const } vector<ConnectorPtr> -IceInternal::UdpEndpointI::connectors(const vector<struct sockaddr_in>& addresses) const +IceInternal::UdpEndpointI::connectors(const vector<struct sockaddr_storage>& addresses) const { vector<ConnectorPtr> connectors; for(unsigned int i = 0; i < addresses.size(); ++i) @@ -759,9 +773,9 @@ IceInternal::UdpEndpointFactory::protocol() const } EndpointIPtr -IceInternal::UdpEndpointFactory::create(const std::string& str, bool server) const +IceInternal::UdpEndpointFactory::create(const std::string& str, bool oaEndpoint) const { - return new UdpEndpointI(_instance, str, server); + return new UdpEndpointI(_instance, str, oaEndpoint); } EndpointIPtr diff --git a/cpp/src/Ice/UdpEndpointI.h b/cpp/src/Ice/UdpEndpointI.h index 07fb3daaf2d..051efd646b4 100644 --- a/cpp/src/Ice/UdpEndpointI.h +++ b/cpp/src/Ice/UdpEndpointI.h @@ -51,7 +51,7 @@ public: private: - virtual std::vector<ConnectorPtr> connectors(const std::vector<struct sockaddr_in>&) const; + virtual std::vector<ConnectorPtr> connectors(const std::vector<struct sockaddr_storage>&) const; #if defined(__SUNPRO_CC) // diff --git a/cpp/src/Ice/UdpTransceiver.cpp b/cpp/src/Ice/UdpTransceiver.cpp index 2736587f7a8..1d889d686de 100644 --- a/cpp/src/Ice/UdpTransceiver.cpp +++ b/cpp/src/Ice/UdpTransceiver.cpp @@ -72,7 +72,7 @@ IceInternal::UdpTransceiver::shutdownReadWrite() // // Save the local address before shutting down or disconnecting. // - struct sockaddr_in localAddr; + struct sockaddr_storage localAddr; fdToLocalAddress(_fd, localAddr); assert(_fd != INVALID_SOCKET); @@ -84,9 +84,9 @@ IceInternal::UdpTransceiver::shutdownReadWrite() // if(!_connect) { - struct sockaddr_in unspec; + struct sockaddr_storage unspec; memset(&unspec, 0, sizeof(unspec)); - unspec.sin_family = AF_UNSPEC; + unspec.ss_family = AF_UNSPEC; ::connect(_fd, reinterpret_cast<struct sockaddr*>(&unspec), int(sizeof(unspec))); } @@ -94,7 +94,7 @@ IceInternal::UdpTransceiver::shutdownReadWrite() // Send a dummy packet to the socket. This packet is ignored because we have // already set _shutdownReadWrite. // - SOCKET fd = createSocket(true); + SOCKET fd = createSocket(true, localAddr.ss_family); setBlock(fd, false); doConnect(fd, localAddr, -1); ::send(fd, "", 1, 0); @@ -259,8 +259,8 @@ repeat: // If we must connect, then we connect to the first peer that // sends us a packet. // - struct sockaddr_in peerAddr; - memset(&peerAddr, 0, sizeof(struct sockaddr_in)); + struct sockaddr_storage peerAddr; + memset(&peerAddr, 0, sizeof(struct sockaddr_storage)); socklen_t len = static_cast<socklen_t>(sizeof(peerAddr)); assert(_fd != INVALID_SOCKET); ret = recvfrom(_fd, reinterpret_cast<char*>(&buf.b[0]), packetSize, @@ -374,7 +374,7 @@ IceInternal::UdpTransceiver::toString() const { if(_mcastServer && _fd != INVALID_SOCKET) { - struct sockaddr_in remoteAddr; + struct sockaddr_storage remoteAddr; bool peerConnected = fdToRemoteAddress(_fd, remoteAddr); return addressesToString(_addr, remoteAddr, peerConnected); } @@ -407,10 +407,10 @@ IceInternal::UdpTransceiver::checkSendSize(const Buffer& buf, size_t messageSize int IceInternal::UdpTransceiver::effectivePort() const { - return ntohs(_addr.sin_port); + return getPort(_addr); } -IceInternal::UdpTransceiver::UdpTransceiver(const InstancePtr& instance, const struct sockaddr_in& addr, +IceInternal::UdpTransceiver::UdpTransceiver(const InstancePtr& instance, const struct sockaddr_storage& addr, const string& mcastInterface, int mcastTtl) : _traceLevels(instance->traceLevels()), _logger(instance->initializationData().logger), @@ -423,18 +423,35 @@ IceInternal::UdpTransceiver::UdpTransceiver(const InstancePtr& instance, const s { try { - _fd = createSocket(true); + _fd = createSocket(true, _addr.ss_family); setBufSize(instance); setBlock(_fd, false); doConnect(_fd, _addr, -1); _connect = false; // We're connected now - if(IN_MULTICAST(ntohl(_addr.sin_addr.s_addr))) + + bool multicast = false; + int port; + if(_addr.ss_family == AF_INET) + { + struct sockaddr_in* addrin = reinterpret_cast<struct sockaddr_in*>(&_addr); + multicast = IN_MULTICAST(ntohl(addrin->sin_addr.s_addr)); + port = ntohs(addrin->sin_port); + } + /* + else + { + struct sockaddr_in6* addrin = reinterpret_cast<struct sockaddr_in6*>(&_addr); + multicast = IN6_IS_ADDR_MULTICAST(&addrin->sin6_addr); + port = ntohs(addrin->sin6_port); + } + */ + if(multicast) { if(mcastInterface.length() > 0) { - struct sockaddr_in addr; - getAddress(mcastInterface, ntohs(_addr.sin_port), addr); - setMcastInterface(_fd, addr.sin_addr); + struct sockaddr_storage addr; + getAddress(mcastInterface, port, addr, instance->protocolSupport()); + setMcastInterface(_fd, reinterpret_cast<struct sockaddr_in*>(&addr)->sin_addr); } if(mcastTtl != -1) { @@ -472,39 +489,56 @@ IceInternal::UdpTransceiver::UdpTransceiver(const InstancePtr& instance, const s { try { - _fd = createSocket(true); + getAddressForServer(host, port, _addr, instance->protocolSupport()); + _fd = createSocket(true, _addr.ss_family); setBufSize(instance); setBlock(_fd, false); - getAddress(host, port, _addr); if(_traceLevels->network >= 2) { Trace out(_logger, _traceLevels->networkCat); out << "attempting to bind to udp socket " << addrToString(_addr); } - if(IN_MULTICAST(ntohl(_addr.sin_addr.s_addr))) + bool multicast = false; + int port; + if(_addr.ss_family == AF_INET) + { + struct sockaddr_in* addrin = reinterpret_cast<struct sockaddr_in*>(&_addr); + multicast = IN_MULTICAST(ntohl(addrin->sin_addr.s_addr)); + port = ntohs(addrin->sin_port); + } + /* + else + { + struct sockaddr_in6* addrin = reinterpret_cast<struct sockaddr_in6*>(&_addr); + multicast = IN6_IS_ADDR_MULTICAST(&addrin->sin6_addr); + port = ntohs(addrin->sin6_port); + } + */ + if(multicast) { setReuseAddress(_fd, true); - struct sockaddr_in addr; + struct sockaddr_storage addr; // // Windows does not allow binding to the mcast address itself // so we bind to INADDR_ANY (0.0.0.0) instead. // #ifdef _WIN32 - getAddress("0.0.0.0", port, addr); + getAddressForServer("", port, addr, instance->protocolSupport()); doBind(_fd, addr); #else doBind(_fd, _addr); #endif + struct sockaddr_in* maddr = reinterpret_cast<sockaddr_in*>(&addr); if(mcastInterface.length() > 0) { - getAddress(mcastInterface, port, addr); + getAddress(mcastInterface, port, addr, instance->protocolSupport()); } else { - addr.sin_addr.s_addr = INADDR_ANY; + maddr->sin_addr.s_addr = INADDR_ANY; } - setMcastGroup(_fd, _addr.sin_addr, addr.sin_addr); + setMcastGroup(_fd, reinterpret_cast<struct sockaddr_in*>(&_addr)->sin_addr, maddr->sin_addr); _mcastServer = true; } else diff --git a/cpp/src/Ice/UdpTransceiver.h b/cpp/src/Ice/UdpTransceiver.h index 6fe77182793..ebe9a2f4669 100644 --- a/cpp/src/Ice/UdpTransceiver.h +++ b/cpp/src/Ice/UdpTransceiver.h @@ -18,7 +18,7 @@ #include <IceUtil/Mutex.h> #ifndef _WIN32 -# include <netinet/in.h> // For struct sockaddr_in +# include <netinet/in.h> // For struct sockaddr_storage #endif namespace IceInternal @@ -47,7 +47,7 @@ public: private: - UdpTransceiver(const InstancePtr&, const struct sockaddr_in&, const std::string&, int); + UdpTransceiver(const InstancePtr&, const struct sockaddr_storage&, const std::string&, int); UdpTransceiver(const InstancePtr&, const std::string&, int, const std::string&, bool); virtual ~UdpTransceiver(); @@ -62,7 +62,7 @@ private: const bool _incoming; SOCKET _fd; - struct sockaddr_in _addr; + struct sockaddr_storage _addr; bool _mcastServer; #ifdef _WIN32 fd_set _rFdSet; diff --git a/cpp/src/Ice/UnknownEndpointI.cpp b/cpp/src/Ice/UnknownEndpointI.cpp index e7762649979..7611eb10b03 100644 --- a/cpp/src/Ice/UnknownEndpointI.cpp +++ b/cpp/src/Ice/UnknownEndpointI.cpp @@ -138,7 +138,6 @@ IceInternal::UnknownEndpointI::streamWrite(BasicStream* s) const string IceInternal::UnknownEndpointI::toString() const { - ostringstream s; string val = IceUtil::Base64::encode(_rawBytes); s << "opaque -t " << _type << " -v " << val; diff --git a/cpp/src/IceGrid/RegistryI.cpp b/cpp/src/IceGrid/RegistryI.cpp index 64272b1d16f..663a3173691 100644 --- a/cpp/src/IceGrid/RegistryI.cpp +++ b/cpp/src/IceGrid/RegistryI.cpp @@ -1215,10 +1215,24 @@ RegistryI::getSSLInfo(const ConnectionPtr& connection, string& userDN) try { IceSSL::ConnectionInfo info = IceSSL::getConnectionInfo(connection); - sslinfo.remotePort = ntohs(info.remoteAddr.sin_port); - sslinfo.remoteHost = IceInternal::inetAddrToString(info.remoteAddr.sin_addr); - sslinfo.localPort = ntohs(info.localAddr.sin_port); - sslinfo.localHost = IceInternal::inetAddrToString(info.localAddr.sin_addr); + if(info.remoteAddr.ss_family == AF_INET) + { + sslinfo.remotePort = ntohs(reinterpret_cast<sockaddr_in*>(&info.remoteAddr)->sin_port); + } + else + { + sslinfo.remotePort = ntohs(reinterpret_cast<sockaddr_in6*>(&info.remoteAddr)->sin6_port); + } + sslinfo.remoteHost = IceInternal::inetAddrToString(info.remoteAddr); + if(info.remoteAddr.ss_family == AF_INET) + { + sslinfo.localPort = ntohs(reinterpret_cast<sockaddr_in*>(&info.localAddr)->sin_port); + } + else + { + sslinfo.localPort = ntohs(reinterpret_cast<sockaddr_in6*>(&info.localAddr)->sin6_port); + } + sslinfo.localHost = IceInternal::inetAddrToString(info.localAddr); sslinfo.cipher = info.cipher; diff --git a/cpp/src/IceSSL/AcceptorI.cpp b/cpp/src/IceSSL/AcceptorI.cpp index 7f467fee5c0..70fa17a3759 100644 --- a/cpp/src/IceSSL/AcceptorI.cpp +++ b/cpp/src/IceSSL/AcceptorI.cpp @@ -114,7 +114,7 @@ IceSSL::AcceptorI::accept(int timeout) void IceSSL::AcceptorI::connectToSelf() { - SOCKET fd = IceInternal::createSocket(false); + SOCKET fd = IceInternal::createSocket(false, _addr.ss_family); IceInternal::setBlock(fd, false); IceInternal::doConnect(fd, _addr, -1); IceInternal::closeSocket(fd); @@ -127,9 +127,16 @@ IceSSL::AcceptorI::toString() const } int -IceSSL::AcceptorI::effectivePort() +IceSSL::AcceptorI::effectivePort() const { - return ntohs(_addr.sin_port); + if(_addr.ss_family == AF_INET) + { + return ntohs(reinterpret_cast<const sockaddr_in*>(&_addr)->sin_port); + } + else + { + return ntohs(reinterpret_cast<const sockaddr_in6*>(&_addr)->sin6_port); + } } IceSSL::AcceptorI::AcceptorI(const InstancePtr& instance, const string& adapterName, const string& host, int port) : @@ -145,9 +152,9 @@ IceSSL::AcceptorI::AcceptorI(const InstancePtr& instance, const string& adapterN try { - _fd = IceInternal::createSocket(false); + IceInternal::getAddressForServer(host, port, _addr, _instance->protocolSupport()); + _fd = IceInternal::createSocket(false, _addr.ss_family); IceInternal::setBlock(_fd, false); - IceInternal::getAddress(host, port, _addr); IceInternal::setTcpBufSize(_fd, _instance->communicator()->getProperties(), _logger); #ifndef _WIN32 // diff --git a/cpp/src/IceSSL/AcceptorI.h b/cpp/src/IceSSL/AcceptorI.h index 183ff0abf24..38d1fcf864e 100644 --- a/cpp/src/IceSSL/AcceptorI.h +++ b/cpp/src/IceSSL/AcceptorI.h @@ -13,10 +13,11 @@ #include <Ice/LoggerF.h> #include <Ice/TransceiverF.h> #include <Ice/Acceptor.h> +#include <Ice/Protocol.h> #include <IceSSL/InstanceF.h> #ifndef _WIN32 -# include <netinet/in.h> // For struct sockaddr_in +# include <netinet/in.h> // For struct sockaddr_storage #endif namespace IceSSL @@ -35,7 +36,7 @@ public: virtual void connectToSelf(); virtual std::string toString() const; - int effectivePort(); + int effectivePort() const; private: @@ -48,7 +49,7 @@ private: Ice::LoggerPtr _logger; SOCKET _fd; int _backlog; - struct sockaddr_in _addr; + struct sockaddr_storage _addr; }; } diff --git a/cpp/src/IceSSL/ConnectorI.cpp b/cpp/src/IceSSL/ConnectorI.cpp index feb4c4b4e89..31f2c176e15 100644 --- a/cpp/src/IceSSL/ConnectorI.cpp +++ b/cpp/src/IceSSL/ConnectorI.cpp @@ -40,7 +40,7 @@ IceSSL::ConnectorI::connect(int timeout) out << "trying to establish ssl connection to " << toString(); } - SOCKET fd = IceInternal::createSocket(false); + SOCKET fd = IceInternal::createSocket(false, _addr.ss_family); IceInternal::setBlock(fd, false); IceInternal::setTcpBufSize(fd, _instance->communicator()->getProperties(), _logger); bool connected = IceInternal::doConnect(fd, _addr, timeout); @@ -147,10 +147,9 @@ IceSSL::ConnectorI::operator<(const IceInternal::Connector& r) const return IceInternal::compareAddress(_addr, p->_addr) == -1; } -IceSSL::ConnectorI::ConnectorI(const InstancePtr& instance, const struct sockaddr_in& addr, Ice::Int timeout, +IceSSL::ConnectorI::ConnectorI(const InstancePtr& instance, const struct sockaddr_storage& addr, Ice::Int timeout, const string& connectionId) : _instance(instance), - _host(IceInternal::inetAddrToString(addr.sin_addr)), _logger(instance->communicator()->getLogger()), _addr(addr), _timeout(timeout), diff --git a/cpp/src/IceSSL/ConnectorI.h b/cpp/src/IceSSL/ConnectorI.h index 72f7a61fb32..4102a478c48 100644 --- a/cpp/src/IceSSL/ConnectorI.h +++ b/cpp/src/IceSSL/ConnectorI.h @@ -18,7 +18,7 @@ #ifdef _WIN32 # include <winsock2.h> #else -# include <netinet/in.h> // For struct sockaddr_in +# include <netinet/in.h> // For struct sockaddr_storage #endif namespace IceSSL @@ -41,14 +41,13 @@ public: private: - ConnectorI(const InstancePtr&, const struct sockaddr_in&, Ice::Int, const std::string&); + ConnectorI(const InstancePtr&, const struct sockaddr_storage&, Ice::Int, const std::string&); virtual ~ConnectorI(); friend class EndpointI; const InstancePtr _instance; - const std::string _host; const Ice::LoggerPtr _logger; - struct sockaddr_in _addr; + struct sockaddr_storage _addr; const Ice::Int _timeout; const std::string _connectionId; SOCKET _fd; diff --git a/cpp/src/IceSSL/EndpointI.cpp b/cpp/src/IceSSL/EndpointI.cpp index fd9edd4f42d..31edfbe0995 100644 --- a/cpp/src/IceSSL/EndpointI.cpp +++ b/cpp/src/IceSSL/EndpointI.cpp @@ -32,7 +32,7 @@ IceSSL::EndpointI::EndpointI(const InstancePtr& instance, const string& ho, Int { } -IceSSL::EndpointI::EndpointI(const InstancePtr& instance, const string& str, bool server) : +IceSSL::EndpointI::EndpointI(const InstancePtr& instance, const string& str, bool oaEndpoint) : _instance(instance), _port(0), _timeout(-1), @@ -76,6 +76,10 @@ IceSSL::EndpointI::EndpointI(const InstancePtr& instance, const string& str, boo end = str.length(); } argument = str.substr(beg, end - beg); + if(argument[0] == '\"' && argument[argument.size() - 1] == '\"') + { + argument = argument.substr(1, argument.size() - 2); + } } switch(option[1]) @@ -140,21 +144,19 @@ IceSSL::EndpointI::EndpointI(const InstancePtr& instance, const string& str, boo if(_host.empty()) { const_cast<string&>(_host) = _instance->defaultHost(); - if(_host.empty()) - { - if(server) - { - const_cast<string&>(_host) = "0.0.0.0"; - } - else - { - const_cast<string&>(_host) = "127.0.0.1"; - } - } } else if(_host == "*") { - const_cast<string&>(_host) = "0.0.0.0"; + if(oaEndpoint) + { + const_cast<string&>(_host) = string(); + } + else + { + EndpointParseException ex(__FILE__, __LINE__); + ex.str = "ssl " + str; + throw ex; + } } } @@ -195,7 +197,24 @@ IceSSL::EndpointI::toString() const // format of proxyToString() before changing this and related code. // ostringstream s; - s << "ssl -h " << _host << " -p " << _port; + s << "ssl"; + + if(!_host.empty()) + { + s << " -h "; + bool addQuote = _host.find(':') != string::npos; + if(addQuote) + { + s << "\""; + } + s << _host; + if(addQuote) + { + s << "\""; + } + } + + s << " -p " << _port; if(_timeout != -1) { s << " -t " << _timeout; @@ -292,7 +311,7 @@ IceSSL::EndpointI::transceiver(IceInternal::EndpointIPtr& endp) const vector<IceInternal::ConnectorPtr> IceSSL::EndpointI::connectors() const { - return connectors(IceInternal::getAddresses(_host, _port)); + return connectors(IceInternal::getAddresses(_host, _port, _instance->protocolSupport(), true)); } void @@ -313,20 +332,17 @@ vector<IceInternal::EndpointIPtr> IceSSL::EndpointI::expand() const { vector<IceInternal::EndpointIPtr> endps; - if(_host == "0.0.0.0") + vector<string> hosts = IceInternal::getHostsForEndpointExpand(_host, _instance->protocolSupport()); + if(hosts.empty()) { - vector<string> hosts = IceInternal::getLocalHosts(); - for(unsigned int i = 0; i < hosts.size(); ++i) - { - if(hosts.size() == 1 || hosts[i] != "127.0.0.1") - { - endps.push_back(new EndpointI(_instance, hosts[i], _port, _timeout, _connectionId, _compress)); - } - } + endps.push_back(const_cast<EndpointI*>(this)); } else { - endps.push_back(const_cast<EndpointI*>(this)); + for(vector<string>::const_iterator p = hosts.begin(); p != hosts.end(); ++p) + { + endps.push_back(new EndpointI(_instance, *p, _port, _timeout, _connectionId, _compress)); + } } return endps; } @@ -453,7 +469,7 @@ IceSSL::EndpointI::operator<(const IceInternal::EndpointI& r) const } vector<IceInternal::ConnectorPtr> -IceSSL::EndpointI::connectors(const vector<struct sockaddr_in>& addresses) const +IceSSL::EndpointI::connectors(const vector<struct sockaddr_storage>& addresses) const { vector<IceInternal::ConnectorPtr> connectors; for(unsigned int i = 0; i < addresses.size(); ++i) @@ -485,9 +501,9 @@ IceSSL::EndpointFactoryI::protocol() const } IceInternal::EndpointIPtr -IceSSL::EndpointFactoryI::create(const string& str, bool server) const +IceSSL::EndpointFactoryI::create(const string& str, bool oaEndpoint) const { - return new EndpointI(_instance, str, server); + return new EndpointI(_instance, str, oaEndpoint); } IceInternal::EndpointIPtr diff --git a/cpp/src/IceSSL/EndpointI.h b/cpp/src/IceSSL/EndpointI.h index 99e748e7782..1fbf9d6ace2 100644 --- a/cpp/src/IceSSL/EndpointI.h +++ b/cpp/src/IceSSL/EndpointI.h @@ -51,7 +51,7 @@ public: private: - virtual std::vector<IceInternal::ConnectorPtr> connectors(const std::vector<struct sockaddr_in>&) const; + virtual std::vector<IceInternal::ConnectorPtr> connectors(const std::vector<struct sockaddr_storage>&) const; #if defined(__SUNPRO_CC) // diff --git a/cpp/src/IceSSL/Instance.cpp b/cpp/src/IceSSL/Instance.cpp index a0933c5420d..15176f9131d 100644 --- a/cpp/src/IceSSL/Instance.cpp +++ b/cpp/src/IceSSL/Instance.cpp @@ -538,6 +538,12 @@ IceSSL::Instance::endpointHostResolver() const return _facade->getEndpointHostResolver(); } +IceInternal::ProtocolSupport +IceSSL::Instance::protocolSupport() const +{ + return _facade->getProtocolSupport(); +} + string IceSSL::Instance::defaultHost() const { diff --git a/cpp/src/IceSSL/Instance.h b/cpp/src/IceSSL/Instance.h index 9f3d69284ff..fcfb6fcef14 100644 --- a/cpp/src/IceSSL/Instance.h +++ b/cpp/src/IceSSL/Instance.h @@ -36,6 +36,7 @@ public: Ice::CommunicatorPtr communicator() const; IceInternal::EndpointHostResolverPtr endpointHostResolver() const; + IceInternal::ProtocolSupport protocolSupport() const; std::string defaultHost() const; int networkTraceLevel() const; std::string networkTraceCategory() const; diff --git a/cpp/src/IceSSL/TransceiverI.cpp b/cpp/src/IceSSL/TransceiverI.cpp index d930c3d8cff..9b4fdb7f726 100644 --- a/cpp/src/IceSSL/TransceiverI.cpp +++ b/cpp/src/IceSSL/TransceiverI.cpp @@ -532,7 +532,7 @@ IceSSL::TransceiverI::initialize(int timeout) } case SSL_ERROR_SSL: { - struct sockaddr_in remoteAddr; + struct sockaddr_storage remoteAddr; string desc; if(IceInternal::fdToRemoteAddress(_fd, remoteAddr)) { |