diff options
author | vridosh <vridosh@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2007-07-12 12:06:21 +0000 |
---|---|---|
committer | vridosh <vridosh@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2007-07-12 12:06:21 +0000 |
commit | 1d2221460dedfedc6f93a9697098d0d63eb2df86 (patch) | |
tree | 889690c6d78984a69c659d4931e309ced61303e4 /TAO/tao/Strategies | |
parent | ebc8d8113bd7dc657ec3db3600718721d6364deb (diff) | |
download | ATCD-1d2221460dedfedc6f93a9697098d0d63eb2df86.tar.gz |
ChangeLogTag: Thu Jul 12 11:29:39 UTC 2007 Vadym Ridosh <vridosh@prismtech.com>
Diffstat (limited to 'TAO/tao/Strategies')
-rw-r--r-- | TAO/tao/Strategies/DIOP_Acceptor.cpp | 459 | ||||
-rw-r--r-- | TAO/tao/Strategies/DIOP_Acceptor.h | 38 | ||||
-rw-r--r-- | TAO/tao/Strategies/DIOP_Acceptor.inl | 12 | ||||
-rw-r--r-- | TAO/tao/Strategies/DIOP_Connection_Handler.cpp | 72 | ||||
-rw-r--r-- | TAO/tao/Strategies/DIOP_Connector.cpp | 142 | ||||
-rw-r--r-- | TAO/tao/Strategies/DIOP_Connector.h | 14 | ||||
-rw-r--r-- | TAO/tao/Strategies/DIOP_Endpoint.cpp | 137 | ||||
-rw-r--r-- | TAO/tao/Strategies/DIOP_Endpoint.h | 12 | ||||
-rw-r--r-- | TAO/tao/Strategies/DIOP_Profile.cpp | 236 | ||||
-rw-r--r-- | TAO/tao/Strategies/DIOP_Transport.cpp | 9 |
10 files changed, 895 insertions, 236 deletions
diff --git a/TAO/tao/Strategies/DIOP_Acceptor.cpp b/TAO/tao/Strategies/DIOP_Acceptor.cpp index 937d738068d..84d7d84c1fb 100644 --- a/TAO/tao/Strategies/DIOP_Acceptor.cpp +++ b/TAO/tao/Strategies/DIOP_Acceptor.cpp @@ -36,6 +36,11 @@ TAO_DIOP_Acceptor::TAO_DIOP_Acceptor (CORBA::Boolean flag) version_ (TAO_DEF_GIOP_MAJOR, TAO_DEF_GIOP_MINOR), orb_core_ (0), lite_flag_ (flag), +#if defined (ACE_HAS_IPV6) + default_address_ (static_cast<unsigned short> (0), ACE_IPV6_ANY, AF_INET6), +#else + default_address_ (static_cast<unsigned short> (0), static_cast<ACE_UINT32> (INADDR_ANY)), +#endif /* ACE_HAS_IPV6 */ connection_handler_ (0) { } @@ -48,7 +53,7 @@ TAO_DIOP_Acceptor::~TAO_DIOP_Acceptor (void) delete [] this->addrs_; - for (size_t i = 0; i < this->endpoint_count_; ++i) + for (CORBA::ULong i = 0; i < this->endpoint_count_; ++i) CORBA::string_free (this->hosts_[i]); delete [] this->hosts_; @@ -68,7 +73,8 @@ TAO_DIOP_Acceptor::create_profile (const TAO::ObjectKey & object_key, // Check if multiple endpoints should be put in one profile or if // they should be spread across multiple profiles. - if (priority == TAO_INVALID_PRIORITY) + if (priority == TAO_INVALID_PRIORITY && + this->orb_core_->orb_params ()->shared_profile () == 0) return this->create_new_profile (object_key, mprofile, priority); else return this->create_shared_profile (object_key, mprofile, priority); @@ -80,14 +86,20 @@ TAO_DIOP_Acceptor::create_new_profile (const TAO::ObjectKey &object_key, CORBA::Short priority) { // Adding this->endpoint_count_ to the TAO_MProfile. - int const count = mprofile.profile_count (); + int count = mprofile.profile_count (); if ((mprofile.size () - count) < this->endpoint_count_ && mprofile.grow (count + this->endpoint_count_) == -1) return -1; // Create a profile for each acceptor endpoint. - for (size_t i = 0; i < this->endpoint_count_; ++i) + for (CORBA::ULong i = 0; i < this->endpoint_count_; ++i) { + // Skip if the host name + if (i > 0 + && (this->addrs_[i].get_port_number () == this->addrs_[0].get_port_number ()) + && ACE_OS::strcmp (this->hosts_[i], this->hosts_[0]) == 0) + continue; + TAO_DIOP_Profile *pfile = 0; ACE_NEW_RETURN (pfile, TAO_DIOP_Profile (this->hosts_[i], @@ -115,9 +127,9 @@ TAO_DIOP_Acceptor::create_new_profile (const TAO::ObjectKey &object_key, pfile->tagged_components ().set_orb_type (TAO_ORB_TYPE); - TAO_Codeset_Manager *csm = this->orb_core_->codeset_manager(); + TAO_Codeset_Manager *csm = this->orb_core_->codeset_manager (); if (csm) - csm->set_codeset(pfile->tagged_components()); + csm->set_codeset (pfile->tagged_components ()); } return 0; @@ -128,9 +140,9 @@ TAO_DIOP_Acceptor::create_shared_profile (const TAO::ObjectKey &object_key, TAO_MProfile &mprofile, CORBA::Short priority) { - size_t index = 0; + CORBA::ULong index = 0; TAO_Profile *pfile = 0; - TAO_DIOP_Profile *iiop_profile = 0; + TAO_DIOP_Profile *diop_profile = 0; // First see if <mprofile> already contains a DIOP profile. for (TAO_PHandle i = 0; i != mprofile.profile_count (); ++i) @@ -138,16 +150,16 @@ TAO_DIOP_Acceptor::create_shared_profile (const TAO::ObjectKey &object_key, pfile = mprofile.get_profile (i); if (pfile->tag () == TAO_TAG_DIOP_PROFILE) { - iiop_profile = dynamic_cast<TAO_DIOP_Profile *> (pfile); + diop_profile = dynamic_cast<TAO_DIOP_Profile *> (pfile); break; } } // If <mprofile> doesn't contain a DIOP_Profile, we need to create // one. - if (iiop_profile == 0) + if (diop_profile == 0) { - ACE_NEW_RETURN (iiop_profile, + ACE_NEW_RETURN (diop_profile, TAO_DIOP_Profile (this->hosts_[0], this->addrs_[0].get_port_number (), object_key, @@ -155,22 +167,22 @@ TAO_DIOP_Acceptor::create_shared_profile (const TAO::ObjectKey &object_key, this->version_, this->orb_core_), -1); - iiop_profile->endpoint ()->priority (priority); + diop_profile->endpoint ()->priority (priority); - if (mprofile.give_profile (iiop_profile) == -1) + if (mprofile.give_profile (diop_profile) == -1) { - iiop_profile->_decr_refcnt (); - iiop_profile = 0; + diop_profile->_decr_refcnt (); + diop_profile = 0; return -1; } if (this->orb_core_->orb_params ()->std_profile_components () != 0 && (this->version_.major >= 1 && this->version_.minor >= 1)) { - iiop_profile->tagged_components ().set_orb_type (TAO_ORB_TYPE); - TAO_Codeset_Manager *csm = this->orb_core_->codeset_manager(); + diop_profile->tagged_components ().set_orb_type (TAO_ORB_TYPE); + TAO_Codeset_Manager *csm = this->orb_core_->codeset_manager (); if (csm) - csm->set_codeset(pfile->tagged_components()); + csm->set_codeset (pfile->tagged_components ()); } index = 1; @@ -181,6 +193,11 @@ TAO_DIOP_Acceptor::create_shared_profile (const TAO::ObjectKey &object_key, index < this->endpoint_count_; ++index) { + if (index > 0 && + this->addrs_[index].get_port_number () == this->addrs_[0].get_port_number () && + ACE_OS::strcmp (this->hosts_[index], this->hosts_[0]) == 0) + continue; + TAO_DIOP_Endpoint *endpoint = 0; ACE_NEW_RETURN (endpoint, TAO_DIOP_Endpoint (this->hosts_[index], @@ -188,7 +205,7 @@ TAO_DIOP_Acceptor::create_shared_profile (const TAO::ObjectKey &object_key, this->addrs_[index]), -1); endpoint->priority (priority); - iiop_profile->add_endpoint (endpoint); + diop_profile->add_endpoint (endpoint); } return 0; @@ -204,7 +221,7 @@ TAO_DIOP_Acceptor::is_collocated (const TAO_Endpoint *endpoint) if (endp == 0) return 0; - for (size_t i = 0; i < this->endpoint_count_; ++i) + for (CORBA::ULong i = 0; i < this->endpoint_count_; ++i) { // compare the port and host name. Please do *NOT* optimize // this code by comparing the IP address instead. That would @@ -212,8 +229,8 @@ TAO_DIOP_Acceptor::is_collocated (const TAO_Endpoint *endpoint) // // http://deuce.doc.wustl.edu/bugzilla/show_bug.cgi?id=1220 // - if (endp->port() == this->addrs_[i].get_port_number() - && ACE_OS::strcmp(endp->host(), this->hosts_[i]) == 0) + if (endp->port () == this->addrs_[i].get_port_number () + && ACE_OS::strcmp (endp->host (), this->hosts_[i]) == 0) return 1; // Collocated } @@ -242,7 +259,7 @@ TAO_DIOP_Acceptor::open (TAO_ORB_Core *orb_core, // This is bad mojo, i.e. an internal TAO error. ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("TAO (%P|%t) - ") - ACE_TEXT ("DIOP_Acceptor::open - ") + ACE_TEXT ("DIOP_Acceptor::open, ") ACE_TEXT ("hostname already set\n\n")), -1); } @@ -257,55 +274,57 @@ TAO_DIOP_Acceptor::open (TAO_ORB_Core *orb_core, if (this->parse_options (options) == -1) return -1; + ACE_CString specified_hostname; ACE_INET_Addr addr; + int def_type = AF_UNSPEC; - const char *port_separator_loc = ACE_OS::strchr (address, ':'); - const char *specified_hostname = 0; - char tmp_host[MAXHOSTNAMELEN + 1]; + if (this->parse_address (address, + addr, + specified_hostname, + &def_type) == -1) + return -1; - if (port_separator_loc == address) + if (specified_hostname.length () == 0) { // The address is a port number or port name. No hostname was // specified. The hostname for each network interface and the // fully qualified domain name must be obtained. // Check for multiple network interfaces. - if (this->probe_interfaces (orb_core) == -1) + if (this->probe_interfaces (orb_core, def_type) == -1) return -1; - // First convert the port into a usable form. - if (addr.set (address + sizeof (':')) != 0) - return -1; + // Probe interfaces has a side effect of potentially modifying + // the default address, since that is where the address family + // is considered. + addr.set (this->default_address_); - // Now reset the port and set the host. - if (addr.set (addr.get_port_number (), - static_cast<ACE_UINT32> (INADDR_ANY), - 1) != 0) - return -1; - else - return this->open_i (addr, reactor); + return this->open_i (addr, + reactor); } - else if (port_separator_loc == 0) - { - // The address is a hostname. No port was specified, so assume - // port zero (port will be chosen for us). - if (addr.set ((unsigned short) 0, address) != 0) - return -1; - specified_hostname = address; - } - else +#if defined (ACE_HAS_IPV6) + // Check for violation of ORBConnectIPV6Only option + if (this->orb_core_->orb_params ()->connect_ipv6_only () && + (addr.get_type () != AF_INET6 || + addr.is_ipv4_mapped_ipv6 ())) { - // Host and port were specified. - if (addr.set (address) != 0) - return -1; - - // Extract out just the host part of the address. - size_t len = port_separator_loc - address; - ACE_OS::memcpy (tmp_host, address, len); - tmp_host[len] = '\0'; + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("TAO (%P|%t) - ") + ACE_TEXT ("DIOP_Acceptor::open, ") + ACE_TEXT ("non-IPv6 endpoints not allowed when ") + ACE_TEXT ("connect_ipv6_only is set\n\n")), + -1); + } +#endif /* ACE_HAS_IPV6 */ - specified_hostname = tmp_host; + if (TAO_debug_level > 2) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - ") + ACE_TEXT ("DIOP_Acceptor::open, specified host=%s:%d\n"), + (specified_hostname.length () == 0 ? "<null>" : specified_hostname.c_str ()), + addr.get_port_number ())); } this->endpoint_count_ = 1; // Only one hostname to store @@ -323,7 +342,7 @@ TAO_DIOP_Acceptor::open (TAO_ORB_Core *orb_core, if (this->hostname (orb_core, addr, this->hosts_[0], - specified_hostname) != 0) + specified_hostname.c_str ()) != 0) return -1; // Copy the addr. The port is (re)set in @@ -355,7 +374,7 @@ TAO_DIOP_Acceptor::open_default (TAO_ORB_Core *orb_core, -1); } - if (major >=0 && minor >= 0) + if (major >= 0 && minor >= 0) this->version_.set_version (static_cast<CORBA::Octet> (major), static_cast<CORBA::Octet> (minor)); @@ -372,9 +391,7 @@ TAO_DIOP_Acceptor::open_default (TAO_ORB_Core *orb_core, // address. ACE_INET_Addr addr; - if (addr.set (static_cast<unsigned short> (0), - static_cast<ACE_UINT32> (INADDR_ANY), - 1) != 0) + if (addr.set (this->default_address_) != 0) return -1; return this->open_i (addr, reactor); @@ -412,7 +429,7 @@ TAO_DIOP_Acceptor::open_i (const ACE_INET_Addr& addr, ACE_ERROR ((LM_ERROR, ACE_TEXT ("TAO (%P|%t) DIOP_Acceptor::open_i, ") ACE_TEXT ("%p"), - ACE_TEXT ("cannot get local addr\n"))); + ACE_TEXT ("cannot get local addr\n\n"))); return -1; } @@ -420,13 +437,15 @@ TAO_DIOP_Acceptor::open_i (const ACE_INET_Addr& addr, // interface then the endpoint created on each interface will be on // the same port. This is how a wildcard socket bind() is supposed // to work. - u_short const port = address.get_port_number (); - for (size_t j = 0; j < this->endpoint_count_; ++j) + unsigned short port = address.get_port_number (); + for (CORBA::ULong j = 0; j < this->endpoint_count_; ++j) this->addrs_[j].set_port_number (port, 1); + this->default_address_.set_port_number (port); + if (TAO_debug_level > 5) { - for (size_t i = 0; i < this->endpoint_count_; ++i) + for (CORBA::ULong i = 0; i < this->endpoint_count_; ++i) { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("TAO (%P|%t) - DIOP_Acceptor::open_i, ") @@ -451,8 +470,7 @@ TAO_DIOP_Acceptor::hostname (TAO_ORB_Core *orb_core, // just return ours. return this->dotted_decimal_address (addr, host); } - else - if (specified_hostname != 0) + else if (specified_hostname != 0) { // If the user specified a hostname, pass it back // blindly as it overrides our choice of hostname. @@ -463,7 +481,16 @@ TAO_DIOP_Acceptor::hostname (TAO_ORB_Core *orb_core, char tmp_host[MAXHOSTNAMELEN + 1]; // Get the hostname associated with our address +#if defined (ACE_HAS_IPV6) + // If we have a IPv4-compatible IPv6 address don't do hostname lookup + // because that gets us into trouble. Most likely we get the same hostname + // returned as for the actual IPv4 address but resolving that into an IPv6 + // address at the client will fail. + if (addr.is_ipv4_compat_ipv6 () || + addr.get_host_name (tmp_host, sizeof (tmp_host)) != 0) +#else /* ACE_HAS_IPV6 */ if (addr.get_host_name (tmp_host, sizeof (tmp_host)) != 0) +#endif /* !ACE_HAS_IPV6 */ { // On failure, just return the decimal address. return this->dotted_decimal_address (addr, host); @@ -478,11 +505,172 @@ TAO_DIOP_Acceptor::hostname (TAO_ORB_Core *orb_core, } int +TAO_DIOP_Acceptor::parse_address (const char *address, + ACE_INET_Addr &addr, + ACE_CString &specified_hostname, + int *def_type) +{ + { + ACE_INET_Addr tmp; + addr.set (tmp); + specified_hostname.clear(); + } + + const char *port_separator_loc = ACE_OS::strchr (address, ':'); + char tmp_host[MAXHOSTNAMELEN + 1]; + tmp_host[0] = '\0'; + bool host_defaulted = port_separator_loc == address; + bool ipv6_in_host = false; + if (def_type) + *def_type = AF_UNSPEC; + +#if defined (ACE_HAS_IPV6) + // Check if this is a (possibly) IPv6 supporting profile containing a + // numeric IPv6 address representation. + if ((this->version_.major > TAO_MIN_IPV6_IIOP_MAJOR || + this->version_.minor >= TAO_MIN_IPV6_IIOP_MINOR) && + address[0] == '[') + { + // In this case we have to find the end of the numeric address and + // start looking for the port separator from there. + char const * const cp_pos = ACE_OS::strchr (address, ']'); + if (cp_pos == 0) + { + // No valid IPv6 address specified. + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("TAO (%P|%t) - ") + ACE_TEXT ("DIOP_Acceptor::open, ") + ACE_TEXT ("invalid IPv6 decimal address specified\n\n")), + -1); + } + else + { + // Extract out just the host part of the address. + size_t const len = cp_pos - (address + 1); + + if (len >= sizeof (tmp_host)) + return -1; + + ipv6_in_host = true; + host_defaulted = (cp_pos == address+1) || + (cp_pos == address+3 && address[1] == ':' && address[2] == ':'); + if (cp_pos[1] == ':') // Look for a port + port_separator_loc = cp_pos + 1; + else + port_separator_loc = 0; + if (def_type) + *def_type = AF_INET6; + + ACE_OS::memcpy (tmp_host, address + 1, len); + tmp_host[len] = '\0'; + } + } + else +#endif /* ACE_HAS_IPV6 */ + if (!host_defaulted) + { + if (port_separator_loc != 0) + { + // Extract out just the host part of the address. + size_t const len = port_separator_loc - address; + + if (len >= sizeof (tmp_host)) + return -1; + + ACE_OS::memcpy (tmp_host, address, len); + tmp_host[len] = '\0'; + } + else + ACE_OS::strcpy (tmp_host, address); + } + + if (!ipv6_in_host && !host_defaulted) + { + if (addr.set ((unsigned short) 0, tmp_host) != 0) + return -1; + this->default_address_.set (addr); + host_defaulted = addr.is_any (); + if (def_type) + *def_type = AF_INET; + } + + if (host_defaulted) + { + // First convert the port into a usable form. + unsigned short portno = 0; + if (port_separator_loc != 0) + { + portno = + static_cast<u_short> (ACE_OS::atoi (port_separator_loc + + sizeof (':'))); + } + this->default_address_.set_port_number (portno); + + // Now reset the port and set the host. + if (addr.set (this->default_address_) != 0) + return -1; + } + else if (port_separator_loc == 0) + { + // The address is a hostname. No port was specified, so assume + // port zero (port will be chosen for us). + specified_hostname = tmp_host[0] == '\0' ? address : tmp_host; + if (addr.set ((unsigned short) 0, + specified_hostname.c_str ()) != 0) + return -1; + } + else + { + // Host and port were specified. + if (addr.set (address) != 0) + return -1; + if (tmp_host[0] == '\0') + { + // Extract out just the host part of the address. + size_t const len = port_separator_loc - address; + + if (len >= sizeof (tmp_host)) + return -1; + + ACE_OS::memcpy (tmp_host, address, len); + tmp_host[len] = '\0'; + } + specified_hostname = tmp_host; + } + + return 1; +} + +int TAO_DIOP_Acceptor::dotted_decimal_address (ACE_INET_Addr &addr, char *&host) { - const char *tmp = addr.get_host_addr (); - if (tmp == 0) + int result = 0; + const char *tmp = 0; + + // If the IP address in the INET_Addr is the IN(6)ADDR_ANY address, + // then force the actual IP address to be used by initializing a new + // INET_Addr with the hostname from the original one. If that fails + // then something is seriously wrong with the systems networking + // setup. + if (addr.is_any ()) + { + ACE_INET_Addr new_addr; +#if defined (ACE_HAS_IPV6) + result = new_addr.set (addr.get_port_number (), + addr.get_host_name (), + 1, /* encode */ + addr.get_type ()); +#else /* ACE_HAS_IPV6 */ + result = new_addr.set (addr.get_port_number (), + addr.get_host_name ()); +#endif /* !ACE_HAS_IPV6 */ + tmp = new_addr.get_host_addr (); + } + else + tmp = addr.get_host_addr (); + + if (tmp == 0 || result != 0) { if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, @@ -498,7 +686,7 @@ TAO_DIOP_Acceptor::dotted_decimal_address (ACE_INET_Addr &addr, } int -TAO_DIOP_Acceptor::probe_interfaces (TAO_ORB_Core *orb_core) +TAO_DIOP_Acceptor::probe_interfaces (TAO_ORB_Core *orb_core, int def_type) { // Extract the hostname for each network interface, and then cache // it. The hostnames will then be used when creating a @@ -537,20 +725,108 @@ TAO_DIOP_Acceptor::probe_interfaces (TAO_ORB_Core *orb_core) // the list of cached hostnames unless it is the only interface. size_t lo_cnt = 0; // Loopback interface count for (size_t j = 0; j < if_cnt; ++j) - if (if_addrs[j].get_ip_address () == INADDR_LOOPBACK) + if (if_addrs[j].is_loopback ()) lo_cnt++; +#if defined (ACE_HAS_IPV6) + size_t ipv4_cnt = 0; + size_t ipv4_lo_cnt = 0; + size_t ipv6_ll = 0; + bool ipv6_non_ll = false; + // Scan for IPv4 interfaces since these should not be included + // when IPv6-only is selected. + for (size_t j = 0; j < if_cnt; ++j) + if (if_addrs[j].get_type () != AF_INET6 || + if_addrs[j].is_ipv4_mapped_ipv6 ()) + { + ++ipv4_cnt; + if (if_addrs[j].is_loopback ()) + ++ipv4_lo_cnt; // keep track of IPv4 loopback ifs + } + else if (!if_addrs[j].is_linklocal () && + !if_addrs[j].is_loopback()) + { + ipv6_non_ll = true; // we have at least 1 non-local IPv6 if + } + else if (!orb_core->orb_params ()->use_ipv6_link_local () && + if_addrs[j].is_linklocal ()) + { + ++ipv6_ll; // count link local addrs to exclude them afterwards + } +#endif /* ACE_HAS_IPV6 */ + // The instantiation for this template is in // tao/DIOP_Connector.cpp. ACE_Auto_Basic_Array_Ptr<ACE_INET_Addr> safe_if_addrs (if_addrs); +#if defined (ACE_HAS_IPV6) + bool ipv4_only = def_type == AF_INET; + bool ipv6_only = (def_type == AF_INET6) || + orb_core->orb_params ()->connect_ipv6_only (); +#if defined (ACE_WIN32) + if (this->default_address_.get_type () == AF_INET) + ipv4_only = true; + else + ipv6_only = true; +#endif /* ACE_WIN32 */ + // If the loopback interface is the only interface then include it + // in the list of interfaces to query for a hostname, otherwise + // exclude it from the list. + bool ignore_lo; + if (ipv6_only) + // only exclude loopback if non-local if exists + ignore_lo = ipv6_non_ll; + else if (ipv4_only) + ignore_lo = ipv4_cnt != ipv4_lo_cnt; + else + ignore_lo = if_cnt != lo_cnt; + + // Adjust counts for IPv6 only if required + size_t if_ok_cnt = if_cnt; + if (ipv6_only) + { + if_ok_cnt -= ipv4_cnt; + lo_cnt -= ipv4_lo_cnt; + ipv4_lo_cnt = 0; + } + else if (ipv4_only) + { + if_ok_cnt = ipv4_cnt; + lo_cnt = ipv4_lo_cnt; + } + + // In case there are no non-local IPv6 ifs in the list only exclude + // IPv4 loopback. + // IPv6 loopback will be needed to successfully connect IPv6 clients + // in a localhost environment. + if (!ipv4_only && !ipv6_non_ll) + lo_cnt = ipv4_lo_cnt; + + if (!ignore_lo) + this->endpoint_count_ = static_cast<CORBA::ULong> (if_ok_cnt - ipv6_ll); + else + this->endpoint_count_ = static_cast<CORBA::ULong> (if_ok_cnt - ipv6_ll - lo_cnt); +#else /* ACE_HAS_IPV6 */ // If the loopback interface is the only interface then include it // in the list of interfaces to query for a hostname, otherwise // exclude it from the list. - if (if_cnt == lo_cnt) + bool ignore_lo; + ignore_lo = if_cnt != lo_cnt; + if (!ignore_lo) this->endpoint_count_ = static_cast<CORBA::ULong> (if_cnt); else this->endpoint_count_ = static_cast<CORBA::ULong> (if_cnt - lo_cnt); +#endif /* !ACE_HAS_IPV6 */ + + if (this->endpoint_count_ == 0) + { + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT("(%P|%t) - DIOP_Acceptor::probe_interfaces, ") + ACE_TEXT("found no usable addresses, def_type = %d\n"), + def_type)); + return -1; + } ACE_NEW_RETURN (this->addrs_, ACE_INET_Addr[this->endpoint_count_], @@ -569,11 +845,38 @@ TAO_DIOP_Acceptor::probe_interfaces (TAO_ORB_Core *orb_core) for (size_t i = 0; i < if_cnt; ++i) { +#if defined (ACE_HAS_IPV6) + // Ignore any loopback interface if there are other + // non-loopback interfaces. + if (ignore_lo && + if_addrs[i].is_loopback () && + (ipv4_only || + ipv6_non_ll || + if_addrs[i].get_type () != AF_INET6)) + continue; + + // Ignore any non-IPv4 interfaces when so required. + if (ipv4_only && + (if_addrs[i].get_type () != AF_INET)) + continue; + + // Ignore any non-IPv6 interfaces when so required. + if (ipv6_only && + (if_addrs[i].get_type () != AF_INET6 || + if_addrs[i].is_ipv4_mapped_ipv6 ())) + continue; + + // Ignore all IPv6 link local interfaces when so required. + if (!orb_core->orb_params ()->use_ipv6_link_local () && + if_addrs[i].is_linklocal ()) + continue; +#else /* ACE_HAS_IPV6 */ // Ignore any loopback interface if there are other // non-loopback interfaces. - if (if_cnt != lo_cnt && - if_addrs[i].get_ip_address() == INADDR_LOOPBACK) + if (ignore_lo && + if_addrs[i].is_loopback ()) continue; +#endif /* !ACE_HAS_IPV6 */ if (this->hostname (orb_core, if_addrs[i], @@ -620,7 +923,7 @@ TAO_DIOP_Acceptor::object_key (IOP::TaggedProfile &profile, if (TAO_debug_level > 0) { ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("TAO (%P|%t) - DIOP_Profile::decode, v%d.%d\n"), + ACE_TEXT ("TAO (%P|%t) - DIOP_Profile::object_key, v%d.%d\n"), major, minor)); } @@ -663,11 +966,11 @@ TAO_DIOP_Acceptor::parse_options (const char *str) // HTTP URLs. // e.g.: option1=foo&option2=bar - ACE_CString options (str); + const ACE_CString options (str); - size_t len = options.length (); + const size_t len = options.length (); - const char option_delimiter = '&'; + static const char option_delimiter = '&'; // Count the number of options. diff --git a/TAO/tao/Strategies/DIOP_Acceptor.h b/TAO/tao/Strategies/DIOP_Acceptor.h index 334ef2b47dd..6dd90a72e43 100644 --- a/TAO/tao/Strategies/DIOP_Acceptor.h +++ b/TAO/tao/Strategies/DIOP_Acceptor.h @@ -59,6 +59,12 @@ public: /// Returns the array of endpoints in this acceptor const ACE_INET_Addr *endpoints (void); + /// Returns address for default endpoint + const ACE_INET_Addr& default_address (void) const; + + /// Set address for default endpoint + void set_default_address (const ACE_INET_Addr& addr); + /** * @name The TAO_Acceptor Methods * @@ -95,10 +101,10 @@ public: * hostname and the desired one cannot be determined in any * other way. */ - int hostname (TAO_ORB_Core *orb_core, - ACE_INET_Addr &addr, - char *&host, - const char *specified_hostname = 0); + virtual int hostname (TAO_ORB_Core *orb_core, + ACE_INET_Addr &addr, + char *&host, + const char *specified_hostname = 0); /** * Set the host name for the given address using the dotted decimal @@ -110,6 +116,20 @@ public: protected: /** + * Helper method + * Clear out 'addr' & 'specified_hostname' and initialize them based + * upon 'address'. If a non-zero pointer is passed in for def_type, + * this will be set to AF_INET6 if IPv6 support is enabled and + * supplied hostname is either [] or [::]. It will be set to AF_INET + * if the hostname is 0.0.0.0, otherwise it is set to + * AF_UNSPEC. This value is then passed to probe_interfaces by open. + */ + int parse_address (const char *address, + ACE_INET_Addr &addr, + ACE_CString &specified_hostname, + int *def_type = 0); + + /** * Implement the common part of the open*() methods. This method is * virtual to allow a derived class implementation to be invoked * instead. @@ -123,8 +143,13 @@ protected: * interface. The port for each initialized ACE_INET_Addr will be * set in the open_i() method. This method only gets invoked when * no explicit hostname is provided in the specified endpoint. + * + * The optional argument def_type is used to constrain the resulting + * list of interfaces to be either only IPv6 or IPv4, or both, when + * ACE_HAS_IPV6 is enabled and the source endpoint was an explicitly + * declared wildcard. */ - int probe_interfaces (TAO_ORB_Core *orb_core); + int probe_interfaces (TAO_ORB_Core *orb_core, int def_type = AF_UNSPEC); /// Parse protocol specific options. virtual int parse_options (const char *options); @@ -172,6 +197,9 @@ protected: /// Should we use GIOP lite?? CORBA::Boolean lite_flag_; + /// Address for default endpoint + ACE_INET_Addr default_address_; + private: // @@ Frank: From DIOP_Acceptor.h TAO_DIOP_Connection_Handler *connection_handler_; diff --git a/TAO/tao/Strategies/DIOP_Acceptor.inl b/TAO/tao/Strategies/DIOP_Acceptor.inl index 2603d4e7156..8aa46f549c1 100644 --- a/TAO/tao/Strategies/DIOP_Acceptor.inl +++ b/TAO/tao/Strategies/DIOP_Acceptor.inl @@ -25,4 +25,16 @@ TAO_DIOP_Acceptor::endpoints (void) return this->addrs_; } +ACE_INLINE const ACE_INET_Addr& +TAO_DIOP_Acceptor::default_address (void) const +{ + return this->default_address_; +} + +ACE_INLINE void +TAO_DIOP_Acceptor::set_default_address (const ACE_INET_Addr& addr) +{ + this->default_address_.set (addr); +} + TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/Strategies/DIOP_Connection_Handler.cpp b/TAO/tao/Strategies/DIOP_Connection_Handler.cpp index f76d739af62..940d69d8897 100644 --- a/TAO/tao/Strategies/DIOP_Connection_Handler.cpp +++ b/TAO/tao/Strategies/DIOP_Connection_Handler.cpp @@ -49,7 +49,7 @@ TAO_DIOP_Connection_Handler::TAO_DIOP_Connection_Handler (TAO_ORB_Core *orb_core { TAO_DIOP_Transport* specific_transport = 0; ACE_NEW (specific_transport, - TAO_DIOP_Transport(this, orb_core, flag)); + TAO_DIOP_Transport (this, orb_core, flag)); // store this pointer (indirectly increment ref count) this->transport (specific_transport); @@ -65,9 +65,9 @@ TAO_DIOP_Connection_Handler::~TAO_DIOP_Connection_Handler (void) if (result == -1 && TAO_debug_level) { ACE_ERROR ((LM_ERROR, - ACE_TEXT("TAO (%P|%t) - DIOP_Connection_Handler::") - ACE_TEXT("~DIOP_Connection_Handler, ") - ACE_TEXT("release_os_resources() failed %m\n"))); + ACE_TEXT ("TAO (%P|%t) - DIOP_Connection_Handler::") + ACE_TEXT ("~DIOP_Connection_Handler, ") + ACE_TEXT ("release_os_resources() failed %m\n"))); } this->udp_socket_.close (); } @@ -97,14 +97,14 @@ TAO_DIOP_Connection_Handler::addr (const ACE_INET_Addr &addr) const ACE_INET_Addr & TAO_DIOP_Connection_Handler::local_addr (void) { - return local_addr_; + return this->local_addr_; } void TAO_DIOP_Connection_Handler::local_addr (const ACE_INET_Addr &addr) { - local_addr_ = addr; + this->local_addr_ = addr; } @@ -220,7 +220,7 @@ TAO_DIOP_Connection_Handler::open_server (void) protocol_properties.recv_buffer_size_) == -1) return -1; - if( TAO_debug_level > 5) + if (TAO_debug_level > 5) { ACE_DEBUG ((LM_DEBUG, ACE_TEXT("TAO (%P|%t) - DIOP_Connection_Handler::open_server, ") @@ -302,14 +302,64 @@ TAO_DIOP_Connection_Handler::release_os_resources (void) } int +TAO_DIOP_Connection_Handler::add_transport_to_cache (void) +{ + ACE_INET_Addr addr; + + // This function is called by the acceptor to add this + // transport to the transport cache. This is really + // important for proper shutdown. The address used + // is irrelevent, since DIOP is connectionless. + + // Construct a DIOP_Endpoint object. + TAO_DIOP_Endpoint endpoint ( + addr, + this->orb_core ()->orb_params ()->cache_incoming_by_dotted_decimal_address ()); + + // Construct a property object + TAO_Base_Transport_Property prop (&endpoint); + + // Add the handler to Cache + return this->orb_core ()->lane_resources () + .transport_cache ().cache_transport (&prop, + this->transport ()); +} + +int TAO_DIOP_Connection_Handler::set_tos (int tos) { if (tos != this->dscp_codepoint_) { - int const result = this->dgram ().set_option (IPPROTO_IP, - IP_TOS, - (int *) &tos , - (int) sizeof (tos)); + int result = 0; +#if defined (ACE_HAS_IPV6) + ACE_INET_Addr local_addr; + if (this->dgram ().get_local_addr (local_addr) == -1) + return -1; + else if (local_addr.get_type () == AF_INET6) +# if !defined (IPV6_TCLASS) + // IPv6 defines option IPV6_TCLASS for specifying traffic class/priority + // but not many implementations yet (very new;-). + { + if (TAO_debug_level) + { + ACE_DEBUG ((LM_DEBUG, + "TAO (%P|%t) - DIOP_Connection_Handler::" + "set_dscp_codepoint -> IPV6_TCLASS not supported yet\n")); + } + return 0; + } +# else /* !IPV6_TCLASS */ + result = this->dgram ().set_option (IPPROTO_IPV6, + IPV6_TCLASS, + (int *) &tos , + (int) sizeof (tos)); + else +# endif /* IPV6_TCLASS */ +#endif /* ACE_HAS_IPV6 */ + result = this->dgram ().set_option (IPPROTO_IP, + IP_TOS, + (int *) &tos , + (int) sizeof (tos)); if (TAO_debug_level) { diff --git a/TAO/tao/Strategies/DIOP_Connector.cpp b/TAO/tao/Strategies/DIOP_Connector.cpp index 9a4182b3822..048c2830cd9 100644 --- a/TAO/tao/Strategies/DIOP_Connector.cpp +++ b/TAO/tao/Strategies/DIOP_Connector.cpp @@ -14,6 +14,8 @@ #include "tao/Protocols_Hooks.h" #include "ace/OS_NS_strings.h" #include "ace/OS_NS_string.h" +#include "tao/Thread_Lane_Resources.h" +#include "ace/os_include/os_netdb.h" #include "tao/Strategies/DIOP_Profile.h" @@ -44,24 +46,12 @@ TAO_DIOP_Connector::open (TAO_ORB_Core *orb_core) if (this->create_connect_strategy () == -1) return -1; - // @@ Michael: We do not use regular connection management. - return 0; } int TAO_DIOP_Connector::close (void) { - // The list of service handlers cleans itself?? - SvcHandlerIterator iter (svc_handler_table_); - - while (!iter.done ()) - { - (*iter).int_id_->remove_reference (); - iter++; - } - - // @@ Michael: We do not use regular connection management. return 0; } @@ -80,7 +70,12 @@ TAO_DIOP_Connector::set_validate_endpoint (TAO_Endpoint *endpoint) // Verify that the remote ACE_INET_Addr was initialized properly. // Failure can occur if hostname lookup failed when initializing the // remote ACE_INET_Addr. +#if defined (ACE_HAS_IPV6) + if (remote_address.get_type () != AF_INET && + remote_address.get_type () != AF_INET6) +#else /* ACE_HAS_IPV6 */ if (remote_address.get_type () != AF_INET) +#endif /* !ACE_HAS_IPV6 */ { if (TAO_debug_level > 0) { @@ -111,34 +106,107 @@ TAO_DIOP_Connector::make_connection (TAO::Profile_Transport_Resolver *, const ACE_INET_Addr &remote_address = diop_endpoint->object_addr (); +#if defined (ACE_HAS_IPV6) && !defined (ACE_HAS_IPV6_V6ONLY) + // Check if we need to invalidate accepted connections + // from IPv4 mapped IPv6 addresses + if (this->orb_core ()->orb_params ()->connect_ipv6_only () && + remote_address.is_ipv4_mapped_ipv6 ()) + { + if (TAO_debug_level > 0) + { + ACE_TCHAR remote_as_string[MAXHOSTNAMELEN + 16]; + + (void) remote_address.addr_to_string (remote_as_string, + sizeof remote_as_string); + + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("TAO (%P|%t) - DIOP_Connection_Handler::open, ") + ACE_TEXT ("invalid connection to IPv4 mapped IPv6 interface <%s>!\n"), + remote_as_string)); + } + return 0; + } +#endif /* ACE_HAS_IPV6 && ACE_HAS_IPV6_V6ONLY */ + TAO_DIOP_Connection_Handler *svc_handler = 0; - if (svc_handler_table_.find (remote_address, svc_handler) == -1) + ACE_NEW_RETURN (svc_handler, + TAO_DIOP_Connection_Handler (this->orb_core (), + this->lite_flag_), + 0); + + u_short port = 0; + const ACE_UINT32 ia_any = INADDR_ANY; + ACE_INET_Addr local_addr (port, ia_any); + +#if defined (ACE_HAS_IPV6) + if (remote_address.get_type () == AF_INET6) + local_addr.set (port, + ACE_IPV6_ANY); +#endif /* ACE_HAS_IPV6 */ + + svc_handler->local_addr (local_addr); + svc_handler->addr (remote_address); + + int retval = svc_handler->open (0); + + // Failure to open a connection. + if (retval != 0) { - TAO_DIOP_Connection_Handler *svc_handler_i = 0; - ACE_NEW_RETURN (svc_handler_i, - TAO_DIOP_Connection_Handler (this->orb_core (), - this->lite_flag_), - 0); - - svc_handler_i->local_addr (ACE_sap_any_cast (ACE_INET_Addr &)); - svc_handler_i->addr (remote_address); - - svc_handler_i->open (0); - - svc_handler_table_.bind (remote_address, svc_handler_i); - svc_handler = svc_handler_i; - - if (TAO_debug_level > 2) - ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("TAO (%P|%t) - DIOP_Connector::connect, ") - ACE_TEXT ("new connection on HANDLE %d\n"), - svc_handler->get_handle ())); - } - - // @@ Michael: We do not use regular connection management. - svc_handler->add_reference (); - TAO_Transport *transport = svc_handler->transport (); + if (TAO_debug_level > 0) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("TAO (%P|%t) - DIOP_Connector::make_connection, ") + ACE_TEXT ("could not make a new connection\n"))); + } + + return 0; + } + + if (TAO_debug_level > 2) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - DIOP_Connector::connect, ") + ACE_TEXT ("new connection on HANDLE %d\n"), + svc_handler->get_handle ())); + + TAO_DIOP_Transport *transport = + dynamic_cast <TAO_DIOP_Transport *> (svc_handler->transport ()); + + // In case of errors transport is zero + if (transport == 0) + { + // Give users a clue to the problem. + if (TAO_debug_level > 3) + ACE_DEBUG ((LM_ERROR, + ACE_TEXT ("TAO (%P|%t) - DIOP_Connector::make_connection, ") + ACE_TEXT ("connection to <%s:%u> failed (%p)\n"), + ACE_TEXT_CHAR_TO_TCHAR (diop_endpoint->host ()), + diop_endpoint->port (), + ACE_TEXT ("errno"))); + + return 0; + } + + // Add the handler to Cache + retval = + this->orb_core ()->lane_resources ().transport_cache ().cache_transport (&desc, + transport); + + // Failure in adding to cache. + if (retval != 0) + { + // Close the handler. + svc_handler->close (); + + if (TAO_debug_level > 0) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("TAO (%P|%t) - DIOP_Connector::make_connection, ") + ACE_TEXT ("could not add the new connection to cache\n"))); + } + + return 0; + } return transport; } diff --git a/TAO/tao/Strategies/DIOP_Connector.h b/TAO/tao/Strategies/DIOP_Connector.h index 90061e3d823..2e4befc78b8 100644 --- a/TAO/tao/Strategies/DIOP_Connector.h +++ b/TAO/tao/Strategies/DIOP_Connector.h @@ -99,20 +99,6 @@ private: /// Return the remote endpoint, a helper function TAO_DIOP_Endpoint *remote_endpoint (TAO_Endpoint *ep); - -private: - // @@ Michael: UDP Addition - ACE_Hash_Map_Manager_Ex < ACE_INET_Addr, - TAO_DIOP_Connection_Handler *, - ACE_Hash < ACE_INET_Addr >, - ACE_Equal_To < ACE_INET_Addr >, - ACE_Null_Mutex > svc_handler_table_; - - typedef ACE_Hash_Map_Iterator_Ex < ACE_INET_Addr, - TAO_DIOP_Connection_Handler *, - ACE_Hash < ACE_INET_Addr >, - ACE_Equal_To < ACE_INET_Addr >, - ACE_Null_Mutex > SvcHandlerIterator; }; TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/Strategies/DIOP_Endpoint.cpp b/TAO/tao/Strategies/DIOP_Endpoint.cpp index 5efa0efd332..ace8929ad97 100644 --- a/TAO/tao/Strategies/DIOP_Endpoint.cpp +++ b/TAO/tao/Strategies/DIOP_Endpoint.cpp @@ -33,6 +33,9 @@ TAO_DIOP_Endpoint::TAO_DIOP_Endpoint (const ACE_INET_Addr &addr, : TAO_Endpoint (TAO_TAG_DIOP_PROFILE) , host_ () , port_ (0) +#if defined (ACE_HAS_IPV6) + , is_ipv6_decimal_ (false) +#endif /* ACE_HAS_IPV6 */ , object_addr_ (addr) , object_addr_set_ (false) , next_ (0) @@ -48,18 +51,23 @@ TAO_DIOP_Endpoint::TAO_DIOP_Endpoint (const char *host, priority) , host_ () , port_ (port) +#if defined (ACE_HAS_IPV6) + , is_ipv6_decimal_ (false) +#endif /* ACE_HAS_IPV6 */ , object_addr_ (addr) , object_addr_set_ (false) , next_ (0) { - if (host != 0) - this->host_ = host; + this->host (host); // With IPv6 performs check for decimal address } TAO_DIOP_Endpoint::TAO_DIOP_Endpoint (void) : TAO_Endpoint (TAO_TAG_DIOP_PROFILE), host_ (), port_ (0), +#if defined (ACE_HAS_IPV6) + is_ipv6_decimal_ (false), +#endif /* ACE_HAS_IPV6 */ object_addr_ (), object_addr_set_ (false), next_ (0) @@ -69,17 +77,17 @@ TAO_DIOP_Endpoint::TAO_DIOP_Endpoint (void) TAO_DIOP_Endpoint::TAO_DIOP_Endpoint (const char *host, CORBA::UShort port, CORBA::Short priority) - : TAO_Endpoint (TAO_TAG_DIOP_PROFILE), + : TAO_Endpoint (TAO_TAG_DIOP_PROFILE, priority), host_ (), port_ (port), +#if defined (ACE_HAS_IPV6) + is_ipv6_decimal_ (false), +#endif /* ACE_HAS_IPV6 */ object_addr_ (), object_addr_set_ (false), next_ (0) { - if (host != 0) - this->host_ = host; - - this->priority (priority); + this->host (host); // With IPv6 performs check for decimal address } TAO_DIOP_Endpoint::~TAO_DIOP_Endpoint (void) @@ -92,9 +100,21 @@ TAO_DIOP_Endpoint::set (const ACE_INET_Addr &addr, { char tmp_host[MAXHOSTNAMELEN + 1]; +#if defined (ACE_HAS_IPV6) + this->is_ipv6_decimal_ = false; // Reset +#endif /* ACE_HAS_IPV6 */ + if (use_dotted_decimal_addresses || addr.get_host_name (tmp_host, sizeof (tmp_host)) != 0) { + if (use_dotted_decimal_addresses == 0 && TAO_debug_level > 5) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - DIOP_Endpoint::set, ") + ACE_TEXT ("%p\n"), + ACE_TEXT ("cannot determine hostname"))); + } + const char *tmp = addr.get_host_addr (); if (tmp == 0) { @@ -102,17 +122,23 @@ TAO_DIOP_Endpoint::set (const ACE_INET_Addr &addr, ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("TAO (%P|%t) - ") ACE_TEXT ("DIOP_Endpoint::set, ") - ACE_TEXT ("%p\n\n"), + ACE_TEXT ("%p\n"), ACE_TEXT ("cannot determine hostname\n"))); return -1; } else - this->host_ = tmp; + { + this->host_ = tmp; +#if defined (ACE_HAS_IPV6) + if (addr.get_type () == PF_INET6) + this->is_ipv6_decimal_ = true; +#endif /* ACE_HAS_IPV6 */ + } } else this->host_ = CORBA::string_dup (tmp_host); - this->port_ = addr.get_port_number(); + this->port_ = addr.get_port_number (); return 0; } @@ -120,15 +146,26 @@ TAO_DIOP_Endpoint::set (const ACE_INET_Addr &addr, int TAO_DIOP_Endpoint::addr_to_string (char *buffer, size_t length) { - size_t const actual_len = + size_t actual_len = ACE_OS::strlen (this->host_.in ()) // chars in host name + sizeof (':') // delimiter + ACE_OS::strlen ("65536") // max port + sizeof ('\0'); +#if defined (ACE_HAS_IPV6) + if (this->is_ipv6_decimal_) + actual_len += 2; // '[' + ']' +#endif /* ACE_HAS_IPV6 */ + if (length < actual_len) return -1; +#if defined (ACE_HAS_IPV6) + if (this->is_ipv6_decimal_) + ACE_OS::sprintf (buffer, "[%s]:%d", + this->host_.in (), this->port_); + else +#endif /* ACE_HAS_IPV6 */ ACE_OS::sprintf (buffer, "%s:%d", this->host_.in (), this->port_); @@ -139,6 +176,10 @@ const char * TAO_DIOP_Endpoint::host (const char *h) { this->host_ = h; +#if defined (ACE_HAS_IPV6) + if (ACE_OS::strchr (h, ':') != 0) + this->is_ipv6_decimal_ = true; +#endif /* ACE_HAS_IPV6 */ return this->host_.in (); } @@ -174,7 +215,7 @@ TAO_DIOP_Endpoint::is_equivalent (const TAO_Endpoint *other_endpoint) return 0; return (this->port () == endpoint->port () - && ACE_OS::strcmp(this->host (), endpoint->host()) == 0); + && ACE_OS::strcmp (this->host (), endpoint->host ()) == 0); } CORBA::ULong @@ -211,40 +252,66 @@ TAO_DIOP_Endpoint::object_addr (void) const // Double checked locking optimization. if (!this->object_addr_set_) { - // We need to modify the object_addr_ in this method. Do so - // using a non-const copy of the <this> pointer. - TAO_DIOP_Endpoint *endpoint = - const_cast<TAO_DIOP_Endpoint *> (this); - ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, - endpoint->addr_lookup_lock_, + this->addr_lookup_lock_, this->object_addr_ ); if (!this->object_addr_set_) { - if (endpoint->object_addr_.set (this->port_, - this->host_.in ()) == -1) - { - // If this call fails, it most likely due a hostname - // lookup failure caused by a DNS misconfiguration. If - // a request is made to the object at the given host and - // port, then a CORBA::TRANSIENT() exception should be - // thrown. - - // Invalidate the ACE_INET_Addr. This is used as a flag - // to denote that ACE_INET_Addr initialization failed. - endpoint->object_addr_.set_type (-1); - } - else - { - endpoint->object_addr_set_ = true; - } + (void) this->object_addr_i (); } } return this->object_addr_; } +void +TAO_DIOP_Endpoint::object_addr_i (void) const +{ + // We should have already held the lock + +#if defined (ACE_HAS_IPV6) + bool is_ipv4_decimal_ = false; + if (!this->is_ipv6_decimal_) + is_ipv4_decimal_ = + ACE_OS::strspn (this->host_.in (), ".0123456789") == + ACE_OS::strlen (this->host_.in ()); + + // If this is *not* an IPv4 decimal address at first try to + // resolve the address as an IPv6 address; if that fails + // (or it's an IPv4 address) and the address is *not* an IPv6 + // decimal address try to resolve it as an IPv4 address. + if ((is_ipv4_decimal_ || + this->object_addr_.set (this->port_, + this->host_.in (), + 1, + AF_INET6) == -1) && + (this->is_ipv6_decimal_ || + this->object_addr_.set (this->port_, + this->host_.in (), + 1, + AF_INET) == -1)) +#else + if (this->object_addr_.set (this->port_, + this->host_.in ()) == -1) +#endif /* ACE_HAS_IPV6 */ + { + // If this call fails, it most likely due a hostname + // lookup failure caused by a DNS misconfiguration. If + // a request is made to the object at the given host and + // port, then a CORBA::TRANSIENT() exception should be + // thrown. + + // Invalidate the ACE_INET_Addr. This is used as a flag + // to denote that ACE_INET_Addr initialization failed. + this->object_addr_.set_type (-1); + } + else + { + this->object_addr_set_ = true; + } +} + TAO_END_VERSIONED_NAMESPACE_DECL #endif /* TAO_HAS_DIOP && TAO_HAS_DIOP != 0 */ diff --git a/TAO/tao/Strategies/DIOP_Endpoint.h b/TAO/tao/Strategies/DIOP_Endpoint.h index 3c664bc4096..0a54dec186e 100644 --- a/TAO/tao/Strategies/DIOP_Endpoint.h +++ b/TAO/tao/Strategies/DIOP_Endpoint.h @@ -117,18 +117,26 @@ private: int set (const ACE_INET_Addr &addr, int use_dotted_decimal_addresses); + /// Helper method for object_addr () call. + void object_addr_i (void) const; + /// String representing the host name. CORBA::String_var host_; /// TCP port number. CORBA::UShort port_; +#if defined (ACE_HAS_IPV6) + /// Does the host string represent an IPv6 decimal address. + bool is_ipv6_decimal_; +#endif /* ACE_HAS_IPV6 */ + /// Cached instance of <ACE_INET_Addr> for use in making /// invocations, etc. - ACE_INET_Addr object_addr_; + mutable ACE_INET_Addr object_addr_; /// Flag to indicate if the address has been resolved and set. - bool object_addr_set_; + mutable bool object_addr_set_; /// DIOP Endpoints can be stringed into a list. Return the next /// endpoint in the list, if any. diff --git a/TAO/tao/Strategies/DIOP_Profile.cpp b/TAO/tao/Strategies/DIOP_Profile.cpp index ccac587348c..14ef4fbd3b1 100644 --- a/TAO/tao/Strategies/DIOP_Profile.cpp +++ b/TAO/tao/Strategies/DIOP_Profile.cpp @@ -101,7 +101,7 @@ TAO_DIOP_Profile::decode_profile (TAO_InputCDR& cdr) { if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("TAO (%P|%t) - DIOP_Profile::decode - ") + ACE_TEXT ("TAO (%P|%t) - DIOP_Profile::decode_profile, ") ACE_TEXT ("error while decoding host/port\n"))); return -1; } @@ -139,6 +139,45 @@ TAO_DIOP_Profile::parse_string_i (const char *ior) CORBA::ULong length_host = 0; const char *cp_pos = ACE_OS::strchr (ior, ':'); // Look for a port +#if defined (ACE_HAS_IPV6) + // IPv6 numeric address in host string? + bool ipv6_in_host = false; + + // Check if this is a (possibly) IPv6 supporting profile containing a + // decimal IPv6 address representation. + if ((this->version ().major > TAO_MIN_IPV6_IIOP_MAJOR || + this->version ().minor >= TAO_MIN_IPV6_IIOP_MINOR) && + ior[0] == '[') + { + // In this case we have to find the end of the numeric address and + // start looking for the port separator from there. + const char *cp_pos_a = ACE_OS::strchr (ior, ']'); + if (cp_pos_a == 0) + { + // No valid IPv6 address specified. + if (TAO_debug_level > 0) + { + ACE_DEBUG ((LM_ERROR, + ACE_TEXT ("\nTAO (%P|%t) - DIOP_Profile::parse_string_i, ") + ACE_TEXT ("invalid IPv6 decimal address specified.\n"))); + } + + ACE_THROW (CORBA::INV_OBJREF ( + CORBA::SystemException::_tao_minor_code ( + 0, + EINVAL), + CORBA::COMPLETED_NO)); + } + else + { + if (cp_pos_a[1] == ':') // Look for a port + cp_pos = cp_pos_a + 1; + else + cp_pos = 0; + ipv6_in_host = true; // host string contains full IPv6 numeric address + } + } +#endif /* ACE_HAS_IPV6 */ if (cp_pos == ior) { @@ -159,21 +198,53 @@ TAO_DIOP_Profile::parse_string_i (const char *ior) ACE_OS::strncpy (tmp.inout (), cp_pos + 1, length_port); tmp[length_port] = '\0'; - this->endpoint_.port_ = - static_cast<CORBA::UShort> (ACE_OS::atoi (tmp.in ())); + if (ACE_OS::strspn (tmp.in (), "1234567890") == length_port) + { + this->endpoint_.port_ = + static_cast<CORBA::UShort> (ACE_OS::atoi (tmp.in ())); + } + else + { + ACE_INET_Addr ia; + if (ia.string_to_addr (tmp.in ()) == -1) + { + ACE_THROW (CORBA::INV_OBJREF ( + CORBA::SystemException::_tao_minor_code ( + 0, + EINVAL), + CORBA::COMPLETED_NO)); + } + else + { + this->endpoint_.port_ = ia.get_port_number (); + } + } length_host = cp_pos - ior; } else length_host = okd - ior; +#if defined (ACE_HAS_IPV6) + if (ipv6_in_host) + length_host -= 2; // don't store '[' and ']' +#endif /* ACE_HAS_IPV6 */ + CORBA::String_var tmp = CORBA::string_alloc (length_host); +#if defined (ACE_HAS_IPV6) + if (ipv6_in_host) + ACE_OS::strncpy (tmp.inout (), ior + 1, length_host); + else +#endif /* ACE_HAS_IPV6 */ // Skip the trailing '/' ACE_OS::strncpy (tmp.inout (), ior, length_host); tmp[length_host] = '\0'; this->endpoint_.host_ = tmp._retn (); +#if defined (ACE_HAS_IPV6) + this->endpoint_.is_ipv6_decimal_ = ipv6_in_host; +#endif /* ACE_HAS_IPV6 */ if (ACE_OS::strcmp (this->endpoint_.host_.in (), "") == 0) { @@ -192,8 +263,8 @@ TAO_DIOP_Profile::parse_string_i (const char *ior) if (TAO_debug_level > 0) ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("TAO (%P|%t) - ") - ACE_TEXT ("DIOP_Profile::parse_string ") - ACE_TEXT ("- %p\n\n"), + ACE_TEXT ("DIOP_Profile::parse_string_i, ") + ACE_TEXT ("%p\n\n"), ACE_TEXT ("cannot determine hostname"))); // @@ What's the right exception to throw here? @@ -221,6 +292,10 @@ TAO_DIOP_Profile::do_is_equivalent (const TAO_Profile *other_profile) const TAO_DIOP_Profile *op = dynamic_cast<const TAO_DIOP_Profile *> (other_profile); + // Make sure we have a TAO_DIOP_Profile. + if (op == 0) + return 0; + // Check endpoints equivalence. const TAO_DIOP_Endpoint *other_endp = &op->endpoint_; for (TAO_DIOP_Endpoint *endp = &this->endpoint_; @@ -289,35 +364,83 @@ TAO_DIOP_Profile::add_endpoint (TAO_DIOP_Endpoint *endp) char * TAO_DIOP_Profile::to_string (void) { + // corbaloc:diop:1.2@host:port,diop:1.2@host:port,.../key + CORBA::String_var key; - TAO::ObjectKey::encode_sequence_to_string (key.inout(), - this->ref_object_key_->object_key ()); - - size_t buflen = (8 /* "corbaloc" */ + - 1 /* colon separator */ + - ACE_OS::strlen (::the_prefix) + - 1 /* colon separator */ + - 1 /* major version */ + - 1 /* decimal point */ + - 1 /* minor version */ + - 1 /* `@' character */ + - ACE_OS::strlen (this->endpoint_.host ()) + - 1 /* colon separator */ + - 5 /* port number */ + - 1 /* object key separator */ + - ACE_OS::strlen (key.in ())); + TAO::ObjectKey::encode_sequence_to_string (key.inout (), + this->ref_object_key_->object_key ()); + + size_t buflen = ( + 8 /* "corbaloc" */ + + 1 /* colon separator */ + + 1 /* object key separator */ + + ACE_OS::strlen (key.in ())); + size_t pfx_len = ( + ACE_OS::strlen (::the_prefix) /* "diop" */ + + 1 /* colon separator */); + + const TAO_DIOP_Endpoint *endp = 0; + for (endp = &this->endpoint_; endp != 0; endp = endp->next_) + { + buflen += ( + pfx_len + + 1 /* major version */ + + 1 /* decimal point */ + + 1 /* minor version */ + + 1 /* `@' character */ + + ACE_OS::strlen (endp->host ()) + + 1 /* colon separator */ + + 5 /* port number */ + + 1 /* comma */); +#if defined (ACE_HAS_IPV6) + if (endp->is_ipv6_decimal_) + buflen += 2; // room for '[' and ']' +#endif /* ACE_HAS_IPV6 */ + } + + static const char digits [] = "0123456789"; char * buf = CORBA::string_alloc (static_cast<CORBA::ULong> (buflen)); - static const char digits [] = "0123456789"; + ACE_OS::strcpy (buf, "corbaloc:"); + + for (endp = &this->endpoint_; endp != 0; endp = endp->next_) + { + if (&this->endpoint_ != endp) + ACE_OS::strcat (buf, ","); - ACE_OS::sprintf (buf, - "corbaloc:%s:%c.%c@%s:%d%c%s", - ::the_prefix, - digits [this->version_.major], - digits [this->version_.minor], - this->endpoint_.host (), - this->endpoint_.port (), +#if defined (ACE_HAS_IPV6) + if (endp->is_ipv6_decimal_) + { + // Don't publish scopeid if included. + ACE_CString tmp (endp->host ()); + ACE_CString::size_type pos = tmp.find ('%'); + if (pos != ACE_CString::npos) + { + tmp = tmp.substr (0, pos + 1); + tmp[pos] = '\0'; + } + ACE_OS::sprintf (buf + ACE_OS::strlen (buf), + "%s:%c.%c@[%s]:%d", + ::the_prefix, + digits [this->version_.major], + digits [this->version_.minor], + tmp.c_str (), + endp->port ()); + } + else +#endif + ACE_OS::sprintf (buf + ACE_OS::strlen (buf), + "%s:%c.%c@%s:%d", + ::the_prefix, + digits [this->version_.major], + digits [this->version_.minor], + endp->host (), + endp->port ()); + + } + ACE_OS::sprintf (buf + ACE_OS::strlen (buf), + "%c%s", this->object_key_delimiter_, key.in ()); @@ -340,6 +463,21 @@ TAO_DIOP_Profile::create_profile_body (TAO_OutputCDR &encap) const encap.write_octet (this->version_.minor); // STRING hostname from profile +#if defined (ACE_HAS_IPV6) + // For IPv6 decimal addresses make sure the possibly included scopeid + // is not published as this has only local meaning. + const char* host; + const char* pos; + if (this->endpoint_.is_ipv6_decimal_ && + (pos = ACE_OS::strchr (host = this->endpoint_.host (), '%')) != 0) + { + ACE_CString tmp; + size_t len = pos - host; + tmp.set (this->endpoint_.host (), len, 1); + encap.write_string (tmp.c_str ()); + } + else +#endif /* ACE_HAS_IPV6 */ encap.write_string (this->endpoint_.host ()); // UNSIGNED SHORT port number @@ -351,7 +489,7 @@ TAO_DIOP_Profile::create_profile_body (TAO_OutputCDR &encap) const else { ACE_ERROR ((LM_ERROR, - "TAO (%P|%t) - DIOP_Profile::create_profile_body " + "TAO (%P|%t) - DIOP_Profile::create_profile_body, " "no object key marshalled\n")); } @@ -378,6 +516,23 @@ TAO_DIOP_Profile::encode_endpoints (void) i < this->count_; ++i) { +#if defined (ACE_HAS_IPV6) + if (endpoint->is_ipv6_decimal_) + { + // Don't publish scopeid if included. + ACE_CString tmp (endpoint->host ()); + ACE_CString::size_type pos = tmp.find ('%'); + if (pos != ACE_CString::npos) + { + tmp = tmp.substr (0, pos + 1); + tmp[pos] = '\0'; + endpoints[i].host = tmp.c_str (); + } + else + endpoints[i].host = tmp.c_str (); + } + else +#endif /* ACE_HAS_IPV6 */ endpoints[i].host = endpoint->host (); endpoints[i].port = endpoint->port (); endpoints[i].priority = endpoint->priority (); @@ -391,27 +546,8 @@ TAO_DIOP_Profile::encode_endpoints (void) == 0) || (out_cdr << endpoints) == 0) return -1; - size_t length = out_cdr.total_length (); - - IOP::TaggedComponent tagged_component; - tagged_component.tag = TAO_TAG_ENDPOINTS; - tagged_component.component_data.length (static_cast<CORBA::ULong> (length)); - CORBA::Octet *buf = - tagged_component.component_data.get_buffer (); - - for (const ACE_Message_Block *iterator = out_cdr.begin (); - iterator != 0; - iterator = iterator->cont ()) - { - size_t i_length = iterator->length (); - ACE_OS::memcpy (buf, iterator->rd_ptr (), i_length); - - buf += i_length; - } - // Add component with encoded endpoint data to this profile's - // TaggedComponents. - tagged_components_.set_component (tagged_component); + this->set_tagged_components (out_cdr); return 0; } diff --git a/TAO/tao/Strategies/DIOP_Transport.cpp b/TAO/tao/Strategies/DIOP_Transport.cpp index 180317673b3..9541913700f 100644 --- a/TAO/tao/Strategies/DIOP_Transport.cpp +++ b/TAO/tao/Strategies/DIOP_Transport.cpp @@ -117,7 +117,7 @@ TAO_DIOP_Transport::recv (char *buf, if (TAO_debug_level > 0) { ACE_DEBUG ((LM_DEBUG, - "TAO (%P|%t) - DIOP_Transport::recv_i: received %d bytes from %s:%d %d\n", + "TAO (%P|%t) - DIOP_Transport::recv, received %d bytes from %s:%d %d\n", n, ACE_TEXT_CHAR_TO_TCHAR (from_addr.get_host_name ()), from_addr.get_port_number (), @@ -129,7 +129,7 @@ TAO_DIOP_Transport::recv (char *buf, if (n == -1 && TAO_debug_level > 4) { ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("TAO (%P|%t) - %p \n"), + ACE_TEXT ("TAO (%P|%t) - DIOP_Transport::recv, %p \n"), ACE_TEXT ("TAO - read message failure ") ACE_TEXT ("recv () \n"))); } @@ -277,7 +277,7 @@ TAO_DIOP_Transport::send_request (TAO_Stub *stub, return -1; - this->first_request_sent(); + this->first_request_sent (); return 0; } @@ -306,7 +306,8 @@ TAO_DIOP_Transport::send_message (TAO_OutputCDR &stream, { if (TAO_debug_level) ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("TAO (%P|%t) - DIOP_Transport, closing transport %d after fault %p\n"), + ACE_TEXT ("TAO (%P|%t) - DIOP_Transport::send_message, ") + ACE_TEXT ("closing transport %d after fault %p\n"), this->id (), ACE_TEXT ("send_message ()\n"))); |