IIOP_Acceptor.cpp

Go to the documentation of this file.
00001 /*
00002  * Hook to copy all include and forward declarations.
00003  */
00004 //@@ TAO_ACCEPTOR_SPL_COPY_HOOK_START
00005 #include "tao/IIOP_Acceptor.h"
00006 
00007 #if defined (TAO_HAS_IIOP) && (TAO_HAS_IIOP != 0)
00008 
00009 #include "tao/IIOP_Profile.h"
00010 #include "tao/MProfile.h"
00011 #include "tao/debug.h"
00012 #include "tao/Protocols_Hooks.h"
00013 #include "tao/Codeset_Manager.h"
00014 #include "tao/Transport.h"
00015 #include "tao/ORB_Core.h"
00016 #include "tao/CDR.h"
00017 
00018 #if !defined(__ACE_INLINE__)
00019 #include "tao/IIOP_Acceptor.inl"
00020 #endif /* __ACE_INLINE__ */
00021 
00022 #include "ace/Auto_Ptr.h"
00023 #include "ace/OS_NS_string.h"
00024 #include "ace/os_include/os_netdb.h"
00025 
00026 ACE_RCSID (tao,
00027            IIOP_Acceptor,
00028            "$Id: IIOP_Acceptor.cpp 78995 2007-07-23 11:59:20Z johnnyw $")
00029 
00030 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00031 
00032 TAO_IIOP_Acceptor::TAO_IIOP_Acceptor (void)
00033   : TAO_Acceptor (IOP::TAG_INTERNET_IOP),
00034     addrs_ (0),
00035     port_span_ (1),
00036     hosts_ (0),
00037     hostname_in_ior_ (0),
00038     endpoint_count_ (0),
00039     version_ (TAO_DEF_GIOP_MAJOR, TAO_DEF_GIOP_MINOR),
00040     orb_core_ (0),
00041     reuse_addr_ (1),
00042 #if defined (ACE_HAS_IPV6)
00043     default_address_ (static_cast<unsigned short> (0), ACE_IPV6_ANY, AF_INET6),
00044 #else
00045     default_address_ (static_cast<unsigned short> (0), static_cast<ACE_UINT32> (INADDR_ANY)),
00046 #endif /* ACE_HAS_IPV6 */
00047     base_acceptor_ (),
00048     creation_strategy_ (0),
00049     concurrency_strategy_ (0),
00050     accept_strategy_ (0)
00051 {
00052 }
00053 
00054 //@@ TAO_ACCEPTOR_SPL_COPY_HOOK_END
00055 
00056 TAO_IIOP_Acceptor::~TAO_IIOP_Acceptor (void)
00057 {
00058   // Make sure we are closed before we start destroying the
00059   // strategies.
00060   this->close ();
00061 
00062   delete this->creation_strategy_;
00063   delete this->concurrency_strategy_;
00064   delete this->accept_strategy_;
00065 
00066   delete [] this->addrs_;
00067 
00068   for (CORBA::ULong i = 0; i < this->endpoint_count_; ++i)
00069     CORBA::string_free (this->hosts_[i]);
00070 
00071   delete [] this->hosts_;
00072 
00073   delete [] this->hostname_in_ior_;
00074 }
00075 
00076 //@@ TAO_ACCEPTOR_SPL_COPY_HOOK_START
00077 
00078 // TODO =
00079 //    2) For V1.[1,2] there are tagged components
00080 int
00081 TAO_IIOP_Acceptor::create_profile (const TAO::ObjectKey &object_key,
00082                                    TAO_MProfile &mprofile,
00083                                    CORBA::Short priority)
00084 {
00085   // Sanity check.
00086   if (this->endpoint_count_ == 0)
00087     return -1;
00088 
00089   // Check if multiple endpoints should be put in one profile or
00090   // if they should be spread across multiple profiles.
00091   if (priority == TAO_INVALID_PRIORITY &&
00092       this->orb_core_->orb_params ()->shared_profile () == 0)
00093     return this->create_new_profile (object_key, mprofile, priority);
00094   else
00095     return this->create_shared_profile (object_key, mprofile, priority);
00096 }
00097 
00098 int
00099 TAO_IIOP_Acceptor::create_new_profile (const TAO::ObjectKey &object_key,
00100                                        TAO_MProfile &mprofile,
00101                                        CORBA::Short priority)
00102 {
00103   // Adding this->endpoint_count_ to the TAO_MProfile.
00104   int const count = mprofile.profile_count ();
00105   if ((mprofile.size () - count) < this->endpoint_count_
00106       && mprofile.grow (count + this->endpoint_count_) == -1)
00107     return -1;
00108 
00109   // Create a profile for each acceptor endpoint.
00110   for (CORBA::ULong i = 0; i < this->endpoint_count_; ++i)
00111     {
00112       // Skip if the host name
00113       if (i > 0
00114           && (this->addrs_[i].get_port_number() == this->addrs_[0].get_port_number())
00115           && ACE_OS::strcmp(this->hosts_[i], this->hosts_[0]) == 0)
00116         continue;
00117 
00118       TAO_IIOP_Profile *pfile = 0;
00119       ACE_NEW_RETURN (pfile,
00120                       TAO_IIOP_Profile (this->hosts_[i],
00121                                         this->addrs_[i].get_port_number (),
00122                                         object_key,
00123                                         this->addrs_[i],
00124                                         this->version_,
00125                                         this->orb_core_),
00126                       -1);
00127       pfile->endpoint ()->priority (priority);
00128 
00129       if (mprofile.give_profile (pfile) == -1)
00130         {
00131           pfile->_decr_refcnt ();
00132           pfile = 0;
00133           return -1;
00134         }
00135 
00136       // Do not add any tagged components to the profile if configured
00137       // by the user not to do so, or if an IIOP 1.0 endpoint is being
00138       // created (IIOP 1.0 did not support tagged components).
00139       if (this->orb_core_->orb_params ()->std_profile_components () == 0
00140           || (this->version_.major == 1 && this->version_.minor == 0))
00141         continue;
00142 
00143       pfile->tagged_components ().set_orb_type (TAO_ORB_TYPE);
00144 
00145       TAO_Codeset_Manager *csm = this->orb_core_->codeset_manager();
00146       if (csm)
00147         csm->set_codeset(pfile->tagged_components());
00148     }
00149 
00150   return 0;
00151 }
00152 
00153 int
00154 TAO_IIOP_Acceptor::create_shared_profile (const TAO::ObjectKey &object_key,
00155                                           TAO_MProfile &mprofile,
00156                                           CORBA::Short priority)
00157 {
00158   CORBA::ULong index = 0;
00159   TAO_Profile *pfile = 0;
00160   TAO_IIOP_Profile *iiop_profile = 0;
00161 
00162   // First see if <mprofile> already contains a IIOP profile.
00163   for (TAO_PHandle i = 0; i != mprofile.profile_count (); ++i)
00164     {
00165       pfile = mprofile.get_profile (i);
00166       if (pfile->tag () == IOP::TAG_INTERNET_IOP)
00167         {
00168           iiop_profile = dynamic_cast<TAO_IIOP_Profile *> (pfile);
00169           break;
00170         }
00171     }
00172 
00173   // If <mprofile> doesn't contain a IIOP_Profile, we need to create
00174   // one.
00175   if (iiop_profile == 0)
00176     {
00177       ACE_NEW_RETURN (iiop_profile,
00178                       TAO_IIOP_Profile (this->hosts_[0],
00179                                         this->addrs_[0].get_port_number (),
00180                                         object_key,
00181                                         this->addrs_[0],
00182                                         this->version_,
00183                                         this->orb_core_),
00184                       -1);
00185 
00186       iiop_profile->endpoint ()->priority (priority);
00187 
00188       if (mprofile.give_profile (iiop_profile) == -1)
00189         {
00190           iiop_profile->_decr_refcnt ();
00191           iiop_profile = 0;
00192           return -1;
00193         }
00194 
00195       // Do not add any tagged components to the profile if configured
00196       // by the user not to do so, or if an IIOP 1.0 endpoint is being
00197       // created (IIOP 1.0 did not support tagged components).
00198       if (this->orb_core_->orb_params ()->std_profile_components () != 0
00199           && (this->version_.major >= 1 && this->version_.minor >= 1))
00200         {
00201           iiop_profile->tagged_components ().set_orb_type (TAO_ORB_TYPE);
00202           TAO_Codeset_Manager *csm = this->orb_core_->codeset_manager();
00203           if (csm)
00204             csm->set_codeset(iiop_profile->tagged_components());
00205         }
00206 
00207       index = 1;
00208     }
00209 
00210   // Add any remaining acceptor endpoints to the IIOP_Profile.
00211   for (;
00212        index < this->endpoint_count_;
00213        ++index)
00214     {
00215       if (index > 0 &&
00216           this->addrs_[index].get_port_number() == this->addrs_[0].get_port_number() &&
00217           ACE_OS::strcmp(this->hosts_[index], this->hosts_[0]) == 0)
00218         continue;
00219 
00220       TAO_IIOP_Endpoint *endpoint = 0;
00221       ACE_NEW_RETURN (endpoint,
00222                       TAO_IIOP_Endpoint (this->hosts_[index],
00223                                          this->addrs_[index].get_port_number (),
00224                                          this->addrs_[index]),
00225                       -1);
00226       endpoint->priority (priority);
00227       iiop_profile->add_endpoint (endpoint);
00228     }
00229 
00230   return 0;
00231 }
00232 
00233 int
00234 TAO_IIOP_Acceptor::is_collocated (const TAO_Endpoint *endpoint)
00235 {
00236   const TAO_IIOP_Endpoint *endp =
00237     dynamic_cast<const TAO_IIOP_Endpoint *> (endpoint);
00238 
00239   // Make sure the dynamically cast pointer is valid.
00240   if (endp == 0)
00241     return 0;
00242 
00243   for (CORBA::ULong i = 0; i < this->endpoint_count_; ++i)
00244     {
00245       // compare the port and host name.  Please do *NOT* optimize
00246       // this code by comparing the IP address instead.  That would
00247       // trigger the following bug:
00248       //
00249       // http://deuce.doc.wustl.edu/bugzilla/show_bug.cgi?id=1220
00250       //
00251       if (endp->port() == this->addrs_[i].get_port_number()
00252           && ACE_OS::strcmp(endp->host(), this->hosts_[i]) == 0)
00253         return 1;
00254     }
00255 
00256   return 0;
00257 }
00258 
00259 int
00260 TAO_IIOP_Acceptor::close (void)
00261 {
00262   return this->base_acceptor_.close ();
00263 }
00264 
00265 int
00266 TAO_IIOP_Acceptor::open (TAO_ORB_Core *orb_core,
00267                          ACE_Reactor *reactor,
00268                          int major,
00269                          int minor,
00270                          const char *address,
00271                          const char *options)
00272 {
00273   if (TAO_debug_level > 2)
00274     {
00275       ACE_DEBUG ((LM_DEBUG,
00276                   ACE_TEXT ("TAO (%P|%t) - ")
00277                   ACE_TEXT ("IIOP_Acceptor::open, address==%s, options=%s\n"),
00278                   address, options));
00279     }
00280 
00281   this->orb_core_ = orb_core;
00282 
00283   if (this->hosts_ != 0)
00284     {
00285       // The hostname cache has already been set!
00286       // This is bad mojo, i.e. an internal TAO error.
00287       ACE_ERROR_RETURN ((LM_ERROR,
00288                          ACE_TEXT ("TAO (%P|%t) - ")
00289                          ACE_TEXT ("IIOP_Acceptor::open, ")
00290                          ACE_TEXT ("hostname already set\n\n")),
00291                         -1);
00292     }
00293 
00294   if (address == 0)
00295     return -1;
00296 
00297   if (major >=0 && minor >= 0)
00298     this->version_.set_version (static_cast<CORBA::Octet> (major),
00299                                 static_cast<CORBA::Octet> (minor));
00300   // Parse options
00301   if (this->parse_options (options) == -1)
00302     return -1;
00303 
00304   ACE_CString specified_hostname;
00305   ACE_INET_Addr addr;
00306   int def_type = AF_UNSPEC;
00307 
00308   if (this->parse_address (address,
00309                            addr,
00310                            specified_hostname,
00311                            &def_type) == -1)
00312     return -1;
00313 
00314   if (specified_hostname.length() == 0)
00315     {
00316       // The address is a port number or port name.  No hostname was
00317       // specified.  The hostname for each network interface and the
00318       // fully qualified domain name must be obtained.
00319 
00320       // Check for multiple network interfaces.
00321       if (this->probe_interfaces (orb_core, def_type) == -1)
00322         return -1;
00323 
00324       // Probe interfaces has a side effect of potentially modifying
00325       // the default address, since that is where the address family
00326       // is considered.
00327       addr.set(this->default_address_);
00328 
00329       return this->open_i (addr, reactor);
00330     }
00331 
00332 #if defined (ACE_HAS_IPV6)
00333   // Check for violation of ORBConnectIPV6Only option
00334   if (this->orb_core_->orb_params ()->connect_ipv6_only () &&
00335       (addr.get_type () != AF_INET6 ||
00336        addr.is_ipv4_mapped_ipv6 ()))
00337     {
00338       ACE_ERROR_RETURN ((LM_ERROR,
00339                          ACE_TEXT ("TAO (%P|%t) - ")
00340                          ACE_TEXT ("IIOP_Acceptor::open, ")
00341                          ACE_TEXT ("non-IPv6 endpoints not allowed when ")
00342                          ACE_TEXT ("connect_ipv6_only is set\n\n")),
00343                         -1);
00344     }
00345 #endif /* ACE_HAS_IPV6 */
00346 
00347   if (TAO_debug_level > 2)
00348     {
00349       ACE_DEBUG ((LM_DEBUG,
00350                   ACE_TEXT ("TAO (%P|%t) - ")
00351                   ACE_TEXT ("IIOP_Acceptor::open, specified host=%s:%d\n"),
00352                   (specified_hostname.length() == 0 ? "<null>" : specified_hostname.c_str()),
00353                   addr.get_port_number ()));
00354     }
00355 
00356   this->endpoint_count_ = 1;  // Only one hostname to store
00357 
00358   ACE_NEW_RETURN (this->addrs_,
00359                   ACE_INET_Addr[this->endpoint_count_],
00360                   -1);
00361 
00362   ACE_NEW_RETURN (this->hosts_,
00363                   char *[this->endpoint_count_],
00364                   -1);
00365 
00366   this->hosts_[0] = 0;
00367 
00368   if (this->hostname_in_ior_ != 0)
00369     {
00370       if (TAO_debug_level > 2)
00371         {
00372           ACE_DEBUG ((LM_DEBUG,
00373                       ACE_TEXT ("TAO (%P|%t) - ")
00374                       ACE_TEXT ("IIOP_Acceptor::open, ")
00375                       ACE_TEXT ("Overriding address in IOR with %s\n"),
00376                       ACE_TEXT_CHAR_TO_TCHAR (this->hostname_in_ior_)));
00377         }
00378       specified_hostname = this->hostname_in_ior_;
00379     }
00380 
00381   if (this->hostname (orb_core,
00382                       addr,
00383                       this->hosts_[0],
00384                       specified_hostname.c_str()) != 0)
00385     return -1;
00386 
00387   // Copy the addr.  The port is (re)set in
00388   // TAO_IIOP_Acceptor::open_i().
00389   if (this->addrs_[0].set (addr) != 0)
00390     return -1;
00391 
00392   return this->open_i (addr,
00393                        reactor);
00394 }
00395 
00396 int
00397 TAO_IIOP_Acceptor::open_default (TAO_ORB_Core *orb_core,
00398                                  ACE_Reactor *reactor,
00399                                  int major,
00400                                  int minor,
00401                                  const char *options)
00402 {
00403   this->orb_core_ = orb_core;
00404 
00405   if (this->hosts_ != 0)
00406     {
00407       // The hostname cache has already been set!
00408       // This is bad mojo, i.e. an internal TAO error.
00409       ACE_ERROR_RETURN ((LM_ERROR,
00410                          ACE_TEXT ("TAO (%P|%t) - ")
00411                          ACE_TEXT ("IIOP_Acceptor::open_default, ")
00412                          ACE_TEXT ("hostname already set\n\n")),
00413                         -1);
00414     }
00415 
00416   if (major >= 0 && minor >= 0)
00417     this->version_.set_version (static_cast<CORBA::Octet> (major),
00418                                 static_cast<CORBA::Octet> (minor));
00419 
00420   // Parse options
00421   if (this->parse_options (options) == -1)
00422     return -1;
00423 
00424   // Check for multiple network interfaces.
00425   if (this->probe_interfaces (orb_core) == -1)
00426     return -1;
00427 
00428   // Now that each network interface's hostname has been cached, open
00429   // an endpoint on each network interface using the INADDR_ANY
00430   // address.
00431   ACE_INET_Addr addr;
00432 
00433   if (addr.set (this->default_address_) != 0)
00434     return -1;
00435 
00436   return this->open_i (addr, reactor);
00437 }
00438 
00439 int
00440 TAO_IIOP_Acceptor::open_i (const ACE_INET_Addr& addr,
00441                            ACE_Reactor *reactor)
00442 {
00443   ACE_NEW_RETURN (this->creation_strategy_,
00444                   CREATION_STRATEGY (this->orb_core_),
00445                   -1);
00446 
00447   ACE_NEW_RETURN (this->concurrency_strategy_,
00448                   CONCURRENCY_STRATEGY (this->orb_core_),
00449                   -1);
00450 
00451   ACE_NEW_RETURN (this->accept_strategy_,
00452                   ACCEPT_STRATEGY (this->orb_core_),
00453                   -1);
00454 
00455   unsigned short requested_port = addr.get_port_number ();
00456   if (requested_port == 0)
00457     {
00458       // don't care, i.e., let the OS choose an ephemeral port
00459       if (this->base_acceptor_.open (addr,
00460                                      reactor,
00461                                      this->creation_strategy_,
00462                                      this->accept_strategy_,
00463                                      this->concurrency_strategy_,
00464                                      0, 0, 0, 1,
00465                                      this->reuse_addr_) == -1)
00466         {
00467           if (TAO_debug_level > 0)
00468             ACE_DEBUG ((LM_DEBUG,
00469                         ACE_TEXT ("TAO (%P|%t) - IIOP_Acceptor::open_i, ")
00470                         ACE_TEXT ("%p, "),
00471                         ACE_TEXT ("cannot open acceptor\n")));
00472           return -1;
00473         }
00474     }
00475   else
00476     {
00477       ACE_INET_Addr a(addr);
00478 
00479       bool found_a_port = false;
00480       ACE_UINT32 last_port = requested_port + this->port_span_ - 1;
00481       if (last_port > ACE_MAX_DEFAULT_PORT)
00482         {
00483           last_port = ACE_MAX_DEFAULT_PORT;
00484         }
00485 
00486       for (ACE_UINT32 p = requested_port; p <= last_port; p++)
00487         {
00488           if (TAO_debug_level > 5)
00489             ACE_DEBUG ((LM_DEBUG,
00490                         ACE_TEXT ("TAO (%P|%t) - IIOP_Acceptor::open_i, ")
00491                         ACE_TEXT ("trying to listen on port %d\n"), p));
00492 
00493           // Now try to actually open on that port
00494           a.set_port_number ((u_short)p);
00495           if (this->base_acceptor_.open (a,
00496                                          reactor,
00497                                          this->creation_strategy_,
00498                                          this->accept_strategy_,
00499                                          this->concurrency_strategy_,
00500                                          0, 0, 0, 1,
00501                                          this->reuse_addr_) != -1)
00502             {
00503               found_a_port = true;
00504               break;
00505             }
00506         }
00507 
00508       // Now, if we couldn't locate a port, we punt
00509       if (! found_a_port)
00510         {
00511           if (TAO_debug_level > 0)
00512             ACE_DEBUG ((LM_DEBUG,
00513                         ACE_TEXT ("TAO (%P|%t) - IIOP_Acceptor::open_i, ")
00514                         ACE_TEXT ("cannot open acceptor in port range (%d,%d)")
00515                         ACE_TEXT ("- %p\n"),
00516                         requested_port, last_port, ACE_TEXT("")));
00517           return -1;
00518         }
00519     }
00520 
00521 #if defined (ACE_HAS_IPV6) && defined (ACE_HAS_IPV6_V6ONLY)
00522   // Check if need to prevent this acceptor from accepting connections
00523   // from IPv4 mapped IPv6 addresses
00524   if (this->orb_core_->orb_params ()->connect_ipv6_only () &&
00525       addr.is_any ())
00526   {
00527     if (TAO_debug_level > 5)
00528       ACE_DEBUG ((LM_DEBUG,
00529                   ACE_TEXT("TAO (%P|%t) - IIOP_Acceptor::open_i, ")
00530                   ACE_TEXT("setting IPV6_V6ONLY\n")));
00531 
00532     // Prevent server from accepting connections from IPv4-mapped addresses.
00533     int on = 1;
00534     if (this->base_acceptor_.acceptor ().set_option (IPPROTO_IPV6,
00535                                                      IPV6_V6ONLY,
00536                                                      (void *) &on,
00537                                                      sizeof (on)) == -1)
00538       {
00539         ACE_ERROR ((LM_ERROR,
00540                     ACE_TEXT ("TAO (%P|%t) - IIOP_Acceptor::open_i, ")
00541                     ACE_TEXT ("%p\n"),
00542                     ACE_TEXT ("cannot set IPV6_V6ONLY")));
00543       }
00544   }
00545 #endif /* ACE_HAS_IPV6 && ACE_HAS_IPV6_V6ONLY */
00546 
00547   ACE_INET_Addr address;
00548 
00549   // We do this make sure the port number the endpoint is listening on
00550   // gets set in the addr.
00551   if (this->base_acceptor_.acceptor ().get_local_addr (address) != 0)
00552     {
00553       if (TAO_debug_level > 0)
00554         ACE_ERROR ((LM_ERROR,
00555                     ACE_TEXT ("TAO (%P|%t) - IIOP_Acceptor::open_i, ")
00556                     ACE_TEXT ("%p"),
00557                     ACE_TEXT ("cannot get local addr\n")));
00558       return -1;
00559     }
00560 
00561   // Set the port for each addr.  If there is more than one network
00562   // interface then the endpoint created on each interface will be on
00563   // the same port.  This is how a wildcard socket bind() is supposed
00564   // to work.
00565   unsigned short port = address.get_port_number ();
00566   for (CORBA::ULong j = 0; j < this->endpoint_count_; ++j)
00567     this->addrs_[j].set_port_number (port, 1);
00568 
00569   this->default_address_.set_port_number (port);
00570 
00571   (void) this->base_acceptor_.acceptor().enable (ACE_CLOEXEC);
00572   // This avoids having child processes acquire the listen socket thereby
00573   // denying the server the opportunity to restart on a well-known endpoint.
00574   // This does not affect the aberrent behavior on Win32 platforms.
00575 
00576   if (TAO_debug_level > 5)
00577     {
00578       for (CORBA::ULong i = 0; i < this->endpoint_count_; ++i)
00579         {
00580           ACE_DEBUG ((LM_DEBUG,
00581                       ACE_TEXT ("TAO (%P|%t) - IIOP_Acceptor::open_i, ")
00582                       ACE_TEXT ("listening on: <%s:%u>\n"),
00583                       ACE_TEXT_CHAR_TO_TCHAR(this->hosts_[i]),
00584                       this->addrs_[i].get_port_number ()));
00585         }
00586     }
00587 
00588   return 0;
00589 }
00590 
00591 int
00592 TAO_IIOP_Acceptor::hostname (TAO_ORB_Core *orb_core,
00593                              ACE_INET_Addr &addr,
00594                              char *&host,
00595                              const char *specified_hostname)
00596 {
00597   if (this->hostname_in_ior_ != 0)
00598     {
00599       if (TAO_debug_level >= 5)
00600           ACE_DEBUG ((LM_DEBUG,
00601                       ACE_TEXT ("TAO (%P|%t) IIOP_Acceptor - ")
00602                       ACE_TEXT ("Overriding the hostname with <%s>\n"),
00603                       this->hostname_in_ior_));
00604 
00605       host = CORBA::string_dup (this->hostname_in_ior_);
00606     }
00607   else if (orb_core->orb_params ()->use_dotted_decimal_addresses ())
00608     {
00609       // If dotted decimal addresses are enabled,
00610       // just return ours.
00611       return this->dotted_decimal_address (addr, host);
00612     }
00613   else if (specified_hostname != 0)
00614     {
00615       // If the user specified a hostname, pass it back
00616       // blindly as it overrides our choice of hostname.
00617       host = CORBA::string_dup (specified_hostname);
00618     }
00619   else
00620     {
00621       char tmp_host[MAXHOSTNAMELEN + 1];
00622 
00623       // Get the hostname associated with our address
00624 #if defined (ACE_HAS_IPV6)
00625       // If we have a IPv4-compatible IPv6 address don't do hostname lookup
00626       // because that gets us into trouble. Most likely we get the same hostname
00627       // returned as for the actual IPv4 address but resolving that into an IPv6
00628       // address at the client will fail.
00629       if (addr.is_ipv4_compat_ipv6 () ||
00630           addr.get_host_name (tmp_host, sizeof (tmp_host)) != 0)
00631 #else /* ACE_HAS_IPV6 */
00632       if (addr.get_host_name (tmp_host, sizeof (tmp_host)) != 0)
00633 #endif /* !ACE_HAS_IPV6 */
00634         {
00635           // On failure, just return the decimal address.
00636           return this->dotted_decimal_address (addr, host);
00637         }
00638       else
00639         {
00640           host = CORBA::string_dup (tmp_host);
00641         }
00642     }
00643 
00644   return 0;
00645 }
00646 
00647 
00648 int
00649 TAO_IIOP_Acceptor::parse_address (const char *address,
00650                                   ACE_INET_Addr &addr,
00651                                   ACE_CString &specified_hostname,
00652                                   int *def_type)
00653 {
00654   {
00655     ACE_INET_Addr tmp;
00656     addr.set (tmp);
00657     specified_hostname.clear();
00658   }
00659 
00660   const char *port_separator_loc = ACE_OS::strchr (address, ':');
00661   char tmp_host[MAXHOSTNAMELEN + 1];
00662   tmp_host[0] = '\0';
00663   bool host_defaulted = port_separator_loc == address;
00664   bool ipv6_in_host = false;
00665   if (def_type)
00666     *def_type = AF_UNSPEC;
00667 
00668 #if defined (ACE_HAS_IPV6)
00669   // Check if this is a (possibly) IPv6 supporting profile containing a
00670   // numeric IPv6 address representation.
00671   if ((this->version_.major > TAO_MIN_IPV6_IIOP_MAJOR ||
00672         this->version_.minor >= TAO_MIN_IPV6_IIOP_MINOR) &&
00673       address[0] == '[')
00674     {
00675       // In this case we have to find the end of the numeric address and
00676       // start looking for the port separator from there.
00677       char const * const cp_pos = ACE_OS::strchr (address, ']');
00678       if (cp_pos == 0)
00679         {
00680           // No valid IPv6 address specified.
00681           ACE_ERROR_RETURN ((LM_ERROR,
00682                              ACE_TEXT ("TAO (%P|%t) - ")
00683                              ACE_TEXT ("IIOP_Acceptor::open, ")
00684                              ACE_TEXT ("Invalid IPv6 decimal address specified\n\n")),
00685                             -1);
00686         }
00687       else
00688         {
00689           // Extract out just the host part of the address.
00690           size_t const len = cp_pos - (address + 1);
00691 
00692           if (len >= sizeof (tmp_host))
00693             return -1;
00694 
00695           ipv6_in_host = true;
00696           host_defaulted = (cp_pos == address+1) ||
00697             (cp_pos == address+3 && address[1] == ':' && address[2] == ':');
00698           if (cp_pos[1] == ':')    // Look for a port
00699             port_separator_loc = cp_pos + 1;
00700           else
00701             port_separator_loc = 0;
00702           if (def_type)
00703             *def_type = AF_INET6;
00704 
00705           ACE_OS::memcpy (tmp_host, address + 1, len);
00706           tmp_host[len] = '\0';
00707         }
00708     }
00709   else
00710 #endif /* ACE_HAS_IPV6 */
00711     if (!host_defaulted)
00712       {
00713         if (port_separator_loc != 0)
00714           {
00715             // Extract out just the host part of the address.
00716             size_t const len = port_separator_loc - address;
00717 
00718             if (len >= sizeof (tmp_host))
00719               return -1;
00720 
00721             ACE_OS::memcpy (tmp_host, address, len);
00722             tmp_host[len] = '\0';
00723           }
00724         else
00725           ACE_OS::strcpy (tmp_host, address);
00726       }
00727 
00728   if (!ipv6_in_host && !host_defaulted)
00729     {
00730       if (addr.set((unsigned short)0,tmp_host) != 0)
00731         return -1;
00732       this->default_address_.set(addr);
00733       host_defaulted = addr.is_any();
00734       if (def_type)
00735         *def_type = AF_INET;
00736     }
00737 
00738   if (host_defaulted)
00739     {
00740       // First convert the port into a usable form.
00741       unsigned short portno = 0;
00742       if (port_separator_loc != 0)
00743         {
00744           portno =
00745             static_cast<u_short> (ACE_OS::atoi (port_separator_loc +
00746                                                 sizeof (':')));
00747         }
00748       this->default_address_.set_port_number (portno);
00749 
00750       // Now reset the port and set the host.
00751       if (addr.set (this->default_address_) != 0)
00752         return -1;
00753     }
00754   else if (port_separator_loc == 0)
00755     {
00756       // The address is a hostname.  No port was specified, so assume
00757       // port zero (port will be chosen for us).
00758       specified_hostname = tmp_host[0] == '\0' ? address : tmp_host;
00759       if (addr.set ((unsigned short) 0,
00760                     specified_hostname.c_str()) != 0)
00761         return -1;
00762     }
00763   else
00764     {
00765       // Host and port were specified.
00766       if (addr.set (address) != 0)
00767         return -1;
00768       if (tmp_host[0] == '\0')
00769         {
00770           // Extract out just the host part of the address.
00771           size_t const len = port_separator_loc - address;
00772 
00773           if (len >= sizeof (tmp_host))
00774             return -1;
00775 
00776           ACE_OS::memcpy (tmp_host, address, len);
00777           tmp_host[len] = '\0';
00778         }
00779       specified_hostname = tmp_host;
00780     }
00781 
00782   return 1;
00783 }
00784 
00785 
00786 int
00787 TAO_IIOP_Acceptor::dotted_decimal_address (ACE_INET_Addr &addr,
00788                                            char *&host)
00789 {
00790   int result = 0;
00791   const char *tmp = 0;
00792 
00793   // If the IP address in the INET_Addr is the IN(6)ADDR_ANY address,
00794   // then force the actual IP address to be used by initializing a new
00795   // INET_Addr with the hostname from the original one.  If that fails
00796   // then something is seriously wrong with the systems networking
00797   // setup.
00798   if (addr.is_any ())
00799     {
00800       ACE_INET_Addr new_addr;
00801 #if defined (ACE_HAS_IPV6)
00802       result = new_addr.set (addr.get_port_number (),
00803                              addr.get_host_name (),
00804                              1, /* encode */
00805                              addr.get_type ());
00806 #else /* ACE_HAS_IPV6 */
00807       result = new_addr.set (addr.get_port_number (),
00808                              addr.get_host_name ());
00809 #endif /* !ACE_HAS_IPV6 */
00810       tmp = new_addr.get_host_addr ();
00811     }
00812   else
00813     tmp = addr.get_host_addr ();
00814 
00815   if (tmp == 0 || result != 0)
00816     {
00817       if (TAO_debug_level > 0)
00818         ACE_ERROR ((LM_ERROR,
00819                     ACE_TEXT ("TAO (%P|%t) - ")
00820                     ACE_TEXT ("IIOP_Acceptor::dotted_decimal_address, ")
00821                     ACE_TEXT ("- %p, "),
00822                     ACE_TEXT ("cannot determine hostname\n")));
00823       return -1;
00824     }
00825 
00826   host = CORBA::string_dup (tmp);
00827   return 0;
00828 }
00829 
00830 int
00831 TAO_IIOP_Acceptor::probe_interfaces (TAO_ORB_Core *orb_core, int def_type)
00832 {
00833   // Extract the hostname for each network interface, and then cache
00834   // it.  The hostnames will then be used when creating a
00835   // TAO_IIOP_Profile for each endpoint setup on the probed
00836   // network interfaces.
00837   ACE_INET_Addr *if_addrs = 0;
00838   size_t if_cnt = 0;
00839 
00840   if (ACE::get_ip_interfaces (if_cnt, if_addrs) != 0
00841       && errno != ENOTSUP)
00842     {
00843       // In the case where errno == ENOTSUP, if_cnt and if_addrs will
00844       // not be modified, and will each remain equal to zero.  This
00845       // causes the default interface to be used.
00846       return -1;
00847     }
00848 
00849   if (if_cnt == 0 || if_addrs == 0)
00850     {
00851       if (TAO_debug_level > 0)
00852         {
00853           ACE_DEBUG ((LM_WARNING,
00854                       ACE_TEXT ("TAO (%P|%t) - Unable to probe network ")
00855                       ACE_TEXT ("interfaces. Using default.\n")));
00856         }
00857 
00858       if_cnt = 1; // Force the network interface count to be one.
00859       delete [] if_addrs;
00860       ACE_NEW_RETURN (if_addrs,
00861                       ACE_INET_Addr[if_cnt],
00862                       -1);
00863     }
00864 
00865   // Scan for the loopback interface since it shouldn't be included in
00866   // the list of cached hostnames unless it is the only interface.
00867   size_t lo_cnt = 0;  // Loopback interface count
00868   for (size_t j = 0; j < if_cnt; ++j)
00869     if (if_addrs[j].is_loopback ())
00870       ++lo_cnt;
00871 
00872 #if defined (ACE_HAS_IPV6)
00873   size_t ipv4_cnt = 0;
00874   size_t ipv4_lo_cnt = 0;
00875   size_t ipv6_ll = 0;
00876   bool ipv6_non_ll = false;
00877   // Scan for IPv4 interfaces since these should not be included
00878   // when IPv6-only is selected.
00879   for (size_t j = 0; j < if_cnt; ++j)
00880     if (if_addrs[j].get_type () != AF_INET6 ||
00881         if_addrs[j].is_ipv4_mapped_ipv6 ())
00882       {
00883         ++ipv4_cnt;
00884         if (if_addrs[j].is_loopback ())
00885           ++ipv4_lo_cnt;  // keep track of IPv4 loopback ifs
00886       }
00887     else if (!if_addrs[j].is_linklocal () &&
00888              !if_addrs[j].is_loopback())
00889       {
00890         ipv6_non_ll = true; // we have at least 1 non-local IPv6 if
00891       }
00892     else if (!orb_core->orb_params ()->use_ipv6_link_local () &&
00893              if_addrs[j].is_linklocal ())
00894       {
00895         ++ipv6_ll;  // count link local addrs to exclude them afterwards
00896       }
00897 #endif /* ACE_HAS_IPV6 */
00898 
00899   // The instantiation for this template is in
00900   // tao/IIOP_Connector.cpp.
00901   ACE_Auto_Basic_Array_Ptr<ACE_INET_Addr> safe_if_addrs (if_addrs);
00902 
00903 #if defined (ACE_HAS_IPV6)
00904   bool ipv4_only = def_type == AF_INET;
00905   bool ipv6_only = (def_type == AF_INET6) ||
00906     orb_core->orb_params ()->connect_ipv6_only ();
00907 #if defined (ACE_WIN32)
00908   if (this->default_address_.get_type () == AF_INET)
00909     ipv4_only = true;
00910   else
00911     ipv6_only = true;
00912 #endif /* ACE_WIN32 */
00913   // If the loopback interface is the only interface then include it
00914   // in the list of interfaces to query for a hostname, otherwise
00915   // exclude it from the list.
00916   bool ignore_lo;
00917   if (ipv6_only)
00918     // only exclude loopback if non-local if exists
00919     ignore_lo = ipv6_non_ll;
00920   else if (ipv4_only)
00921     ignore_lo = ipv4_cnt != ipv4_lo_cnt;
00922   else
00923     ignore_lo = if_cnt != lo_cnt;
00924 
00925   // Adjust counts for IPv6 only if required
00926   size_t if_ok_cnt = if_cnt;
00927   if (ipv6_only)
00928     {
00929       if_ok_cnt -= ipv4_cnt;
00930       lo_cnt -= ipv4_lo_cnt;
00931       ipv4_lo_cnt = 0;
00932     }
00933   else if (ipv4_only)
00934     {
00935       if_ok_cnt = ipv4_cnt;
00936       lo_cnt = ipv4_lo_cnt;
00937       ipv6_ll = 0;
00938     }
00939 
00940   // In case there are no non-local IPv6 ifs in the list only exclude
00941   // IPv4 loopback.
00942   // IPv6 loopback will be needed to successfully connect IPv6 clients
00943   // in a localhost environment.
00944   if (!ipv4_only && !ipv6_non_ll)
00945     lo_cnt = ipv4_lo_cnt;
00946 
00947   if (!ignore_lo)
00948     this->endpoint_count_ = static_cast<CORBA::ULong> (if_ok_cnt - ipv6_ll);
00949   else
00950     this->endpoint_count_ = static_cast<CORBA::ULong> (if_ok_cnt - ipv6_ll - lo_cnt);
00951 #else /* ACE_HAS_IPV6 */
00952   // If the loopback interface is the only interface then include it
00953   // in the list of interfaces to query for a hostname, otherwise
00954   // exclude it from the list.
00955   bool ignore_lo;
00956   ignore_lo = if_cnt != lo_cnt;
00957   if (!ignore_lo)
00958     this->endpoint_count_ = static_cast<CORBA::ULong> (if_cnt);
00959   else
00960     this->endpoint_count_ = static_cast<CORBA::ULong> (if_cnt - lo_cnt);
00961 #endif /* !ACE_HAS_IPV6 */
00962 
00963   if (this->endpoint_count_ == 0)
00964     {
00965       if (TAO_debug_level > 0)
00966         ACE_DEBUG ((LM_DEBUG,
00967                     ACE_TEXT("(%P|%t) TAO_IIOP_Acceptor::probe_interfaces ")
00968                     ACE_TEXT("found no usable addresses, def_type = %d\n"),
00969                     def_type));
00970       return -1;
00971     }
00972 
00973   ACE_NEW_RETURN (this->addrs_,
00974                   ACE_INET_Addr[this->endpoint_count_],
00975                   -1);
00976 
00977   ACE_NEW_RETURN (this->hosts_,
00978                   char *[this->endpoint_count_],
00979                   -1);
00980 
00981   ACE_OS::memset (this->hosts_, 0, sizeof (char*) * this->endpoint_count_);
00982 
00983   // The number of hosts/interfaces we want to cache may not be the
00984   // same as the number of detected interfaces so keep a separate
00985   // count.
00986   size_t host_cnt = 0;
00987 
00988   for (size_t i = 0; i < if_cnt; ++i)
00989     {
00990 #if defined (ACE_HAS_IPV6)
00991       // Ignore any loopback interface if there are other
00992       // non-loopback interfaces.
00993       if (ignore_lo &&
00994           if_addrs[i].is_loopback () &&
00995           (ipv4_only ||
00996            ipv6_non_ll ||
00997            if_addrs[i].get_type () != AF_INET6))
00998         continue;
00999 
01000       // Ignore any non-IPv4 interfaces when so required.
01001       if (ipv4_only &&
01002           (if_addrs[i].get_type () != AF_INET))
01003         continue;
01004 
01005       // Ignore any non-IPv6 interfaces when so required.
01006       if (ipv6_only &&
01007           (if_addrs[i].get_type () != AF_INET6 ||
01008            if_addrs[i].is_ipv4_mapped_ipv6 ()))
01009         continue;
01010 
01011       // Ignore all IPv6 link local interfaces when so required.
01012       if (!orb_core->orb_params ()->use_ipv6_link_local () &&
01013           if_addrs[i].is_linklocal ())
01014         continue;
01015 #else /* ACE_HAS_IPV6 */
01016       // Ignore any loopback interface if there are other
01017       // non-loopback interfaces.
01018       if (ignore_lo &&
01019           if_addrs[i].is_loopback ())
01020         continue;
01021 #endif /* !ACE_HAS_IPV6 */
01022 
01023       if (this->hostname (orb_core,
01024                           if_addrs[i],
01025                           this->hosts_[host_cnt]) != 0)
01026         return -1;
01027 
01028       // Copy the addr.  The port is (re)set in
01029       // TAO_IIOP_Acceptor::open_i().
01030       if (this->addrs_[host_cnt].set (if_addrs[i]) != 0)
01031         return -1;
01032 
01033       ++host_cnt;
01034     }
01035 
01036   return 0;
01037 }
01038 
01039 CORBA::ULong
01040 TAO_IIOP_Acceptor::endpoint_count (void)
01041 {
01042   return this->endpoint_count_;
01043 }
01044 
01045 int
01046 TAO_IIOP_Acceptor::object_key (IOP::TaggedProfile &profile,
01047                                TAO::ObjectKey &object_key)
01048 {
01049   // Create the decoding stream from the encapsulation in the buffer,
01050 #if (TAO_NO_COPY_OCTET_SEQUENCES == 1)
01051   TAO_InputCDR cdr (profile.profile_data.mb ());
01052 #else
01053   TAO_InputCDR cdr (reinterpret_cast<char*> (profile.profile_data.get_buffer ()),
01054                     profile.profile_data.length ());
01055 #endif /* TAO_NO_COPY_OCTET_SEQUENCES == 1 */
01056 
01057   CORBA::Octet major;
01058   CORBA::Octet minor = CORBA::Octet();
01059 
01060   // Read the version. We just read it here. We don't*do any*
01061   // processing.
01062   if (!(cdr.read_octet (major)
01063         && cdr.read_octet (minor)))
01064     {
01065       if (TAO_debug_level > 0)
01066         {
01067           ACE_DEBUG ((LM_DEBUG,
01068                       ACE_TEXT ("TAO (%P|%t) - TAO_IIOP_Acceptor::object_key, v%d.%d\n"),
01069                       major,
01070                       minor));
01071         }
01072       return -1;
01073     }
01074 
01075   CORBA::String_var host;
01076   CORBA::UShort port = 0;
01077 
01078   // Get host and port. No processing here too..
01079   if (cdr.read_string (host.out ()) == 0
01080       || cdr.read_ushort (port) == 0)
01081     {
01082       if (TAO_debug_level > 0)
01083         {
01084           ACE_DEBUG ((LM_DEBUG,
01085                       ACE_TEXT ("TAO (%P|%t) - TAO_IIOP_Acceptor::object_key, ")
01086                       ACE_TEXT ("error while decoding host/port\n")));
01087         }
01088       return -1;
01089     }
01090 
01091   // ... and object key.
01092   if ((cdr >> object_key) == 0)
01093     return -1;
01094 
01095   // We are NOT bothered about the rest.
01096 
01097   return 1;
01098 }
01099 
01100 int
01101 TAO_IIOP_Acceptor::parse_options (const char *str)
01102 {
01103   if (str == 0)
01104     return 0;  // No options to parse.  Not a problem.
01105 
01106   // Use an option format similar to the one used for CGI scripts in
01107   // HTTP URLs.
01108   // e.g.:  option1=foo&option2=bar
01109 
01110   const ACE_CString options (str);
01111 
01112   const size_t len = options.length ();
01113 
01114   static const char option_delimiter = '&';
01115 
01116   // Count the number of options.
01117   int argc = 1;
01118 
01119   for (size_t i = 0; i < len; ++i)
01120     if (options[i] == option_delimiter)
01121       argc++;
01122 
01123   // The idea behind the following loop is to split the options into
01124   // (option, name) pairs.
01125   // For example,
01126   //    `option1=foo&option2=bar'
01127   // will be parsed into:
01128   //    `option1=foo'
01129   //    `option2=bar'
01130 
01131   ACE_CString *argv_base = 0;
01132   ACE_NEW_RETURN (argv_base, ACE_CString[argc],-1);
01133   ACE_CString **argv = 0;
01134   ACE_NEW_RETURN (argv, ACE_CString*[argc],-1);
01135 
01136   ACE_CString::size_type begin = 0;
01137   ACE_CString::size_type end = 0;
01138   int result = 0;
01139   for (int j = 0; j < argc; ++j)
01140     {
01141       if (j < argc - 1)
01142         end = options.find (option_delimiter, begin);
01143       else
01144         end = len;
01145 
01146       if (end == begin)
01147         {
01148           ACE_ERROR ((LM_ERROR,
01149                       ACE_TEXT ("TAO (%P|%t) - Zero length IIOP option.\n")));
01150           result = -1;
01151           break;
01152         }
01153       else if (end != options.npos)
01154         {
01155           argv_base[j] = options.substring (begin, end - begin);
01156           argv[j] = &argv_base[j];
01157           begin = end + 1;
01158         }
01159       else
01160         {
01161           break;  // No other options.
01162         }
01163     }
01164 
01165   if (result == 0)
01166     result = this->parse_options_i (argc,argv);
01167 
01168   if (argc > 0)
01169     {
01170       ACE_ERROR ((LM_ERROR,
01171                   ACE_TEXT ("TAO (%P|%t) - IIOP")
01172                   ACE_TEXT (" endpoint has %d unknown options:\n"),
01173                   argc));
01174       for (int i = 0; i < argc; i++)
01175         ACE_ERROR ((LM_ERROR,
01176                     ACE_TEXT("\t%s\n"),
01177                     argv[i]->c_str()));
01178       result = -1;
01179     }
01180   delete [] argv;
01181   delete [] argv_base;
01182   return result;
01183 }
01184 
01185 int
01186 TAO_IIOP_Acceptor::parse_options_i (int &argc,
01187                                     ACE_CString **argv)
01188 {
01189   int i = 0;
01190   while (i < argc)
01191     {
01192       ACE_CString::size_type const len  = argv[i]->length ();
01193       ACE_CString::size_type const slot = argv[i]->find ('=');
01194 
01195       if (slot == len - 1
01196           || slot == ACE_CString::npos)
01197         ACE_ERROR_RETURN ((LM_ERROR,
01198                            ACE_TEXT ("TAO (%P|%t) - IIOP option <%s> is ")
01199                            ACE_TEXT ("missing a value.\n"),
01200                            ACE_TEXT_CHAR_TO_TCHAR(argv[i]->c_str ())),
01201                           -1);
01202 
01203       ACE_CString name = argv[i]->substring (0, slot);
01204       ACE_CString value = argv[i]->substring (slot + 1);
01205 
01206       if (name.length () == 0)
01207         ACE_ERROR_RETURN ((LM_ERROR,
01208                            ACE_TEXT ("TAO (%P|%t) Zero length IIOP ")
01209                            ACE_TEXT ("option name.\n")),
01210                           -1);
01211       if (name == "portspan")
01212         {
01213           int range = static_cast <int> (ACE_OS::atoi (value.c_str ()));
01214           // @@ What's the lower bound on the range?  zero, or one?
01215           if (range < 1 || range > ACE_MAX_DEFAULT_PORT)
01216             ACE_ERROR_RETURN ((LM_ERROR,
01217                                ACE_TEXT ("TAO (%P|%t) Invalid IIOP endpoint ")
01218                                ACE_TEXT ("portspan: <%s>\n")
01219                                ACE_TEXT ("Valid range 1 -- %d\n"),
01220                                value.c_str (), ACE_MAX_DEFAULT_PORT),
01221                               -1);
01222 
01223           this->port_span_ = static_cast <u_short> (range);
01224         }
01225       else if (name == "hostname_in_ior")
01226         {
01227           this->hostname_in_ior_ = value.rep ();
01228         }
01229       else if (name == "reuse_addr")
01230         {
01231           this->reuse_addr_ = ACE_OS::atoi (value.c_str ());
01232         }
01233       else
01234         {
01235           // the name is not known, skip to the next option
01236           ++i;
01237           continue;
01238         }
01239       // at the end, we've consumed this argument. Shift the list and
01240       // put this one on the end. This technique has the effect of
01241       // putting them in reverse order, but that doesn't matter, since
01242       // these arguments are only whole strings.
01243       --argc;
01244       ACE_CString *temp = argv[i];
01245       for (int j = i; j <= argc-1; ++j)
01246         argv[j] = argv[j+1];
01247       argv[argc] = temp;
01248     }
01249   return 0;
01250 }
01251 
01252 TAO_END_VERSIONED_NAMESPACE_DECL
01253 
01254 #endif /* TAO_HAS_IIOP && TAO_HAS_IIOP != 0 */
01255 
01256 //@@ TAO_ACCEPTOR_SPL_COPY_HOOK_END

Generated on Sun Jan 27 13:07:33 2008 for TAO by doxygen 1.3.6