SCIOP_Profile.cpp

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

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