UIOP_Acceptor.cpp

Go to the documentation of this file.
00001 #include "tao/Strategies/UIOP_Acceptor.h"
00002 
00003 #if TAO_HAS_UIOP == 1
00004 
00005 #include "tao/Strategies/UIOP_Profile.h"
00006 #include "tao/MProfile.h"
00007 #include "tao/ORB_Core.h"
00008 #include "tao/Server_Strategy_Factory.h"
00009 #include "tao/debug.h"
00010 #include "tao/Protocols_Hooks.h"
00011 #include "tao/Codeset_Manager.h"
00012 #include "tao/CDR.h"
00013 
00014 #include "ace/OS_NS_stdio.h"
00015 #include "ace/OS_NS_string.h"
00016 #include "ace/OS_NS_unistd.h"
00017 
00018 ACE_RCSID (Strategies,
00019            UIOP_Acceptor,
00020            "UIOP_Acceptor.cpp,v 1.29 2006/03/10 07:19:19 jtc Exp")
00021 
00022 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00023 
00024 TAO_UIOP_Acceptor::TAO_UIOP_Acceptor (CORBA::Boolean flag)
00025   : TAO_Acceptor (TAO_TAG_UIOP_PROFILE),
00026     base_acceptor_ (),
00027     creation_strategy_ (0),
00028     concurrency_strategy_ (0),
00029     accept_strategy_ (0),
00030     version_ (TAO_DEF_GIOP_MAJOR, TAO_DEF_GIOP_MINOR),
00031     orb_core_ (0),
00032     unlink_on_close_ (true),
00033     lite_flag_ (flag)
00034 {
00035 }
00036 
00037 TAO_UIOP_Acceptor::~TAO_UIOP_Acceptor (void)
00038 {
00039   // Make sure we are closed before we start destroying the
00040   // strategies.
00041   this->close ();
00042 
00043   delete this->creation_strategy_;
00044   delete this->concurrency_strategy_;
00045   delete this->accept_strategy_;
00046 }
00047 
00048 int
00049 TAO_UIOP_Acceptor::create_profile (const TAO::ObjectKey &object_key,
00050                                    TAO_MProfile &mprofile,
00051                                    CORBA::Short priority)
00052 {
00053   // Check if multiple endpoints should be put in one profile or
00054   // if they should be spread across multiple profiles.
00055   if (priority == TAO_INVALID_PRIORITY)
00056     return this->create_new_profile (object_key,
00057                                      mprofile,
00058                                      priority);
00059   else
00060     return this->create_shared_profile (object_key,
00061                                         mprofile,
00062                                         priority);
00063 
00064 }
00065 
00066 int
00067 TAO_UIOP_Acceptor::create_new_profile (const TAO::ObjectKey &object_key,
00068                                        TAO_MProfile &mprofile,
00069                                        CORBA::Short priority)
00070 {
00071   ACE_UNIX_Addr addr;
00072 
00073   if (this->base_acceptor_.acceptor ().get_local_addr (addr) == -1)
00074     return 0;
00075 
00076   int count = mprofile.profile_count ();
00077   if ((mprofile.size () - count) < 1
00078       && mprofile.grow (count + 1) == -1)
00079     return -1;
00080 
00081   TAO_UIOP_Profile *pfile = 0;
00082   ACE_NEW_RETURN (pfile,
00083                   TAO_UIOP_Profile (addr,
00084                                     object_key,
00085                                     this->version_,
00086                                     this->orb_core_),
00087                   -1);
00088   pfile->endpoint ()->priority (priority);
00089 
00090   if (mprofile.give_profile (pfile) == -1)
00091     {
00092       pfile->_decr_refcnt ();
00093       pfile = 0;
00094       return -1;
00095     }
00096 
00097   // Do not add any tagged components to the profile if configured
00098   // by the user not to do so, or if an UIOP 1.0 endpoint is being
00099   // created (IIOP 1.0 did not support tagged components, so we follow
00100   // the same convention for UIOP).
00101   if (this->orb_core_->orb_params ()->std_profile_components () == 0
00102       || (this->version_.major == 1 && this->version_.minor == 0))
00103     return 0;
00104 
00105   pfile->tagged_components ().set_orb_type (TAO_ORB_TYPE);
00106   TAO_Codeset_Manager *csm = this->orb_core_->codeset_manager();
00107   if (csm)
00108     csm->set_codeset(pfile->tagged_components());
00109   return 0;
00110 }
00111 
00112 int
00113 TAO_UIOP_Acceptor::create_shared_profile (const TAO::ObjectKey &object_key,
00114                                           TAO_MProfile &mprofile,
00115                                           CORBA::Short priority)
00116 {
00117   TAO_Profile *pfile = 0;
00118   TAO_UIOP_Profile *uiop_profile = 0;
00119 
00120   // First see if <mprofile> already contains a UIOP profile.
00121   for (TAO_PHandle i = 0; i != mprofile.profile_count (); ++i)
00122     {
00123       pfile = mprofile.get_profile (i);
00124       if (pfile->tag () == TAO_TAG_UIOP_PROFILE)
00125       {
00126         uiop_profile = dynamic_cast<TAO_UIOP_Profile *> (pfile);
00127         break;
00128       }
00129     }
00130 
00131   if (uiop_profile == 0)
00132     {
00133       // If <mprofile> doesn't contain UIOP_Profile, we need to create
00134       // one.
00135       return create_new_profile (object_key,
00136                                  mprofile,
00137                                  priority);
00138     }
00139   else
00140     {
00141       // A UIOP_Profile already exists - just add our endpoint to it.
00142       ACE_UNIX_Addr addr;
00143 
00144       if (this->base_acceptor_.acceptor ().get_local_addr (addr) == -1)
00145         return 0;
00146 
00147       TAO_UIOP_Endpoint *endpoint = 0;
00148       ACE_NEW_RETURN (endpoint,
00149                       TAO_UIOP_Endpoint (addr),
00150                       -1);
00151       endpoint->priority (priority);
00152       uiop_profile->add_endpoint (endpoint);
00153 
00154       return 0;
00155     }
00156 }
00157 
00158 int
00159 TAO_UIOP_Acceptor::is_collocated (const TAO_Endpoint *endpoint)
00160 {
00161   const TAO_UIOP_Endpoint *endp =
00162     dynamic_cast<const TAO_UIOP_Endpoint *> (endpoint);
00163 
00164   // Make sure the dynamically cast pointer is valid.
00165   if (endp == 0)
00166     return 0;
00167 
00168   // For UNIX Files this is relatively cheap.
00169   ACE_UNIX_Addr address;
00170   if (this->base_acceptor_.acceptor ().get_local_addr (address) == -1)
00171     return 0;
00172 
00173   return endp->object_addr () == address;
00174 }
00175 
00176 int
00177 TAO_UIOP_Acceptor::close (void)
00178 {
00179   if (this->unlink_on_close_)
00180     {
00181       ACE_UNIX_Addr addr;
00182 
00183       if (this->base_acceptor_.acceptor ().get_local_addr (addr) == 0)
00184         (void) ACE_OS::unlink (addr.get_path_name ());
00185 
00186       this->unlink_on_close_ = false;
00187     }
00188 
00189   return this->base_acceptor_.close ();
00190 }
00191 
00192 int
00193 TAO_UIOP_Acceptor::open (TAO_ORB_Core *orb_core,
00194                          ACE_Reactor *reactor,
00195                          int major,
00196                          int minor,
00197                          const char *address,
00198                          const char *options)
00199 {
00200   this->orb_core_ = orb_core;
00201 
00202   if (address == 0)
00203     return -1;
00204 
00205   if (major >= 0 && minor >= 0)
00206     this->version_.set_version (static_cast<CORBA::Octet> (major),
00207                                 static_cast<CORBA::Octet> (minor));
00208   // Parse options
00209   if (this->parse_options (options) == -1)
00210     return -1;
00211   else
00212     return this->open_i (address,
00213                          reactor);
00214 }
00215 
00216 int
00217 TAO_UIOP_Acceptor::open_default (TAO_ORB_Core *orb_core,
00218                                  ACE_Reactor *reactor,
00219                                  int major,
00220                                  int minor,
00221                                  const char *options)
00222 {
00223   this->orb_core_ = orb_core;
00224 
00225   if (major >= 0 && minor >= 0)
00226     this->version_.set_version (static_cast<CORBA::Octet> (major),
00227                                 static_cast<CORBA::Octet> (minor));
00228 
00229   // Parse options
00230   if (this->parse_options (options) == -1)
00231     return -1;
00232 
00233   ACE_Auto_String_Free tempname (ACE_OS::tempnam (0, "TAO"));
00234 
00235   if (tempname.get () == 0)
00236     return -1;
00237 
00238   return this->open_i (tempname.get (),
00239                        reactor);
00240 }
00241 
00242 int
00243 TAO_UIOP_Acceptor::open_i (const char *rendezvous,
00244                            ACE_Reactor *reactor)
00245 {
00246   ACE_NEW_RETURN (this->creation_strategy_,
00247                   TAO_UIOP_CREATION_STRATEGY (this->orb_core_,
00248                                               this->lite_flag_),
00249                   -1);
00250 
00251   ACE_NEW_RETURN (this->concurrency_strategy_,
00252                   TAO_UIOP_CONCURRENCY_STRATEGY (this->orb_core_),
00253                   -1);
00254 
00255   ACE_NEW_RETURN (this->accept_strategy_,
00256                   TAO_UIOP_ACCEPT_STRATEGY (this->orb_core_),
00257                   -1);
00258 
00259   ACE_UNIX_Addr addr;
00260 
00261   this->rendezvous_point (addr, rendezvous);
00262 
00263   if (this->base_acceptor_.open (addr,
00264                                  reactor,
00265                                  this->creation_strategy_,
00266                                  this->accept_strategy_,
00267                                  this->concurrency_strategy_) == -1)
00268     {
00269       // Don't unlink an existing rendezvous point since it may be in
00270       // use by another UIOP server/client.
00271       if (errno == EADDRINUSE)
00272         this->unlink_on_close_ = false;
00273 
00274       return -1;
00275     }
00276 
00277   (void) this->base_acceptor_.acceptor().enable (ACE_CLOEXEC);
00278   // This avoids having child processes acquire the listen socket thereby
00279   // denying the server the opportunity to restart on a well-known endpoint.
00280   // This does not affect the aberrent behavior on Win32 platforms.
00281 
00282   // @@ If Profile creation is slow we may need to cache the
00283   //    rendezvous point here
00284 
00285   if (TAO_debug_level > 5)
00286     ACE_DEBUG ((LM_DEBUG,
00287                 "\nTAO (%P|%t) UIOP_Acceptor::open_i - "
00288                 "listening on: <%s>\n",
00289                 addr.get_path_name ()));
00290   return 0;
00291 }
00292 
00293 void
00294 TAO_UIOP_Acceptor::rendezvous_point (ACE_UNIX_Addr &addr,
00295                                      const char *rendezvous)
00296 {
00297   // To guarantee portability, local IPC rendezvous points (including
00298   // the path and filename) should not be longer than 99 characters
00299   // long. Some platforms may support longer rendezvous points,
00300   // usually 108 characters including the null terminator, but
00301   // Posix.1g only requires that local IPC rendezvous point arrays
00302   // contain a maximum of at least 100 characters, including the null
00303   // terminator.  If an endpoint is longer than what the platform
00304   // supports then it will be truncated so that it fits, and a warning
00305   // will be issued.
00306 
00307   // Avoid using relative paths in your UIOP endpoints.  If possible,
00308   // use absolute paths instead.  Imagine that the server is given an
00309   // endpoint to create using -ORBEndpoint uiop://foobar.  A local IPC
00310   // rendezvous point called foobar will be created in the current
00311   // working directory.  If the client is not started in the directory
00312   // where the foobar rendezvous point exists then the client will not
00313   // be able to communicate with the server since its point of
00314   // communication, the rendezvous point, was not found. On the other
00315   // hand, if an absolute path was used, the client would know exactly
00316   // where to find the rendezvous point.  It is up to the user to make
00317   // sure that a given UIOP endpoint is accessible by both the server
00318   // and the client.
00319 
00320   addr.set (rendezvous);
00321 
00322   const size_t length = ACE_OS::strlen (addr.get_path_name ());
00323 
00324   // Check if rendezvous point was truncated by ACE_UNIX_Addr since
00325   // most UNIX domain socket rendezvous points can only be less than
00326   // 108 characters long.
00327   if (length < ACE_OS::strlen (rendezvous))
00328     ACE_DEBUG ((LM_WARNING,
00329                 "TAO (%P|%t) UIOP rendezvous point was truncated to <%s>\n"
00330                 "since it was longer than %d characters long.\n",
00331                 addr.get_path_name (),
00332                 length));
00333 }
00334 
00335 CORBA::ULong
00336 TAO_UIOP_Acceptor::endpoint_count (void)
00337 {
00338   return 1;
00339 }
00340 
00341 int
00342 TAO_UIOP_Acceptor::object_key (IOP::TaggedProfile &profile,
00343                                TAO::ObjectKey &object_key)
00344 {
00345   // Create the decoding stream from the encapsulation in the buffer,
00346 #if (TAO_NO_COPY_OCTET_SEQUENCES == 1)
00347   TAO_InputCDR cdr (profile.profile_data.mb ());
00348 #else
00349   TAO_InputCDR cdr (reinterpret_cast<char*> (profile.profile_data.get_buffer ()),
00350                     profile.profile_data.length ());
00351 #endif /* TAO_NO_COPY_OCTET_SEQUENCES == 1 */
00352 
00353   CORBA::Octet major, minor;
00354 
00355   // Read the version. We just read it here. We don't *do any*
00356   // processing.
00357   if (!(cdr.read_octet (major) && cdr.read_octet (minor)))
00358     {
00359       if (TAO_debug_level > 0)
00360         {
00361           ACE_DEBUG ((LM_DEBUG,
00362                       ACE_TEXT ("TAO (%P|%t) IIOP_Profile::decode - v%d.%d\n"),
00363                       major,
00364                       minor));
00365         }
00366 
00367       return -1;
00368     }
00369 
00370   char * rendezvous = 0;
00371 
00372   // Get rendezvous_point
00373   if (cdr.read_string (rendezvous) == 0)
00374     {
00375       ACE_ERROR ((LM_ERROR, "error decoding UIOP rendezvous_point"));
00376 
00377       return -1;
00378     }
00379 
00380   // delete the rendezvous point. We don't do any processing.
00381   delete [] rendezvous;
00382 
00383   // ... and object key.
00384   if ((cdr >> object_key) == 0)
00385     return -1;
00386 
00387   return 1;
00388 }
00389 
00390 int
00391 TAO_UIOP_Acceptor::parse_options (const char *str)
00392 {
00393   if (str == 0)
00394     return 0;  // No options to parse.  Not a problem.
00395 
00396   // Use an option format similar to the one used for CGI scripts in
00397   // HTTP URLs.
00398   // e.g.:  option1=foo&option2=bar
00399 
00400   ACE_CString options (str);
00401 
00402   const size_t len = options.length ();
00403 
00404   static const char option_delimiter = '&';
00405 
00406   // Count the number of options.
00407 
00408   CORBA::ULong option_count = 1;
00409   // Number of endpoints in the string (initialized to 1).
00410 
00411   // Only check for endpoints after the protocol specification and
00412   // before the object key.
00413   for (size_t i = 0; i < len; ++i)
00414     if (options[i] == option_delimiter)
00415       ++option_count;
00416 
00417   // The idea behind the following loop is to split the options into
00418   // (option, name) pairs.
00419   // For example,
00420   //    `option1=foo&option2=bar'
00421   // will be parsed into:
00422   //    `option1=foo'
00423   //    `option2=bar'
00424 
00425   int begin = 0;
00426   int end = -1;
00427 
00428   for (CORBA::ULong j = 0; j < option_count; ++j)
00429     {
00430       begin += end + 1;
00431 
00432       if (j < option_count - 1)
00433         end = options.find (option_delimiter, begin);
00434       else
00435         end = len - begin;  // Handle last endpoint differently
00436 
00437       if (end == begin)
00438         ACE_ERROR_RETURN ((LM_ERROR,
00439                            "TAO (%P|%t) Zero length UIOP option.\n"),
00440                           -1);
00441       else if (end != ACE_CString::npos)
00442         {
00443           ACE_CString opt =
00444             options.substring (begin, end);
00445 
00446           const int slot = opt.find ("=");
00447 
00448           if (slot == static_cast<int> (len - 1)
00449               || slot == ACE_CString::npos)
00450             ACE_ERROR_RETURN ((LM_ERROR,
00451                                "TAO (%P|%t) UIOP option <%s> is "
00452                                "missing a value.\n",
00453                                opt.c_str ()),
00454                               -1);
00455 
00456           const ACE_CString name (opt.substring (0, slot));
00457           ACE_CString value = opt.substring (slot + 1);
00458 
00459           if (name.length () == 0)
00460             ACE_ERROR_RETURN ((LM_ERROR,
00461                                "TAO (%P|%t) Zero length UIOP "
00462                                "option name.\n"),
00463                               -1);
00464 
00465           if (name == "priority")
00466             {
00467               ACE_ERROR_RETURN ((LM_ERROR,
00468                                  ACE_TEXT ("TAO (%P|%t) Invalid IIOP endpoint format: ")
00469                                  ACE_TEXT ("endpoint priorities no longer supported. \n")),
00470                                 -1);
00471             }
00472           else
00473             ACE_ERROR_RETURN ((LM_ERROR,
00474                                "TAO (%P|%t) Invalid UIOP option: <%s>\n",
00475                                name.c_str ()),
00476                               -1);
00477         }
00478     }
00479   return 0;
00480 }
00481 
00482 TAO_END_VERSIONED_NAMESPACE_DECL
00483 
00484 #endif  /* TAO_HAS_UIOP == 1 */

Generated on Thu Nov 9 13:39:30 2006 for TAO_Strategies by doxygen 1.3.6