UIPMC_Acceptor.cpp

Go to the documentation of this file.
00001 // This may look like C, but it's really -*- C++ -*-
00002 //
00003 // UIPMC_Acceptor.cpp,v 1.19 2006/05/23 16:09:33 mitza Exp
00004 
00005 #include "orbsvcs/PortableGroup/UIPMC_Profile.h"
00006 #include "orbsvcs/PortableGroup/UIPMC_Acceptor.h"
00007 
00008 #include "tao/MProfile.h"
00009 #include "tao/ORB_Core.h"
00010 #include "tao/debug.h"
00011 #include "tao/Protocols_Hooks.h"
00012 #include "tao/ORB_Constants.h"
00013 
00014 #include "ace/Auto_Ptr.h"
00015 #include "ace/os_include/os_netdb.h"
00016 
00017 #if !defined(__ACE_INLINE__)
00018 #include "orbsvcs/PortableGroup/UIPMC_Acceptor.i"
00019 #endif /* __ACE_INLINE__ */
00020 
00021 ACE_RCSID (PortableGroup,
00022            UIPMC_Acceptor,
00023            "UIPMC_Acceptor.cpp,v 1.19 2006/05/23 16:09:33 mitza Exp")
00024 
00025 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00026 
00027 TAO_UIPMC_Acceptor::TAO_UIPMC_Acceptor (CORBA::Boolean /*flag*/)
00028   : TAO_Acceptor (IOP::TAG_UIPMC),
00029     addrs_ (0),
00030     hosts_ (0),
00031     endpoint_count_ (0),
00032     version_ (TAO_DEF_GIOP_MAJOR, TAO_DEF_GIOP_MINOR),
00033     orb_core_ (0),
00034     connection_handler_ (0)
00035 {
00036 }
00037 
00038 TAO_UIPMC_Acceptor::~TAO_UIPMC_Acceptor (void)
00039 {
00040   // Make sure we are closed before we start destroying the
00041   // strategies.
00042   this->close ();
00043 
00044   delete [] this->addrs_;
00045 
00046   for (size_t i = 0; i < this->endpoint_count_; ++i)
00047     CORBA::string_free (this->hosts_[i]);
00048 
00049   delete [] this->hosts_;
00050 }
00051 
00052 int
00053 TAO_UIPMC_Acceptor::create_profile (const TAO::ObjectKey &,
00054   TAO_MProfile &,
00055   CORBA::Short)
00056 {
00057   // The standard mechanism for adding profiles to object references
00058   // for each pluggable protocol doesn't apply to UIPMC profiles, so
00059   // this function just returns success without doing anything.  The
00060   // appropiate mechanism for getting UIPMC profiles is to call the
00061   // multicast group manager to get a Group reference.  Invocations
00062   // sent to this group reference will be dispatched to the servants
00063   // that belong to that group.
00064   return 0;
00065 }
00066 
00067 int
00068 TAO_UIPMC_Acceptor::is_collocated (const TAO_Endpoint *)
00069 {
00070   // @@ Not clear how
00071   // to best handle collation.  For example, one servant could
00072   // be collocated, but we still need to send the request out on
00073   // the network to see if there are any other servants in the
00074   // group.
00075   return 0;  // Not collocated
00076 }
00077 
00078 int
00079 TAO_UIPMC_Acceptor::close (void)
00080 {
00081   return 0;
00082 }
00083 
00084 int
00085 TAO_UIPMC_Acceptor::open (TAO_ORB_Core *orb_core,
00086                           ACE_Reactor *reactor,
00087                           int major,
00088                           int minor,
00089                           const char *address,
00090                           const char *options)
00091 {
00092   this->orb_core_ = orb_core;
00093 
00094   if (this->hosts_ != 0)
00095     {
00096       // The hostname cache has already been set!
00097       // This is bad mojo, i.e. an internal TAO error.
00098       ACE_ERROR_RETURN ((LM_ERROR,
00099                          ACE_TEXT ("TAO (%P|%t) ")
00100                          ACE_TEXT ("UIPMC_Acceptor::open - ")
00101                          ACE_TEXT ("hostname already set\n\n")),
00102                         -1);
00103     }
00104 
00105   if (address == 0)
00106     return -1;
00107 
00108   if (major >=0 && minor >= 0)
00109     this->version_.set_version (static_cast<CORBA::Octet> (major),
00110                                 static_cast<CORBA::Octet> (minor));
00111   // Parse options
00112   if (this->parse_options (options) == -1)
00113     return -1;
00114 
00115   ACE_INET_Addr addr;
00116 
00117   const char *port_separator_loc = ACE_OS::strchr (address, ':');
00118   const char *specified_hostname = 0;
00119   char tmp_host[MAXHOSTNAMELEN + 1];
00120 
00121   // Both host and port have to be specified.
00122   if (addr.set (address) != 0)
00123     return -1;
00124 
00125   // Extract out just the host part of the address.
00126   size_t len = port_separator_loc - address;
00127   ACE_OS::memcpy (tmp_host, address, len);
00128   tmp_host[len] = '\0';
00129 
00130   specified_hostname = tmp_host;
00131 
00132   this->endpoint_count_ = 1;  // Only one hostname to store
00133 
00134   ACE_NEW_RETURN (this->addrs_,
00135                   ACE_INET_Addr[this->endpoint_count_],
00136                   -1);
00137 
00138   ACE_NEW_RETURN (this->hosts_,
00139                   char *[this->endpoint_count_],
00140                   -1);
00141 
00142   this->hosts_[0] = 0;
00143 
00144   if (this->hostname (orb_core,
00145                       addr,
00146                       this->hosts_[0],
00147                       specified_hostname) != 0)
00148     return -1;
00149 
00150   // Copy the addr.  The port is (re)set in
00151   // TAO_UIPMC_Acceptor::open_i().
00152   if (this->addrs_[0].set (addr) != 0)
00153     return -1;
00154 
00155   return this->open_i (addr,
00156                        reactor);
00157 }
00158 
00159 int
00160 TAO_UIPMC_Acceptor::open_default (TAO_ORB_Core *,
00161                                   ACE_Reactor *,
00162                                   int,
00163                                   int,
00164                                   const char *)
00165 {
00166   // There is no such thing as a default multicast listen
00167   // port.  The mechanism for choosing these ports is done
00168   // when creating the group ids.  (I.e. not here).
00169   return -1;
00170 }
00171 
00172 int
00173 TAO_UIPMC_Acceptor::open_i (const ACE_INET_Addr& addr,
00174                             ACE_Reactor *reactor)
00175 {
00176   ACE_NEW_RETURN (this->connection_handler_,
00177                   TAO_UIPMC_Connection_Handler (this->orb_core_),
00178                   -1);
00179 
00180   this->connection_handler_->local_addr (addr);
00181   this->connection_handler_->open_server ();
00182 
00183   int result =
00184     reactor->register_handler (this->connection_handler_,
00185                                ACE_Event_Handler::READ_MASK);
00186   if (result == -1)
00187     return result;
00188 
00189   // Connection handler ownership now belongs to the Reactor.
00190   this->connection_handler_->remove_reference ();
00191 
00192   // Set the port for each addr.  If there is more than one network
00193   // interface then the endpoint created on each interface will be on
00194   // the same port.  This is how a wildcard socket bind() is supposed
00195   // to work.
00196   u_short port = addr.get_port_number ();
00197   for (size_t j = 0; j < this->endpoint_count_; ++j)
00198     this->addrs_[j].set_port_number (port, 1);
00199 
00200   if (TAO_debug_level > 5)
00201     {
00202       for (size_t i = 0; i < this->endpoint_count_; ++i)
00203         {
00204           ACE_DEBUG ((LM_DEBUG,
00205                       ACE_TEXT ("\nTAO (%P|%t) UIPMC_Acceptor::open_i - ")
00206                       ACE_TEXT ("listening on: <%s:%u>\n"),
00207                       this->hosts_[i],
00208                       this->addrs_[i].get_port_number ()));
00209         }
00210     }
00211 
00212   return 0;
00213 }
00214 
00215 int
00216 TAO_UIPMC_Acceptor::hostname (TAO_ORB_Core *,
00217                               ACE_INET_Addr &addr,
00218                               char *&host,
00219                               const char *)
00220 {
00221   // Only have dotted decimal addresses for multicast.
00222   return this->dotted_decimal_address (addr, host);
00223 }
00224 
00225 int
00226 TAO_UIPMC_Acceptor::dotted_decimal_address (ACE_INET_Addr &addr,
00227                                             char *&host)
00228 {
00229   const char *tmp = addr.get_host_addr ();
00230   if (tmp == 0)
00231     {
00232       if (TAO_debug_level > 0)
00233         ACE_DEBUG ((LM_DEBUG,
00234                     ACE_TEXT ("\n\nTAO (%P|%t) ")
00235                     ACE_TEXT ("UIPMC_Acceptor::dotted_decimal_address ")
00236                     ACE_TEXT ("- %p\n\n"),
00237                     ACE_TEXT ("cannot determine hostname")));
00238       return -1;
00239     }
00240 
00241   host = CORBA::string_dup (tmp);
00242   return 0;
00243 }
00244 
00245 CORBA::ULong
00246 TAO_UIPMC_Acceptor::endpoint_count (void)
00247 {
00248   return this->endpoint_count_;
00249 }
00250 
00251 int
00252 TAO_UIPMC_Acceptor::object_key (IOP::TaggedProfile &,
00253                                 TAO::ObjectKey &)
00254 {
00255   // No object key to extract.  Just return success.
00256   return 1;
00257 }
00258 
00259 
00260 int
00261 TAO_UIPMC_Acceptor::parse_options (const char *str)
00262 {
00263   if (str == 0)
00264     return 0;  // No options to parse.  Not a problem.
00265 
00266   // Use an option format similar to the one used for CGI scripts in
00267   // HTTP URLs.
00268   // e.g.:  option1=foo&option2=bar
00269 
00270   ACE_CString options (str);
00271 
00272   size_t len = options.length ();
00273 
00274   const char option_delimiter = '&';
00275 
00276   // Count the number of options.
00277 
00278   CORBA::ULong option_count = 1;
00279   // Number of endpoints in the string  (initialized to 1).
00280 
00281   // Only check for endpoints after the protocol specification and
00282   // before the object key.
00283   for (size_t i = 0; i < len; ++i)
00284     if (options[i] == option_delimiter)
00285       option_count++;
00286 
00287   // The idea behind the following loop is to split the options into
00288   // (option, name) pairs.
00289   // For example,
00290   //    `option1=foo&option2=bar'
00291   // will be parsed into:
00292   //    `option1=foo'
00293   //    `option2=bar'
00294 
00295   int begin = 0;
00296   int end = -1;
00297 
00298   for (CORBA::ULong j = 0; j < option_count; ++j)
00299     {
00300       begin += end + 1;
00301 
00302       if (j < option_count - 1)
00303         end = options.find (option_delimiter, begin);
00304       else
00305         end = static_cast<int> (len - begin); // Handle last endpoint differently
00306 
00307       if (end == begin)
00308         ACE_ERROR_RETURN ((LM_ERROR,
00309                            ACE_TEXT ("TAO (%P|%t) Zero length UIPMC option.\n")),
00310                           -1);
00311       else if (end != ACE_CString::npos)
00312         {
00313           ACE_CString opt = options.substring (begin, end);
00314 
00315           int slot = opt.find ("=");
00316 
00317           if (slot == static_cast<int> (len - 1)
00318               || slot == ACE_CString::npos)
00319             ACE_ERROR_RETURN ((LM_ERROR,
00320                                ACE_TEXT ("TAO (%P|%t) UIPMC option <%s> is ")
00321                                ACE_TEXT ("missing a value.\n"),
00322                                opt.c_str ()),
00323                               -1);
00324 
00325           ACE_CString name = opt.substring (0, slot);
00326           ACE_CString value = opt.substring (slot + 1);
00327 
00328           if (name.length () == 0)
00329             ACE_ERROR_RETURN ((LM_ERROR,
00330                                ACE_TEXT ("TAO (%P|%t) Zero length UIPMC ")
00331                                ACE_TEXT ("option name.\n")),
00332                               -1);
00333 
00334           if (name == "priority")
00335             {
00336               ACE_ERROR_RETURN ((LM_ERROR,
00337                                  ACE_TEXT ("TAO (%P|%t) Invalid UIPMC endpoint format: ")
00338                                  ACE_TEXT ("endpoint priorities no longer supported. \n"),
00339                                  value.c_str ()),
00340                                 -1);
00341             }
00342           else
00343             ACE_ERROR_RETURN ((LM_ERROR,
00344                                ACE_TEXT ("TAO (%P|%t) Invalid UIPMC option: <%s>\n"),
00345                                name.c_str ()),
00346                               -1);
00347         }
00348     }
00349   return 0;
00350 }
00351 
00352 TAO_END_VERSIONED_NAMESPACE_DECL

Generated on Thu Nov 9 14:03:34 2006 for TAO_PortableGroup by doxygen 1.3.6