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

Generated on Sun Jan 27 15:59:50 2008 for TAO_Strategies by doxygen 1.3.6