IIOP_Profile.cpp

Go to the documentation of this file.
00001 #include "tao/IIOP_Profile.h"
00002 
00003 #if defined (TAO_HAS_IIOP) && (TAO_HAS_IIOP != 0)
00004 
00005 #include "tao/ORB_Core.h"
00006 #include "tao/debug.h"
00007 #include "tao/IIOP_EndpointsC.h"
00008 #include "tao/CDR.h"
00009 #include "tao/SystemException.h"
00010 
00011 #include "ace/OS_NS_string.h"
00012 #include "ace/OS_NS_stdio.h"
00013 
00014 ACE_RCSID (tao,
00015            IIOP_Profile,
00016            "$Id: IIOP_Profile.cpp 78128 2007-04-20 08:07:58Z johnnyw $")
00017 
00018 #include "ace/os_include/os_netdb.h"
00019 
00020 static const char the_prefix[] = "iiop";
00021 
00022 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00023 
00024 TAO_IIOP_Profile::~TAO_IIOP_Profile (void)
00025 {
00026   // Clean up the list of endpoints since we own it.
00027   // Skip the head, since it is not dynamically allocated.
00028   TAO_Endpoint *tmp = 0;
00029 
00030   for (TAO_Endpoint *next = this->endpoint ()->next ();
00031        next != 0;
00032        next = tmp)
00033     {
00034       tmp = next->next ();
00035       delete next;
00036     }
00037 }
00038 
00039 //@@ TAO_PROFILE_SPL_COPY_HOOK_START
00040 
00041 const char TAO_IIOP_Profile::object_key_delimiter_ = '/';
00042 
00043 char
00044 TAO_IIOP_Profile::object_key_delimiter (void) const
00045 {
00046   return TAO_IIOP_Profile::object_key_delimiter_;
00047 }
00048 
00049 //@@ TAO_PROFILE_SPL_COPY_HOOK_END
00050 
00051 TAO_IIOP_Profile::TAO_IIOP_Profile (const ACE_INET_Addr &addr,
00052                                     const TAO::ObjectKey &object_key,
00053                                     const TAO_GIOP_Message_Version &version,
00054                                     TAO_ORB_Core *orb_core)
00055   : TAO_Profile (IOP::TAG_INTERNET_IOP,
00056                  orb_core,
00057                  object_key,
00058                  version),
00059     endpoint_ (addr,
00060                orb_core->orb_params ()->use_dotted_decimal_addresses ()),
00061     count_ (1)
00062 {
00063 }
00064 
00065 TAO_IIOP_Profile::TAO_IIOP_Profile (const char* host,
00066                                     CORBA::UShort port,
00067                                     const TAO::ObjectKey &object_key,
00068                                     const ACE_INET_Addr &addr,
00069                                     const TAO_GIOP_Message_Version &version,
00070                                     TAO_ORB_Core *orb_core)
00071   : TAO_Profile (IOP::TAG_INTERNET_IOP,
00072                  orb_core,
00073                  object_key,
00074                  version),
00075     endpoint_ (host, port, addr),
00076     count_ (1)
00077 {
00078 }
00079 
00080 TAO_IIOP_Profile::TAO_IIOP_Profile (TAO_ORB_Core *orb_core)
00081   : TAO_Profile (IOP::TAG_INTERNET_IOP,
00082                  orb_core,
00083                  TAO_GIOP_Message_Version (TAO_DEF_GIOP_MAJOR,
00084                                            TAO_DEF_GIOP_MINOR)),
00085     endpoint_ (),
00086     count_ (1)
00087 {
00088 }
00089 
00090 //@@ TAO_PROFILE_SPL_COPY_HOOK_START
00091 int
00092 TAO_IIOP_Profile::decode_profile (TAO_InputCDR& cdr)
00093 {
00094   // Decode host and port into the <endpoint_>.
00095   // it is necessary to do it indirectly so that IPv6 host addresses
00096   // can be evaluated correctly.
00097   CORBA::String_var host;
00098   CORBA::UShort port;
00099 
00100   if (cdr.read_string(host.out()) == 0 ||
00101       cdr.read_ushort (port) == 0)
00102     {
00103       if (TAO_debug_level > 0)
00104         ACE_DEBUG ((LM_DEBUG,
00105                     ACE_TEXT ("TAO (%P|%t) IIOP_Profile::decode - ")
00106                     ACE_TEXT ("error while decoding host/port\n")));
00107       return -1;
00108     }
00109 
00110   this->endpoint_.host(host.in());
00111   this->endpoint_.port(port);
00112 
00113   if (cdr.good_bit ())
00114     {
00115       // Invalidate the object_addr_ until first access.
00116       this->endpoint_.object_addr_.set_type (-1);
00117 
00118       const char* csv = this->orb_core()->orb_params()->preferred_interfaces();
00119       bool const enforce =
00120         this->orb_core()->orb_params()->enforce_pref_interfaces();
00121       this->count_ += this->endpoint_.preferred_interfaces(csv, enforce);
00122 
00123       return 1;
00124     }
00125 
00126   return -1;
00127 }
00128 
00129 void
00130 TAO_IIOP_Profile::parse_string_i (const char *ior)
00131 {
00132   // Pull off the "hostname:port/" part of the objref
00133   // Copy the string because we are going to modify it...
00134 
00135   const char *okd = ACE_OS::strchr (ior, this->object_key_delimiter_);
00136 
00137   if (okd == 0 || okd == ior)
00138     {
00139       // No object key delimiter or no hostname specified.
00140       throw ::CORBA::INV_OBJREF (
00141                    CORBA::SystemException::_tao_minor_code (
00142                      0,
00143                      EINVAL),
00144                    CORBA::COMPLETED_NO);
00145     }
00146 
00147   // Length of host string.
00148   CORBA::ULong length_host = 0;
00149 
00150   const char *cp_pos = ACE_OS::strchr (ior, ':');  // Look for a port
00151 #if defined (ACE_HAS_IPV6)
00152   // IPv6 numeric address in host string?
00153   bool ipv6_in_host = false;
00154 
00155   // Check if this is a (possibly) IPv6 supporting profile containing a
00156   // decimal IPv6 address representation.
00157   if ((this->version().major > TAO_MIN_IPV6_IIOP_MAJOR ||
00158         this->version().minor >= TAO_MIN_IPV6_IIOP_MINOR) &&
00159       ior[0] == '[')
00160     {
00161       // In this case we have to find the end of the numeric address and
00162       // start looking for the port separator from there.
00163       const char *cp_pos_a = ACE_OS::strchr(ior, ']');
00164       if (cp_pos_a == 0)
00165         {
00166           // No valid IPv6 address specified.
00167           if (TAO_debug_level > 0)
00168             {
00169               ACE_ERROR ((LM_ERROR,
00170                        ACE_TEXT ("\nTAO (%P|%t) IIOP_Profile: ")
00171                        ACE_TEXT ("Invalid IPv6 decimal address specified.\n")));
00172             }
00173 
00174           throw ::CORBA::INV_OBJREF (
00175                        CORBA::SystemException::_tao_minor_code (
00176                          0,
00177                          EINVAL),
00178                        CORBA::COMPLETED_NO);
00179         }
00180       else
00181         {
00182           if (cp_pos_a[1] == ':')    // Look for a port
00183             cp_pos = cp_pos_a + 1;
00184           else
00185             cp_pos = 0;
00186           ipv6_in_host = true; // host string contains full IPv6 numeric address
00187         }
00188     }
00189 #endif /* ACE_HAS_IPV6 */
00190 
00191   if (cp_pos == ior)
00192     {
00193       // No hostname, however one is required by the spec when specifying a port.
00194       // See formal-04-03-01, section 13.6.10.3
00195       if (TAO_debug_level > 0)
00196         {
00197           ACE_ERROR ((LM_ERROR,
00198                    ACE_TEXT ("\nTAO (%P|%t) IIOP_Profile: ")
00199                    ACE_TEXT ("Host address may be omited only when no port has been specified.\n")));
00200         }
00201 
00202       throw ::CORBA::INV_OBJREF (
00203                    CORBA::SystemException::_tao_minor_code (
00204                      0,
00205                      EINVAL),
00206                    CORBA::COMPLETED_NO);
00207     }
00208   else if (cp_pos != 0)
00209     {
00210       // A port number or port name was specified.
00211       CORBA::ULong length_port = okd - cp_pos - 1;
00212       CORBA::String_var tmp = CORBA::string_alloc (length_port);
00213 
00214       if (tmp.in() != 0)
00215         {
00216           ACE_OS::strncpy (tmp.inout (), cp_pos + 1, length_port);
00217           tmp[length_port] = '\0';
00218         }
00219 
00220       if (length_port == 0)
00221         {
00222           this->endpoint_.port_ = 2809; // default IIOP port for
00223           // parsing corbaloc strings
00224         }
00225       else if (tmp.in () != 0 && ACE_OS::strspn (tmp.in (), "1234567890") == length_port)
00226         {
00227           this->endpoint_.port_ =
00228             static_cast<CORBA::UShort> (ACE_OS::atoi (tmp.in ()));
00229         }
00230       else
00231         {
00232           ACE_INET_Addr ia;
00233           if (tmp.in () == 0 || ia.string_to_addr (tmp.in ()) == -1)
00234             {
00235               throw ::CORBA::INV_OBJREF (
00236                              CORBA::SystemException::_tao_minor_code (
00237                                0,
00238                                EINVAL),
00239                              CORBA::COMPLETED_NO);
00240             }
00241           else
00242             {
00243               this->endpoint_.port_ = ia.get_port_number ();
00244             }
00245         }
00246       length_host = cp_pos - ior;
00247     }
00248   else
00249     length_host = okd - ior;
00250 
00251 #if defined (ACE_HAS_IPV6)
00252   if (ipv6_in_host)
00253     length_host -= 2; // don't store '[' and ']'
00254 #endif /* ACE_HAS_IPV6 */
00255 
00256   CORBA::String_var tmp = CORBA::string_alloc (length_host);
00257 
00258 #if defined (ACE_HAS_IPV6)
00259   if (ipv6_in_host)
00260     ACE_OS::strncpy (tmp.inout (), ior + 1, length_host);
00261   else
00262 #endif /* ACE_HAS_IPV6 */
00263   // Skip the trailing '/'
00264   ACE_OS::strncpy (tmp.inout (), ior, length_host);
00265   tmp[length_host] = '\0';
00266 
00267   this->endpoint_.host_ = tmp._retn ();
00268 #if defined (ACE_HAS_IPV6)
00269   this->endpoint_.is_ipv6_decimal_ = ipv6_in_host;
00270 #endif /* ACE_HAS_IPV6 */
00271 
00272   if (ACE_OS::strcmp (this->endpoint_.host_.in (), "") == 0)
00273     {
00274       ACE_INET_Addr host_addr;
00275 
00276       char tmp_host [MAXHOSTNAMELEN + 1];
00277 
00278       // If no host is specified: assign the default host, i.e. the
00279       // local host.
00280       if (host_addr.get_host_name (tmp_host,
00281                                    sizeof (tmp_host)) != 0)
00282         {
00283           // Can't get the IP address since the INET_Addr wasn't
00284           // initialized.  Just throw an exception.
00285 
00286           if (TAO_debug_level > 0)
00287             ACE_DEBUG ((LM_DEBUG,
00288                         ACE_TEXT ("\n\nTAO (%P|%t) ")
00289                         ACE_TEXT ("IIOP_Profile::parse_string ")
00290                         ACE_TEXT ("- %p\n\n"),
00291                         ACE_TEXT ("cannot determine hostname")));
00292 
00293           // @@ What's the right exception to throw here?
00294           throw ::CORBA::INV_OBJREF (
00295                        CORBA::SystemException::_tao_minor_code (
00296                          0,
00297                          EINVAL),
00298                        CORBA::COMPLETED_NO);
00299         }
00300       else
00301         this->endpoint_.host_ = CORBA::string_dup (tmp_host);
00302     }
00303 
00304   TAO::ObjectKey ok;
00305 
00306   TAO::ObjectKey::decode_string_to_sequence (ok,
00307                                              okd + 1);
00308 
00309   (void) this->orb_core ()->object_key_table ().bind (ok,
00310                                                       this->ref_object_key_);
00311 }
00312 
00313 CORBA::Boolean
00314 TAO_IIOP_Profile::do_is_equivalent (const TAO_Profile *other_profile)
00315 {
00316   if (other_profile == this)
00317     return true;
00318 
00319   const TAO_IIOP_Profile *op =
00320     dynamic_cast<const TAO_IIOP_Profile *> (other_profile);
00321 
00322   // Make sure we have a TAO_IIOP_Profile.
00323   if (op == 0)
00324     return false;
00325 
00326   if (this->count_ == 0 && op->count_ == 0)
00327     return true;
00328   if (this->count_ != op->count_)
00329     return false;
00330   // Check endpoints equivalence.
00331   const TAO_IIOP_Endpoint *other_endp = &op->endpoint_;
00332   for (TAO_IIOP_Endpoint *endp = &this->endpoint_;
00333        endp != 0;
00334        endp = endp->next_)
00335     {
00336       if (endp->is_equivalent (other_endp))
00337         other_endp = other_endp->next_;
00338       else
00339         return false;
00340     }
00341 
00342   return true;
00343 }
00344 
00345 CORBA::ULong
00346 TAO_IIOP_Profile::hash (CORBA::ULong max)
00347 {
00348   // Get the hash value for all endpoints.
00349   CORBA::ULong hashval = 0;
00350   for (TAO_IIOP_Endpoint *endp = &this->endpoint_;
00351        endp != 0;
00352        endp = endp->next_)
00353     {
00354       hashval += endp->hash ();
00355     }
00356 
00357   hashval += this->version_.minor;
00358   hashval += this->tag ();
00359 
00360   const TAO::ObjectKey &ok =
00361     this->ref_object_key_->object_key ();
00362 
00363   if (ok.length () >= 4)
00364     {
00365       hashval += ok[1];
00366       hashval += ok[3];
00367     }
00368 
00369   hashval += TAO_Profile::hash_service_i (max);
00370 
00371   return hashval % max;
00372 }
00373 
00374 TAO_Endpoint*
00375 TAO_IIOP_Profile::endpoint (void)
00376 {
00377   return &this->endpoint_;
00378 }
00379 
00380 TAO_Endpoint *
00381 TAO_IIOP_Profile::base_endpoint (void)
00382 {
00383   // do not call endpoint(), return the value directly. This is to
00384   // avoid calling a derived implementation of endpoint().
00385   return &this->endpoint_;
00386 }
00387 
00388 CORBA::ULong
00389 TAO_IIOP_Profile::endpoint_count (void) const
00390 {
00391   return this->count_;
00392 }
00393 
00394 void
00395 TAO_IIOP_Profile::add_endpoint (TAO_IIOP_Endpoint *endp)
00396 {
00397   endp->next_ = this->endpoint_.next_;
00398   this->endpoint_.next_ = endp;
00399 
00400   ++this->count_;
00401 }
00402 
00403 void
00404 TAO_IIOP_Profile::remove_endpoint (TAO_IIOP_Endpoint *endp)
00405 {
00406   if (endp == 0)
00407     return;
00408 
00409   // special handling for the target matching the base endpoint
00410   if (endp == &this->endpoint_)
00411     {
00412       if (--this->count_ > 0)
00413         {
00414           TAO_IIOP_Endpoint* n = this->endpoint_.next_;
00415           this->endpoint_ = *n;
00416           // since the assignment operator does not copy the next_
00417           // pointer, we must do it by hand
00418           this->endpoint_.next_ = n->next_;
00419           delete n;
00420         }
00421       return;
00422     }
00423 
00424   TAO_IIOP_Endpoint* last = &this->endpoint_;
00425   TAO_IIOP_Endpoint* cur = this->endpoint_.next_;
00426 
00427   while (cur != 0)
00428   {
00429     if (cur == endp)
00430       break;
00431     last = cur;
00432     cur = cur->next_;
00433   }
00434 
00435   if (cur != 0)
00436   {
00437     last->next_ = cur->next_;
00438     cur->next_ = 0;
00439     --this->count_;
00440     delete cur;
00441   }
00442 }
00443 
00444 void
00445 TAO_IIOP_Profile::remove_generic_endpoint (TAO_Endpoint *ep)
00446 {
00447   this->remove_endpoint(dynamic_cast<TAO_IIOP_Endpoint *>(ep));
00448 }
00449 
00450 void
00451 TAO_IIOP_Profile::add_generic_endpoint (TAO_Endpoint *endp)
00452 {
00453   TAO_IIOP_Endpoint *iep = dynamic_cast<TAO_IIOP_Endpoint *>(endp);
00454   if (iep != 0)
00455     {
00456       TAO_IIOP_Endpoint *clone;
00457       ACE_NEW (clone, TAO_IIOP_Endpoint(*iep));
00458       this->add_endpoint(clone);
00459     }
00460 }
00461 
00462 char *
00463 TAO_IIOP_Profile::to_string (void)
00464 {
00465   // corbaloc:iiop:1.2@host:port,iiop:1.2@host:port,.../key
00466 
00467   CORBA::String_var key;
00468   TAO::ObjectKey::encode_sequence_to_string (key.inout(),
00469                                              this->ref_object_key_->object_key ());
00470 
00471   size_t buflen = (
00472        8 /* "corbaloc" */ +
00473        1 /* colon separator */ +
00474        1 /* object key separator */ +
00475        ACE_OS::strlen (key.in ()));
00476   size_t const pfx_len = (
00477        ACE_OS::strlen (::the_prefix) /* "iiop" */ +
00478        1 /* colon separator */);
00479 
00480  const TAO_IIOP_Endpoint *endp = 0;
00481  for (endp = &this->endpoint_; endp != 0; endp = endp->next_)
00482    {
00483       buflen += (
00484           pfx_len +
00485           1 /* major version */ +
00486           1 /* decimal point */ +
00487           1 /* minor version */ +
00488           1 /* `@' character */ +
00489           ACE_OS::strlen (endp->host ()) +
00490           1 /* colon separator */ +
00491           5 /* port number */ +
00492           1 /* comma */);
00493 #if defined (ACE_HAS_IPV6)
00494       if (endp->is_ipv6_decimal_)
00495         buflen += 2; // room for '[' and ']'
00496 #endif /* ACE_HAS_IPV6 */
00497    }
00498 
00499   static const char digits [] = "0123456789";
00500 
00501   char * buf = CORBA::string_alloc (static_cast<CORBA::ULong> (buflen));
00502 
00503   ACE_OS::strcpy(buf, "corbaloc:");
00504 
00505   for (endp = &this->endpoint_; endp != 0; endp = endp->next_)
00506     {
00507       if(&this->endpoint_ != endp)
00508       ACE_OS::strcat(buf, ",");
00509 
00510 #if defined (ACE_HAS_IPV6)
00511       if (endp->is_ipv6_decimal_)
00512         {
00513           // Don't publish scopeid if included.
00514           ACE_CString tmp(endp->host ());
00515           ACE_CString::size_type pos = tmp.find('%');
00516           if (pos != ACE_CString::npos)
00517             {
00518               tmp = tmp.substr(0, pos + 1);
00519               tmp[pos] = '\0';
00520             }
00521           ACE_OS::sprintf (buf + ACE_OS::strlen(buf),
00522                   "%s:%c.%c@[%s]:%d",
00523                   ::the_prefix,
00524                   digits [this->version_.major],
00525                   digits [this->version_.minor],
00526                   tmp.c_str (),
00527                   endp->port () );
00528         }
00529       else
00530 #endif
00531       ACE_OS::sprintf (buf + ACE_OS::strlen(buf),
00532               "%s:%c.%c@%s:%d",
00533               ::the_prefix,
00534               digits [this->version_.major],
00535               digits [this->version_.minor],
00536               endp->host (),
00537               endp->port () );
00538 
00539   }
00540   ACE_OS::sprintf (buf + ACE_OS::strlen(buf),
00541           "%c%s",
00542           this->object_key_delimiter_,
00543           key.in ());
00544 
00545   return buf;
00546 }
00547 
00548 const char *
00549 TAO_IIOP_Profile::prefix (void)
00550 {
00551   return ::the_prefix;
00552 }
00553 
00554 void
00555 TAO_IIOP_Profile::create_profile_body (TAO_OutputCDR &encap) const
00556 {
00557   encap.write_octet (TAO_ENCAP_BYTE_ORDER);
00558 
00559   // The GIOP version
00560   encap.write_octet (this->version_.major);
00561   encap.write_octet (this->version_.minor);
00562 
00563   // STRING hostname from profile
00564 #if defined (ACE_HAS_IPV6)
00565   // For IPv6 decimal addresses make sure the possibly included scopeid
00566   // is not published as this has only local meaning.
00567   const char* host = 0;
00568   const char* pos = 0;
00569   if (this->endpoint_.is_ipv6_decimal_ &&
00570       (pos = ACE_OS::strchr (host = this->endpoint_.host (), '%')) != 0)
00571     {
00572       ACE_CString tmp;
00573       size_t len = pos - host;
00574       tmp.set (this->endpoint_.host (), len, 1);
00575       encap.write_string (tmp.c_str ());
00576     }
00577   else
00578 #endif /* ACE_HAS_IPV6 */
00579   encap.write_string (this->endpoint_.host ());
00580 
00581 
00582   // UNSIGNED SHORT port number
00583   encap.write_ushort (this->endpoint_.port ());
00584 
00585   // OCTET SEQUENCE for object key
00586   if (this->ref_object_key_)
00587     encap << this->ref_object_key_->object_key ();
00588   else
00589     {
00590       ACE_ERROR ((LM_ERROR,
00591                   "(%P|%t) TAO - IIOP_Profile::create_profile_body "
00592                   "no object key marshalled \n"));
00593     }
00594 
00595   if (this->version_.major > 1
00596       || this->version_.minor > 0)
00597     this->tagged_components ().encode (encap);
00598 }
00599 
00600 int
00601 TAO_IIOP_Profile::encode_alternate_endpoints (void)
00602 {
00603   // encode IOP::TAG_ALTERNATE_IIOP_ADDRESS tags if there are more
00604   // than one endpoints to listen to.
00605   const TAO_IIOP_Endpoint *endpoint = &this->endpoint_;
00606   for (CORBA::ULong i = 1;
00607        i < this->count_;
00608        ++i)
00609     {
00610       // The first endpoint is the actual endpoint. The rest of the
00611       // endpoints are the alternate endpoints. So, neglect the first
00612       // endpoint for TAG_ALTERNATE_IIOP_ADDRESS
00613       endpoint = endpoint->next_;
00614 
00615       if (!endpoint->is_encodable_)
00616         continue;
00617 
00618       // Encode the data structure. - The CORBA specification does not
00619       // mandate a particular container for the endpoints, only that
00620       // it is encoded as host first, then port.
00621       TAO_OutputCDR out_cdr;
00622 
00623 #if defined (ACE_HAS_IPV6)
00624       // For IPv6 decimal addresses make sure the possibly included scopeid
00625       // is not published as this has only local meaning.
00626       const char* host = 0;
00627       const char* pos = 0;
00628       if (endpoint->is_ipv6_decimal_ &&
00629           (pos = ACE_OS::strchr (host = endpoint->host (), '%')) != 0)
00630         {
00631           ACE_CString tmp;
00632           size_t len = pos - host;
00633           tmp.set (endpoint->host (), len, 1);
00634           if ((out_cdr << ACE_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER) == 0)
00635               || (out_cdr << tmp.c_str () == 0)
00636               || (out_cdr << endpoint->port () == 0))
00637             return -1;
00638           out_cdr.write_string (len, endpoint->host ());
00639         }
00640       else
00641 #endif /* ACE_HAS_IPV6 */
00642       if ((out_cdr << ACE_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER) == 0)
00643                 || (out_cdr << endpoint->host () == 0)
00644           || (out_cdr << endpoint->port () == 0))
00645         return -1;
00646 
00647       IOP::TaggedComponent tagged_component;
00648       tagged_component.tag = IOP::TAG_ALTERNATE_IIOP_ADDRESS;
00649 
00650       size_t length = out_cdr.total_length ();
00651       tagged_component.component_data.length
00652         (static_cast<CORBA::ULong>(length));
00653       CORBA::Octet *buf =
00654         tagged_component.component_data.get_buffer ();
00655 
00656       for (const ACE_Message_Block *iterator = out_cdr.begin ();
00657                  iterator != 0;
00658            iterator = iterator->cont ())
00659         {
00660           size_t i_length = iterator->length ();
00661           ACE_OS::memcpy (buf, iterator->rd_ptr (), i_length);
00662 
00663           buf += i_length;
00664         }
00665 
00666       // Add component with encoded endpoint data to this profile's
00667       // TaggedComponents.
00668       tagged_components_.set_component (tagged_component);
00669     }
00670   return  0;
00671 }
00672 
00673 int
00674 TAO_IIOP_Profile::encode_endpoints (void)
00675 {
00676   CORBA::ULong actual_count = 0;
00677 
00678   const TAO_IIOP_Endpoint *endpoint = &this->endpoint_;
00679 
00680   // Count the number of endpoints that needs to be encoded
00681   for (CORBA::ULong c = 0;
00682        c != this->count_;
00683        ++c)
00684     {
00685       if (endpoint->is_encodable_)
00686         ++actual_count;
00687 
00688       endpoint = endpoint->next_;
00689     }
00690 
00691   // Create a data structure and fill it with endpoint info for wire
00692   // transfer.
00693   // We include information for the head of the list
00694   // together with other endpoints because even though its addressing
00695   // info is transmitted using standard ProfileBody components, its
00696   // priority is not!
00697 
00698   TAO::IIOPEndpointSequence endpoints;
00699   endpoints.length (actual_count);
00700 
00701   endpoint = &this->endpoint_;
00702 
00703   for (CORBA::ULong i = 0;
00704        i < actual_count;
00705        ++i)
00706     {
00707       if (endpoint->is_encodable_)
00708         {
00709 #if defined (ACE_HAS_IPV6)
00710           if (endpoint->is_ipv6_decimal_)
00711             {
00712               // Don't publish scopeid if included.
00713               ACE_CString tmp(endpoint->host ());
00714               ACE_CString::size_type pos = tmp.find('%');
00715               if (pos != ACE_CString::npos)
00716                 {
00717                   tmp = tmp.substr (0, pos + 1);
00718                   tmp[pos] = '\0';
00719                   endpoints[i].host = tmp.c_str();
00720                 }
00721               else
00722                 endpoints[i].host = tmp.c_str();
00723             }
00724           else
00725 #endif /* ACE_HAS_IPV6 */
00726           endpoints[i].host = endpoint->host ();
00727           endpoints[i].port = endpoint->port ();
00728           endpoints[i].priority = endpoint->priority ();
00729         }
00730       endpoint = endpoint->next_;
00731     }
00732 
00733   // Encode the data structure.
00734   TAO_OutputCDR out_cdr;
00735   if ((out_cdr << ACE_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER)
00736        == 0)
00737       || (out_cdr << endpoints) == 0)
00738     return -1;
00739 
00740   this->set_tagged_components (out_cdr);
00741 
00742   return  0;
00743 }
00744 
00745 
00746 int
00747 TAO_IIOP_Profile::decode_endpoints (void)
00748 {
00749   IOP::TaggedComponent tagged_component;
00750   tagged_component.tag = TAO_TAG_ENDPOINTS;
00751 
00752   if (this->tagged_components_.get_component (tagged_component))
00753     {
00754       const CORBA::Octet *buf =
00755         tagged_component.component_data.get_buffer ();
00756 
00757       TAO_InputCDR in_cdr (reinterpret_cast<const char *> (buf),
00758                            tagged_component.component_data.length ());
00759 
00760       // Extract the Byte Order.
00761       CORBA::Boolean byte_order;
00762       if ((in_cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0)
00763         return -1;
00764       in_cdr.reset_byte_order (static_cast<int> (byte_order));
00765 
00766       // Extract endpoints sequence.
00767       TAO::IIOPEndpointSequence endpoints;
00768 
00769       if ((in_cdr >> endpoints) == 0)
00770         return -1;
00771 
00772       // Get the priority of the first endpoint (head of the list.
00773       // It's other data is extracted as part of the standard profile
00774       // decoding.
00775       this->endpoint_.priority (endpoints[0].priority);
00776 
00777       // Use information extracted from the tagged component to
00778       // populate the profile.  Skip the first endpoint, since it is
00779       // always extracted through standard profile body.  Also, begin
00780       // from the end of the sequence to preserve endpoint order,
00781       // since <add_endpoint> method reverses the order of endpoints
00782       // in the list.
00783       for (CORBA::ULong i = endpoints.length () - 1;
00784            i > 0;
00785            --i)
00786         {
00787           TAO_IIOP_Endpoint *endpoint = 0;
00788           ACE_NEW_RETURN (endpoint,
00789                           TAO_IIOP_Endpoint (endpoints[i].host,
00790                                              endpoints[i].port,
00791                                              endpoints[i].priority),
00792                           -1);
00793 
00794           this->add_endpoint (endpoint);
00795         }
00796     }
00797 
00798   // Now decode if there are any TAG_ALTERNATE_IIOP_ADDRESS
00799   // components.
00800 
00801   IOP::MultipleComponentProfile& tc = this->tagged_components_.components();
00802   for (CORBA::ULong index = 0; index < tc.length(); index++)
00803     {
00804       if (tc[index].tag != IOP::TAG_ALTERNATE_IIOP_ADDRESS)
00805         continue;
00806       const CORBA::Octet *buf =
00807         tc[index].component_data.get_buffer ();
00808 
00809       TAO_InputCDR in_cdr (reinterpret_cast<const char*>(buf),
00810                            tc[index].component_data.length ());
00811 
00812       // Extract the Byte Order.
00813       CORBA::Boolean byte_order;
00814       if ((in_cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0)
00815         return -1;
00816 
00817       in_cdr.reset_byte_order (static_cast<int>(byte_order));
00818 
00819       CORBA::String_var host;
00820       CORBA::Short port;
00821 
00822       if ((in_cdr >> host.out()) == 0 ||
00823           (in_cdr >> port) == 0)
00824         return -1;
00825 
00826       TAO_IIOP_Endpoint *endpoint = 0;
00827       ACE_NEW_RETURN (endpoint,
00828                       TAO_IIOP_Endpoint (host.in(),
00829                                          port,
00830                                          TAO_INVALID_PRIORITY),
00831                       -1);
00832 
00833       this->add_endpoint (endpoint);
00834     }
00835 
00836   return 0;
00837 }
00838 //@@ TAO_PROFILE_SPL_COPY_HOOK_END
00839 
00840 TAO_END_VERSIONED_NAMESPACE_DECL
00841 
00842 #endif /* TAO_HAS_IIOP && TAO_HAS_IIOP != 0 */

Generated on Tue Feb 2 17:37:52 2010 for TAO by  doxygen 1.4.7