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 81470 2008-04-28 12:40:23Z elliott_c $")
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_ (this),
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, reactor);
00393 }
00394 
00395 int
00396 TAO_IIOP_Acceptor::open_default (TAO_ORB_Core *orb_core,
00397                                  ACE_Reactor *reactor,
00398                                  int major,
00399                                  int minor,
00400                                  const char *options)
00401 {
00402   this->orb_core_ = orb_core;
00403 
00404   if (this->hosts_ != 0)
00405     {
00406       // The hostname cache has already been set!
00407       // This is bad mojo, i.e. an internal TAO error.
00408       ACE_ERROR_RETURN ((LM_ERROR,
00409                          ACE_TEXT ("TAO (%P|%t) - ")
00410                          ACE_TEXT ("IIOP_Acceptor::open_default, ")
00411                          ACE_TEXT ("hostname already set\n\n")),
00412                         -1);
00413     }
00414 
00415   if (major >= 0 && minor >= 0)
00416     this->version_.set_version (static_cast<CORBA::Octet> (major),
00417                                 static_cast<CORBA::Octet> (minor));
00418 
00419   // Parse options
00420   if (this->parse_options (options) == -1)
00421     return -1;
00422 
00423   // Check for multiple network interfaces.
00424   if (this->probe_interfaces (orb_core) == -1)
00425     return -1;
00426 
00427   // Now that each network interface's hostname has been cached, open
00428   // an endpoint on each network interface using the INADDR_ANY
00429   // address.
00430   ACE_INET_Addr addr;
00431 
00432   if (addr.set (this->default_address_) != 0)
00433     return -1;
00434 
00435   return this->open_i (addr, reactor);
00436 }
00437 
00438 int
00439 TAO_IIOP_Acceptor::open_i (const ACE_INET_Addr& addr,
00440                            ACE_Reactor *reactor)
00441 {
00442   ACE_NEW_RETURN (this->creation_strategy_,
00443                   CREATION_STRATEGY (this->orb_core_),
00444                   -1);
00445 
00446   ACE_NEW_RETURN (this->concurrency_strategy_,
00447                   CONCURRENCY_STRATEGY (this->orb_core_),
00448                   -1);
00449 
00450   ACE_NEW_RETURN (this->accept_strategy_,
00451                   ACCEPT_STRATEGY (this->orb_core_),
00452                   -1);
00453 
00454   unsigned short requested_port = addr.get_port_number ();
00455   if (requested_port == 0)
00456     {
00457       // don't care, i.e., let the OS choose an ephemeral port
00458       if (this->base_acceptor_.open (addr,
00459                                      reactor,
00460                                      this->creation_strategy_,
00461                                      this->accept_strategy_,
00462                                      this->concurrency_strategy_,
00463                                      0, 0, 0, 1,
00464                                      this->reuse_addr_) == -1)
00465         {
00466           if (TAO_debug_level > 0)
00467             ACE_ERROR ((LM_ERROR,
00468                         ACE_TEXT ("TAO (%P|%t) - IIOP_Acceptor::open_i, ")
00469                         ACE_TEXT ("%p, "),
00470                         ACE_TEXT ("cannot open acceptor\n")));
00471           return -1;
00472         }
00473     }
00474   else
00475     {
00476       ACE_INET_Addr a(addr);
00477 
00478       bool found_a_port = false;
00479       ACE_UINT32 last_port = requested_port + this->port_span_ - 1;
00480       if (last_port > ACE_MAX_DEFAULT_PORT)
00481         {
00482           last_port = ACE_MAX_DEFAULT_PORT;
00483         }
00484 
00485       for (ACE_UINT32 p = requested_port; p <= last_port; p++)
00486         {
00487           if (TAO_debug_level > 5)
00488             ACE_DEBUG ((LM_DEBUG,
00489                         ACE_TEXT ("TAO (%P|%t) - IIOP_Acceptor::open_i, ")
00490                         ACE_TEXT ("trying to listen on port %d\n"), p));
00491 
00492           // Now try to actually open on that port
00493           a.set_port_number ((u_short)p);
00494           if (this->base_acceptor_.open (a,
00495                                          reactor,
00496                                          this->creation_strategy_,
00497                                          this->accept_strategy_,
00498                                          this->concurrency_strategy_,
00499                                          0, 0, 0, 1,
00500                                          this->reuse_addr_) != -1)
00501             {
00502               found_a_port = true;
00503               break;
00504             }
00505         }
00506 
00507       // Now, if we couldn't locate a port, we punt
00508       if (! found_a_port)
00509         {
00510           if (TAO_debug_level > 0)
00511             ACE_DEBUG ((LM_DEBUG,
00512                         ACE_TEXT ("TAO (%P|%t) - IIOP_Acceptor::open_i, ")
00513                         ACE_TEXT ("cannot open acceptor in port range (%d,%d)")
00514                         ACE_TEXT ("- %p\n"),
00515                         requested_port, last_port, ACE_TEXT("")));
00516           return -1;
00517         }
00518     }
00519 
00520 #if defined (ACE_HAS_IPV6) && defined (ACE_HAS_IPV6_V6ONLY)
00521   // Check if need to prevent this acceptor from accepting connections
00522   // from IPv4 mapped IPv6 addresses
00523   if (this->orb_core_->orb_params ()->connect_ipv6_only () &&
00524       addr.is_any ())
00525   {
00526     if (TAO_debug_level > 5)
00527       ACE_DEBUG ((LM_DEBUG,
00528                   ACE_TEXT("TAO (%P|%t) - IIOP_Acceptor::open_i, ")
00529                   ACE_TEXT("setting IPV6_V6ONLY\n")));
00530 
00531     // Prevent server from accepting connections from IPv4-mapped addresses.
00532     int on = 1;
00533     if (this->base_acceptor_.acceptor ().set_option (IPPROTO_IPV6,
00534                                                      IPV6_V6ONLY,
00535                                                      (void *) &on,
00536                                                      sizeof (on)) == -1)
00537       {
00538         ACE_ERROR ((LM_ERROR,
00539                     ACE_TEXT ("TAO (%P|%t) - IIOP_Acceptor::open_i, ")
00540                     ACE_TEXT ("%p\n"),
00541                     ACE_TEXT ("cannot set IPV6_V6ONLY")));
00542       }
00543   }
00544 #endif /* ACE_HAS_IPV6 && ACE_HAS_IPV6_V6ONLY */
00545 
00546   ACE_INET_Addr address;
00547 
00548   // We do this make sure the port number the endpoint is listening on
00549   // gets set in the addr.
00550   if (this->base_acceptor_.acceptor ().get_local_addr (address) != 0)
00551     {
00552       if (TAO_debug_level > 0)
00553         ACE_ERROR ((LM_ERROR,
00554                     ACE_TEXT ("TAO (%P|%t) - IIOP_Acceptor::open_i, ")
00555                     ACE_TEXT ("%p"),
00556                     ACE_TEXT ("cannot get local addr\n")));
00557       return -1;
00558     }
00559 
00560   // Set the port for each addr.  If there is more than one network
00561   // interface then the endpoint created on each interface will be on
00562   // the same port.  This is how a wildcard socket bind() is supposed
00563   // to work.
00564   unsigned short port = address.get_port_number ();
00565   for (CORBA::ULong j = 0; j < this->endpoint_count_; ++j)
00566     this->addrs_[j].set_port_number (port, 1);
00567 
00568   this->default_address_.set_port_number (port);
00569 
00570   (void) this->base_acceptor_.acceptor().enable (ACE_CLOEXEC);
00571   // This avoids having child processes acquire the listen socket thereby
00572   // denying the server the opportunity to restart on a well-known endpoint.
00573   // This does not affect the aberrent behavior on Win32 platforms.
00574 
00575   if (TAO_debug_level > 5)
00576     {
00577       for (CORBA::ULong i = 0; i < this->endpoint_count_; ++i)
00578         {
00579           ACE_DEBUG ((LM_DEBUG,
00580                       ACE_TEXT ("TAO (%P|%t) - IIOP_Acceptor::open_i, ")
00581                       ACE_TEXT ("listening on: <%s:%u>\n"),
00582                       ACE_TEXT_CHAR_TO_TCHAR(this->hosts_[i]),
00583                       this->addrs_[i].get_port_number ()));
00584         }
00585     }
00586 
00587   // In the event that an accept() fails, we can examine the reason.  If
00588   // the reason warrants it, we can try accepting again at a later time.
00589   // The amount of time we wait to accept again is governed by this orb
00590   // parameter.
00591   this->set_error_retry_delay (
00592     this->orb_core_->orb_params ()->accept_error_delay());
00593 
00594   return 0;
00595 }
00596 
00597 int
00598 TAO_IIOP_Acceptor::hostname (TAO_ORB_Core *orb_core,
00599                              ACE_INET_Addr &addr,
00600                              char *&host,
00601                              const char *specified_hostname)
00602 {
00603   if (this->hostname_in_ior_ != 0)
00604     {
00605       if (TAO_debug_level >= 5)
00606           ACE_DEBUG ((LM_DEBUG,
00607                       ACE_TEXT ("TAO (%P|%t) IIOP_Acceptor - ")
00608                       ACE_TEXT ("Overriding the hostname with <%s>\n"),
00609                       this->hostname_in_ior_));
00610 
00611       host = CORBA::string_dup (this->hostname_in_ior_);
00612     }
00613   else if (orb_core->orb_params ()->use_dotted_decimal_addresses ())
00614     {
00615       // If dotted decimal addresses are enabled,
00616       // just return ours.
00617       return this->dotted_decimal_address (addr, host);
00618     }
00619   else if (specified_hostname != 0)
00620     {
00621       // If the user specified a hostname, pass it back
00622       // blindly as it overrides our choice of hostname.
00623       host = CORBA::string_dup (specified_hostname);
00624     }
00625   else
00626     {
00627       char tmp_host[MAXHOSTNAMELEN + 1];
00628 
00629       // Get the hostname associated with our address
00630 #if defined (ACE_HAS_IPV6)
00631       // If we have a IPv4-compatible IPv6 address don't do hostname lookup
00632       // because that gets us into trouble. Most likely we get the same hostname
00633       // returned as for the actual IPv4 address but resolving that into an IPv6
00634       // address at the client will fail.
00635       if (addr.is_ipv4_compat_ipv6 () ||
00636           addr.get_host_name (tmp_host, sizeof (tmp_host)) != 0)
00637 #else /* ACE_HAS_IPV6 */
00638       if (addr.get_host_name (tmp_host, sizeof (tmp_host)) != 0)
00639 #endif /* !ACE_HAS_IPV6 */
00640         {
00641           // On failure, just return the decimal address.
00642           return this->dotted_decimal_address (addr, host);
00643         }
00644       else
00645         {
00646           host = CORBA::string_dup (tmp_host);
00647         }
00648     }
00649 
00650   return 0;
00651 }
00652 
00653 
00654 int
00655 TAO_IIOP_Acceptor::parse_address (const char *address,
00656                                   ACE_INET_Addr &addr,
00657                                   ACE_CString &specified_hostname,
00658                                   int *def_type)
00659 {
00660   {
00661     ACE_INET_Addr tmp;
00662     addr.set (tmp);
00663     specified_hostname.clear();
00664   }
00665 
00666   const char *port_separator_loc = ACE_OS::strchr (address, ':');
00667   char tmp_host[MAXHOSTNAMELEN + 1];
00668   tmp_host[0] = '\0';
00669   bool host_defaulted = port_separator_loc == address;
00670   bool ipv6_in_host = false;
00671   if (def_type)
00672     *def_type = AF_UNSPEC;
00673 
00674 #if defined (ACE_HAS_IPV6)
00675   // Check if this is a (possibly) IPv6 supporting profile containing a
00676   // numeric IPv6 address representation.
00677   if ((this->version_.major > TAO_MIN_IPV6_IIOP_MAJOR ||
00678         this->version_.minor >= TAO_MIN_IPV6_IIOP_MINOR) &&
00679       address[0] == '[')
00680     {
00681       // In this case we have to find the end of the numeric address and
00682       // start looking for the port separator from there.
00683       char const * const cp_pos = ACE_OS::strchr (address, ']');
00684       if (cp_pos == 0)
00685         {
00686           // No valid IPv6 address specified.
00687           ACE_ERROR_RETURN ((LM_ERROR,
00688                              ACE_TEXT ("TAO (%P|%t) - ")
00689                              ACE_TEXT ("IIOP_Acceptor::open, ")
00690                              ACE_TEXT ("Invalid IPv6 decimal address specified\n\n")),
00691                             -1);
00692         }
00693       else
00694         {
00695           // Extract out just the host part of the address.
00696           size_t const len = cp_pos - (address + 1);
00697 
00698           if (len >= sizeof (tmp_host))
00699             return -1;
00700 
00701           ipv6_in_host = true;
00702           host_defaulted = (cp_pos == address+1) ||
00703             (cp_pos == address+3 && address[1] == ':' && address[2] == ':');
00704           if (cp_pos[1] == ':')    // Look for a port
00705             port_separator_loc = cp_pos + 1;
00706           else
00707             port_separator_loc = 0;
00708           if (def_type)
00709             *def_type = AF_INET6;
00710 
00711           ACE_OS::memcpy (tmp_host, address + 1, len);
00712           tmp_host[len] = '\0';
00713         }
00714     }
00715   else
00716 #endif /* ACE_HAS_IPV6 */
00717     if (!host_defaulted)
00718       {
00719         if (port_separator_loc != 0)
00720           {
00721             // Extract out just the host part of the address.
00722             size_t const len = port_separator_loc - address;
00723 
00724             if (len >= sizeof (tmp_host))
00725               return -1;
00726 
00727             ACE_OS::memcpy (tmp_host, address, len);
00728             tmp_host[len] = '\0';
00729           }
00730         else
00731           ACE_OS::strcpy (tmp_host, address);
00732       }
00733 
00734   if (!ipv6_in_host && !host_defaulted)
00735     {
00736       if (addr.set((unsigned short)0,tmp_host) != 0)
00737         return -1;
00738       this->default_address_.set(addr);
00739       host_defaulted = addr.is_any();
00740       if (def_type)
00741         *def_type = AF_INET;
00742     }
00743 
00744   if (host_defaulted)
00745     {
00746       // First convert the port into a usable form.
00747       unsigned short portno = 0;
00748       if (port_separator_loc != 0)
00749         {
00750           portno =
00751             static_cast<u_short> (ACE_OS::atoi (port_separator_loc +
00752                                                 sizeof (':')));
00753         }
00754       this->default_address_.set_port_number (portno);
00755 
00756       // Now reset the port and set the host.
00757       if (addr.set (this->default_address_) != 0)
00758         return -1;
00759     }
00760   else if (port_separator_loc == 0)
00761     {
00762       // The address is a hostname.  No port was specified, so assume
00763       // port zero (port will be chosen for us).
00764       specified_hostname = tmp_host[0] == '\0' ? address : tmp_host;
00765       if (addr.set ((unsigned short) 0,
00766                     specified_hostname.c_str()) != 0)
00767         return -1;
00768     }
00769   else
00770     {
00771       // Host and port were specified.
00772       if (addr.set (address) != 0)
00773         return -1;
00774       if (tmp_host[0] == '\0')
00775         {
00776           // Extract out just the host part of the address.
00777           size_t const len = port_separator_loc - address;
00778 
00779           if (len >= sizeof (tmp_host))
00780             return -1;
00781 
00782           ACE_OS::memcpy (tmp_host, address, len);
00783           tmp_host[len] = '\0';
00784         }
00785       specified_hostname = tmp_host;
00786     }
00787 
00788   return 1;
00789 }
00790 
00791 
00792 int
00793 TAO_IIOP_Acceptor::dotted_decimal_address (ACE_INET_Addr &addr,
00794                                            char *&host)
00795 {
00796   int result = 0;
00797   const char *tmp = 0;
00798 
00799   // If the IP address in the INET_Addr is the IN(6)ADDR_ANY address,
00800   // then force the actual IP address to be used by initializing a new
00801   // INET_Addr with the hostname from the original one.  If that fails
00802   // then something is seriously wrong with the systems networking
00803   // setup.
00804   if (addr.is_any ())
00805     {
00806       ACE_INET_Addr new_addr;
00807 #if defined (ACE_HAS_IPV6)
00808       result = new_addr.set (addr.get_port_number (),
00809                              addr.get_host_name (),
00810                              1, /* encode */
00811                              addr.get_type ());
00812 #else /* ACE_HAS_IPV6 */
00813       result = new_addr.set (addr.get_port_number (),
00814                              addr.get_host_name ());
00815 #endif /* !ACE_HAS_IPV6 */
00816       tmp = new_addr.get_host_addr ();
00817     }
00818   else
00819     tmp = addr.get_host_addr ();
00820 
00821   if (tmp == 0 || result != 0)
00822     {
00823       if (TAO_debug_level > 0)
00824         ACE_ERROR ((LM_ERROR,
00825                     ACE_TEXT ("TAO (%P|%t) - ")
00826                     ACE_TEXT ("IIOP_Acceptor::dotted_decimal_address, ")
00827                     ACE_TEXT ("- %p, "),
00828                     ACE_TEXT ("cannot determine hostname\n")));
00829       return -1;
00830     }
00831 
00832   host = CORBA::string_dup (tmp);
00833   return 0;
00834 }
00835 
00836 int
00837 TAO_IIOP_Acceptor::probe_interfaces (TAO_ORB_Core *orb_core, int def_type)
00838 {
00839   // Extract the hostname for each network interface, and then cache
00840   // it.  The hostnames will then be used when creating a
00841   // TAO_IIOP_Profile for each endpoint setup on the probed
00842   // network interfaces.
00843   ACE_INET_Addr *if_addrs = 0;
00844   size_t if_cnt = 0;
00845 
00846   if (ACE::get_ip_interfaces (if_cnt, if_addrs) != 0
00847       && errno != ENOTSUP)
00848     {
00849       // In the case where errno == ENOTSUP, if_cnt and if_addrs will
00850       // not be modified, and will each remain equal to zero.  This
00851       // causes the default interface to be used.
00852       return -1;
00853     }
00854 
00855   if (if_cnt == 0 || if_addrs == 0)
00856     {
00857       if (TAO_debug_level > 0)
00858         {
00859           ACE_DEBUG ((LM_WARNING,
00860                       ACE_TEXT ("TAO (%P|%t) - Unable to probe network ")
00861                       ACE_TEXT ("interfaces. Using default.\n")));
00862         }
00863 
00864       if_cnt = 1; // Force the network interface count to be one.
00865       delete [] if_addrs;
00866       ACE_NEW_RETURN (if_addrs,
00867                       ACE_INET_Addr[if_cnt],
00868                       -1);
00869     }
00870 
00871   // Scan for the loopback interface since it shouldn't be included in
00872   // the list of cached hostnames unless it is the only interface.
00873   size_t lo_cnt = 0;  // Loopback interface count
00874   for (size_t j = 0; j < if_cnt; ++j)
00875     if (if_addrs[j].is_loopback ())
00876       ++lo_cnt;
00877 
00878 #if defined (ACE_HAS_IPV6)
00879   size_t ipv4_cnt = 0;
00880   size_t ipv4_lo_cnt = 0;
00881   size_t ipv6_ll = 0;
00882   bool ipv6_non_ll = false;
00883   // Scan for IPv4 interfaces since these should not be included
00884   // when IPv6-only is selected.
00885   for (size_t j = 0; j < if_cnt; ++j)
00886     if (if_addrs[j].get_type () != AF_INET6 ||
00887         if_addrs[j].is_ipv4_mapped_ipv6 ())
00888       {
00889         ++ipv4_cnt;
00890         if (if_addrs[j].is_loopback ())
00891           ++ipv4_lo_cnt;  // keep track of IPv4 loopback ifs
00892       }
00893     else if (!if_addrs[j].is_linklocal () &&
00894              !if_addrs[j].is_loopback())
00895       {
00896         ipv6_non_ll = true; // we have at least 1 non-local IPv6 if
00897       }
00898     else if (!orb_core->orb_params ()->use_ipv6_link_local () &&
00899              if_addrs[j].is_linklocal ())
00900       {
00901         ++ipv6_ll;  // count link local addrs to exclude them afterwards
00902       }
00903 #endif /* ACE_HAS_IPV6 */
00904 
00905   // The instantiation for this template is in
00906   // tao/IIOP_Connector.cpp.
00907   ACE_Auto_Basic_Array_Ptr<ACE_INET_Addr> safe_if_addrs (if_addrs);
00908 
00909 #if defined (ACE_HAS_IPV6)
00910   bool ipv4_only = def_type == AF_INET;
00911   bool ipv6_only = (def_type == AF_INET6) ||
00912     orb_core->orb_params ()->connect_ipv6_only ();
00913 #if defined (ACE_WIN32)
00914   if (this->default_address_.get_type () == AF_INET)
00915     ipv4_only = true;
00916   else
00917     ipv6_only = true;
00918 #endif /* ACE_WIN32 */
00919   // If the loopback interface is the only interface then include it
00920   // in the list of interfaces to query for a hostname, otherwise
00921   // exclude it from the list.
00922   bool ignore_lo;
00923   if (ipv6_only)
00924     // only exclude loopback if non-local if exists
00925     ignore_lo = ipv6_non_ll;
00926   else if (ipv4_only)
00927     ignore_lo = ipv4_cnt != ipv4_lo_cnt;
00928   else
00929     ignore_lo = if_cnt != lo_cnt;
00930 
00931   // Adjust counts for IPv6 only if required
00932   size_t if_ok_cnt = if_cnt;
00933   if (ipv6_only)
00934     {
00935       if_ok_cnt -= ipv4_cnt;
00936       lo_cnt -= ipv4_lo_cnt;
00937       ipv4_lo_cnt = 0;
00938     }
00939   else if (ipv4_only)
00940     {
00941       if_ok_cnt = ipv4_cnt;
00942       lo_cnt = ipv4_lo_cnt;
00943       ipv6_ll = 0;
00944     }
00945 
00946   // In case there are no non-local IPv6 ifs in the list only exclude
00947   // IPv4 loopback.
00948   // IPv6 loopback will be needed to successfully connect IPv6 clients
00949   // in a localhost environment.
00950   if (!ipv4_only && !ipv6_non_ll)
00951     lo_cnt = ipv4_lo_cnt;
00952 
00953   if (!ignore_lo)
00954     this->endpoint_count_ = static_cast<CORBA::ULong> (if_ok_cnt - ipv6_ll);
00955   else
00956     this->endpoint_count_ = static_cast<CORBA::ULong> (if_ok_cnt - ipv6_ll - lo_cnt);
00957 #else /* ACE_HAS_IPV6 */
00958   // If the loopback interface is the only interface then include it
00959   // in the list of interfaces to query for a hostname, otherwise
00960   // exclude it from the list.
00961   bool ignore_lo;
00962   ignore_lo = if_cnt != lo_cnt;
00963   if (!ignore_lo)
00964     this->endpoint_count_ = static_cast<CORBA::ULong> (if_cnt);
00965   else
00966     this->endpoint_count_ = static_cast<CORBA::ULong> (if_cnt - lo_cnt);
00967 #endif /* !ACE_HAS_IPV6 */
00968 
00969   if (this->endpoint_count_ == 0)
00970     {
00971       if (TAO_debug_level > 0)
00972         ACE_DEBUG ((LM_DEBUG,
00973                     ACE_TEXT("(%P|%t) TAO_IIOP_Acceptor::probe_interfaces ")
00974                     ACE_TEXT("found no usable addresses, def_type = %d\n"),
00975                     def_type));
00976       return -1;
00977     }
00978 
00979   ACE_NEW_RETURN (this->addrs_,
00980                   ACE_INET_Addr[this->endpoint_count_],
00981                   -1);
00982 
00983   ACE_NEW_RETURN (this->hosts_,
00984                   char *[this->endpoint_count_],
00985                   -1);
00986 
00987   ACE_OS::memset (this->hosts_, 0, sizeof (char*) * this->endpoint_count_);
00988 
00989   // The number of hosts/interfaces we want to cache may not be the
00990   // same as the number of detected interfaces so keep a separate
00991   // count.
00992   size_t host_cnt = 0;
00993 
00994   for (size_t i = 0; i < if_cnt; ++i)
00995     {
00996 #if defined (ACE_HAS_IPV6)
00997       // Ignore any loopback interface if there are other
00998       // non-loopback interfaces.
00999       if (ignore_lo &&
01000           if_addrs[i].is_loopback () &&
01001           (ipv4_only ||
01002            ipv6_non_ll ||
01003            if_addrs[i].get_type () != AF_INET6))
01004         continue;
01005 
01006       // Ignore any non-IPv4 interfaces when so required.
01007       if (ipv4_only &&
01008           (if_addrs[i].get_type () != AF_INET))
01009         continue;
01010 
01011       // Ignore any non-IPv6 interfaces when so required.
01012       if (ipv6_only &&
01013           (if_addrs[i].get_type () != AF_INET6 ||
01014            if_addrs[i].is_ipv4_mapped_ipv6 ()))
01015         continue;
01016 
01017       // Ignore all IPv6 link local interfaces when so required.
01018       if (!orb_core->orb_params ()->use_ipv6_link_local () &&
01019           if_addrs[i].is_linklocal ())
01020         continue;
01021 #else /* ACE_HAS_IPV6 */
01022       // Ignore any loopback interface if there are other
01023       // non-loopback interfaces.
01024       if (ignore_lo &&
01025           if_addrs[i].is_loopback ())
01026         continue;
01027 #endif /* !ACE_HAS_IPV6 */
01028 
01029       if (this->hostname (orb_core,
01030                           if_addrs[i],
01031                           this->hosts_[host_cnt]) != 0)
01032         return -1;
01033 
01034       // Copy the addr.  The port is (re)set in
01035       // TAO_IIOP_Acceptor::open_i().
01036       if (this->addrs_[host_cnt].set (if_addrs[i]) != 0)
01037         return -1;
01038 
01039       ++host_cnt;
01040     }
01041 
01042   return 0;
01043 }
01044 
01045 CORBA::ULong
01046 TAO_IIOP_Acceptor::endpoint_count (void)
01047 {
01048   return this->endpoint_count_;
01049 }
01050 
01051 int
01052 TAO_IIOP_Acceptor::object_key (IOP::TaggedProfile &profile,
01053                                TAO::ObjectKey &object_key)
01054 {
01055   // Create the decoding stream from the encapsulation in the buffer,
01056 #if (TAO_NO_COPY_OCTET_SEQUENCES == 1)
01057   TAO_InputCDR cdr (profile.profile_data.mb ());
01058 #else
01059   TAO_InputCDR cdr (reinterpret_cast<char*> (profile.profile_data.get_buffer ()),
01060                     profile.profile_data.length ());
01061 #endif /* TAO_NO_COPY_OCTET_SEQUENCES == 1 */
01062 
01063   CORBA::Octet major;
01064   CORBA::Octet minor = CORBA::Octet();
01065 
01066   // Read the version. We just read it here. We don't*do any*
01067   // processing.
01068   if (!(cdr.read_octet (major)
01069         && cdr.read_octet (minor)))
01070     {
01071       if (TAO_debug_level > 0)
01072         {
01073           ACE_DEBUG ((LM_DEBUG,
01074                       ACE_TEXT ("TAO (%P|%t) - TAO_IIOP_Acceptor::object_key, v%d.%d\n"),
01075                       major,
01076                       minor));
01077         }
01078       return -1;
01079     }
01080 
01081   CORBA::String_var host;
01082   CORBA::UShort port = 0;
01083 
01084   // Get host and port. No processing here too..
01085   if (cdr.read_string (host.out ()) == 0
01086       || cdr.read_ushort (port) == 0)
01087     {
01088       if (TAO_debug_level > 0)
01089         {
01090           ACE_DEBUG ((LM_DEBUG,
01091                       ACE_TEXT ("TAO (%P|%t) - TAO_IIOP_Acceptor::object_key, ")
01092                       ACE_TEXT ("error while decoding host/port\n")));
01093         }
01094       return -1;
01095     }
01096 
01097   // ... and object key.
01098   if ((cdr >> object_key) == 0)
01099     return -1;
01100 
01101   // We are NOT bothered about the rest.
01102 
01103   return 1;
01104 }
01105 
01106 int
01107 TAO_IIOP_Acceptor::parse_options (const char *str)
01108 {
01109   if (str == 0)
01110     return 0;  // No options to parse.  Not a problem.
01111 
01112   // Use an option format similar to the one used for CGI scripts in
01113   // HTTP URLs.
01114   // e.g.:  option1=foo&option2=bar
01115 
01116   const ACE_CString options (str);
01117 
01118   const size_t len = options.length ();
01119 
01120   static const char option_delimiter = '&';
01121 
01122   // Count the number of options.
01123   int argc = 1;
01124 
01125   for (size_t i = 0; i < len; ++i)
01126     if (options[i] == option_delimiter)
01127       argc++;
01128 
01129   // The idea behind the following loop is to split the options into
01130   // (option, name) pairs.
01131   // For example,
01132   //    `option1=foo&option2=bar'
01133   // will be parsed into:
01134   //    `option1=foo'
01135   //    `option2=bar'
01136 
01137   ACE_CString *argv_base = 0;
01138   ACE_NEW_RETURN (argv_base, ACE_CString[argc],-1);
01139   ACE_CString **argv = 0;
01140   ACE_NEW_RETURN (argv, ACE_CString*[argc],-1);
01141 
01142   ACE_CString::size_type begin = 0;
01143   ACE_CString::size_type end = 0;
01144   int result = 0;
01145   for (int j = 0; j < argc; ++j)
01146     {
01147       if (j < argc - 1)
01148         end = options.find (option_delimiter, begin);
01149       else
01150         end = len;
01151 
01152       if (end == begin)
01153         {
01154           ACE_ERROR ((LM_ERROR,
01155                       ACE_TEXT ("TAO (%P|%t) - Zero length IIOP option.\n")));
01156           result = -1;
01157           break;
01158         }
01159       else if (end != options.npos)
01160         {
01161           argv_base[j] = options.substring (begin, end - begin);
01162           argv[j] = &argv_base[j];
01163           begin = end + 1;
01164         }
01165       else
01166         {
01167           break;  // No other options.
01168         }
01169     }
01170 
01171   if (result == 0)
01172     result = this->parse_options_i (argc,argv);
01173 
01174   if (argc > 0)
01175     {
01176       ACE_ERROR ((LM_ERROR,
01177                   ACE_TEXT ("TAO (%P|%t) - IIOP")
01178                   ACE_TEXT (" endpoint has %d unknown options:\n"),
01179                   argc));
01180       for (int i = 0; i < argc; i++)
01181         ACE_ERROR ((LM_ERROR,
01182                     ACE_TEXT("\t%s\n"),
01183                     argv[i]->c_str()));
01184       result = -1;
01185     }
01186   delete [] argv;
01187   delete [] argv_base;
01188   return result;
01189 }
01190 
01191 int
01192 TAO_IIOP_Acceptor::parse_options_i (int &argc,
01193                                     ACE_CString **argv)
01194 {
01195   int i = 0;
01196   while (i < argc)
01197     {
01198       ACE_CString::size_type const len  = argv[i]->length ();
01199       ACE_CString::size_type const slot = argv[i]->find ('=');
01200 
01201       if (slot == len - 1
01202           || slot == ACE_CString::npos)
01203         ACE_ERROR_RETURN ((LM_ERROR,
01204                            ACE_TEXT ("TAO (%P|%t) - IIOP option <%s> is ")
01205                            ACE_TEXT ("missing a value.\n"),
01206                            ACE_TEXT_CHAR_TO_TCHAR(argv[i]->c_str ())),
01207                           -1);
01208 
01209       ACE_CString name = argv[i]->substring (0, slot);
01210       ACE_CString value = argv[i]->substring (slot + 1);
01211 
01212       if (name.length () == 0)
01213         ACE_ERROR_RETURN ((LM_ERROR,
01214                            ACE_TEXT ("TAO (%P|%t) Zero length IIOP ")
01215                            ACE_TEXT ("option name.\n")),
01216                           -1);
01217       if (name == "portspan")
01218         {
01219           int range = static_cast <int> (ACE_OS::atoi (value.c_str ()));
01220           // @@ What's the lower bound on the range?  zero, or one?
01221           if (range < 1 || range > ACE_MAX_DEFAULT_PORT)
01222             ACE_ERROR_RETURN ((LM_ERROR,
01223                                ACE_TEXT ("TAO (%P|%t) Invalid IIOP endpoint ")
01224                                ACE_TEXT ("portspan: <%s>\n")
01225                                ACE_TEXT ("Valid range 1 -- %d\n"),
01226                                value.c_str (), ACE_MAX_DEFAULT_PORT),
01227                               -1);
01228 
01229           this->port_span_ = static_cast <u_short> (range);
01230         }
01231       else if (name == "hostname_in_ior")
01232         {
01233           this->hostname_in_ior_ = value.rep ();
01234         }
01235       else if (name == "reuse_addr")
01236         {
01237           this->reuse_addr_ = ACE_OS::atoi (value.c_str ());
01238         }
01239       else
01240         {
01241           // the name is not known, skip to the next option
01242           ++i;
01243           continue;
01244         }
01245       // at the end, we've consumed this argument. Shift the list and
01246       // put this one on the end. This technique has the effect of
01247       // putting them in reverse order, but that doesn't matter, since
01248       // these arguments are only whole strings.
01249       --argc;
01250       ACE_CString *temp = argv[i];
01251       for (int j = i; j <= argc-1; ++j)
01252         argv[j] = argv[j+1];
01253       argv[argc] = temp;
01254     }
01255   return 0;
01256 }
01257 
01258 TAO_END_VERSIONED_NAMESPACE_DECL
01259 
01260 #endif /* TAO_HAS_IIOP && TAO_HAS_IIOP != 0 */
01261 
01262 //@@ TAO_ACCEPTOR_SPL_COPY_HOOK_END

Generated on Tue Feb 2 17:37:52 2010 for TAO by  doxygen 1.4.7