DIOP_Acceptor.cpp

Go to the documentation of this file.
00001 // This may look like C, but it's really -*- C++ -*-
00002 // DIOP_Acceptor.cpp,v 1.28 2006/05/16 12:35:17 jwillemsen Exp
00003 
00004 #include "tao/Strategies/DIOP_Acceptor.h"
00005 
00006 #if defined (TAO_HAS_DIOP) && (TAO_HAS_DIOP != 0)
00007 
00008 #include "tao/Strategies/DIOP_Profile.h"
00009 #include "tao/MProfile.h"
00010 #include "tao/ORB_Core.h"
00011 #include "tao/debug.h"
00012 #include "tao/Protocols_Hooks.h"
00013 #include "tao/Codeset_Manager.h"
00014 #include "tao/CDR.h"
00015 
00016 #include "ace/Auto_Ptr.h"
00017 #include "ace/OS_NS_string.h"
00018 
00019 #if !defined(__ACE_INLINE__)
00020 #include "tao/Strategies/DIOP_Acceptor.i"
00021 #endif /* __ACE_INLINE__ */
00022 
00023 #include "ace/os_include/os_netdb.h"
00024 
00025 ACE_RCSID (Strategies,
00026            DIOP_Acceptor,
00027            "DIOP_Acceptor.cpp,v 1.28 2006/05/16 12:35:17 jwillemsen Exp")
00028 
00029 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00030 
00031 TAO_DIOP_Acceptor::TAO_DIOP_Acceptor (CORBA::Boolean flag)
00032   : TAO_Acceptor (TAO_TAG_DIOP_PROFILE),
00033     addrs_ (0),
00034     hosts_ (0),
00035     endpoint_count_ (0),
00036     version_ (TAO_DEF_GIOP_MAJOR, TAO_DEF_GIOP_MINOR),
00037     orb_core_ (0),
00038     lite_flag_ (flag),
00039     connection_handler_ (0)
00040 {
00041 }
00042 
00043 TAO_DIOP_Acceptor::~TAO_DIOP_Acceptor (void)
00044 {
00045   // Make sure we are closed before we start destroying the
00046   // strategies.
00047   this->close ();
00048 
00049   delete [] this->addrs_;
00050 
00051   for (size_t i = 0; i < this->endpoint_count_; ++i)
00052     CORBA::string_free (this->hosts_[i]);
00053 
00054   delete [] this->hosts_;
00055 }
00056 
00057 // TODO =
00058 //    2) For V1.[1,2] there are tagged components
00059 
00060 int
00061 TAO_DIOP_Acceptor::create_profile (const TAO::ObjectKey & object_key,
00062                                    TAO_MProfile &mprofile,
00063                                    CORBA::Short priority)
00064 {
00065   // Sanity check.
00066   if (this->endpoint_count_ == 0)
00067     return -1;
00068 
00069   // Check if multiple endpoints should be put in one profile or if
00070   // they should be spread across multiple profiles.
00071   if (priority == TAO_INVALID_PRIORITY)
00072     return this->create_new_profile (object_key,
00073                                      mprofile,
00074                                      priority);
00075   else
00076     return this->create_shared_profile (object_key,
00077                                         mprofile,
00078                                         priority);
00079 }
00080 
00081 int
00082 TAO_DIOP_Acceptor::create_new_profile (const TAO::ObjectKey &object_key,
00083                                        TAO_MProfile &mprofile,
00084                                        CORBA::Short priority)
00085 {
00086   // Adding this->endpoint_count_ to the TAO_MProfile.
00087   int const count = mprofile.profile_count ();
00088   if ((mprofile.size () - count) < this->endpoint_count_
00089       && mprofile.grow (count + this->endpoint_count_) == -1)
00090     return -1;
00091 
00092   // Create a profile for each acceptor endpoint.
00093   for (size_t i = 0; i < this->endpoint_count_; ++i)
00094     {
00095       TAO_DIOP_Profile *pfile = 0;
00096       ACE_NEW_RETURN (pfile,
00097                       TAO_DIOP_Profile (this->hosts_[i],
00098                                         this->addrs_[i].get_port_number (),
00099                                         object_key,
00100                                         this->addrs_[i],
00101                                         this->version_,
00102                                         this->orb_core_),
00103                       -1);
00104       pfile->endpoint ()->priority (priority);
00105 
00106       if (mprofile.give_profile (pfile) == -1)
00107         {
00108           pfile->_decr_refcnt ();
00109           pfile = 0;
00110           return -1;
00111         }
00112 
00113       // Do not add any tagged components to the profile if configured
00114       // by the user not to do so, or if an IIOP 1.0 endpoint is being
00115       // created (IIOP 1.0 did not support tagged components).
00116       if (this->orb_core_->orb_params ()->std_profile_components () == 0
00117           || (this->version_.major == 1 && this->version_.minor == 0))
00118         continue;
00119 
00120       pfile->tagged_components ().set_orb_type (TAO_ORB_TYPE);
00121 
00122       TAO_Codeset_Manager *csm = this->orb_core_->codeset_manager();
00123       if (csm)
00124         csm->set_codeset(pfile->tagged_components());
00125     }
00126 
00127   return 0;
00128 }
00129 
00130 int
00131 TAO_DIOP_Acceptor::create_shared_profile (const TAO::ObjectKey &object_key,
00132                                           TAO_MProfile &mprofile,
00133                                           CORBA::Short priority)
00134 {
00135   size_t index = 0;
00136   TAO_Profile *pfile = 0;
00137   TAO_DIOP_Profile *iiop_profile = 0;
00138 
00139   // First see if <mprofile> already contains a DIOP profile.
00140   for (TAO_PHandle i = 0; i != mprofile.profile_count (); ++i)
00141     {
00142       pfile = mprofile.get_profile (i);
00143       if (pfile->tag () == TAO_TAG_DIOP_PROFILE)
00144       {
00145         iiop_profile = dynamic_cast<TAO_DIOP_Profile *> (pfile);
00146         break;
00147       }
00148     }
00149 
00150   // If <mprofile> doesn't contain a DIOP_Profile, we need to create
00151   // one.
00152   if (iiop_profile == 0)
00153     {
00154       ACE_NEW_RETURN (iiop_profile,
00155                       TAO_DIOP_Profile (this->hosts_[0],
00156                                         this->addrs_[0].get_port_number (),
00157                                         object_key,
00158                                         this->addrs_[0],
00159                                         this->version_,
00160                                         this->orb_core_),
00161                       -1);
00162       iiop_profile->endpoint ()->priority (priority);
00163 
00164       if (mprofile.give_profile (iiop_profile) == -1)
00165         {
00166           iiop_profile->_decr_refcnt ();
00167           iiop_profile = 0;
00168           return -1;
00169         }
00170 
00171       if (this->orb_core_->orb_params ()->std_profile_components () != 0
00172           && (this->version_.major >= 1 && this->version_.minor >= 1))
00173         {
00174           iiop_profile->tagged_components ().set_orb_type (TAO_ORB_TYPE);
00175           TAO_Codeset_Manager *csm = this->orb_core_->codeset_manager();
00176           if (csm)
00177             csm->set_codeset(pfile->tagged_components());
00178         }
00179 
00180       index = 1;
00181     }
00182 
00183   // Add any remaining acceptor endpoints to the DIOP_Profile.
00184   for (;
00185        index < this->endpoint_count_;
00186        ++index)
00187     {
00188       TAO_DIOP_Endpoint *endpoint = 0;
00189       ACE_NEW_RETURN (endpoint,
00190                       TAO_DIOP_Endpoint (this->hosts_[index],
00191                                          this->addrs_[index].get_port_number (),
00192                                          this->addrs_[index]),
00193                       -1);
00194       endpoint->priority (priority);
00195       iiop_profile->add_endpoint (endpoint);
00196     }
00197 
00198   return 0;
00199 }
00200 
00201 int
00202 TAO_DIOP_Acceptor::is_collocated (const TAO_Endpoint *endpoint)
00203 {
00204   const TAO_DIOP_Endpoint *endp =
00205     dynamic_cast<const TAO_DIOP_Endpoint *> (endpoint);
00206 
00207   // Make sure the dynamically cast pointer is valid.
00208   if (endp == 0)
00209     return 0;
00210 
00211   for (size_t i = 0; i < this->endpoint_count_; ++i)
00212     {
00213       // compare the port and host name.  Please do *NOT* optimize
00214       // this code by comparing the IP address instead.  That would
00215       // trigger the following bug:
00216       //
00217       // http://deuce.doc.wustl.edu/bugzilla/show_bug.cgi?id=1220
00218       //
00219       if (endp->port() == this->addrs_[i].get_port_number()
00220           && ACE_OS::strcmp(endp->host(), this->hosts_[i]) == 0)
00221         return 1;  // Collocated
00222     }
00223 
00224   return 0;  // Not collocated
00225 }
00226 
00227 int
00228 TAO_DIOP_Acceptor::close (void)
00229 {
00230   return 0;
00231 }
00232 
00233 int
00234 TAO_DIOP_Acceptor::open (TAO_ORB_Core *orb_core,
00235                          ACE_Reactor *reactor,
00236                          int major,
00237                          int minor,
00238                          const char *address,
00239                          const char *options)
00240 {
00241   this->orb_core_ = orb_core;
00242 
00243   if (this->hosts_ != 0)
00244     {
00245       // The hostname cache has already been set!
00246       // This is bad mojo, i.e. an internal TAO error.
00247       ACE_ERROR_RETURN ((LM_ERROR,
00248                          ACE_TEXT ("TAO (%P|%t) ")
00249                          ACE_TEXT ("DIOP_Acceptor::open - ")
00250                          ACE_TEXT ("hostname already set\n\n")),
00251                         -1);
00252     }
00253 
00254   if (address == 0)
00255     return -1;
00256 
00257   if (major >=0 && minor >= 0)
00258     this->version_.set_version (static_cast<CORBA::Octet> (major),
00259                                 static_cast<CORBA::Octet> (minor));
00260   // Parse options
00261   if (this->parse_options (options) == -1)
00262     return -1;
00263 
00264   ACE_INET_Addr addr;
00265 
00266   const char *port_separator_loc = ACE_OS::strchr (address, ':');
00267   const char *specified_hostname = 0;
00268   char tmp_host[MAXHOSTNAMELEN + 1];
00269 
00270   if (port_separator_loc == address)
00271     {
00272       // The address is a port number or port name.  No hostname was
00273       // specified.  The hostname for each network interface and the
00274       // fully qualified domain name must be obtained.
00275 
00276       // Check for multiple network interfaces.
00277       if (this->probe_interfaces (orb_core) == -1)
00278         return -1;
00279 
00280       // First convert the port into a usable form.
00281       if (addr.set (address + sizeof (':')) != 0)
00282         return -1;
00283 
00284       // Now reset the port and set the host.
00285       if (addr.set (addr.get_port_number (),
00286                     static_cast<ACE_UINT32> (INADDR_ANY),
00287                     1) != 0)
00288         return -1;
00289       else
00290         return this->open_i (addr,
00291                              reactor);
00292     }
00293   else if (port_separator_loc == 0)
00294     {
00295       // The address is a hostname.  No port was specified, so assume
00296       // port zero (port will be chosen for us).
00297       if (addr.set ((unsigned short) 0, address) != 0)
00298         return -1;
00299 
00300       specified_hostname = address;
00301     }
00302   else
00303     {
00304       // Host and port were specified.
00305       if (addr.set (address) != 0)
00306         return -1;
00307 
00308       // Extract out just the host part of the address.
00309       size_t len = port_separator_loc - address;
00310       ACE_OS::memcpy (tmp_host, address, len);
00311       tmp_host[len] = '\0';
00312 
00313       specified_hostname = tmp_host;
00314     }
00315 
00316   this->endpoint_count_ = 1;  // Only one hostname to store
00317 
00318   ACE_NEW_RETURN (this->addrs_,
00319                   ACE_INET_Addr[this->endpoint_count_],
00320                   -1);
00321 
00322   ACE_NEW_RETURN (this->hosts_,
00323                   char *[this->endpoint_count_],
00324                   -1);
00325 
00326   this->hosts_[0] = 0;
00327 
00328   if (this->hostname (orb_core,
00329                       addr,
00330                       this->hosts_[0],
00331                       specified_hostname) != 0)
00332     return -1;
00333 
00334   // Copy the addr.  The port is (re)set in
00335   // TAO_DIOP_Acceptor::open_i().
00336   if (this->addrs_[0].set (addr) != 0)
00337     return -1;
00338 
00339   return this->open_i (addr,
00340                        reactor);
00341 }
00342 
00343 int
00344 TAO_DIOP_Acceptor::open_default (TAO_ORB_Core *orb_core,
00345                                  ACE_Reactor *reactor,
00346                                  int major,
00347                                  int minor,
00348                                  const char *options)
00349 {
00350   this->orb_core_ = orb_core;
00351 
00352   if (this->hosts_ != 0)
00353     {
00354       // The hostname cache has already been set!
00355       // This is bad mojo, i.e. an internal TAO error.
00356       ACE_ERROR_RETURN ((LM_ERROR,
00357                          ACE_TEXT ("TAO (%P|%t) ")
00358                          ACE_TEXT ("DIOP_Acceptor::open_default - ")
00359                          ACE_TEXT ("hostname already set\n\n")),
00360                         -1);
00361     }
00362 
00363   if (major >=0 && minor >= 0)
00364     this->version_.set_version (static_cast<CORBA::Octet> (major),
00365                                 static_cast<CORBA::Octet> (minor));
00366 
00367   // Parse options
00368   if (this->parse_options (options) == -1)
00369     return -1;
00370 
00371   // Check for multiple network interfaces.
00372   if (this->probe_interfaces (orb_core) == -1)
00373     return -1;
00374 
00375   // Now that each network interface's hostname has been cached, open
00376   // an endpoint on each network interface using the INADDR_ANY
00377   // address.
00378   ACE_INET_Addr addr;
00379 
00380   if (addr.set (static_cast<unsigned short> (0),
00381                 static_cast<ACE_UINT32> (INADDR_ANY),
00382                 1) != 0)
00383     return -1;
00384 
00385   return this->open_i (addr,
00386                        reactor);
00387 }
00388 
00389 int
00390 TAO_DIOP_Acceptor::open_i (const ACE_INET_Addr& addr,
00391                            ACE_Reactor *reactor)
00392 {
00393   ACE_NEW_RETURN (this->connection_handler_,
00394                   TAO_DIOP_Connection_Handler (this->orb_core_,
00395                                                this->lite_flag_),
00396                   -1);
00397 
00398   this->connection_handler_->local_addr (addr);
00399   this->connection_handler_->open_server ();
00400 
00401   // Register only with a valid handle
00402   int const result =
00403     reactor->register_handler (this->connection_handler_,
00404                                ACE_Event_Handler::READ_MASK);
00405   if (result == -1)
00406     return result;
00407 
00408   // Connection handler ownership now belongs to the Reactor.
00409   this->connection_handler_->remove_reference ();
00410 
00411   ACE_INET_Addr address;
00412 
00413   // We do this make sure the port number the endpoint is listening on
00414   // gets set in the addr.
00415   if (this->connection_handler_->dgram ().get_local_addr (address) != 0)
00416     {
00417       if (TAO_debug_level > 0)
00418         ACE_ERROR ((LM_ERROR,
00419                     ACE_TEXT ("TAO (%P|%t) DIOP_Acceptor::open_i ")
00420                     ACE_TEXT ("- %p"),
00421                     ACE_TEXT ("cannot get local addr\n")));
00422       return -1;
00423     }
00424 
00425   // Set the port for each addr.  If there is more than one network
00426   // interface then the endpoint created on each interface will be on
00427   // the same port.  This is how a wildcard socket bind() is supposed
00428   // to work.
00429   u_short const port = address.get_port_number ();
00430   for (size_t j = 0; j < this->endpoint_count_; ++j)
00431     this->addrs_[j].set_port_number (port, 1);
00432 
00433   if (TAO_debug_level > 5)
00434     {
00435       for (size_t i = 0; i < this->endpoint_count_; ++i)
00436         {
00437           ACE_DEBUG ((LM_DEBUG,
00438                       ACE_TEXT ("\nTAO (%P|%t) DIOP_Acceptor::open_i - ")
00439                       ACE_TEXT ("listening on: <%s:%u>\n"),
00440                       ACE_TEXT_CHAR_TO_TCHAR (this->hosts_[i]),
00441                       this->addrs_[i].get_port_number ()));
00442         }
00443     }
00444 
00445   return 0;
00446 }
00447 
00448 int
00449 TAO_DIOP_Acceptor::hostname (TAO_ORB_Core *orb_core,
00450                              ACE_INET_Addr &addr,
00451                              char *&host,
00452                              const char *specified_hostname)
00453 {
00454   if (orb_core->orb_params ()->use_dotted_decimal_addresses ())
00455     {
00456       // If dotted decimal addresses are enabled,
00457       // just return ours.
00458       return this->dotted_decimal_address (addr, host);
00459     }
00460   else
00461   if (specified_hostname != 0)
00462     {
00463       // If the user specified a hostname, pass it back
00464       // blindly as it overrides our choice of hostname.
00465       host = CORBA::string_dup (specified_hostname);
00466     }
00467   else
00468     {
00469       char tmp_host[MAXHOSTNAMELEN + 1];
00470 
00471       // Get the hostname associated with our address
00472       if (addr.get_host_name (tmp_host, sizeof (tmp_host)) != 0)
00473         {
00474           // On failure, just return the decimal address.
00475           return this->dotted_decimal_address (addr, host);
00476         }
00477       else
00478         {
00479           host = CORBA::string_dup (tmp_host);
00480         }
00481     }
00482 
00483   return 0;
00484 }
00485 
00486 int
00487 TAO_DIOP_Acceptor::dotted_decimal_address (ACE_INET_Addr &addr,
00488                                            char *&host)
00489 {
00490   const char *tmp = addr.get_host_addr ();
00491   if (tmp == 0)
00492     {
00493       if (TAO_debug_level > 0)
00494         ACE_DEBUG ((LM_DEBUG,
00495                     ACE_TEXT ("\n\nTAO (%P|%t) ")
00496                     ACE_TEXT ("DIOP_Acceptor::dotted_decimal_address ")
00497                     ACE_TEXT ("- %p\n\n"),
00498                     ACE_TEXT ("cannot determine hostname")));
00499       return -1;
00500     }
00501 
00502   host = CORBA::string_dup (tmp);
00503   return 0;
00504 }
00505 
00506 int
00507 TAO_DIOP_Acceptor::probe_interfaces (TAO_ORB_Core *orb_core)
00508 {
00509   // Extract the hostname for each network interface, and then cache
00510   // it.  The hostnames will then be used when creating a
00511   // TAO_DIOP_Profile for each endpoint setup on the probed
00512   // network interfaces.
00513   ACE_INET_Addr *if_addrs = 0;
00514   size_t if_cnt = 0;
00515 
00516   if (ACE::get_ip_interfaces (if_cnt,
00517                               if_addrs) != 0
00518       && errno != ENOTSUP)
00519     {
00520       // In the case where errno == ENOTSUP, if_cnt and if_addrs will
00521       // not be modified, and will each remain equal to zero.  This
00522       // causes the default interface to be used.
00523       return -1;
00524     }
00525 
00526   if (if_cnt == 0 || if_addrs == 0)
00527     {
00528       if (TAO_debug_level > 0)
00529         {
00530           ACE_DEBUG ((LM_WARNING,
00531                       ACE_TEXT ("TAO (%P|%t) Unable to probe network ")
00532                       ACE_TEXT ("interfaces.  Using default.")));
00533         }
00534 
00535       if_cnt = 1; // Force the network interface count to be one.
00536       delete [] if_addrs;
00537       ACE_NEW_RETURN (if_addrs,
00538                       ACE_INET_Addr[if_cnt],
00539                       -1);
00540     }
00541 
00542   // Scan for the loopback interface since it shouldn't be included in
00543   // the list of cached hostnames unless it is the only interface.
00544   size_t lo_cnt = 0;  // Loopback interface count
00545   for (size_t j = 0; j < if_cnt; ++j)
00546     if (if_addrs[j].get_ip_address () == INADDR_LOOPBACK)
00547       lo_cnt++;
00548 
00549   // The instantiation for this template is in
00550   // tao/DIOP_Connector.cpp.
00551   ACE_Auto_Basic_Array_Ptr<ACE_INET_Addr> safe_if_addrs (if_addrs);
00552 
00553   // If the loopback interface is the only interface then include it
00554   // in the list of interfaces to query for a hostname, otherwise
00555   // exclude it from the list.
00556   if (if_cnt == lo_cnt)
00557     this->endpoint_count_ = static_cast<CORBA::ULong> (if_cnt);
00558   else
00559     this->endpoint_count_ = static_cast<CORBA::ULong> (if_cnt - lo_cnt);
00560 
00561   ACE_NEW_RETURN (this->addrs_,
00562                   ACE_INET_Addr[this->endpoint_count_],
00563                   -1);
00564 
00565   ACE_NEW_RETURN (this->hosts_,
00566                   char *[this->endpoint_count_],
00567                   -1);
00568 
00569   ACE_OS::memset (this->hosts_, 0, sizeof (char*) * this->endpoint_count_);
00570 
00571   // The number of hosts/interfaces we want to cache may not be the
00572   // same as the number of detected interfaces so keep a separate
00573   // count.
00574   size_t host_cnt = 0;
00575 
00576   for (size_t i = 0; i < if_cnt; ++i)
00577     {
00578       // Ignore any loopback interface if there are other
00579       // non-loopback interfaces.
00580       if (if_cnt != lo_cnt &&
00581           if_addrs[i].get_ip_address() == INADDR_LOOPBACK)
00582         continue;
00583 
00584       if (this->hostname (orb_core,
00585                           if_addrs[i],
00586                           this->hosts_[host_cnt]) != 0)
00587         return -1;
00588 
00589       // Copy the addr.  The port is (re)set in
00590       // TAO_DIOP_Acceptor::open_i().
00591       if (this->addrs_[host_cnt].set (if_addrs[i]) != 0)
00592         return -1;
00593 
00594       host_cnt++;
00595     }
00596 
00597   return 0;
00598 }
00599 
00600 CORBA::ULong
00601 TAO_DIOP_Acceptor::endpoint_count (void)
00602 {
00603   return this->endpoint_count_;
00604 }
00605 
00606 int
00607 TAO_DIOP_Acceptor::object_key (IOP::TaggedProfile &profile,
00608                                TAO::ObjectKey &object_key)
00609 {
00610   // Create the decoding stream from the encapsulation in the buffer,
00611 #if (TAO_NO_COPY_OCTET_SEQUENCES == 1)
00612   TAO_InputCDR cdr (profile.profile_data.mb ());
00613 #else
00614   TAO_InputCDR cdr (reinterpret_cast<char*> (profile.profile_data.get_buffer ()),
00615                     profile.profile_data.length ());
00616 #endif /* TAO_NO_COPY_OCTET_SEQUENCES == 1 */
00617 
00618   CORBA::Octet major;
00619   CORBA::Octet minor = CORBA::Octet();
00620 
00621   // Read the version. We just read it here. We don't*do any*
00622   // processing.
00623   if (!(cdr.read_octet (major)
00624         && cdr.read_octet (minor)))
00625   {
00626     if (TAO_debug_level > 0)
00627       {
00628         ACE_DEBUG ((LM_DEBUG,
00629                     ACE_TEXT ("TAO (%P|%t) DIOP_Profile::decode - v%d.%d\n"),
00630                     major,
00631                     minor));
00632       }
00633     return -1;
00634   }
00635 
00636   CORBA::String_var host;
00637   CORBA::UShort port = 0;
00638 
00639   // Get host and port. No processing here too..
00640   if (cdr.read_string (host.out ()) == 0
00641       || cdr.read_ushort (port) == 0)
00642     {
00643       if (TAO_debug_level > 0)
00644         {
00645           ACE_DEBUG ((LM_DEBUG,
00646                       ACE_TEXT ("TAO (%P|%t) TAO_DIOP_Acceptor::object_key - ")
00647                       ACE_TEXT ("error while decoding host/port")));
00648         }
00649       return -1;
00650     }
00651 
00652   // ... and object key.
00653   if ((cdr >> object_key) == 0)
00654     return -1;
00655 
00656   // We are NOT bothered about the rest.
00657 
00658   return 1;
00659 }
00660 
00661 
00662 int
00663 TAO_DIOP_Acceptor::parse_options (const char *str)
00664 {
00665   if (str == 0)
00666     return 0;  // No options to parse.  Not a problem.
00667 
00668   // Use an option format similar to the one used for CGI scripts in
00669   // HTTP URLs.
00670   // e.g.:  option1=foo&option2=bar
00671 
00672   ACE_CString options (str);
00673 
00674   size_t len = options.length ();
00675 
00676   const char option_delimiter = '&';
00677 
00678   // Count the number of options.
00679 
00680   CORBA::ULong option_count = 1;
00681   // Number of endpoints in the string  (initialized to 1).
00682 
00683   // Only check for endpoints after the protocol specification and
00684   // before the object key.
00685   for (size_t i = 0; i < len; ++i)
00686     if (options[i] == option_delimiter)
00687       option_count++;
00688 
00689   // The idea behind the following loop is to split the options into
00690   // (option, name) pairs.
00691   // For example,
00692   //    `option1=foo&option2=bar'
00693   // will be parsed into:
00694   //    `option1=foo'
00695   //    `option2=bar'
00696 
00697   ssize_t begin = 0;
00698   ssize_t end = -1;
00699 
00700   for (CORBA::ULong j = 0; j < option_count; ++j)
00701     {
00702       begin += end + 1;
00703 
00704       if (j < option_count - 1)
00705         end = options.find (option_delimiter, begin);
00706       else
00707         end = (len - begin); // Handle last endpoint differently
00708 
00709       if (end == begin)
00710         ACE_ERROR_RETURN ((LM_ERROR,
00711                            ACE_TEXT ("TAO (%P|%t) Zero length DIOP option.\n")),
00712                           -1);
00713       else if (end != ACE_CString::npos)
00714         {
00715           ACE_CString opt = options.substring (begin, end);
00716 
00717           ssize_t slot = opt.find ("=");
00718 
00719           if (slot == static_cast<ssize_t> (len - 1)
00720               || slot == ACE_CString::npos)
00721             ACE_ERROR_RETURN ((LM_ERROR,
00722                                ACE_TEXT ("TAO (%P|%t) DIOP option <%s> is ")
00723                                ACE_TEXT ("missing a value.\n"),
00724                                ACE_TEXT_CHAR_TO_TCHAR (opt.c_str ())),
00725                               -1);
00726 
00727           ACE_CString name = opt.substring (0, slot);
00728           ACE_CString value = opt.substring (slot + 1);
00729 
00730           if (name.length () == 0)
00731             ACE_ERROR_RETURN ((LM_ERROR,
00732                                ACE_TEXT ("TAO (%P|%t) Zero length DIOP ")
00733                                ACE_TEXT ("option name.\n")),
00734                               -1);
00735 
00736           if (name == "priority")
00737             {
00738               ACE_ERROR_RETURN ((LM_ERROR,
00739                                  ACE_TEXT ("TAO (%P|%t) Invalid DIOP endpoint format: ")
00740                                  ACE_TEXT ("endpoint priorities no longer supported. \n")),
00741                                 -1);
00742             }
00743           else
00744             ACE_ERROR_RETURN ((LM_ERROR,
00745                                ACE_TEXT ("TAO (%P|%t) Invalid DIOP option: <%s>\n"),
00746                                ACE_TEXT_CHAR_TO_TCHAR (name.c_str ())),
00747                               -1);
00748         }
00749     }
00750   return 0;
00751 }
00752 
00753 TAO_END_VERSIONED_NAMESPACE_DECL
00754 
00755 #endif /* TAO_HAS_DIOP && TAO_HAS_DIOP != 0 */

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