diff options
author | Bernard Normier <bernard@zeroc.com> | 2007-12-21 15:25:37 -0500 |
---|---|---|
committer | Bernard Normier <bernard@zeroc.com> | 2007-12-21 15:25:37 -0500 |
commit | e099cd4fd77c718f9c241ad609f5aa7a80627ba8 (patch) | |
tree | 998305e426f74429b00122dcdc4f839e2f97ade5 /cpp/src | |
parent | IceUtil cleanup (first commit) (diff) | |
parent | Fix bug 2520: Test suite unsets ICE_CONFIG to avoid configuration conflicts (diff) | |
download | ice-e099cd4fd77c718f9c241ad609f5aa7a80627ba8.tar.bz2 ice-e099cd4fd77c718f9c241ad609f5aa7a80627ba8.tar.xz ice-e099cd4fd77c718f9c241ad609f5aa7a80627ba8.zip |
Merge branch 'master' of ssh://cvs.zeroc.com/home/git/ice
Conflicts:
cpp/src/Slice/VbUtil.cpp
Diffstat (limited to 'cpp/src')
56 files changed, 2083 insertions, 1878 deletions
diff --git a/cpp/src/FreezeScript/Scanner.l b/cpp/src/FreezeScript/Scanner.l index 8fa7a97c01f..b480edac7ae 100644 --- a/cpp/src/FreezeScript/Scanner.l +++ b/cpp/src/FreezeScript/Scanner.l @@ -124,7 +124,7 @@ floating_literal (({fractional_constant}{exponent_part}?)|((\+|-)?[[:digit:]]+{e {integer_constant} { IntegerTokPtr itp = new IntegerTok; *yylvalp = itp; - if(!IceUtil::stringToInt64(string(yytext), itp->v)) + if(!IceUtilInternal::stringToInt64(string(yytext), itp->v)) { assert(itp->v != 0); string msg = "integer constant `"; 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 c28bfac02f1..1e84d1f4957 100644 --- a/cpp/src/Ice/Application.cpp +++ b/cpp/src/Ice/Application.cpp @@ -652,7 +652,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/Base64.cpp b/cpp/src/Ice/Base64.cpp new file mode 100644 index 00000000000..9f241146534 --- /dev/null +++ b/cpp/src/Ice/Base64.cpp @@ -0,0 +1,271 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Ice/Base64.h> +#ifdef __BCPLUSPLUS__ +# include <iterator> +#endif + +using namespace std; + +string +IceInternal::Base64::encode(const vector<unsigned char>& plainSeq) +{ + string retval; + + if(plainSeq.size() == 0) + { + return retval; + } + + // Reserve enough space for the returned base64 string + size_t base64Bytes = (((plainSeq.size() * 4) / 3) + 1); + size_t newlineBytes = (((base64Bytes * 2) / 76) + 1); + size_t totalBytes = base64Bytes + newlineBytes; + + retval.reserve(totalBytes); + + unsigned char by1 = 0; + unsigned char by2 = 0; + unsigned char by3 = 0; + unsigned char by4 = 0; + unsigned char by5 = 0; + unsigned char by6 = 0; + unsigned char by7 = 0; + + for(size_t i = 0; i < plainSeq.size(); i += 3) + { + by1 = plainSeq[i]; + by2 = 0; + by3 = 0; + + if((i + 1) < plainSeq.size()) + { + by2 = plainSeq[i+1]; + } + + if((i + 2) < plainSeq.size()) + { + by3 = plainSeq[i+2]; + } + + by4 = by1 >> 2; + by5 = ((by1 & 0x3) << 4) | (by2 >> 4); + by6 = ((by2 & 0xf) << 2) | (by3 >> 6); + by7 = by3 & 0x3f; + + retval += encode(by4); + retval += encode(by5); + + if((i + 1) < plainSeq.size()) + { + retval += encode(by6); + } + else + { + retval += "="; + } + + if((i + 2) < plainSeq.size()) + { + retval += encode(by7); + } + else + { + retval += "="; + } + } + + string outString; + outString.reserve(totalBytes); + string::iterator iter = retval.begin(); + + while((retval.end() - iter) > 76) + { + copy(iter, iter+76, back_inserter(outString)); + outString += "\r\n"; + iter += 76; + } + + copy(iter, retval.end(), back_inserter(outString)); + + return outString; +} + +vector<unsigned char> +IceInternal::Base64::decode(const string& str) +{ + string newStr; + + newStr.reserve(str.length()); + + for(size_t j = 0; j < str.length(); j++) + { + if(isBase64(str[j])) + { + newStr += str[j]; + } + } + + vector<unsigned char> retval; + + if(newStr.length() == 0) + { + return retval; + } + + // Note: This is how we were previously computing the size of the return + // sequence. The method below is more efficient (and correct). + // size_t lines = str.size() / 78; + // size_t totalBytes = (lines * 76) + (((str.size() - (lines * 78)) * 3) / 4); + + // Figure out how long the final sequence is going to be. + size_t totalBytes = (newStr.size() * 3 / 4) + 1; + + retval.reserve(totalBytes); + + unsigned char by1 = 0; + unsigned char by2 = 0; + unsigned char by3 = 0; + unsigned char by4 = 0; + + char c1, c2, c3, c4; + + for(size_t i = 0; i < newStr.length(); i += 4) + { + c1 = 'A'; + c2 = 'A'; + c3 = 'A'; + c4 = 'A'; + + c1 = newStr[i]; + + if((i + 1) < newStr.length()) + { + c2 = newStr[i + 1]; + } + + if((i + 2) < newStr.length()) + { + c3 = newStr[i + 2]; + } + + if((i + 3) < newStr.length()) + { + c4 = newStr[i + 3]; + } + + by1 = decode(c1); + by2 = decode(c2); + by3 = decode(c3); + by4 = decode(c4); + + retval.push_back((by1 << 2) | (by2 >> 4)); + + if(c3 != '=') + { + retval.push_back(((by2 & 0xf) << 4) | (by3 >> 2)); + } + + if(c4 != '=') + { + retval.push_back(((by3 & 0x3) << 6) | by4); + } + } + + return retval; +} + +bool +IceInternal::Base64::isBase64(char c) +{ + if(c >= 'A' && c <= 'Z') + { + return true; + } + + if(c >= 'a' && c <= 'z') + { + return true; + } + + if(c >= '0' && c <= '9') + { + return true; + } + + if(c == '+') + { + return true; + } + + if(c == '/') + { + return true; + } + + if(c == '=') + { + return true; + } + + return false; +} + +char +IceInternal::Base64::encode(unsigned char uc) +{ + if(uc < 26) + { + return 'A' + uc; + } + + if(uc < 52) + { + return 'a' + (uc - 26); + } + + if(uc < 62) + { + return '0' + (uc - 52); + } + + if(uc == 62) + { + return '+'; + } + + return '/'; +} + +unsigned char +IceInternal::Base64::decode(char c) +{ + if(c >= 'A' && c <= 'Z') + { + return c - 'A'; + } + + if(c >= 'a' && c <= 'z') + { + return c - 'a' + 26; + } + + if(c >= '0' && c <= '9') + { + return c - '0' + 52; + } + + if(c == '+') + { + return 62; + } + + return 63; +} diff --git a/cpp/src/Ice/Base64.h b/cpp/src/Ice/Base64.h new file mode 100644 index 00000000000..fece85491bb --- /dev/null +++ b/cpp/src/Ice/Base64.h @@ -0,0 +1,36 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef ICE_BASE_64_H +#define ICE_BASE_64_H + +#include <Ice/Config.h> +#include <string> +#include <vector> + +namespace IceInternal +{ + +class Base64 +{ +public: + + static std::string encode(const std::vector<unsigned char>&); + static std::vector<unsigned char> decode(const std::string&); + static bool isBase64(char); + +private: + + static char encode(unsigned char); + static unsigned char decode(char); +}; + +} + +#endif diff --git a/cpp/src/Ice/ConnectionFactory.cpp b/cpp/src/Ice/ConnectionFactory.cpp index 94079e88077..39e5a178dd0 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 38984229732..5fedbabce4c 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/Makefile.mak b/cpp/src/Ice/Makefile.mak index 6b4d6ee0318..5beb39cb0a3 100644 --- a/cpp/src/Ice/Makefile.mak +++ b/cpp/src/Ice/Makefile.mak @@ -16,6 +16,7 @@ TARGETS = $(LIBNAME) $(DLLNAME) OBJS = Acceptor.obj \ Application.obj \ + Base64.obj \ Buffer.obj \ BasicStream.obj \ BuiltinSequences.obj \ 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 1ec79aa047e..0220d90d54c 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 9262a39e672..8a9682b27e1 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 = 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)) { diff --git a/cpp/src/Slice/Grammar.y b/cpp/src/Slice/Grammar.y index 0e8b7274525..3b38486d84c 100644 --- a/cpp/src/Slice/Grammar.y +++ b/cpp/src/Slice/Grammar.y @@ -1588,9 +1588,12 @@ const_initializer IntegerTokPtr intVal = IntegerTokPtr::dynamicCast($1); ostringstream sstr; sstr << intVal->v; - SyntaxTreeBaseStringTokPtr basestring = new SyntaxTreeBaseStringTok; - basestring->v = pair<SyntaxTreeBasePtr,string>(type, sstr.str()); - $$ = basestring; + ConstDefTokPtr def = new ConstDefTok; + def->v.type = type; + def->v.value = type; + def->v.valueAsString = sstr.str(); + def->v.valueAsLiteral = intVal->literal; + $$ = def; } | ICE_FLOATING_POINT_LITERAL { @@ -1598,18 +1601,24 @@ const_initializer FloatingTokPtr floatVal = FloatingTokPtr::dynamicCast($1); ostringstream sstr; sstr << floatVal->v; - SyntaxTreeBaseStringTokPtr basestring = new SyntaxTreeBaseStringTok; - basestring->v = pair<SyntaxTreeBasePtr,string>(type, sstr.str()); - $$ = basestring; + ConstDefTokPtr def = new ConstDefTok; + def->v.type = type; + def->v.value = type; + def->v.valueAsString = sstr.str(); + def->v.valueAsLiteral = floatVal->literal; + $$ = def; } | scoped_name { StringTokPtr scoped = StringTokPtr::dynamicCast($1); - SyntaxTreeBaseStringTokPtr basestring = new SyntaxTreeBaseStringTok; + ConstDefTokPtr def = new ConstDefTok; ContainedList cl = unit->currentContainer()->lookupContained(scoped->v); if(cl.empty()) { - basestring->v = pair<SyntaxTreeBasePtr,string>(TypePtr(0), scoped->v); + def->v.type = TypePtr(0); + def->v.value = TypePtr(0); + def->v.valueAsString = scoped->v; + def->v.valueAsLiteral = scoped->v; } else { @@ -1627,33 +1636,45 @@ const_initializer unit->error(msg); // $$ is dummy } unit->currentContainer()->checkIntroduced(scoped->v, enumerator); - basestring->v = pair<SyntaxTreeBasePtr,string>(enumerator, scoped->v); + def->v.type = enumerator->type(); + def->v.value = enumerator; + def->v.valueAsString = scoped->v; + def->v.valueAsLiteral = scoped->v; } - $$ = basestring; + $$ = def; } | ICE_STRING_LITERAL { BuiltinPtr type = unit->builtin(Builtin::KindString); StringTokPtr literal = StringTokPtr::dynamicCast($1); - SyntaxTreeBaseStringTokPtr basestring = new SyntaxTreeBaseStringTok; - basestring->v = pair<SyntaxTreeBasePtr,string>(type, literal->v); - $$ = basestring; + ConstDefTokPtr def = new ConstDefTok; + def->v.type = type; + def->v.value = type; + def->v.valueAsString = literal->v; + def->v.valueAsLiteral = literal->literal; + $$ = def; } | ICE_FALSE { BuiltinPtr type = unit->builtin(Builtin::KindBool); StringTokPtr literal = StringTokPtr::dynamicCast($1); - SyntaxTreeBaseStringTokPtr basestring = new SyntaxTreeBaseStringTok; - basestring->v = pair<SyntaxTreeBasePtr,string>(type, literal->v); - $$ = basestring; + ConstDefTokPtr def = new ConstDefTok; + def->v.type = type; + def->v.value = type; + def->v.valueAsString = literal->v; + def->v.valueAsLiteral = "false"; + $$ = def; } | ICE_TRUE { BuiltinPtr type = unit->builtin(Builtin::KindBool); StringTokPtr literal = StringTokPtr::dynamicCast($1); - SyntaxTreeBaseStringTokPtr basestring = new SyntaxTreeBaseStringTok; - basestring->v = pair<SyntaxTreeBasePtr,string>(type, literal->v); - $$ = basestring; + ConstDefTokPtr def = new ConstDefTok; + def->v.type = type; + def->v.value = type; + def->v.valueAsString = literal->v; + def->v.valueAsLiteral = "true"; + $$ = def; } ; @@ -1665,17 +1686,19 @@ const_def StringListTokPtr metaData = StringListTokPtr::dynamicCast($2); TypePtr const_type = TypePtr::dynamicCast($3); StringTokPtr ident = StringTokPtr::dynamicCast($4); - SyntaxTreeBaseStringTokPtr value = SyntaxTreeBaseStringTokPtr::dynamicCast($6); - $$ = unit->currentContainer()->createConst(ident->v, const_type, metaData->v, value->v.first, value->v.second); + ConstDefTokPtr value = ConstDefTokPtr::dynamicCast($6); + $$ = unit->currentContainer()->createConst(ident->v, const_type, metaData->v, + value->v.value, value->v.valueAsString, value->v.valueAsLiteral); } | ICE_CONST meta_data type '=' const_initializer { StringListTokPtr metaData = StringListTokPtr::dynamicCast($2); TypePtr const_type = TypePtr::dynamicCast($3); - SyntaxTreeBaseStringTokPtr value = SyntaxTreeBaseStringTokPtr::dynamicCast($5); + ConstDefTokPtr value = ConstDefTokPtr::dynamicCast($5); unit->error("missing constant name"); - $$ = unit->currentContainer()->createConst(IceUtil::generateUUID(), const_type, metaData->v, value->v.first, - value->v.second, Dummy); // Dummy + $$ = unit->currentContainer()->createConst(IceUtil::generateUUID(), const_type, metaData->v, + value->v.value, value->v.valueAsString, + value->v.valueAsLiteral, Dummy); // Dummy } ; diff --git a/cpp/src/Slice/GrammarUtil.h b/cpp/src/Slice/GrammarUtil.h index d8c6c9d3de6..8acd6e65667 100644 --- a/cpp/src/Slice/GrammarUtil.h +++ b/cpp/src/Slice/GrammarUtil.h @@ -25,7 +25,7 @@ class FloatingTok; class ExceptionListTok; class ClassListTok; class EnumeratorListTok; -class SyntaxTreeBaseStringTok; +class ConstDefTok; typedef ::IceUtil::Handle<StringTok> StringTokPtr; typedef ::IceUtil::Handle<StringListTok> StringListTokPtr; @@ -37,7 +37,7 @@ typedef ::IceUtil::Handle<FloatingTok> FloatingTokPtr; typedef ::IceUtil::Handle<ExceptionListTok> ExceptionListTokPtr; typedef ::IceUtil::Handle<ClassListTok> ClassListTokPtr; typedef ::IceUtil::Handle<EnumeratorListTok> EnumeratorListTokPtr; -typedef ::IceUtil::Handle<SyntaxTreeBaseStringTok> SyntaxTreeBaseStringTokPtr; +typedef ::IceUtil::Handle<ConstDefTok> ConstDefTokPtr; // ---------------------------------------------------------------------- // StringTok @@ -49,6 +49,7 @@ public: StringTok() { } std::string v; + std::string literal; }; // ---------------------------------------------------------------------- @@ -97,6 +98,7 @@ public: IntegerTok() { } IceUtil::Int64 v; + std::string literal; }; // ---------------------------------------------------------------------- @@ -109,6 +111,7 @@ public: FloatingTok() { } double v; + std::string literal; }; // ---------------------------------------------------------------------- @@ -160,15 +163,15 @@ public: }; // ---------------------------------------------------------------------- -// SyntaxTreeBaseStringTok +// ConstDefTok // ---------------------------------------------------------------------- -class SLICE_API SyntaxTreeBaseStringTok : public GrammarBase +class SLICE_API ConstDefTok : public GrammarBase { public: - SyntaxTreeBaseStringTok() { } - SyntaxTreeBaseString v; + ConstDefTok() { } + ConstDef v; }; } diff --git a/cpp/src/Slice/MD5.cpp b/cpp/src/Slice/MD5.cpp new file mode 100644 index 00000000000..0583b6ddc32 --- /dev/null +++ b/cpp/src/Slice/MD5.cpp @@ -0,0 +1,56 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Slice/MD5.h> +#include <Slice/MD5I.h> + +using namespace std; + +// +// This class is a C++ wrapper around the C implementation contained in +// MD5I.cpp, obtained from http://sourceforge.net/projects/libmd5-rfc/. +// + +Slice::MD5::MD5() +{ + _state = new md5_state_s; + md5_init(_state); +} + +Slice::MD5::MD5(const unsigned char* data, int n) +{ + _state = new md5_state_s; + md5_init(_state); + update(data, n); + finish(); +} + +Slice::MD5::~MD5() +{ + delete _state; +} + +void +Slice::MD5::update(const unsigned char* data, int n) +{ + md5_append(_state, data, n); +} + +void +Slice::MD5::finish() +{ + md5_finish(_state, _digest); + md5_init(_state); +} + +void +Slice::MD5::getDigest(unsigned char* digest) const +{ + memcpy(digest, _digest, sizeof(unsigned char) * 16); +} diff --git a/cpp/src/Slice/MD5.h b/cpp/src/Slice/MD5.h new file mode 100644 index 00000000000..ae42456f692 --- /dev/null +++ b/cpp/src/Slice/MD5.h @@ -0,0 +1,44 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef SLICE_MD5_H +#define SLICE_MD5_H + +#include <IceUtil/Config.h> + +extern "C" +{ +struct md5_state_s; +} + +namespace Slice +{ + +class MD5 +{ +public: + + MD5(); + MD5(const unsigned char*, int); + ~MD5(); + + void update(const unsigned char*, int); + void finish(); + + void getDigest(unsigned char*) const; + +private: + + md5_state_s* _state; + unsigned char _digest[16]; +}; + +} + +#endif diff --git a/cpp/src/Slice/MD5I.cpp b/cpp/src/Slice/MD5I.cpp new file mode 100644 index 00000000000..175401d7006 --- /dev/null +++ b/cpp/src/Slice/MD5I.cpp @@ -0,0 +1,381 @@ +/* + Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/* $Id$ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321, whose + text is available at + http://www.ietf.org/rfc/rfc1321.txt + The code is derived from the text of the RFC, including the test suite + (section A.5) but excluding the rest of Appendix A. It does not include + any code or documentation that is identified in the RFC as being + copyrighted. + + The original and principal author of md5.c is L. Peter Deutsch + <ghost@aladdin.com>. Other authors are noted in the change history + that follows (in reverse chronological order): + + 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order + either statically or dynamically; added missing #include <string.h> + in library. + 2002-03-11 lpd Corrected argument list for main(), and added int return + type, in test program and T value program. + 2002-02-21 lpd Added missing #include <stdio.h> in test program. + 2000-07-03 lpd Patched to eliminate warnings about "constant is + unsigned in ANSI C, signed in traditional"; made test program + self-checking. + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). + 1999-05-03 lpd Original version. + */ + +#include <Slice/MD5I.h> +#include <string.h> + +#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ +#ifdef ARCH_IS_BIG_ENDIAN +# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) +#else +# define BYTE_ORDER 0 +#endif + +#define T_MASK ((md5_word_t)~0) +#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) +#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) +#define T3 0x242070db +#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) +#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) +#define T6 0x4787c62a +#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) +#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) +#define T9 0x698098d8 +#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) +#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) +#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) +#define T13 0x6b901122 +#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) +#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) +#define T16 0x49b40821 +#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) +#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) +#define T19 0x265e5a51 +#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) +#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) +#define T22 0x02441453 +#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) +#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) +#define T25 0x21e1cde6 +#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) +#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) +#define T28 0x455a14ed +#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) +#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) +#define T31 0x676f02d9 +#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) +#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) +#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) +#define T35 0x6d9d6122 +#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) +#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) +#define T38 0x4bdecfa9 +#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) +#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) +#define T41 0x289b7ec6 +#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) +#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) +#define T44 0x04881d05 +#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) +#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) +#define T47 0x1fa27cf8 +#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) +#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) +#define T50 0x432aff97 +#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) +#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) +#define T53 0x655b59c3 +#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) +#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) +#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) +#define T57 0x6fa87e4f +#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) +#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) +#define T60 0x4e0811a1 +#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) +#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) +#define T63 0x2ad7d2bb +#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) + + +static void +md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) +{ + md5_word_t + a = pms->abcd[0], b = pms->abcd[1], + c = pms->abcd[2], d = pms->abcd[3]; + md5_word_t t; +#if BYTE_ORDER > 0 + /* Define storage only for big-endian CPUs. */ + md5_word_t X[16]; +#else + /* Define storage for little-endian or both types of CPUs. */ + md5_word_t xbuf[16]; + const md5_word_t *X; +#endif + + { +#if BYTE_ORDER == 0 + /* + * Determine dynamically whether this is a big-endian or + * little-endian machine, since we can use a more efficient + * algorithm on the latter. + */ + static const int w = 1; + + if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ +#endif +#if BYTE_ORDER <= 0 /* little-endian */ + { + /* + * On little-endian machines, we can process properly aligned + * data without copying it. + */ + if (!((data - (const md5_byte_t *)0) & 3)) { + /* data are properly aligned */ + X = (const md5_word_t *)data; + } else { + /* not aligned */ + memcpy(xbuf, data, 64); + X = xbuf; + } + } +#endif +#if BYTE_ORDER == 0 + else /* dynamic big-endian */ +#endif +#if BYTE_ORDER >= 0 /* big-endian */ + { + /* + * On big-endian machines, we must arrange the bytes in the + * right order. + */ + const md5_byte_t *xp = data; + int i; + +# if BYTE_ORDER == 0 + X = xbuf; /* (dynamic only) */ +# else +# define xbuf X /* (static only) */ +# endif + for (i = 0; i < 16; ++i, xp += 4) + xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); + } +#endif + } + +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + + /* Round 1. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ +#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + F(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 7, T1); + SET(d, a, b, c, 1, 12, T2); + SET(c, d, a, b, 2, 17, T3); + SET(b, c, d, a, 3, 22, T4); + SET(a, b, c, d, 4, 7, T5); + SET(d, a, b, c, 5, 12, T6); + SET(c, d, a, b, 6, 17, T7); + SET(b, c, d, a, 7, 22, T8); + SET(a, b, c, d, 8, 7, T9); + SET(d, a, b, c, 9, 12, T10); + SET(c, d, a, b, 10, 17, T11); + SET(b, c, d, a, 11, 22, T12); + SET(a, b, c, d, 12, 7, T13); + SET(d, a, b, c, 13, 12, T14); + SET(c, d, a, b, 14, 17, T15); + SET(b, c, d, a, 15, 22, T16); +#undef SET + + /* Round 2. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ +#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + G(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 1, 5, T17); + SET(d, a, b, c, 6, 9, T18); + SET(c, d, a, b, 11, 14, T19); + SET(b, c, d, a, 0, 20, T20); + SET(a, b, c, d, 5, 5, T21); + SET(d, a, b, c, 10, 9, T22); + SET(c, d, a, b, 15, 14, T23); + SET(b, c, d, a, 4, 20, T24); + SET(a, b, c, d, 9, 5, T25); + SET(d, a, b, c, 14, 9, T26); + SET(c, d, a, b, 3, 14, T27); + SET(b, c, d, a, 8, 20, T28); + SET(a, b, c, d, 13, 5, T29); + SET(d, a, b, c, 2, 9, T30); + SET(c, d, a, b, 7, 14, T31); + SET(b, c, d, a, 12, 20, T32); +#undef SET + + /* Round 3. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + H(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 5, 4, T33); + SET(d, a, b, c, 8, 11, T34); + SET(c, d, a, b, 11, 16, T35); + SET(b, c, d, a, 14, 23, T36); + SET(a, b, c, d, 1, 4, T37); + SET(d, a, b, c, 4, 11, T38); + SET(c, d, a, b, 7, 16, T39); + SET(b, c, d, a, 10, 23, T40); + SET(a, b, c, d, 13, 4, T41); + SET(d, a, b, c, 0, 11, T42); + SET(c, d, a, b, 3, 16, T43); + SET(b, c, d, a, 6, 23, T44); + SET(a, b, c, d, 9, 4, T45); + SET(d, a, b, c, 12, 11, T46); + SET(c, d, a, b, 15, 16, T47); + SET(b, c, d, a, 2, 23, T48); +#undef SET + + /* Round 4. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ +#define I(x, y, z) ((y) ^ ((x) | ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + I(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 6, T49); + SET(d, a, b, c, 7, 10, T50); + SET(c, d, a, b, 14, 15, T51); + SET(b, c, d, a, 5, 21, T52); + SET(a, b, c, d, 12, 6, T53); + SET(d, a, b, c, 3, 10, T54); + SET(c, d, a, b, 10, 15, T55); + SET(b, c, d, a, 1, 21, T56); + SET(a, b, c, d, 8, 6, T57); + SET(d, a, b, c, 15, 10, T58); + SET(c, d, a, b, 6, 15, T59); + SET(b, c, d, a, 13, 21, T60); + SET(a, b, c, d, 4, 6, T61); + SET(d, a, b, c, 11, 10, T62); + SET(c, d, a, b, 2, 15, T63); + SET(b, c, d, a, 9, 21, T64); +#undef SET + + /* Then perform the following additions. (That is increment each + of the four registers by the value it had before this block + was started.) */ + pms->abcd[0] += a; + pms->abcd[1] += b; + pms->abcd[2] += c; + pms->abcd[3] += d; +} + +void +md5_init(md5_state_t *pms) +{ + pms->count[0] = pms->count[1] = 0; + pms->abcd[0] = 0x67452301; + pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; + pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; + pms->abcd[3] = 0x10325476; +} + +void +md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) +{ + const md5_byte_t *p = data; + int left = nbytes; + int offset = (pms->count[0] >> 3) & 63; + md5_word_t nbits = (md5_word_t)(nbytes << 3); + + if (nbytes <= 0) + return; + + /* Update the message length. */ + pms->count[1] += nbytes >> 29; + pms->count[0] += nbits; + if (pms->count[0] < nbits) + pms->count[1]++; + + /* Process an initial partial block. */ + if (offset) { + int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); + + memcpy(pms->buf + offset, p, copy); + if (offset + copy < 64) + return; + p += copy; + left -= copy; + md5_process(pms, pms->buf); + } + + /* Process full blocks. */ + for (; left >= 64; p += 64, left -= 64) + md5_process(pms, p); + + /* Process a final partial block. */ + if (left) + memcpy(pms->buf, p, left); +} + +void +md5_finish(md5_state_t *pms, md5_byte_t digest[16]) +{ + static const md5_byte_t pad[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + md5_byte_t data[8]; + int i; + + /* Save the length before padding. */ + for (i = 0; i < 8; ++i) + data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); + /* Pad to 56 bytes mod 64. */ + md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); + /* Append the length. */ + md5_append(pms, data, 8); + for (i = 0; i < 16; ++i) + digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); +} diff --git a/cpp/src/Slice/MD5I.h b/cpp/src/Slice/MD5I.h new file mode 100644 index 00000000000..66588283e83 --- /dev/null +++ b/cpp/src/Slice/MD5I.h @@ -0,0 +1,91 @@ +/* + Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/* $Id$ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321, whose + text is available at + http://www.ietf.org/rfc/rfc1321.txt + The code is derived from the text of the RFC, including the test suite + (section A.5) but excluding the rest of Appendix A. It does not include + any code or documentation that is identified in the RFC as being + copyrighted. + + The original and principal author of md5.h is L. Peter Deutsch + <ghost@aladdin.com>. Other authors are noted in the change history + that follows (in reverse chronological order): + + 2002-04-13 lpd Removed support for non-ANSI compilers; removed + references to Ghostscript; clarified derivation from RFC 1321; + now handles byte order either statically or dynamically. + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); + added conditionalization for C++ compilation from Martin + Purschke <purschke@bnl.gov>. + 1999-05-03 lpd Original version. + */ + +#ifndef md5_INCLUDED +# define md5_INCLUDED + +/* + * This package supports both compile-time and run-time determination of CPU + * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be + * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is + * defined as non-zero, the code will be compiled to run only on big-endian + * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to + * run on either big- or little-endian CPUs, but will run slightly less + * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. + */ + +typedef unsigned char md5_byte_t; /* 8-bit byte */ +typedef unsigned int md5_word_t; /* 32-bit word */ + +/* Define the state of the MD5 Algorithm. */ +typedef struct md5_state_s { + md5_word_t count[2]; /* message length in bits, lsw first */ + md5_word_t abcd[4]; /* digest buffer */ + md5_byte_t buf[64]; /* accumulate block */ +} md5_state_t; + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Initialize the algorithm. */ +void md5_init(md5_state_t *pms); + +/* Append a string to the message. */ +void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); + +/* Finish the message and return the digest. */ +void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* md5_INCLUDED */ diff --git a/cpp/src/Slice/Makefile b/cpp/src/Slice/Makefile index d962c852749..db10d93cd5a 100644 --- a/cpp/src/Slice/Makefile +++ b/cpp/src/Slice/Makefile @@ -20,7 +20,6 @@ OBJS = Scanner.o \ Parser.o \ CPlusPlusUtil.o \ CsUtil.o \ - VbUtil.o \ JavaUtil.o \ Preprocessor.o \ Checksum.o \ diff --git a/cpp/src/Slice/Makefile.mak b/cpp/src/Slice/Makefile.mak index 044d12b178c..6b1d7d0d6f7 100644 --- a/cpp/src/Slice/Makefile.mak +++ b/cpp/src/Slice/Makefile.mak @@ -19,13 +19,14 @@ OBJS = Scanner.obj \ Parser.obj \ CPlusPlusUtil.obj \ CsUtil.obj \ - VbUtil.obj \ JavaUtil.obj \ Preprocessor.obj \ Checksum.obj \ PythonUtil.obj \ DotNetNames.obj \ - RubyUtil.obj + RubyUtil.obj \ + MD5.obj \ + MD5I.obj SRCS = $(OBJS:.obj=.cpp) diff --git a/cpp/src/Slice/Parser.cpp b/cpp/src/Slice/Parser.cpp index cdc74772be9..7f79e2bf54c 100644 --- a/cpp/src/Slice/Parser.cpp +++ b/cpp/src/Slice/Parser.cpp @@ -1023,7 +1023,8 @@ Slice::Container::createEnumerator(const string& name) ConstPtr Slice::Container::createConst(const string name, const TypePtr& constType, const StringList& metaData, - const SyntaxTreeBasePtr& literalType, const string& value, NodeType nt) + const SyntaxTreeBasePtr& literalType, const string& value, const string& literal, + NodeType nt) { checkPrefix(name); @@ -1084,7 +1085,7 @@ Slice::Container::createConst(const string name, const TypePtr& constType, const return 0; } - ConstPtr p = new Const(this, name, constType, metaData, value); + ConstPtr p = new Const(this, name, constType, metaData, value, literal); _contents.push_back(p); return p; } @@ -1449,6 +1450,21 @@ Slice::Container::enums() const return result; } +ConstList +Slice::Container::consts() const +{ + ConstList result; + for(ContainedList::const_iterator p = _contents.begin(); p != _contents.end(); ++p) + { + ConstPtr q = ConstPtr::dynamicCast(*p); + if(q) + { + result.push_back(q); + } + } + return result; +} + ContainedList Slice::Container::contents() const { @@ -4093,6 +4109,12 @@ Slice::Const::value() const return _value; } +string +Slice::Const::literal() const +{ + return _literal; +} + Contained::ContainedType Slice::Const::containedType() const { @@ -4316,12 +4338,13 @@ Slice::Const::isInRange(const string& name, const TypePtr& constType, const stri } Slice::Const::Const(const ContainerPtr& container, const string& name, const TypePtr& type, - const StringList& typeMetaData, const string& value) : + const StringList& typeMetaData, const string& value, const string& literal) : SyntaxTreeBase(container->unit()), Contained(container, name), _type(type), _typeMetaData(typeMetaData), - _value(value) + _value(value), + _literal(literal) { } diff --git a/cpp/src/Slice/Scanner.l b/cpp/src/Slice/Scanner.l index b132a4e070d..863c54caffb 100644 --- a/cpp/src/Slice/Scanner.l +++ b/cpp/src/Slice/Scanner.l @@ -177,9 +177,11 @@ floating_literal (({fractional_constant}{exponent_part}?)|((\+|-)?[[:digit:]]+{e \" { StringTokPtr str = new StringTok; + str->literal = "\""; while(true) { char c = static_cast<char>(yyinput()); + str->literal += c; if(c == '"') { break; @@ -196,6 +198,7 @@ floating_literal (({fractional_constant}{exponent_part}?)|((\+|-)?[[:digit:]]+{e else if(c == '\\') { char next = static_cast<char>(yyinput()); + str->literal += next; switch(next) { case '\\': @@ -263,6 +266,7 @@ floating_literal (({fractional_constant}{exponent_part}?)|((\+|-)?[[:digit:]]+{e unsigned short us = next - '0'; if(octalDigits.find_first_of(next = static_cast<char>(yyinput())) != string::npos) { + str->literal += next; us = us * 8 + next - '0'; if(octalDigits.find_first_of(next = static_cast<char>(yyinput())) != string::npos) { @@ -289,6 +293,7 @@ floating_literal (({fractional_constant}{exponent_part}?)|((\+|-)?[[:digit:]]+{e IceUtil::Int64 ull = 0; while(isxdigit(next = static_cast<char>(yyinput()))) { + str->literal += next; ull *= 16; if(isdigit(next)) { @@ -332,6 +337,7 @@ floating_literal (({fractional_constant}{exponent_part}?)|((\+|-)?[[:digit:]]+{e {integer_constant} { IntegerTokPtr itp = new IntegerTok; + itp->literal = string(yytext); *yylvalp = itp; if(!IceUtilInternal::stringToInt64(string(yytext), itp->v)) { @@ -349,6 +355,7 @@ floating_literal (({fractional_constant}{exponent_part}?)|((\+|-)?[[:digit:]]+{e FloatingTokPtr ftp = new FloatingTok; *yylvalp = ftp; string literal(yytext); + ftp->literal = literal; char lastChar = literal[literal.size() - 1]; if(lastChar == 'f' || lastChar == 'F') { diff --git a/cpp/src/Slice/VbUtil.cpp b/cpp/src/Slice/VbUtil.cpp deleted file mode 100755 index f1b354a3dd7..00000000000 --- a/cpp/src/Slice/VbUtil.cpp +++ /dev/null @@ -1,1294 +0,0 @@ -// ********************************************************************** -// -// Copyright (c) 2003-2007 ZeroC, Inc. All rights reserved. -// -// This copy of Ice is licensed to you under the terms described in the -// ICE_LICENSE file included in this distribution. -// -// ********************************************************************** - -#include <Slice/VbUtil.h> -#include <Slice/DotNetNames.h> -#include <IceUtil/Functional.h> - -#include <sys/types.h> -#include <sys/stat.h> - -#ifdef _WIN32 -#include <direct.h> -#endif - -#ifndef _WIN32 -#include <unistd.h> -#endif - -using namespace std; -using namespace Slice; -using namespace IceUtil; -using namespace IceUtilInternal; - -static string -lookupKwd(const string& name, int baseTypes, bool mangleCasts = false) -{ - // - // Keyword list. *Must* be kept in alphabetical order. - // - static const string keywordList[] = - { - "AddHandler", "AddressOf", "Alias", "And", "AndAlso", "Ansi", "As", "Assembly", "Auto", - "Boolean", "ByRef", "Byte", "ByVal", "Call", "Case", "Catch", "CBool", "CByte", "CChar", - "CDate", "CDbl", "CDec", "Char", "CInt", "Class", "CLng", "CObj", "Const", "CShort", "CSng", - "CStr", "CType", "Date", "Decimal", "Declare", "Default", "Delegate", "Dim", "DirectCast", - "Do", "Double", "Each", "Else", "ElseIf", "End", "EndIf", "Enum", "Erase", "Error", "Event", - "Exit", "False", "Finally", "For", "Friend", "Function", "Get", "GetType", "GoSub", "GoTo", - "Handles", "If", "Implements", "Imports", "In", "Inherits", "Integer", "Interface", "Is", - "Let", "Lib", "Like", "Long", "Loop", "Me", "Mod", "Module", "MustInherit", "MustOverride", - "MyBase", "MyClass", "Namespace", "New", "Next", "Not", "Nothing", "NotInheritable", - "NotOverridable", "Object", "On", "Option", "Optional", "Or", "OrElse", "Overloads", "Overridable", - "Overrides", "ParamArray", "Preserve", "Private", "Property", "Protected", "Public", "RaiseEvent", - "ReadOnly", "ReDim", "REM", "RemoveHandler", "Resume", "Return", "Select", "Set", - "Shadows", "Shared", "Short", "Single", "Static", "Step", "Stop", "String", "Structure", - "Sub", "SyncLock", "Then", "Throw", "To", "True", "Try", "TypeOf", "Unicode", "Until", - "Variant", "Wend", "When", "While", "With", "WithEvents", "WriteOnly", "Xor" - }; - bool found = binary_search(&keywordList[0], - &keywordList[sizeof(keywordList) / sizeof(*keywordList)], - name, - Slice::CICompare()); - if(found) - { - return "[" + name + "]"; - } - if(mangleCasts && (name == "checkedCast" || name == "uncheckedCast")) - { - return string(DotNet::manglePrefix) + name; - } - return Slice::DotNet::mangleName(name, baseTypes); -} - -// -// Split a scoped name into its components and return the components as a list of (unscoped) identifiers. -// -static StringList -splitScopedName(const string& scoped) -{ - assert(scoped[0] == ':'); - StringList ids; - string::size_type next = 0; - string::size_type pos; - while((pos = scoped.find("::", next)) != string::npos) - { - pos += 2; - if(pos != scoped.size()) - { - string::size_type endpos = scoped.find("::", pos); - if(endpos != string::npos) - { - ids.push_back(scoped.substr(pos, endpos - pos)); - } - } - next = pos; - } - if(next != scoped.size()) - { - ids.push_back(scoped.substr(next)); - } - else - { - ids.push_back(""); - } - - return ids; -} - -// -// If the passed name is a scoped name, return the identical scoped name, -// but with all components that are VB keywords replaced by -// their "[]"-surrounded version; otherwise, if the passed name is -// not scoped, but a VB keyword, return the "[]"-surrounded name; -// otherwise, check if the name is one of the method names of baseTypes; -// if so, prefix it with _Ice_; otherwise, reutrn the name unchanged. -// -string -Slice::VbGenerator::fixId(const string& name, int baseTypes, bool mangleCasts) -{ - if(name.empty()) - { - return name; - } - if(name[0] != ':') - { - return lookupKwd(name, baseTypes, mangleCasts); - } - StringList ids = splitScopedName(name); - StringList newIds; - for(StringList::const_iterator i = ids.begin(); i != ids.end(); ++i) - { - newIds.push_back(lookupKwd(*i, baseTypes)); - } - stringstream result; - for(StringList::const_iterator j = ids.begin(); j != ids.end(); ++j) - { - if(j != ids.begin()) - { - result << '.'; - } - result << *j; - } - return result.str(); -} - -string -Slice::VbGenerator::typeToString(const TypePtr& type) -{ - if(!type) - { - return ""; - } - - static const char* builtinTable[] = - { - "Byte", - "Boolean", - "Short", - "Integer", - "Long", - "Single", - "Double", - "String", - "Ice.Object", - "Ice.ObjectPrx", - "Ice.LocalObject" - }; - - BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); - if(builtin) - { - return builtinTable[builtin->kind()]; - } - - ProxyPtr proxy = ProxyPtr::dynamicCast(type); - if(proxy) - { - return fixId(proxy->_class()->scoped() + "Prx"); - } - - SequencePtr seq = SequencePtr::dynamicCast(type); - if(seq && !seq->hasMetaData("clr:collection")) - { - return typeToString(seq->type()) + "()"; - } - - ContainedPtr contained = ContainedPtr::dynamicCast(type); - if(contained) - { - return fixId(contained->scoped()); - } - - return "???"; -} - -bool -Slice::VbGenerator::isValueType(const TypePtr& type) -{ - BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); - if(builtin) - { - switch(builtin->kind()) - { - case Builtin::KindString: - case Builtin::KindObject: - case Builtin::KindObjectProxy: - case Builtin::KindLocalObject: - { - return false; - break; - } - default: - { - return true; - break; - } - } - } - StructPtr s = StructPtr::dynamicCast(type); - if(s) - { - if(s->hasMetaData("clr:class")) - { - return false; - } - DataMemberList dm = s->dataMembers(); - for(DataMemberList::const_iterator i = dm.begin(); i != dm.end(); ++i) - { - if(!isValueType((*i)->type())) - { - return false; - } - } - return true; - } - if(EnumPtr::dynamicCast(type)) - { - return true; - } - return false; -} - -void -Slice::VbGenerator::writeMarshalUnmarshalCode(Output &out, - const TypePtr& type, - const string& param, - bool marshal, - bool streamingAPI, - bool isOutParam, - const string& patchParams) -{ - string stream; - - if(marshal) - { - stream = streamingAPI ? "outS__" : "os__"; - } - else - { - stream = streamingAPI ? "inS__" : "is__"; - } - - BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); - if(builtin) - { - switch(builtin->kind()) - { - case Builtin::KindByte: - { - if(marshal) - { - out << nl << stream << ".writeByte(" << param << ')'; - } - else - { - out << nl << param << " = " << stream << ".readByte()"; - } - break; - } - case Builtin::KindBool: - { - if(marshal) - { - out << nl << stream << ".writeBool(" << param << ')'; - } - else - { - out << nl << param << " = " << stream << ".readBool()"; - } - break; - } - case Builtin::KindShort: - { - if(marshal) - { - out << nl << stream << ".writeShort(" << param << ')'; - } - else - { - out << nl << param << " = " << stream << ".readShort()"; - } - break; - } - case Builtin::KindInt: - { - if(marshal) - { - out << nl << stream << ".writeInt(" << param << ')'; - } - else - { - out << nl << param << " = " << stream << ".readInt()"; - } - break; - } - case Builtin::KindLong: - { - if(marshal) - { - out << nl << stream << ".writeLong(" << param << ')'; - } - else - { - out << nl << param << " = " << stream << ".readLong()"; - } - break; - } - case Builtin::KindFloat: - { - if(marshal) - { - out << nl << stream << ".writeFloat(" << param << ')'; - } - else - { - out << nl << param << " = " << stream << ".readFloat()"; - } - break; - } - case Builtin::KindDouble: - { - if(marshal) - { - out << nl << stream << ".writeDouble(" << param << ')'; - } - else - { - out << nl << param << " = " << stream << ".readDouble()"; - } - break; - } - case Builtin::KindString: - { - if(marshal) - { - out << nl << stream << ".writeString(" << param << ')'; - } - else - { - out << nl << param << " = " << stream << ".readString()"; - } - break; - } - case Builtin::KindObject: - { - if(marshal) - { - out << nl << stream << ".writeObject(" << param << ')'; - } - else - { - if(isOutParam) - { - out << nl << "Dim " << param - << "_PP As IceInternal.ParamPatcher = New IceInternal.ParamPatcher(GetType(Ice.Object), " - << "\"::Ice::Object\")"; - if(streamingAPI) - { - out << nl << stream << ".readObject(CType(" << param << "_PP, Ice.ReadObjectCallback))"; - } - else - { - out << nl << stream << ".readObject(" << param << "_PP)"; - } - } - else - { - if(streamingAPI) - { - out << nl << stream << ".readObject(CType(New Patcher__(" << patchParams - << ", Ice.ReadObjectCallback)))"; - } - else - { - out << nl << stream << ".readObject(New Patcher__(" << patchParams << "))"; - } - } - } - break; - } - case Builtin::KindObjectProxy: - { - if(marshal) - { - out << nl << stream << ".writeProxy(" << param << ')'; - } - else - { - out << nl << param << " = " << stream << ".readProxy()"; - } - break; - } - case Builtin::KindLocalObject: - { - assert(false); - break; - } - } - return; - } - - ProxyPtr prx = ProxyPtr::dynamicCast(type); - if(prx) - { - ContainedPtr contained = ContainedPtr::dynamicCast(type); - string helperName = fixId((contained ? contained->scoped() : typeToString(type)) + "Helper"); - if(marshal) - { - out << nl << helperName << ".write"; - if(!streamingAPI) - { - out << "__"; - } - out << '(' << stream << ", " << param << ')'; - } - else - { - out << nl << param << " = " << helperName << ".read"; - if(!streamingAPI) - { - out << "__"; - } - out << "(" << stream << ')'; - } - return; - } - - ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); - if(cl) - { - if(marshal) - { - out << nl << stream << ".writeObject(" << param << ")"; - } - else - { - if(isOutParam) - { - ContainedPtr contained = ContainedPtr::dynamicCast(type); - out << nl << "Dim " << param - << "_PP As IceInternal.ParamPatcher = New IceInternal.ParamPatcher(GetType(" - << typeToString(type) << "), \"" << contained->scoped() << "\")"; - if(streamingAPI) - { - out << nl << stream << ".readObject(CType(" << param << "_PP, Ice.ReadObjectCallback))"; - } - else - { - out << nl << stream << ".readObject(" << param << "_PP)"; - } - } - else - { - if(streamingAPI) - { - out << nl << stream << ".readObject(New Patcher__(CType(" << patchParams - << ", Ice.ReadObjectCallback)))"; - } - else - { - out << nl << stream << ".readObject(New Patcher__(" << patchParams << "))"; - } - } - } - return; - } - - StructPtr st = StructPtr::dynamicCast(type); - if(st) - { - if(marshal) - { - if(streamingAPI) - { - out << nl << param << ".ice_write(" << stream << ')'; - } - else - { - out << nl << param << ".write__(" << stream << ')'; - } - } - else - { - string typeS = typeToString(type); - out << nl << param << " = New " << typeS; - if(streamingAPI) - { - out << nl << param << ".ice_read(" << stream << ")"; - } - else - { - out << nl << param << ".read__(" << stream << ")"; - } - } - return; - } - - EnumPtr en = EnumPtr::dynamicCast(type); - if(en) - { - string func; - string cast; - size_t sz = en->getEnumerators().size(); - if(sz <= 0x7f) - { - func = marshal ? "writeByte" : "readByte"; - cast = marshal ? string("Byte") : fixId(en->scoped()); - } - else if(sz <= 0x7fff) - { - func = marshal ? "writeShort" : "readShort"; - cast = marshal ? string("Short") : fixId(en->scoped()); - } - else - { - func = marshal ? "writeInt" : "readInt"; - cast = marshal ? string("Integer") : fixId(en->scoped()); - } - if(marshal) - { - out << nl << stream << '.' << func << "(CType(" << param << ", " << cast << "))"; - } - else - { - out << nl << param << " = CType(" << stream << '.' << func << "(), " << cast << ')'; - } - return; - } - - SequencePtr seq = SequencePtr::dynamicCast(type); - if(seq) - { - writeSequenceMarshalUnmarshalCode(out, seq, param, marshal, streamingAPI); - return; - } - - assert(ConstructedPtr::dynamicCast(type)); - string helperName = fixId(ContainedPtr::dynamicCast(type)->scoped() + "Helper"); - if(marshal) - { - out << nl << helperName << ".write(" << stream << ", " << param << ')'; - } - else - { - out << nl << param << " = " << helperName << ".read(" << stream << ')'; - } -} - -void -Slice::VbGenerator::writeSequenceMarshalUnmarshalCode(Output& out, - const SequencePtr& seq, - const string& param, - bool marshal, - bool streamingAPI) -{ - string stream; - if(marshal) - { - stream = streamingAPI ? "outS__" : "os__"; - } - else - { - stream = streamingAPI ? "inS__" : "is__"; - } - - TypePtr type = seq->type(); - string typeS = typeToString(type); - - bool isArray = !seq->hasMetaData("clr:collection"); - string limitID = isArray ? "Length" : "Count"; - - BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); - if(builtin) - { - switch(builtin->kind()) - { - case Builtin::KindObject: - case Builtin::KindObjectProxy: - { - if(marshal) - { - out << nl << "If " << param << " Is Nothing Then"; - out.inc(); - out << nl << stream << ".writeSize(0)"; - out.dec(); - out << nl << "Else"; - out.inc(); - out << nl << stream << ".writeSize(" << param << '.' << limitID << ")"; - out << nl << "For ix__ As Integer = 0 To " << param << '.' << limitID << " - 1"; - out.inc(); - string func = builtin->kind() == Builtin::KindObject ? "writeObject" : "writeProxy"; - out << nl << stream << '.' << func << '(' << param << "(ix__))"; - out.dec(); - out << nl << "Next"; - out.dec(); - out << nl << "End If"; - } - else - { - out << nl << "For block__ As Integer = 0 To 0"; - out.inc(); - out << nl << "Dim lenx__ As Integer = " << stream << ".readSize()"; - if(!streamingAPI) - { - if(builtin->isVariableLength()) - { - out << nl << stream << ".startSeq(lenx__, " << static_cast<unsigned>(builtin->minWireSize()) - << ")"; - } - else - { - out << nl << stream << ".checkFixedSeq(lenx__, " - << static_cast<unsigned>(builtin->minWireSize()) << ")"; - } - } - out << nl << param << " = New "; - if(builtin->kind() == Builtin::KindObject) - { - if(isArray) - { - out << "Ice.Object(lenx__ - 1) {}"; - } - else - { - out << typeToString(seq); - } - out << nl << "For ix__ As Integer = 0 To lenx__ - 1"; - out.inc(); - if(streamingAPI) - { - out << nl << stream << ".readObject(CType(New IceInternal.SequencePatcher(" - << param << ", GetType(Ice.Object), ix__), Ice.ReadObjectCallback))"; - } - else - { - out << nl << stream << ".readObject(New IceInternal.SequencePatcher(" - << param << ", GetType(Ice.Object), ix__))"; - } - out.dec(); - out << nl << "Next"; - } - else - { - if(isArray) - { - out << "Ice.ObjectPrx(lenx__ - 1) {}"; - } - else - { - out << typeToString(seq); - } - out << nl << "For ix__ As Integer = 0 To lenx__ - 1"; - out.inc(); - if(isArray) - { - out << nl << param << "(ix__) = " << stream << ".readProxy()"; - } - else - { - out << nl << "Dim val__ As Ice.ObjectPrx = New Ice.ObjectPrxHelperBase"; - out << nl << "val__ = " << stream << ".readProxy()"; - out << nl << param << ".Add(val__)"; - } - out.dec(); - out << nl << "Next"; - } - if(!streamingAPI && builtin->isVariableLength()) - { - out << nl << stream << ".checkSeq()"; - out << nl << stream << ".endElement()"; - out << nl << stream << ".endSeq(lenx__)"; - } - out.dec(); - out << nl << "Next"; - } - break; - } - default: - { - string marshalName = builtin->kindAsString(); - marshalName[0] = toupper(marshalName[0]); - if(marshal) - { - out << nl << stream << ".write" << marshalName << "Seq(" << param; - if(!isArray) - { - out << ".ToArray()"; - } - out << ')'; - } - else - { - if(!isArray) - { - out << nl << param << " = New " << fixId(seq->scoped()) - << '(' << stream << ".read" << marshalName << "Seq())"; - } - else - { - out << nl << param << " = " << stream << ".read" << marshalName << "Seq()"; - } - } - break; - } - } - return; - } - - ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); - if(cl) - { - out << nl << "For block__ As Integer = 0 To 0"; - out.inc(); - if(marshal) - { - out << nl << "If " << param << " Is Nothing"; - out.inc(); - out << nl << stream << ".writeSize(0)"; - out.dec(); - out << nl << "Else"; - out.inc(); - out << nl << stream << ".writeSize(" << param << '.' << limitID << ")"; - out << nl << "For ix__ As Integer = 0 To " << param << '.' << limitID << " - 1"; - out.inc(); - out << nl << stream << ".writeObject(" << param << "(ix__))"; - out.dec(); - out << nl << "Next"; - out.dec(); - out << nl << "End If"; - } - else - { - out << nl << "Dim szx__ As Integer = " << stream << ".readSize()"; - if(!streamingAPI) - { - if(type->isVariableLength()) - { - out << nl << stream << ".startSeq(szx__, " << static_cast<unsigned>(type->minWireSize()) << ')'; - } - else - { - out << nl << stream << ".checkFixedSeq(szx__, " << static_cast<unsigned>(type->minWireSize()) << ')'; - } - } - out << nl << param << " = New "; - if(isArray) - { - out << toArrayAlloc(typeS + "()", "szx__ - 1") << " {}"; - } - else - { - out << fixId(seq->scoped()) << "(szx__)"; - } - out << nl << "For ix__ As Integer = 0 To szx__ - 1"; - out.inc(); - out << nl << "Dim spx__ As IceInternal.SequencePatcher = New IceInternal.SequencePatcher(" - << param << ", " << "GetType(" << typeS << "), ix__)"; - if(streamingAPI) - { - out << nl << stream << ".readObject(CType(spx__, Ice.ReadObjectCallback))"; - } - else - { - out << nl << stream << ".readObject(spx__)"; - } - if(!streamingAPI && type->isVariableLength()) - { - out << nl << stream << ".checkSeq()"; - out << nl << stream << ".endElement()"; - } - out.dec(); - out << nl << "Next"; - if(!streamingAPI && type->isVariableLength()) - { - out << nl << stream << ".endSeq(szx__)"; - } - } - out.dec(); - out << nl << "Next"; - return; - } - - StructPtr st = StructPtr::dynamicCast(type); - if(st) - { - out << nl << "For block__ As Integer = 0 To 0"; - out.inc(); - if(marshal) - { - out << nl << "If " << param << " Is Nothing"; - out.inc(); - out << nl << stream << ".writeSize(0)"; - out.dec(); - out << nl << "Else"; - out.inc(); - out << nl << stream << ".writeSize(" << param << '.' << limitID << ")"; - out << nl << "For ix__ As Integer = 0 To " << param << '.' << limitID << " - 1"; - out.inc(); - if(streamingAPI) - { - out << nl << param << "(ix__).ice_write(" << stream << ")"; - } - else - { - out << nl << param << "(ix__).write__(" << stream << ")"; - } - out.dec(); - out << nl << "Next"; - out.dec(); - out << nl << "End If"; - } - else - { - out << nl << "Dim szx__ As Integer = " << stream << ".readSize()"; - if(!streamingAPI) - { - if(type->isVariableLength()) - { - out << nl << stream << ".startSeq(szx__, " << static_cast<unsigned>(type->minWireSize()) << ')'; - } - else - { - out << nl << stream << ".checkFixedSeq(szx__, " << static_cast<unsigned>(type->minWireSize()) << ')'; - } - } - out << nl << param << " = New "; - if(isArray) - { - out << toArrayAlloc(typeS + "()", "szx__ - 1") << " {}"; - } - else - { - out << fixId(seq->scoped()) << "(szx__)"; - } - out << nl << "For ix__ As Integer = 0 To szx__ - 1"; - out.inc(); - if(isArray) - { - if(!isValueType(st)) - { - out << nl << param << "(ix__) = New " << typeS; - } - if(streamingAPI) - { - out << nl << param << "(ix__).ice_read(" << stream << ")"; - } - else - { - out << nl << param << "(ix__).read__(" << stream << ")"; - } - } - else - { - out << nl << "Dim val__ As " << typeS << " = New " << typeS; - if(streamingAPI) - { - out << nl << "val__.ice_read(" << stream << ')'; - } - else - { - out << nl << "val__.read__(" << stream << ')'; - } - out << nl << param << ".Add(val__)"; - } - if(!streamingAPI && type->isVariableLength()) - { - out << nl << stream << ".checkSeq()"; - out << nl << stream << ".endElement()"; - } - out.dec(); - out << nl << "Next"; - if(!streamingAPI && type->isVariableLength()) - { - out << nl << stream << ".endSeq(szx__)"; - } - } - out.dec(); - out << nl << "Next"; - return; - } - - EnumPtr en = EnumPtr::dynamicCast(type); - if(en) - { - out << nl << "For block__ As Integer = 0 To 0"; - out.inc(); - if(marshal) - { - out << nl << "If " << param << " Is Nothing"; - out.inc(); - out << nl << stream << ".writeSize(0)"; - out.dec(); - out << nl << "Else"; - out.inc(); - out << nl << stream << ".writeSize(" << param << '.'<< limitID << ')'; - out << nl << "For ix__ As Integer = 0 To " << param << '.' << limitID << " - 1"; - out.inc(); - out << nl << stream << ".writeByte(CType(" << param << "(ix__), Byte))"; - out.dec(); - out << nl << "Next"; - out.dec(); - out << nl << "End If"; - } - else - { - out << nl << "Dim szx__ As Integer = " << stream << ".readSize()"; - if(!streamingAPI) - { - out << nl << stream << ".checkFixedSeq(szx__, " << static_cast<unsigned>(type->minWireSize()) << ')'; - } - out << nl << param << " = New "; - if(isArray) - { - out << toArrayAlloc(typeS + "()", "szx__ - 1") << " {}"; - } - else - { - out << fixId(seq->scoped()) << "(szx__)"; - } - out << nl << "For ix__ As Integer = 0 To szx__ - 1"; - out.inc(); - if(isArray) - { - out << nl << param << "(ix__) = CType(" << stream << ".readByte(), " << typeS << ')'; - } - else - { - out << nl << param << ".Add(CType(" << stream << ".readByte(), " << typeS << "))"; - } - out.dec(); - out << nl << "Next"; - } - out.dec(); - out << nl << "Next"; - return; - } - - string helperName; - if(ProxyPtr::dynamicCast(type)) - { - helperName = fixId(ProxyPtr::dynamicCast(type)->_class()->scoped() + "PrxHelper"); - } - else - { - helperName = fixId(ContainedPtr::dynamicCast(type)->scoped() + "Helper"); - } - - string func; - if(marshal) - { - func = "write"; - if(!streamingAPI && ProxyPtr::dynamicCast(type)) - { - func += "__"; - } - out << nl << "If " << param << " Is Nothing"; - out.inc(); - out << nl << stream << ".writeSize(0)"; - out.dec(); - out << nl << "Else"; - out.inc(); - out << nl << stream << ".writeSize(" << param << '.' << limitID << ")"; - out << nl << "For ix__ As Integer = 0 To " << param << '.' << limitID << " - 1"; - out.inc(); - out << nl << helperName << '.' << func << '(' << stream << ", " << param << "(ix__))"; - out.dec(); - out << nl << "Next"; - out.dec(); - out << nl << "End If"; - } - else - { - func = "read"; - if(!streamingAPI && ProxyPtr::dynamicCast(type)) - { - func += "__"; - } - out << nl << "For block__ As Integer = 0 To 0"; - out.inc(); - out << nl << "Dim szx__ As Integer = " << stream << ".readSize()"; - if(!streamingAPI) - { - if(type->isVariableLength()) - { - out << nl << stream << ".startSeq(szx__, " << static_cast<unsigned>(type->minWireSize()) << ")"; - } - else - { - out << nl << stream << ".checkFixedSeq(szx__, " << static_cast<unsigned>(type->minWireSize()) << ")"; - } - } - out << nl << param << " = New "; - if(isArray) - { - out << toArrayAlloc(typeS + "()", "szx__ - 1") << " {}"; - } - else - { - out << fixId(seq->scoped()) << "(szx__)"; - } - out << nl << "For ix__ As Integer = 0 To szx__ - 1"; - out.inc(); - if(isArray) - { - out << nl << param << "(ix__) = " << helperName << '.' << func << '(' << stream << ")"; - } - else - { - out << nl << param << ".Add(" << helperName << '.' << func << '(' << stream << "))"; - } - if(!streamingAPI && type->isVariableLength()) - { - if(!SequencePtr::dynamicCast(type)) - { - out << nl << stream << ".checkSeq()"; - } - out << nl << stream << ".endElement()"; - } - out.dec(); - out << nl << "Next"; - if(!streamingAPI && type->isVariableLength()) - { - out << nl << stream << ".endSeq(szx__)"; - } - out.dec(); - out << nl << "Next"; - } - - return; -} - -string -Slice::VbGenerator::toArrayAlloc(const string& decl, const string& sz) -{ - int count = 0; - string::size_type pos = decl.size(); - while(pos > 1 && decl.substr(pos - 2, 2) == "()") - { - ++count; - pos -= 2; - } - assert(count > 0); - - ostringstream o; - o << decl.substr(0, pos) << '(' << sz << ')' << decl.substr(pos + 2); - return o.str(); -} - -void -Slice::VbGenerator::validateMetaData(const UnitPtr& u) -{ - MetaDataVisitor visitor; - u->visit(&visitor, false); -} - -Slice::VbGenerator::MetaDataVisitor::MetaDataVisitor() - : _globalMetaDataDone(false) -{ -} - -bool -Slice::VbGenerator::MetaDataVisitor::visitModuleStart(const ModulePtr& p) -{ - if(!_globalMetaDataDone) - { - // - // Validate global metadata. - // - DefinitionContextPtr dc = p->definitionContext(); - assert(dc); - StringList globalMetaData = dc->getMetaData(); - string file = dc->filename(); - static const string prefix = "vb:"; - for(StringList::const_iterator q = globalMetaData.begin(); q != globalMetaData.end(); ++q) - { - string s = *q; - if(_history.count(s) == 0) - { - if(s.find(prefix) == 0) - { - static const string attributePrefix = "vb:attribute:"; - if(s.find(attributePrefix) != 0 || s.size() == attributePrefix.size()) - { - cout << file << ": warning: ignoring invalid global metadata `" << s << "'" << endl; - } - } - _history.insert(s); - } - } - _globalMetaDataDone = true; - } - validate(p); - return true; -} - -void -Slice::VbGenerator::MetaDataVisitor::visitModuleEnd(const ModulePtr&) -{ -} - -void -Slice::VbGenerator::MetaDataVisitor::visitClassDecl(const ClassDeclPtr& p) -{ - validate(p); -} - -bool -Slice::VbGenerator::MetaDataVisitor::visitClassDefStart(const ClassDefPtr& p) -{ - validate(p); - return true; -} - -void -Slice::VbGenerator::MetaDataVisitor::visitClassDefEnd(const ClassDefPtr&) -{ -} - -bool -Slice::VbGenerator::MetaDataVisitor::visitExceptionStart(const ExceptionPtr& p) -{ - validate(p); - return true; -} - -void -Slice::VbGenerator::MetaDataVisitor::visitExceptionEnd(const ExceptionPtr&) -{ -} - -bool -Slice::VbGenerator::MetaDataVisitor::visitStructStart(const StructPtr& p) -{ - validate(p); - return true; -} - -void -Slice::VbGenerator::MetaDataVisitor::visitStructEnd(const StructPtr&) -{ -} - -void -Slice::VbGenerator::MetaDataVisitor::visitOperation(const OperationPtr& p) -{ - validate(p); -} - -void -Slice::VbGenerator::MetaDataVisitor::visitParamDecl(const ParamDeclPtr& p) -{ - validate(p); -} - -void -Slice::VbGenerator::MetaDataVisitor::visitDataMember(const DataMemberPtr& p) -{ - validate(p); -} - -void -Slice::VbGenerator::MetaDataVisitor::visitSequence(const SequencePtr& p) -{ - validate(p); -} - -void -Slice::VbGenerator::MetaDataVisitor::visitDictionary(const DictionaryPtr& p) -{ - validate(p); -} - -void -Slice::VbGenerator::MetaDataVisitor::visitEnum(const EnumPtr& p) -{ - validate(p); -} - -void -Slice::VbGenerator::MetaDataVisitor::visitConst(const ConstPtr& p) -{ - validate(p); -} - -void -Slice::VbGenerator::MetaDataVisitor::validate(const ContainedPtr& cont) -{ - DefinitionContextPtr dc = cont->definitionContext(); - assert(dc); - string file = dc->filename(); - - StringList localMetaData = cont->getMetaData(); - - StringList::const_iterator p; - - for(p = localMetaData.begin(); p != localMetaData.end(); ++p) - { - string s = *p; - - if(s.find("vb:") == 0) // TODO: remove this statement once "vb:" is a hard error. - { - if(SequencePtr::dynamicCast(cont)) - { - if(s.substr(3) == "collection") - { - cout << file << ":" << cont->line() << ": warning: `vb:' metadata prefix is deprecated; " - << "use `clr:' instead" << endl; - cont->addMetaData("clr:collection"); - } - } - else if(StructPtr::dynamicCast(cont)) - { - if(s.substr(3) == "class") - { - cout << file << ":" << cont->line() << ": warning: `vb:' metadata prefix is deprecated; " - << "use `clr:' instead" << endl; - cont->addMetaData("clr:class"); - } - } - else if(s.find("vb:attribute:") == 0) - { - ; // Do nothing, "vb:attribute:" is OK - } - else - { - cout << file << ":" << cont->line() << ": warning: ignoring invalid metadata `" << s << "'" << endl; - } - } // End TODO - - string prefix = "clr:"; - if(_history.count(s) == 0) - { - if(s.find(prefix) == 0) - { - if(SequencePtr::dynamicCast(cont)) - { - if(s.substr(prefix.size()) == "collection") - { - continue; - } - } - if(StructPtr::dynamicCast(cont)) - { - if(s.substr(prefix.size()) == "class") - { - continue; - } - if(s.substr(prefix.size()) == "property") - { - continue; - } - } - if(ClassDefPtr::dynamicCast(cont)) - { - if(s.substr(prefix.size()) == "property") - { - continue; - } - } - cout << file << ":" << cont->line() << ": warning: ignoring invalid metadata `" << s << "'" << endl; - } - _history.insert(s); - } - - prefix = "vb:"; - if(_history.count(s) == 0) - { - if(s.find(prefix) == 0) - { - if(s.substr(prefix.size()) == "attribute:") - { - continue; - } - cout << file << ":" << cont->line() << ": warning: ignoring invalid metadata `" << s << "'" << endl; - } - _history.insert(s); - } - } -} diff --git a/cpp/src/slice2html/Gen.cpp b/cpp/src/slice2html/Gen.cpp index 93e97489b4f..467257c628c 100644 --- a/cpp/src/slice2html/Gen.cpp +++ b/cpp/src/slice2html/Gen.cpp @@ -2107,6 +2107,29 @@ Slice::ModuleGenerator::visitContainer(const ContainerPtr& p) assert(_out.currIndent() == indent); + ConstList consts = p->consts(); + + if(!consts.empty()) + { + start("h2"); + _out << "Constant Index"; + end(); + start("dl"); + for(ConstList::const_iterator q = consts.begin(); q != consts.end(); ++q) + { + start("dt", "Symbol"); + _out << toString(*q, p, false, true); + end(); + start("dd"); + string metadata; + printSummary(*q, p, (*q)->findMetaData("deprecate", metadata)); + end(); + } + end(); + } + + assert(_out.currIndent() == indent); + EnumList enums = p->enums(); if(!enums.empty()) @@ -2205,6 +2228,46 @@ Slice::ModuleGenerator::visitContainer(const ContainerPtr& p) end(); } } + + if(!consts.empty()) + { + start("h2"); + _out << "Constants"; + end(); + for(ConstList::const_iterator q = consts.begin(); q != consts.end(); ++q) + { + start("dl"); + start("dt"); + start("span", "Synopsis"); + _out << "const " << toString((*q)->type(), p, false, true) << " " << toString(*q, p) << " = "; + if(EnumPtr::dynamicCast((*q)->type())) + { + _out << toString((*q)->value(), p, false, true); + } + else + { + _out << (*q)->literal(); + } + _out << ";"; + end(); + end(); + + start("dd"); + string metadata, deprecateReason; + if((*q)->findMetaData("deprecate", metadata)) + { + deprecateReason = "This type is deprecated."; + if(metadata.find("deprecate:") == 0 && metadata.size() > 10) + { + deprecateReason = metadata.substr(10); + } + } + + printComment(*q, p, deprecateReason, true); + end(); + end(); + } + } } Slice::ExceptionGenerator::ExceptionGenerator(XMLOutput& o, const Files& files) |