00001
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/SystemException.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 "$Id: DIOP_Profile.cpp 84228 2009-01-23 15:22:07Z johnnyw $")
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
00076
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
00089
00090
00091
00092
00093 int
00094 TAO_DIOP_Profile::decode_profile (TAO_InputCDR& cdr)
00095 {
00096
00097
00098
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_profile, ")
00105 ACE_TEXT ("error while decoding host/port\n")));
00106 return -1;
00107 }
00108
00109 if (cdr.good_bit ())
00110 {
00111
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 {
00123
00124
00125 const char *okd = ACE_OS::strchr (ior, this->object_key_delimiter_);
00126
00127 if (okd == 0 || okd == ior)
00128 {
00129
00130 throw ::CORBA::INV_OBJREF (
00131 CORBA::SystemException::_tao_minor_code (
00132 TAO::VMCID,
00133 EINVAL),
00134 CORBA::COMPLETED_NO);
00135 }
00136
00137
00138 CORBA::ULong length_host = 0;
00139
00140 const char *cp_pos = ACE_OS::strchr (ior, ':');
00141 #if defined (ACE_HAS_IPV6)
00142
00143 bool ipv6_in_host = false;
00144
00145
00146
00147 if ((this->version ().major > TAO_MIN_IPV6_IIOP_MAJOR ||
00148 this->version ().minor >= TAO_MIN_IPV6_IIOP_MINOR) &&
00149 ior[0] == '[')
00150 {
00151
00152
00153 const char *cp_pos_a = ACE_OS::strchr (ior, ']');
00154 if (cp_pos_a == 0)
00155 {
00156
00157 if (TAO_debug_level > 0)
00158 {
00159 ACE_DEBUG ((LM_ERROR,
00160 ACE_TEXT ("\nTAO (%P|%t) - DIOP_Profile::parse_string_i, ")
00161 ACE_TEXT ("invalid IPv6 decimal address specified.\n")));
00162 }
00163
00164 throw ::CORBA::INV_OBJREF (
00165 CORBA::SystemException::_tao_minor_code (
00166 0,
00167 EINVAL),
00168 CORBA::COMPLETED_NO);
00169 }
00170 else
00171 {
00172 if (cp_pos_a[1] == ':')
00173 cp_pos = cp_pos_a + 1;
00174 else
00175 cp_pos = 0;
00176 ipv6_in_host = true;
00177 }
00178 }
00179 #endif
00180
00181 if (cp_pos == ior)
00182 {
00183 if (TAO_debug_level > 0)
00184 {
00185 ACE_ERROR ((LM_ERROR,
00186 ACE_TEXT ("\nTAO (%P|%t) DIOP_Profile: ")
00187 ACE_TEXT ("Host address may be omited only when no port has been specified.\n")));
00188 }
00189
00190 throw ::CORBA::INV_OBJREF (
00191 CORBA::SystemException::_tao_minor_code (
00192 TAO::VMCID,
00193 EINVAL),
00194 CORBA::COMPLETED_NO);
00195 }
00196 else if (cp_pos != 0)
00197 {
00198
00199 CORBA::ULong length_port = okd - cp_pos - 1;
00200
00201 CORBA::String_var tmp = CORBA::string_alloc (length_port);
00202
00203 ACE_OS::strncpy (tmp.inout (), cp_pos + 1, length_port);
00204 tmp[length_port] = '\0';
00205
00206 if (ACE_OS::strspn (tmp.in (), "1234567890") == length_port)
00207 {
00208 this->endpoint_.port_ =
00209 static_cast<CORBA::UShort> (ACE_OS::atoi (tmp.in ()));
00210 }
00211 else
00212 {
00213 ACE_INET_Addr ia;
00214 if (ia.string_to_addr (tmp.in ()) == -1)
00215 {
00216 throw ::CORBA::INV_OBJREF (
00217 CORBA::SystemException::_tao_minor_code (
00218 0,
00219 EINVAL),
00220 CORBA::COMPLETED_NO);
00221 }
00222 else
00223 {
00224 this->endpoint_.port_ = ia.get_port_number ();
00225 }
00226 }
00227
00228 length_host = cp_pos - ior;
00229 }
00230 else
00231 length_host = okd - ior;
00232
00233 #if defined (ACE_HAS_IPV6)
00234 if (ipv6_in_host)
00235 length_host -= 2;
00236 #endif
00237
00238 CORBA::String_var tmp = CORBA::string_alloc (length_host);
00239
00240 #if defined (ACE_HAS_IPV6)
00241 if (ipv6_in_host)
00242 ACE_OS::strncpy (tmp.inout (), ior + 1, length_host);
00243 else
00244 #endif
00245
00246 ACE_OS::strncpy (tmp.inout (), ior, length_host);
00247 tmp[length_host] = '\0';
00248
00249 this->endpoint_.host_ = tmp._retn ();
00250 #if defined (ACE_HAS_IPV6)
00251 this->endpoint_.is_ipv6_decimal_ = ipv6_in_host;
00252 #endif
00253
00254 if (ACE_OS::strcmp (this->endpoint_.host_.in (), "") == 0)
00255 {
00256 ACE_INET_Addr host_addr;
00257
00258 char tmp_host [MAXHOSTNAMELEN + 1];
00259
00260
00261
00262 if (host_addr.get_host_name (tmp_host,
00263 sizeof (tmp_host)) != 0)
00264 {
00265
00266
00267
00268 if (TAO_debug_level > 0)
00269 ACE_DEBUG ((LM_DEBUG,
00270 ACE_TEXT ("TAO (%P|%t) - ")
00271 ACE_TEXT ("DIOP_Profile::parse_string_i, ")
00272 ACE_TEXT ("%p\n\n"),
00273 ACE_TEXT ("cannot determine hostname")));
00274
00275
00276 throw ::CORBA::INV_OBJREF (
00277 CORBA::SystemException::_tao_minor_code (
00278 TAO::VMCID,
00279 EINVAL),
00280 CORBA::COMPLETED_NO);
00281 }
00282 else
00283 this->endpoint_.host_ = CORBA::string_dup (tmp_host);
00284 }
00285
00286 TAO::ObjectKey ok;
00287 TAO::ObjectKey::decode_string_to_sequence (ok,
00288 okd + 1);
00289
00290 (void) this->orb_core ()->object_key_table ().bind (ok,
00291 this->ref_object_key_);
00292 }
00293
00294 CORBA::Boolean
00295 TAO_DIOP_Profile::do_is_equivalent (const TAO_Profile *other_profile)
00296 {
00297 const TAO_DIOP_Profile *op =
00298 dynamic_cast<const TAO_DIOP_Profile *> (other_profile);
00299
00300
00301 if (op == 0)
00302 return 0;
00303
00304
00305 const TAO_DIOP_Endpoint *other_endp = &op->endpoint_;
00306 for (TAO_DIOP_Endpoint *endp = &this->endpoint_;
00307 endp != 0;
00308 endp = endp->next_)
00309 {
00310 if (endp->is_equivalent (other_endp))
00311 other_endp = other_endp->next_;
00312 else
00313 return false;
00314 }
00315
00316 return true;
00317 }
00318
00319 CORBA::ULong
00320 TAO_DIOP_Profile::hash (CORBA::ULong max)
00321 {
00322
00323 CORBA::ULong hashval = 0;
00324 for (TAO_DIOP_Endpoint *endp = &this->endpoint_;
00325 endp != 0;
00326 endp = endp->next_)
00327 {
00328 hashval += endp->hash ();
00329 }
00330
00331 hashval += this->version_.minor;
00332 hashval += this->tag ();
00333
00334 const TAO::ObjectKey &ok =
00335 this->ref_object_key_->object_key ();
00336
00337 if (ok.length () >= 4)
00338 {
00339 hashval += ok[1];
00340 hashval += ok[3];
00341 }
00342
00343 hashval += this->hash_service_i (max);
00344
00345 return hashval % max;
00346 }
00347
00348 TAO_Endpoint*
00349 TAO_DIOP_Profile::endpoint (void)
00350 {
00351 return &this->endpoint_;
00352 }
00353
00354 CORBA::ULong
00355 TAO_DIOP_Profile::endpoint_count (void) const
00356 {
00357 return this->count_;
00358 }
00359
00360 void
00361 TAO_DIOP_Profile::add_endpoint (TAO_DIOP_Endpoint *endp)
00362 {
00363 endp->next_ = this->endpoint_.next_;
00364 this->endpoint_.next_ = endp;
00365
00366 this->count_++;
00367 }
00368
00369 char *
00370 TAO_DIOP_Profile::to_string (void)
00371 {
00372
00373
00374 CORBA::String_var key;
00375 TAO::ObjectKey::encode_sequence_to_string (key.inout (),
00376 this->ref_object_key_->object_key ());
00377
00378 size_t buflen = (
00379 8 +
00380 1 +
00381 1 +
00382 ACE_OS::strlen (key.in ()));
00383 size_t pfx_len = (
00384 ACE_OS::strlen (::the_prefix) +
00385 1 );
00386
00387 const TAO_DIOP_Endpoint *endp = 0;
00388 for (endp = &this->endpoint_; endp != 0; endp = endp->next_)
00389 {
00390 buflen += (
00391 pfx_len +
00392 1 +
00393 1 +
00394 1 +
00395 1 +
00396 ACE_OS::strlen (endp->host ()) +
00397 1 +
00398 5 +
00399 1 );
00400 #if defined (ACE_HAS_IPV6)
00401 if (endp->is_ipv6_decimal_)
00402 buflen += 2;
00403 #endif
00404 }
00405
00406 static const char digits [] = "0123456789";
00407
00408 char * buf = CORBA::string_alloc (static_cast<CORBA::ULong> (buflen));
00409
00410 ACE_OS::strcpy (buf, "corbaloc:");
00411
00412 for (endp = &this->endpoint_; endp != 0; endp = endp->next_)
00413 {
00414 if (&this->endpoint_ != endp)
00415 ACE_OS::strcat (buf, ",");
00416
00417 #if defined (ACE_HAS_IPV6)
00418 if (endp->is_ipv6_decimal_)
00419 {
00420
00421 ACE_CString tmp (endp->host ());
00422 ACE_CString::size_type pos = tmp.find ('%');
00423 if (pos != ACE_CString::npos)
00424 {
00425 tmp = tmp.substr (0, pos + 1);
00426 tmp[pos] = '\0';
00427 }
00428 ACE_OS::sprintf (buf + ACE_OS::strlen (buf),
00429 "%s:%c.%c@[%s]:%d",
00430 ::the_prefix,
00431 digits [this->version_.major],
00432 digits [this->version_.minor],
00433 tmp.c_str (),
00434 endp->port ());
00435 }
00436 else
00437 #endif
00438 ACE_OS::sprintf (buf + ACE_OS::strlen (buf),
00439 "%s:%c.%c@%s:%d",
00440 ::the_prefix,
00441 digits [this->version_.major],
00442 digits [this->version_.minor],
00443 endp->host (),
00444 endp->port ());
00445
00446 }
00447 ACE_OS::sprintf (buf + ACE_OS::strlen (buf),
00448 "%c%s",
00449 this->object_key_delimiter_,
00450 key.in ());
00451
00452 return buf;
00453 }
00454
00455 const char *
00456 TAO_DIOP_Profile::prefix (void)
00457 {
00458 return ::the_prefix;
00459 }
00460
00461 void
00462 TAO_DIOP_Profile::create_profile_body (TAO_OutputCDR &encap) const
00463 {
00464 encap.write_octet (TAO_ENCAP_BYTE_ORDER);
00465
00466
00467 encap.write_octet (this->version_.major);
00468 encap.write_octet (this->version_.minor);
00469
00470
00471 #if defined (ACE_HAS_IPV6)
00472
00473
00474 const char* host;
00475 const char* pos;
00476 if (this->endpoint_.is_ipv6_decimal_ &&
00477 (pos = ACE_OS::strchr (host = this->endpoint_.host (), '%')) != 0)
00478 {
00479 ACE_CString tmp;
00480 size_t len = pos - host;
00481 tmp.set (this->endpoint_.host (), len, 1);
00482 encap.write_string (tmp.c_str ());
00483 }
00484 else
00485 #endif
00486 encap.write_string (this->endpoint_.host ());
00487
00488
00489 encap.write_ushort (this->endpoint_.port ());
00490
00491
00492 if (this->ref_object_key_)
00493 encap << this->ref_object_key_->object_key ();
00494 else
00495 {
00496 ACE_ERROR ((LM_ERROR,
00497 "TAO (%P|%t) - DIOP_Profile::create_profile_body, "
00498 "no object key marshalled\n"));
00499 }
00500
00501 if (this->version_.major > 1
00502 || this->version_.minor > 0)
00503 this->tagged_components ().encode (encap);
00504 }
00505
00506 int
00507 TAO_DIOP_Profile::encode_endpoints (void)
00508 {
00509
00510
00511
00512
00513
00514
00515
00516 TAO::IIOPEndpointSequence endpoints;
00517 endpoints.length (this->count_);
00518
00519 const TAO_DIOP_Endpoint *endpoint = &this->endpoint_;
00520 for (CORBA::ULong i = 0;
00521 i < this->count_;
00522 ++i)
00523 {
00524 #if defined (ACE_HAS_IPV6)
00525 if (endpoint->is_ipv6_decimal_)
00526 {
00527
00528 ACE_CString tmp (endpoint->host ());
00529 ACE_CString::size_type pos = tmp.find ('%');
00530 if (pos != ACE_CString::npos)
00531 {
00532 tmp = tmp.substr (0, pos + 1);
00533 tmp[pos] = '\0';
00534 endpoints[i].host = tmp.c_str ();
00535 }
00536 else
00537 endpoints[i].host = tmp.c_str ();
00538 }
00539 else
00540 #endif
00541 endpoints[i].host = endpoint->host ();
00542 endpoints[i].port = endpoint->port ();
00543 endpoints[i].priority = endpoint->priority ();
00544
00545 endpoint = endpoint->next_;
00546 }
00547
00548
00549 TAO_OutputCDR out_cdr;
00550 if ((out_cdr << ACE_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER)
00551 == 0)
00552 || (out_cdr << endpoints) == 0)
00553 return -1;
00554
00555 this->set_tagged_components (out_cdr);
00556
00557 return 0;
00558 }
00559
00560 int
00561 TAO_DIOP_Profile::decode_endpoints (void)
00562 {
00563 IOP::TaggedComponent tagged_component;
00564 tagged_component.tag = TAO_TAG_ENDPOINTS;
00565
00566 if (this->tagged_components_.get_component (tagged_component))
00567 {
00568 const CORBA::Octet *buf =
00569 tagged_component.component_data.get_buffer ();
00570
00571 TAO_InputCDR in_cdr (reinterpret_cast<const char*> (buf),
00572 tagged_component.component_data.length ());
00573
00574
00575 CORBA::Boolean byte_order;
00576 if ((in_cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0)
00577 return -1;
00578 in_cdr.reset_byte_order (static_cast<int> (byte_order));
00579
00580
00581 TAO::IIOPEndpointSequence endpoints;
00582
00583 if (! (in_cdr >> endpoints))
00584 return -1;
00585
00586
00587
00588
00589 this->endpoint_.priority (endpoints[0].priority);
00590
00591
00592
00593
00594
00595
00596
00597 for (CORBA::ULong i = endpoints.length () - 1;
00598 i > 0;
00599 --i)
00600 {
00601 TAO_DIOP_Endpoint *endpoint = 0;
00602 ACE_NEW_RETURN (endpoint,
00603 TAO_DIOP_Endpoint (endpoints[i].host,
00604 endpoints[i].port,
00605 endpoints[i].priority),
00606 -1);
00607
00608 this->add_endpoint (endpoint);
00609 }
00610 }
00611
00612 return 0;
00613 }
00614
00615 TAO_END_VERSIONED_NAMESPACE_DECL
00616
00617 #endif