DIOP_Profile.cpp

Go to the documentation of this file.
00001 // DIOP_Profile.cpp,v 1.25 2006/03/10 07:19:18 jtc Exp
00002 
00003 #include "tao/Strategies/DIOP_Profile.h"
00004 
00005 #if defined (TAO_HAS_DIOP) && (TAO_HAS_DIOP != 0)
00006 
00007 #include "tao/CDR.h"
00008 #include "tao/Environment.h"
00009 #include "tao/ORB.h"
00010 #include "tao/ORB_Core.h"
00011 #include "tao/debug.h"
00012 #include "tao/IIOP_EndpointsC.h"
00013 
00014 #include "ace/OS_NS_stdio.h"
00015 #include "ace/OS_NS_string.h"
00016 #include "ace/os_include/os_netdb.h"
00017 
00018 ACE_RCSID (Strategies,
00019            DIOP_Profile,
00020            "DIOP_Profile.cpp,v 1.25 2006/03/10 07:19:18 jtc Exp")
00021 
00022 static const char the_prefix[] = "diop";
00023 
00024 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00025 
00026 const char TAO_DIOP_Profile::object_key_delimiter_ = '/';
00027 
00028 char
00029 TAO_DIOP_Profile::object_key_delimiter (void) const
00030 {
00031   return TAO_DIOP_Profile::object_key_delimiter_;
00032 }
00033 
00034 
00035 TAO_DIOP_Profile::TAO_DIOP_Profile (const ACE_INET_Addr &addr,
00036                                     const TAO::ObjectKey &object_key,
00037                                     const TAO_GIOP_Message_Version &version,
00038                                     TAO_ORB_Core *orb_core)
00039   : TAO_Profile (TAO_TAG_DIOP_PROFILE,
00040                  orb_core,
00041                  object_key,
00042                  version),
00043     endpoint_ (addr,
00044                orb_core->orb_params ()->use_dotted_decimal_addresses ()),
00045     count_ (1)
00046 {
00047 }
00048 
00049 TAO_DIOP_Profile::TAO_DIOP_Profile (const char* host,
00050                                     CORBA::UShort port,
00051                                     const TAO::ObjectKey &object_key,
00052                                     const ACE_INET_Addr &addr,
00053                                     const TAO_GIOP_Message_Version &version,
00054                                     TAO_ORB_Core *orb_core)
00055   : TAO_Profile (TAO_TAG_DIOP_PROFILE,
00056                  orb_core,
00057                  object_key,
00058                  version),
00059     endpoint_ (host, port, addr),
00060     count_ (1)
00061 {
00062 }
00063 
00064 TAO_DIOP_Profile::TAO_DIOP_Profile (TAO_ORB_Core *orb_core)
00065   : TAO_Profile (TAO_TAG_DIOP_PROFILE,
00066                  orb_core,
00067                  TAO_GIOP_Message_Version (TAO_DEF_GIOP_MAJOR, TAO_DEF_GIOP_MINOR)),
00068     endpoint_ (),
00069     count_ (1)
00070 {
00071 }
00072 
00073 TAO_DIOP_Profile::~TAO_DIOP_Profile (void)
00074 {
00075   // Clean up the list of endpoints since we own it.
00076   // Skip the head, since it is not dynamically allocated.
00077   TAO_Endpoint *tmp = 0;
00078 
00079   for (TAO_Endpoint *next = this->endpoint ()->next ();
00080        next != 0;
00081        next = tmp)
00082     {
00083       tmp = next->next ();
00084       delete next;
00085     }
00086 }
00087 
00088 // return codes:
00089 // -1 -> error
00090 //  0 -> can't understand this version
00091 //  1 -> success.
00092 
00093 int
00094 TAO_DIOP_Profile::decode_profile (TAO_InputCDR& cdr)
00095 {
00096   // @@ NOTE: This code is repeated thrice. Need to factor out in a
00097   // better manner.
00098   // Decode host and port into the <endpoint_>.
00099   if (cdr.read_string (this->endpoint_.host_.out ()) == 0
00100       || cdr.read_ushort (this->endpoint_.port_) == 0)
00101     {
00102       if (TAO_debug_level > 0)
00103         ACE_DEBUG ((LM_DEBUG,
00104                     ACE_TEXT ("TAO (%P|%t) DIOP_Profile::decode - ")
00105                     ACE_TEXT ("error while decoding host/port")));
00106       return -1;
00107     }
00108 
00109   if (cdr.good_bit ())
00110     {
00111       // Invalidate the object_addr_ until first access.
00112       this->endpoint_.object_addr_.set_type (-1);
00113 
00114       return 1;
00115     }
00116 
00117   return -1;
00118 }
00119 
00120 void
00121 TAO_DIOP_Profile::parse_string_i (const char *ior
00122                                   ACE_ENV_ARG_DECL)
00123 {
00124   // Pull off the "hostname:port/" part of the objref
00125   // Copy the string because we are going to modify it...
00126   const char *okd =
00127     ACE_OS::strchr (ior, this->object_key_delimiter_);
00128 
00129   if (okd == 0 || okd == ior)
00130     {
00131       // No object key delimiter or no hostname specified.
00132       ACE_THROW (CORBA::INV_OBJREF (
00133                    CORBA::SystemException::_tao_minor_code (
00134                      TAO::VMCID,
00135                      EINVAL),
00136                    CORBA::COMPLETED_NO));
00137     }
00138 
00139   // Length of host string.
00140   CORBA::ULong length_host = 0;
00141 
00142   const char *cp_pos = ACE_OS::strchr (ior, ':');  // Look for a port
00143 
00144   if (cp_pos == ior)
00145     {
00146       // No hostname specified!  It is required by the spec.
00147       ACE_THROW (CORBA::INV_OBJREF (
00148                    CORBA::SystemException::_tao_minor_code (
00149                      TAO::VMCID,
00150                      EINVAL),
00151                    CORBA::COMPLETED_NO));
00152     }
00153   else if (cp_pos != 0)
00154     {
00155       // A port number or port name was specified.
00156       CORBA::ULong length_port = okd - cp_pos - 1;
00157 
00158       CORBA::String_var tmp = CORBA::string_alloc (length_port);
00159 
00160       ACE_OS::strncpy (tmp.inout (), cp_pos + 1, length_port);
00161       tmp[length_port] = '\0';
00162 
00163       this->endpoint_.port_ =
00164         static_cast<CORBA::UShort> (ACE_OS::atoi (tmp.in ()));
00165 
00166       length_host = cp_pos - ior;
00167     }
00168   else
00169     length_host = okd - ior;
00170 
00171   CORBA::String_var tmp = CORBA::string_alloc (length_host);
00172 
00173   // Skip the trailing '/'
00174   ACE_OS::strncpy (tmp.inout (), ior, length_host);
00175   tmp[length_host] = '\0';
00176 
00177   this->endpoint_.host_ = tmp._retn ();
00178 
00179   if (ACE_OS::strcmp (this->endpoint_.host_.in (), "") == 0)
00180     {
00181       ACE_INET_Addr host_addr;
00182 
00183       char tmp_host [MAXHOSTNAMELEN + 1];
00184 
00185       // If no host is specified: assign the default host, i.e. the
00186       // local host.
00187       if (host_addr.get_host_name (tmp_host,
00188                                    sizeof (tmp_host)) != 0)
00189         {
00190           // Can't get the IP address since the INET_Addr wasn't
00191           // initialized.  Just throw an exception.
00192 
00193           if (TAO_debug_level > 0)
00194             ACE_DEBUG ((LM_DEBUG,
00195                         ACE_TEXT ("\n\nTAO (%P|%t) ")
00196                         ACE_TEXT ("IIOP_Profile::parse_string ")
00197                         ACE_TEXT ("- %p\n\n"),
00198                         ACE_TEXT ("cannot determine hostname")));
00199 
00200           // @@ What's the right exception to throw here?
00201           ACE_THROW (CORBA::INV_OBJREF (
00202                        CORBA::SystemException::_tao_minor_code (
00203                          TAO::VMCID,
00204                          EINVAL),
00205                        CORBA::COMPLETED_NO));
00206         }
00207       else
00208         this->endpoint_.host_ = CORBA::string_dup (tmp_host);
00209     }
00210 
00211   TAO::ObjectKey ok;
00212   TAO::ObjectKey::decode_string_to_sequence (ok,
00213                                              okd + 1);
00214 
00215   (void) this->orb_core ()->object_key_table ().bind (ok,
00216                                                       this->ref_object_key_);
00217 }
00218 
00219 CORBA::Boolean
00220 TAO_DIOP_Profile::do_is_equivalent (const TAO_Profile *other_profile)
00221 {
00222   const TAO_DIOP_Profile *op =
00223     dynamic_cast<const TAO_DIOP_Profile *> (other_profile);
00224 
00225   // Check endpoints equivalence.
00226   const TAO_DIOP_Endpoint *other_endp = &op->endpoint_;
00227   for (TAO_DIOP_Endpoint *endp = &this->endpoint_;
00228        endp != 0;
00229        endp = endp->next_)
00230     {
00231       if (endp->is_equivalent (other_endp))
00232         other_endp = other_endp->next_;
00233       else
00234         return 0;
00235     }
00236 
00237   return 1;
00238 }
00239 
00240 CORBA::ULong
00241 TAO_DIOP_Profile::hash (CORBA::ULong max
00242                         ACE_ENV_ARG_DECL_NOT_USED)
00243 {
00244   // Get the hashvalue for all endpoints.
00245   CORBA::ULong hashval = 0;
00246   for (TAO_DIOP_Endpoint *endp = &this->endpoint_;
00247        endp != 0;
00248        endp = endp->next_)
00249     {
00250       hashval += endp->hash ();
00251     }
00252 
00253   hashval += this->version_.minor;
00254   hashval += this->tag ();
00255 
00256   const TAO::ObjectKey &ok =
00257     this->ref_object_key_->object_key ();
00258 
00259   if (ok.length () >= 4)
00260     {
00261       hashval += ok[1];
00262       hashval += ok[3];
00263     }
00264 
00265   hashval += this->hash_service_i (max);
00266 
00267   return hashval % max;
00268 }
00269 
00270 TAO_Endpoint*
00271 TAO_DIOP_Profile::endpoint (void)
00272 {
00273   return &this->endpoint_;
00274 }
00275 
00276 CORBA::ULong
00277 TAO_DIOP_Profile::endpoint_count (void) const
00278 {
00279   return this->count_;
00280 }
00281 
00282 void
00283 TAO_DIOP_Profile::add_endpoint (TAO_DIOP_Endpoint *endp)
00284 {
00285   endp->next_ = this->endpoint_.next_;
00286   this->endpoint_.next_ = endp;
00287 
00288   this->count_++;
00289 }
00290 
00291 char *
00292 TAO_DIOP_Profile::to_string (ACE_ENV_SINGLE_ARG_DECL_NOT_USED)
00293 {
00294   CORBA::String_var key;
00295   TAO::ObjectKey::encode_sequence_to_string (key.inout(),
00296                                             this->ref_object_key_->object_key ());
00297 
00298   size_t buflen = (8 /* "corbaloc" */ +
00299                    1 /* colon separator */ +
00300                    ACE_OS::strlen (::the_prefix) +
00301                    1 /* colon separator */ +
00302                    1 /* major version */ +
00303                    1 /* decimal point */ +
00304                    1 /* minor version */ +
00305                    1 /* `@' character */ +
00306                    ACE_OS::strlen (this->endpoint_.host ()) +
00307                    1 /* colon separator */ +
00308                    5 /* port number */ +
00309                    1 /* object key separator */ +
00310                    ACE_OS::strlen (key.in ()));
00311 
00312   char * buf = CORBA::string_alloc (static_cast<CORBA::ULong> (buflen));
00313 
00314   static const char digits [] = "0123456789";
00315 
00316   ACE_OS::sprintf (buf,
00317                    "corbaloc:%s:%c.%c@%s:%d%c%s",
00318                    ::the_prefix,
00319                    digits [this->version_.major],
00320                    digits [this->version_.minor],
00321                    this->endpoint_.host (),
00322                    this->endpoint_.port (),
00323                    this->object_key_delimiter_,
00324                    key.in ());
00325 
00326   return buf;
00327 }
00328 
00329 const char *
00330 TAO_DIOP_Profile::prefix (void)
00331 {
00332   return ::the_prefix;
00333 }
00334 
00335 void
00336 TAO_DIOP_Profile::create_profile_body (TAO_OutputCDR &encap) const
00337 {
00338   encap.write_octet (TAO_ENCAP_BYTE_ORDER);
00339 
00340   // The GIOP version
00341   encap.write_octet (this->version_.major);
00342   encap.write_octet (this->version_.minor);
00343 
00344   // STRING hostname from profile
00345   encap.write_string (this->endpoint_.host ());
00346 
00347   // UNSIGNED SHORT port number
00348   encap.write_ushort (this->endpoint_.port ());
00349 
00350   // OCTET SEQUENCE for object key
00351   if (this->ref_object_key_)
00352     encap << this->ref_object_key_->object_key ();
00353   else
00354     {
00355       ACE_ERROR ((LM_ERROR,
00356                   "(%P|%t) TAO - UIOP_Profile::create_profile_body "
00357                   "no object key marshalled \n"));
00358     }
00359 
00360   if (this->version_.major > 1
00361       || this->version_.minor > 0)
00362     this->tagged_components ().encode (encap);
00363 }
00364 
00365 int
00366 TAO_DIOP_Profile::encode_endpoints (void)
00367 {
00368   // Create a data structure and fill it with endpoint info for wire
00369   // transfer.
00370   // We include information for the head of the list
00371   // together with other endpoints because even though its addressing
00372   // info is transmitted using standard ProfileBody components, its
00373   // priority is not!
00374 
00375   TAO::IIOPEndpointSequence endpoints;
00376   endpoints.length (this->count_);
00377 
00378   const TAO_DIOP_Endpoint *endpoint = &this->endpoint_;
00379   for (CORBA::ULong i = 0;
00380        i < this->count_;
00381        ++i)
00382     {
00383       endpoints[i].host = endpoint->host ();
00384       endpoints[i].port = endpoint->port ();
00385       endpoints[i].priority = endpoint->priority ();
00386 
00387       endpoint = endpoint->next_;
00388     }
00389 
00390   // Encode the data structure.
00391   TAO_OutputCDR out_cdr;
00392   if ((out_cdr << ACE_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER)
00393        == 0)
00394       || (out_cdr << endpoints) == 0)
00395     return -1;
00396   size_t length = out_cdr.total_length ();
00397 
00398   IOP::TaggedComponent tagged_component;
00399   tagged_component.tag = TAO_TAG_ENDPOINTS;
00400   tagged_component.component_data.length (static_cast<CORBA::ULong> (length));
00401   CORBA::Octet *buf =
00402     tagged_component.component_data.get_buffer ();
00403 
00404   for (const ACE_Message_Block *iterator = out_cdr.begin ();
00405        iterator != 0;
00406        iterator = iterator->cont ())
00407     {
00408       size_t i_length = iterator->length ();
00409       ACE_OS::memcpy (buf, iterator->rd_ptr (), i_length);
00410 
00411       buf += i_length;
00412     }
00413 
00414   // Add component with encoded endpoint data to this profile's
00415   // TaggedComponents.
00416   tagged_components_.set_component (tagged_component);
00417 
00418   return  0;
00419 }
00420 
00421 int
00422 TAO_DIOP_Profile::decode_endpoints (void)
00423 {
00424   IOP::TaggedComponent tagged_component;
00425   tagged_component.tag = TAO_TAG_ENDPOINTS;
00426 
00427   if (this->tagged_components_.get_component (tagged_component))
00428     {
00429       const CORBA::Octet *buf =
00430         tagged_component.component_data.get_buffer ();
00431 
00432       TAO_InputCDR in_cdr (reinterpret_cast<const char*> (buf),
00433                            tagged_component.component_data.length ());
00434 
00435       // Extract the Byte Order.
00436       CORBA::Boolean byte_order;
00437       if ((in_cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0)
00438         return -1;
00439       in_cdr.reset_byte_order (static_cast<int> (byte_order));
00440 
00441       // Extract endpoints sequence.
00442       TAO::IIOPEndpointSequence endpoints;
00443 
00444       if ((in_cdr >> endpoints) == 0)
00445         return -1;
00446 
00447       // Get the priority of the first endpoint (head of the list.
00448       // It's other data is extracted as part of the standard profile
00449       // decoding.
00450       this->endpoint_.priority (endpoints[0].priority);
00451 
00452       // Use information extracted from the tagged component to
00453       // populate the profile.  Skip the first endpoint, since it is
00454       // always extracted through standard profile body.  Also, begin
00455       // from the end of the sequence to preserve endpoint order,
00456       // since <add_endpoint> method reverses the order of endpoints
00457       // in the list.
00458       for (CORBA::ULong i = endpoints.length () - 1;
00459            i > 0;
00460            --i)
00461         {
00462           TAO_DIOP_Endpoint *endpoint = 0;
00463           ACE_NEW_RETURN (endpoint,
00464                           TAO_DIOP_Endpoint (endpoints[i].host,
00465                                              endpoints[i].port,
00466                                              endpoints[i].priority),
00467                           -1);
00468 
00469           this->add_endpoint (endpoint);
00470         }
00471     }
00472 
00473   return 0;
00474 }
00475 
00476 TAO_END_VERSIONED_NAMESPACE_DECL
00477 
00478 #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