00001
00002
00003
00004
00005
00006
00007 #include "tao/IIOP_Endpoint.h"
00008
00009 #if defined (TAO_HAS_IIOP) && (TAO_HAS_IIOP != 0)
00010
00011 #include "tao/IOP_IORC.h"
00012 #include "tao/debug.h"
00013 #include "tao/ORB_Core.h"
00014
00015 #include "ace/Log_Msg.h"
00016 #include "ace/Guard_T.h"
00017 #include "ace/OS_NS_string.h"
00018 #include "ace/OS_NS_strings.h"
00019
00020 ACE_RCSID (tao,
00021 IIOP_Endpoint,
00022 "$Id: IIOP_Endpoint.cpp 73791 2006-07-27 20:54:56Z wotte $")
00023
00024 #if !defined (__ACE_INLINE__)
00025 # include "tao/IIOP_Endpoint.inl"
00026 #endif
00027
00028 #include "ace/OS_NS_stdio.h"
00029 #include "ace/os_include/os_netdb.h"
00030
00031 #include "ace/Vector_T.h"
00032 #include "ace/ACE.h"
00033 #include "ace/INET_Addr.h"
00034 #include "ace/Sock_Connect.h"
00035
00036
00037
00038 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00039
00040
00041 TAO_IIOP_Endpoint::TAO_IIOP_Endpoint (const ACE_INET_Addr &addr,
00042 int use_dotted_decimal_addresses)
00043 : TAO_Endpoint (IOP::TAG_INTERNET_IOP)
00044 , host_ ()
00045 , port_ (683)
00046 #if defined (ACE_HAS_IPV6)
00047 , is_ipv6_decimal_ (false)
00048 #endif
00049 , is_encodable_ (true)
00050 , object_addr_set_ (false)
00051 , object_addr_ (addr)
00052 , preferred_path_ ()
00053 , next_ (0)
00054 {
00055 this->set (addr, use_dotted_decimal_addresses);
00056 }
00057
00058 TAO_IIOP_Endpoint::TAO_IIOP_Endpoint (const char *host,
00059 CORBA::UShort port,
00060 const ACE_INET_Addr &addr,
00061 CORBA::Short priority)
00062 : TAO_Endpoint (IOP::TAG_INTERNET_IOP, priority)
00063 , host_ ()
00064 , port_ (port)
00065 #if defined (ACE_HAS_IPV6)
00066 , is_ipv6_decimal_ (false)
00067 #endif
00068 , is_encodable_ (true)
00069 , object_addr_set_ (false)
00070 , object_addr_ (addr)
00071 , preferred_path_ ()
00072 , next_ (0)
00073 {
00074 this->host(host);
00075 }
00076
00077 TAO_IIOP_Endpoint::TAO_IIOP_Endpoint (void)
00078 : TAO_Endpoint (IOP::TAG_INTERNET_IOP)
00079 , host_ ()
00080 , port_ (683)
00081 #if defined (ACE_HAS_IPV6)
00082 , is_ipv6_decimal_ (false)
00083 #endif
00084 , is_encodable_ (true)
00085 , object_addr_set_ (false)
00086 , object_addr_ ()
00087 , preferred_path_ ()
00088 , next_ (0)
00089 {
00090 }
00091
00092 TAO_IIOP_Endpoint::TAO_IIOP_Endpoint (const char *host,
00093 CORBA::UShort port,
00094 CORBA::Short priority)
00095 : TAO_Endpoint (IOP::TAG_INTERNET_IOP, priority)
00096 , host_ ()
00097 , port_ (port)
00098 #if defined (ACE_HAS_IPV6)
00099 , is_ipv6_decimal_ (false)
00100 #endif
00101 , is_encodable_ (true)
00102 , object_addr_set_ (false)
00103 , object_addr_ ()
00104 , preferred_path_ ()
00105 , next_ (0)
00106 {
00107 this->host(host);
00108 }
00109
00110
00111
00112 TAO_IIOP_Endpoint &
00113 TAO_IIOP_Endpoint::operator= (const TAO_IIOP_Endpoint &other)
00114 {
00115 this->host_ = other.host_;
00116 this->port_ = other.port_;
00117 #if defined (ACE_HAS_IPV6)
00118 this->is_ipv6_decimal_ = other.is_ipv6_decimal_;
00119 #endif
00120 this->is_encodable_ = other.is_encodable_;
00121 this->object_addr_set_ = other.object_addr_set_;
00122 this->object_addr_ = other.object_addr_;
00123 this->preferred_path_ = other.preferred_path_;
00124 this->next_ = 0;
00125 return *this;
00126 }
00127
00128 TAO_IIOP_Endpoint::~TAO_IIOP_Endpoint (void)
00129 {
00130 }
00131
00132
00133
00134 TAO_IIOP_Endpoint::TAO_IIOP_Endpoint (const TAO_IIOP_Endpoint &rhs)
00135 : TAO_Endpoint (rhs.tag_, rhs.priority_)
00136 , host_ (rhs.host_)
00137 , port_ (rhs.port_)
00138 #if defined (ACE_HAS_IPV6)
00139 , is_ipv6_decimal_ (rhs.is_ipv6_decimal_)
00140 #endif
00141 , is_encodable_ (rhs.is_encodable_)
00142 , object_addr_set_ (rhs.object_addr_set_)
00143 , object_addr_ (rhs.object_addr_)
00144 , preferred_path_ (rhs.preferred_path_)
00145 , next_ (0)
00146 {
00147 }
00148
00149 int
00150 TAO_IIOP_Endpoint::set (const ACE_INET_Addr &addr,
00151 int use_dotted_decimal_addresses)
00152 {
00153 char tmp_host[MAXHOSTNAMELEN + 1];
00154
00155 #if defined (ACE_HAS_IPV6)
00156 this->is_ipv6_decimal_ = false;
00157 #endif
00158
00159 if (use_dotted_decimal_addresses
00160 || addr.get_host_name (tmp_host, sizeof (tmp_host)) != 0)
00161 {
00162 if (use_dotted_decimal_addresses == 0 && TAO_debug_level > 5)
00163 {
00164 ACE_DEBUG ((LM_DEBUG,
00165 ACE_TEXT ("TAO (%P|%t) - IIOP_Endpoint::set, ")
00166 ACE_TEXT ("%p\n"),
00167 ACE_TEXT ("cannot determine hostname")));
00168 }
00169
00170 const char *tmp = addr.get_host_addr ();
00171 if (tmp == 0)
00172 {
00173 if (TAO_debug_level > 0)
00174 {
00175 ACE_ERROR ((LM_ERROR,
00176 ACE_TEXT ("TAO (%P|%t) - IIOP_Endpoint::set, ")
00177 ACE_TEXT ("%p\n"),
00178 ACE_TEXT ("cannot determine hostname and hostaddr")));
00179 }
00180 return -1;
00181 }
00182 else
00183 {
00184 this->host_ = tmp;
00185 #if defined (ACE_HAS_IPV6)
00186 if (addr.get_type () == PF_INET6)
00187 this->is_ipv6_decimal_ = true;
00188 #endif
00189 }
00190 }
00191 else
00192 this->host_ = CORBA::string_dup (tmp_host);
00193
00194 this->port_ = addr.get_port_number();
00195
00196 return 0;
00197 }
00198
00199 int
00200 TAO_IIOP_Endpoint::addr_to_string (char *buffer, size_t length)
00201 {
00202 size_t actual_len =
00203 ACE_OS::strlen (this->host_.in ())
00204 + sizeof (':')
00205 + ACE_OS::strlen ("65536")
00206 + sizeof ('\0');
00207
00208 #if defined (ACE_HAS_IPV6)
00209 if (this->is_ipv6_decimal_)
00210 actual_len += 2;
00211 #endif
00212
00213 if (length < actual_len)
00214 return -1;
00215
00216 #if defined (ACE_HAS_IPV6)
00217 if (this->is_ipv6_decimal_)
00218 ACE_OS::sprintf (buffer, "[%s]:%d",
00219 this->host_.in (), this->port_);
00220 else
00221 #endif
00222 ACE_OS::sprintf (buffer, "%s:%d",
00223 this->host_.in (), this->port_);
00224
00225 return 0;
00226 }
00227
00228 const char *
00229 TAO_IIOP_Endpoint::host (const char *h)
00230 {
00231 this->host_ = h;
00232 #if defined (ACE_HAS_IPV6)
00233 if (ACE_OS::strchr (h, ':') != 0)
00234 this->is_ipv6_decimal_ = true;
00235 #endif
00236
00237 return this->host_.in ();
00238 }
00239
00240 TAO_Endpoint *
00241 TAO_IIOP_Endpoint::next (void)
00242 {
00243 return this->next_;
00244 }
00245
00246 TAO_Endpoint *
00247 TAO_IIOP_Endpoint::next_filtered (TAO_ORB_Core * orb_core, TAO_Endpoint *root)
00248 {
00249 bool want_ipv6 = false;
00250 bool ipv6_only = false;
00251 bool prefer_ipv6 = false;
00252 #if defined (ACE_HAS_IPV6)
00253 want_ipv6 = true;
00254 ipv6_only = orb_core->orb_params()->connect_ipv6_only();
00255 prefer_ipv6 = orb_core->orb_params()->prefer_ipv6_interfaces();
00256 #else
00257 ACE_UNUSED_ARG (orb_core);
00258 #endif
00259 return
00260 this->next_filtered_i (static_cast<TAO_IIOP_Endpoint *>(root),
00261 ipv6_only,
00262 prefer_ipv6,
00263 want_ipv6);
00264 }
00265
00266 TAO_IIOP_Endpoint*
00267 TAO_IIOP_Endpoint::next_filtered_i (TAO_IIOP_Endpoint *root,
00268 bool ipv6_only,
00269 bool prefer_ipv6,
00270 bool want_ipv6)
00271 {
00272
00273
00274
00275 TAO_IIOP_Endpoint *candidate = (root == 0) ? this : next_;
00276 if (root == 0)
00277 root = this;
00278
00279 #if defined (ACE_HAS_IPV6)
00280 if (ipv6_only)
00281 {
00282 if (candidate == 0 || candidate->is_ipv6_decimal())
00283 return candidate;
00284 const ACE_INET_Addr &addr = candidate->object_addr ();
00285 bool allowed = addr.get_type () == AF_INET6 &&
00286 !addr.is_ipv4_mapped_ipv6();
00287
00288 return allowed ? candidate :
00289 candidate->next_filtered_i(root, ipv6_only, prefer_ipv6, true);
00290 }
00291 if (prefer_ipv6)
00292 {
00293 if (candidate == 0)
00294 return !want_ipv6 ? candidate :
00295 root->next_filtered_i(root, ipv6_only, prefer_ipv6, false);
00296
00297 if (want_ipv6 == candidate->is_ipv6_decimal())
00298 return candidate;
00299
00300 const ACE_INET_Addr &addr = candidate->object_addr ();
00301 bool really_ipv6 = addr.get_type () == AF_INET6 &&
00302 !addr.is_ipv4_mapped_ipv6();
00303 return (want_ipv6 == really_ipv6) ? candidate :
00304 candidate->next_filtered_i(root, ipv6_only, prefer_ipv6, want_ipv6);
00305 }
00306 #else
00307 ACE_UNUSED_ARG (want_ipv6);
00308 ACE_UNUSED_ARG (ipv6_only);
00309 ACE_UNUSED_ARG (prefer_ipv6);
00310 #endif
00311
00312 return candidate;
00313 }
00314
00315 TAO_Endpoint *
00316 TAO_IIOP_Endpoint::duplicate (void)
00317 {
00318 TAO_IIOP_Endpoint *endpoint = 0;
00319
00320
00321 ACE_NEW_RETURN (endpoint, TAO_IIOP_Endpoint (*this), 0);
00322
00323 return endpoint;
00324 }
00325
00326 const ACE_INET_Addr &
00327 TAO_IIOP_Endpoint::object_addr (void) const
00328 {
00329
00330
00331
00332
00333
00334
00335
00336 if (!this->object_addr_set_)
00337 {
00338 ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
00339 guard,
00340 this->addr_lookup_lock_,
00341 this->object_addr_);
00342
00343 if (!this->object_addr_set_)
00344 {
00345 (void) this->object_addr_i ();
00346 }
00347 }
00348
00349 return this->object_addr_;
00350 }
00351
00352 void
00353 TAO_IIOP_Endpoint::object_addr_i (void) const
00354 {
00355
00356
00357 #if defined (ACE_HAS_IPV6)
00358 bool is_ipv4_decimal_ = false;
00359 if (!this->is_ipv6_decimal_)
00360 is_ipv4_decimal_ =
00361 ACE_OS::strspn (this->host_.in (), ".0123456789") ==
00362 ACE_OS::strlen (this->host_.in ());
00363
00364
00365
00366
00367
00368 if ((is_ipv4_decimal_ ||
00369 this->object_addr_.set (this->port_,
00370 this->host_.in (),
00371 1,
00372 AF_INET6) == -1) &&
00373 (this->is_ipv6_decimal_ ||
00374 this->object_addr_.set (this->port_,
00375 this->host_.in (),
00376 1,
00377 AF_INET) == -1))
00378 #else
00379 if (this->object_addr_.set (this->port_,
00380 this->host_.in ()) == -1)
00381 #endif
00382 {
00383
00384
00385
00386
00387
00388
00389
00390
00391 this->object_addr_.set_type (-1);
00392 }
00393 else
00394 {
00395 this->object_addr_set_ = true;
00396 }
00397 }
00398
00399 static ACE_CString find_local(const ACE_Vector<ACE_CString>& local_ips,
00400 const ACE_CString& pattern)
00401 {
00402 for (size_t i = 0; i < local_ips.size(); ++i)
00403 {
00404 ACE_CString ret = local_ips[i];
00405 if (ACE::wild_match(ret.c_str(), pattern.c_str()))
00406 return ret;
00407 }
00408 return "";
00409 }
00410
00411 TAO_IIOP_Endpoint*
00412 TAO_IIOP_Endpoint::add_local_endpoint(TAO_IIOP_Endpoint* ep, const char* local)
00413 {
00414 TAO_Endpoint* tmp = ep->duplicate();
00415 ep->next_ = static_cast<TAO_IIOP_Endpoint*>(tmp);
00416 ep->next_->is_encodable_ = true;
00417 ep->next_->preferred_path_.host = CORBA::string_dup(local);
00418 return ep->next_;
00419 }
00420
00421 static void
00422 get_ip_interfaces(ACE_Vector<ACE_CString>& local_ips)
00423 {
00424 ACE_INET_Addr* tmp = 0;
00425 size_t cnt = 0;
00426 int err = ACE::get_ip_interfaces (cnt, tmp);
00427 if (err != 0)
00428 return;
00429 #if defined (ACE_HAS_IPV6)
00430 char buf[64];
00431 #else
00432 char buf[32];
00433 #endif
00434 for (size_t i = 0; i < cnt; ++i)
00435 {
00436 const char *s_if = tmp[i].get_host_addr(buf, sizeof (buf));
00437 ACE_ASSERT(s_if != 0);
00438 ACE_CString tmp(s_if);
00439
00440
00441
00442 local_ips.push_back(tmp);
00443 }
00444 delete[] tmp;
00445 }
00446
00447
00448
00449
00450
00451
00452 static void find_preferred_interfaces (const ACE_CString& host,
00453 const ACE_CString& csvPreferred,
00454 ACE_Vector<ACE_CString>& preferred)
00455 {
00456 ACE_Vector<ACE_CString> local_ips;
00457 get_ip_interfaces(local_ips);
00458 if (local_ips.size() == 0)
00459 return;
00460
00461
00462
00463
00464 ACE_CString::size_type index = 0;
00465 while (index < csvPreferred.length())
00466 {
00467 ACE_CString::size_type comma = csvPreferred.find(',', index);
00468 ACE_CString::size_type assign = csvPreferred.find('=', index);
00469
00470 if (assign == ACE_CString::npos)
00471 {
00472 assign = csvPreferred.find(':', index);
00473 if (assign == ACE_CString::npos)
00474 {
00475 ACE_ASSERT(assign != ACE_CString::npos);
00476 return;
00477 }
00478 }
00479
00480 ACE_CString wild_local;
00481 if (comma == ACE_CString::npos)
00482 wild_local = csvPreferred.substr(assign + 1);
00483 else
00484 wild_local = csvPreferred.substr(assign + 1, comma - assign - 1);
00485 ACE_CString wild_remote = csvPreferred.substr(index, assign - index);
00486
00487 index = comma + 1;
00488
00489
00490
00491
00492
00493 if (ACE::wild_match(host.c_str(), wild_remote.c_str(), false))
00494 {
00495
00496
00497 ACE_CString local = find_local(local_ips, wild_local);
00498 if (local.length() > 0)
00499 {
00500 preferred.push_back(local);
00501 }
00502 else
00503 {
00504
00505
00506 }
00507 }
00508 else
00509 {
00510
00511
00512 }
00513 if (comma == ACE_CString::npos)
00514 break;
00515 }
00516 }
00517
00518 CORBA::ULong
00519 TAO_IIOP_Endpoint::preferred_interfaces (const char* csv, bool enforce)
00520 {
00521 ACE_Vector<ACE_CString> preferred;
00522 find_preferred_interfaces(this->host_.in(), csv, preferred);
00523 CORBA::ULong count = preferred.size();
00524 if (count > 0)
00525 {
00526 this->is_encodable_ = true;
00527 this->preferred_path_.host = CORBA::string_dup(preferred[0].c_str());
00528 TAO_IIOP_Endpoint* ep = this;
00529 for (size_t i = 1; i < count; ++i)
00530 {
00531 ep = add_local_endpoint(ep, preferred[i].c_str());
00532 }
00533
00534
00535
00536 if (! enforce)
00537 {
00538 ep = add_local_endpoint(ep, "");
00539 }
00540 else
00541 {
00542 --count;
00543 }
00544 }
00545 return count;
00546 }
00547
00548 CORBA::Boolean
00549 TAO_IIOP_Endpoint::is_equivalent (const TAO_Endpoint *other_endpoint)
00550 {
00551 const TAO_IIOP_Endpoint *endpoint =
00552 dynamic_cast<const TAO_IIOP_Endpoint *> (other_endpoint);
00553
00554 if (endpoint == 0)
00555 return 0;
00556
00557 return (this->port_ == endpoint->port_
00558 && (ACE_OS::strcmp (this->host (), endpoint->host ()) == 0));
00559 }
00560
00561 CORBA::ULong
00562 TAO_IIOP_Endpoint::hash (void)
00563 {
00564 if (this->hash_val_ != 0)
00565 return this->hash_val_;
00566
00567 {
00568 ACE_GUARD_RETURN (TAO_SYNCH_MUTEX,
00569 guard,
00570 this->addr_lookup_lock_,
00571 this->hash_val_);
00572
00573 if (this->hash_val_ != 0)
00574 return this->hash_val_;
00575
00576
00577
00578
00579 if (!this->object_addr_set_)
00580 {
00581
00582 (void) this->object_addr_i ();
00583 }
00584
00585 this->hash_val_ = this->object_addr_.hash ();
00586 }
00587
00588 return this->hash_val_;
00589 }
00590
00591 bool
00592 TAO_IIOP_Endpoint::is_preferred_network (void) const
00593 {
00594 return (this->preferred_path_.host.in () != 0 &&
00595 this->preferred_path_.host.in ()[0] != 0);
00596 }
00597
00598 const char *
00599 TAO_IIOP_Endpoint::preferred_network (void) const
00600 {
00601 return this->preferred_path_.host.in ();
00602 }
00603
00604
00605
00606 TAO_END_VERSIONED_NAMESPACE_DECL
00607
00608 #endif