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