3 * Add all include files within the following
6 //@@ TAO_ENDPOINT_SPL_COPY_HOOK_START
8 #include "tao/IIOP_Endpoint.h"
10 #if defined (TAO_HAS_IIOP) && (TAO_HAS_IIOP != 0)
13 #include "tao/debug.h"
14 #include "tao/ORB_Core.h"
15 #include "tao/IIOP_Profile.h"
17 #include "ace/Log_Msg.h"
18 #include "ace/Guard_T.h"
19 #include "ace/OS_NS_string.h"
20 #include "ace/OS_NS_strings.h"
22 #if !defined (__ACE_INLINE__)
23 # include "tao/IIOP_Endpoint.inl"
24 #endif /* __ACE_INLINE__ */
26 #include "ace/OS_NS_stdio.h"
27 #include "ace/os_include/os_netdb.h"
29 #include "ace/Vector_T.h"
31 #include "ace/INET_Addr.h"
32 #include "ace/Sock_Connect.h"
34 //@@ TAO_ENDPOINT_SPL_COPY_HOOK_END
36 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
38 //@@ TAO_ENDPOINT_SPL_COPY_HOOK_START
39 TAO_IIOP_Endpoint::TAO_IIOP_Endpoint (const ACE_INET_Addr
&addr
,
40 int use_dotted_decimal_addresses
)
41 : TAO_Endpoint (IOP::TAG_INTERNET_IOP
)
43 , port_ (683) // default port (IANA assigned)
44 #if defined (ACE_HAS_IPV6)
45 , is_ipv6_decimal_ (false)
46 #endif /* ACE_HAS_IPV6 */
47 , is_encodable_ (true)
48 , object_addr_set_ (false)
53 this->set (addr
, use_dotted_decimal_addresses
);
56 TAO_IIOP_Endpoint::TAO_IIOP_Endpoint (const char *host
,
58 const ACE_INET_Addr
&addr
,
59 CORBA::Short priority
)
60 : TAO_Endpoint (IOP::TAG_INTERNET_IOP
, priority
)
63 #if defined (ACE_HAS_IPV6)
64 , is_ipv6_decimal_ (false)
65 #endif /* ACE_HAS_IPV6 */
66 , is_encodable_ (true)
67 , object_addr_set_ (false)
72 this->host(host
); // With IPv6 performs check for decimal address
75 TAO_IIOP_Endpoint::TAO_IIOP_Endpoint (void)
76 : TAO_Endpoint (IOP::TAG_INTERNET_IOP
)
78 , port_ (683) // default port (IANA assigned)
79 #if defined (ACE_HAS_IPV6)
80 , is_ipv6_decimal_ (false)
81 #endif /* ACE_HAS_IPV6 */
82 , is_encodable_ (true)
83 , object_addr_set_ (false)
90 TAO_IIOP_Endpoint::TAO_IIOP_Endpoint (const char *host
,
92 CORBA::Short priority
)
93 : TAO_Endpoint (IOP::TAG_INTERNET_IOP
, priority
)
96 #if defined (ACE_HAS_IPV6)
97 , is_ipv6_decimal_ (false)
98 #endif /* ACE_HAS_IPV6 */
99 , is_encodable_ (true)
100 , object_addr_set_ (false)
105 this->host(host
); // With IPv6 performs check for decimal address
107 //@@ TAO_ENDPOINT_SPL_COPY_HOOK_END
111 TAO_IIOP_Endpoint::operator= (const TAO_IIOP_Endpoint
&other
)
115 this->host_
= other
.host_
;
116 this->port_
= other
.port_
;
117 #if defined (ACE_HAS_IPV6)
118 this->is_ipv6_decimal_
= other
.is_ipv6_decimal_
;
119 #endif /* ACE_HAS_IPV6 */
120 this->is_encodable_
= other
.is_encodable_
;
121 this->object_addr_set_
= other
.object_addr_set_
;
122 this->object_addr_
= other
.object_addr_
;
123 this->preferred_path_
= other
.preferred_path_
;
124 this->next_
= 0; // do not copy list membership, since we are only cloning the values
129 TAO_IIOP_Endpoint::~TAO_IIOP_Endpoint (void)
133 //@@ TAO_ENDPOINT_SPL_COPY_HOOK_START
135 TAO_IIOP_Endpoint::TAO_IIOP_Endpoint (const TAO_IIOP_Endpoint
&rhs
)
136 : TAO_Endpoint (rhs
.tag_
, rhs
.priority_
)
139 #if defined (ACE_HAS_IPV6)
140 , is_ipv6_decimal_ (rhs
.is_ipv6_decimal_
)
141 #endif /* ACE_HAS_IPV6 */
142 , is_encodable_ (rhs
.is_encodable_
)
143 , object_addr_set_ (rhs
.object_addr_set_
)
144 , object_addr_ (rhs
.object_addr_
)
145 , preferred_path_ (rhs
.preferred_path_
)
151 TAO_IIOP_Endpoint::set (const ACE_INET_Addr
&addr
,
152 int use_dotted_decimal_addresses
)
154 char tmp_host
[MAXHOSTNAMELEN
+ 1];
156 #if defined (ACE_HAS_IPV6)
157 this->is_ipv6_decimal_
= false; // Reset
158 #endif /* ACE_HAS_IPV6 */
160 if (use_dotted_decimal_addresses
161 || addr
.get_host_name (tmp_host
, sizeof (tmp_host
)) != 0)
163 if (use_dotted_decimal_addresses
== 0 && TAO_debug_level
> 5)
165 TAOLIB_DEBUG ((LM_DEBUG
,
166 ACE_TEXT ("TAO (%P|%t) - IIOP_Endpoint::set, ")
168 ACE_TEXT ("cannot determine hostname")));
171 const char *tmp
= addr
.get_host_addr ();
174 if (TAO_debug_level
> 0)
176 TAOLIB_ERROR ((LM_ERROR
,
177 ACE_TEXT ("TAO (%P|%t) - IIOP_Endpoint::set, ")
179 ACE_TEXT ("cannot determine hostname and hostaddr")));
186 #if defined (ACE_HAS_IPV6)
187 if (addr
.get_type () == PF_INET6
)
188 this->is_ipv6_decimal_
= true;
189 #endif /* ACE_HAS_IPV6 */
193 this->host_
= CORBA::string_dup (tmp_host
);
195 this->port_
= addr
.get_port_number();
201 TAO_IIOP_Endpoint::addr_to_string (char *buffer
, size_t length
)
204 ACE_OS::strlen (this->host_
.in ()) // chars in host name
205 + sizeof (':') // delimiter
206 + ACE_OS::strlen ("65536") // max port
209 #if defined (ACE_HAS_IPV6)
210 if (this->is_ipv6_decimal_
)
211 actual_len
+= 2; // '[' + ']'
212 #endif /* ACE_HAS_IPV6 */
214 if (length
< actual_len
)
217 #if defined (ACE_HAS_IPV6)
218 if (this->is_ipv6_decimal_
)
219 ACE_OS::sprintf (buffer
, "[%s]:%d",
220 this->host_
.in (), this->port_
);
222 #endif /* ACE_HAS_IPV6 */
223 ACE_OS::sprintf (buffer
, "%s:%d",
224 this->host_
.in (), this->port_
);
230 TAO_IIOP_Endpoint::host (const char *h
)
233 #if defined (ACE_HAS_IPV6)
234 if (ACE_OS::strchr (h
, ':') != 0)
235 this->is_ipv6_decimal_
= true;
236 #endif /* ACE_HAS_IPV6 */
238 return this->host_
.in ();
242 TAO_IIOP_Endpoint::next (void)
248 TAO_IIOP_Endpoint::next_filtered (TAO_ORB_Core
* orb_core
, TAO_Endpoint
*root
)
250 bool want_ipv6
= false;
251 bool ipv6_only
= false;
252 bool prefer_ipv6
= false;
253 #if defined (ACE_HAS_IPV6)
254 want_ipv6
= root
== 0 || this->is_ipv6_decimal();
255 ipv6_only
= orb_core
->orb_params()->connect_ipv6_only();
256 prefer_ipv6
= orb_core
->orb_params()->prefer_ipv6_interfaces();
258 ACE_UNUSED_ARG (orb_core
);
259 #endif /* ACE_HAS_IPV6 */
261 this->next_filtered_i (static_cast<TAO_IIOP_Endpoint
*>(root
),
268 TAO_IIOP_Endpoint::next_filtered_i (TAO_IIOP_Endpoint
*root
,
273 // the candidate is nominally the next entry in the list, but since
274 // the list may loop back on itself, the root of the list needs to be
276 TAO_IIOP_Endpoint
*candidate
= (root
== 0) ? this : next_
;
280 #if defined (ACE_HAS_IPV6)
283 if (candidate
== 0 || candidate
->is_ipv6_decimal())
285 const ACE_INET_Addr
&addr
= candidate
->object_addr ();
286 bool allowed
= addr
.get_type () == AF_INET6
&&
287 !addr
.is_ipv4_mapped_ipv6();
289 return allowed
? candidate
:
290 candidate
->next_filtered_i(root
, ipv6_only
, prefer_ipv6
, true);
295 return !want_ipv6
? candidate
:
296 root
->next_filtered_i(0, ipv6_only
, prefer_ipv6
, false);
298 if (want_ipv6
== candidate
->is_ipv6_decimal())
301 const ACE_INET_Addr
&addr
= candidate
->object_addr ();
302 bool really_ipv6
= addr
.get_type () == AF_INET6
&&
303 !addr
.is_ipv4_mapped_ipv6();
304 return (want_ipv6
== really_ipv6
) ? candidate
:
305 candidate
->next_filtered_i(root
, ipv6_only
, prefer_ipv6
, want_ipv6
);
308 ACE_UNUSED_ARG (want_ipv6
);
309 ACE_UNUSED_ARG (ipv6_only
);
310 ACE_UNUSED_ARG (prefer_ipv6
);
317 TAO_IIOP_Endpoint::duplicate (void)
319 TAO_IIOP_Endpoint
*endpoint
= 0;
321 // @@ NOTE: Not exception safe..
322 ACE_NEW_RETURN (endpoint
, TAO_IIOP_Endpoint (*this), 0);
327 const ACE_INET_Addr
&
328 TAO_IIOP_Endpoint::object_addr (void) const
330 // The object_addr_ is initialized here, rather than at IOR decode
331 // time for several reasons:
332 // 1. A request on the object may never be invoked.
333 // 2. The DNS setup may have changed dynamically.
336 // Double checked locking optimization.
337 if (!this->object_addr_set_
)
339 ACE_GUARD_RETURN (TAO_SYNCH_MUTEX
,
341 this->addr_lookup_lock_
,
344 if (!this->object_addr_set_
)
346 (void) this->object_addr_i ();
350 return this->object_addr_
;
354 TAO_IIOP_Endpoint::object_addr_i (void) const
356 // We should have already held the lock
358 #if defined (ACE_HAS_IPV6)
359 bool is_ipv4_decimal_
= false;
360 if (!this->is_ipv6_decimal_
)
362 ACE_OS::strspn (this->host_
.in (), ".0123456789") ==
363 ACE_OS::strlen (this->host_
.in ());
365 // If this is *not* an IPv4 decimal address at first try to
366 // resolve the address as an IPv6 address; if that fails
367 // (or it's an IPv4 address) and the address is *not* an IPv6
368 // decimal address try to resolve it as an IPv4 address.
369 if ((is_ipv4_decimal_
||
370 (!ACE::ipv6_enabled () ||
371 this->object_addr_
.set (this->port_
,
375 (this->is_ipv6_decimal_
||
376 this->object_addr_
.set (this->port_
,
381 if (this->object_addr_
.set (this->port_
,
382 this->host_
.in ()) == -1)
385 // If this call fails, it most likely due a hostname
386 // lookup failure caused by a DNS misconfiguration. If
387 // a request is made to the object at the given host and
388 // port, then a CORBA::TRANSIENT() exception should be
391 // Invalidate the ACE_INET_Addr. This is used as a flag
392 // to denote that ACE_INET_Addr initialization failed.
393 this->object_addr_
.set_type (-1);
397 this->object_addr_set_
= true;
402 TAO_IIOP_Endpoint::add_local_endpoint (TAO_IIOP_Endpoint
*ep
,
404 TAO_IIOP_Profile
&profile
)
406 TAO_IIOP_Endpoint
*tmp
= static_cast<TAO_IIOP_Endpoint
*> (ep
->duplicate ());
407 tmp
->is_encodable_
= true;
408 tmp
->preferred_path_
.host
= local
;
409 profile
.add_endpoint (tmp
);
413 // local helper function for TAO_IIOP_Endpoint::find_preferred_interfaces
415 TAO_IIOP_Endpoint_get_ip_interfaces (ACE_Vector
<ACE_CString
> &local_ips
)
417 ACE_INET_Addr
* tmp
= 0;
419 int err
= ACE::get_ip_interfaces (cnt
, tmp
);
422 #if defined (ACE_HAS_IPV6)
424 #else /* ACE_HAS_IPV6 */
426 #endif /* !ACE_HAS_IPV6 */
427 for (size_t i
= 0u; i
< cnt
; ++i
)
429 const char *s_if
= tmp
[i
].get_host_addr (buf
, sizeof (buf
));
430 ACE_ASSERT (s_if
!= 0);
431 ACE_CString
tmp (s_if
);
432 local_ips
.push_back (tmp
);
437 // local helper function for TAO_IIOP_Endpoint::find_preferred_interfaces
439 TAO_IIOP_Endpoint_none_duplicate_insert (
440 const ACE_CString
&value
,
441 ACE_Vector
<ACE_CString
> &vector
)
444 for (size_t x
= 0u; x
< vector
.size (); ++x
)
445 if (vector
[x
] == value
)
451 vector
.push_back (value
);
454 // Given a comma separated list of preferred interface directives, which
455 // are of the form <wild_remote>=<wild_local>, this function will retrieve
456 // the list of preferred local ip addresses by matching wild_local against
457 // the list of all local ip interfaces, for any directive where wild_remote
458 // matches the host from our endpoint.
460 TAO_IIOP_Endpoint::find_preferred_interfaces (
461 const ACE_CString
&host
,
462 const ACE_CString
&csvPreferred
,
463 ACE_Vector
<ACE_CString
> &preferred
)
465 ACE_Vector
<ACE_CString
> local_ips
;
466 TAO_IIOP_Endpoint_get_ip_interfaces (local_ips
);
467 if (local_ips
.size () == 0)
470 // The outer loop steps through each preferred interface directive
471 // and chains a new endpoint if the remote interface matches the
473 ACE_CString::size_type index
= 0;
474 while (index
< csvPreferred
.length ())
476 ACE_CString::size_type comma
= csvPreferred
.find (',', index
);
477 ACE_CString::size_type assign
= csvPreferred
.find ('=', index
);
479 if (assign
== ACE_CString::npos
)
481 assign
= csvPreferred
.find (':', index
);
482 if (assign
== ACE_CString::npos
)
484 ACE_ASSERT (assign
!= ACE_CString::npos
);
489 ACE_CString wild_local
;
490 if (comma
== ACE_CString::npos
)
491 wild_local
= csvPreferred
.substr (assign
+ 1);
493 wild_local
= csvPreferred
.substr (assign
+ 1, comma
- assign
- 1);
494 ACE_CString wild_remote
= csvPreferred
.substr (index
, assign
- index
);
497 // For now, we just try to match against the host literally. In
498 // the future it might be worthwhile to resolve some aliases for
499 // this->host_ using DNS (and possibly reverse DNS) lookups. Then we
500 // could try matching against those too.
501 if (ACE::wild_match (host
.c_str (), wild_remote
.c_str (), false))
503 // If it's a match, then it means we need to use any/all
504 // local interface(s) that matches wild_local.
505 const char *const wild_local_cstr
= wild_local
.c_str ();
507 for (size_t i
= 0u; i
< local_ips
.size (); ++i
)
509 ACE_CString
&ret
= local_ips
[i
];
510 if (ACE::wild_match (ret
.c_str (), wild_local_cstr
))
513 TAO_IIOP_Endpoint_none_duplicate_insert (ret
, preferred
);
519 #if defined (ACE_HAS_IPV6)
520 // We interpret the preferred wild_local as an actual interface name/id.
521 // This is useful for link local IPv6 multicast
523 ACE_CString
if_name ("if=");
524 if_name
+= wild_local
;
525 TAO_IIOP_Endpoint_none_duplicate_insert (if_name
, preferred
);
527 // There is no matching local interface, so we can skip
528 // to the next preferred interface directive.
534 // The preferred interface directive is for a different
537 if (comma
== ACE_CString::npos
)
543 TAO_IIOP_Endpoint::preferred_interfaces (const char *csv
,
545 TAO_IIOP_Profile
&profile
)
547 ACE_Vector
<ACE_CString
> preferred
;
548 find_preferred_interfaces(this->host_
.in(), csv
, preferred
);
549 CORBA::ULong count
= static_cast<CORBA::ULong
> (preferred
.size());
551 while (i
< count
&& ACE_OS::strstr (preferred
[i
].c_str(), "if=") != 0)
553 // For now we disregard these with IIOP
558 this->is_encodable_
= true;
559 this->preferred_path_
.host
= CORBA::string_dup(preferred
[i
].c_str());
560 TAO_IIOP_Endpoint
* ep
= this;
561 for (++i
; i
< count
; ++i
)
563 if (ACE_OS::strstr (preferred
[i
].c_str(), "if=") == 0)
564 ep
= add_local_endpoint (ep
, preferred
[i
].c_str(), profile
);
567 // If we're not enforcing the preferred interfaces, then we can just add
568 // a new non-preferred endpoint to the end with a default local addr.
571 ep
= add_local_endpoint (ep
, "", profile
);
582 TAO_IIOP_Endpoint::is_equivalent (const TAO_Endpoint
*other_endpoint
)
584 const TAO_IIOP_Endpoint
*endpoint
=
585 dynamic_cast<const TAO_IIOP_Endpoint
*> (other_endpoint
);
590 return (this->port_
== endpoint
->port_
591 && (ACE_OS::strcmp (this->host (), endpoint
->host ()) == 0));
595 TAO_IIOP_Endpoint::hash (void)
597 if (this->hash_val_
!= 0)
598 return this->hash_val_
;
601 ACE_GUARD_RETURN (TAO_SYNCH_MUTEX
,
603 this->addr_lookup_lock_
,
606 if (this->hash_val_
!= 0)
607 return this->hash_val_
;
609 // A few comments about this optimization. The call below will
610 // deadlock if the object_addr_set is false. If you don't belive
612 if (!this->object_addr_set_
)
614 // Set the object_addr first
615 (void) this->object_addr_i ();
618 this->hash_val_
= this->object_addr_
.hash ();
621 return this->hash_val_
;
625 TAO_IIOP_Endpoint::is_preferred_network (void) const
627 return (this->preferred_path_
.host
.in () != 0 &&
628 this->preferred_path_
.host
.in ()[0] != 0);
632 TAO_IIOP_Endpoint::preferred_network (void) const
634 return this->preferred_path_
.host
.in ();
637 //@@ TAO_ENDPOINT_SPL_COPY_HOOK_END
639 TAO_END_VERSIONED_NAMESPACE_DECL
641 #endif /* TAO_HAS_IIOP && TAO_HAS_IIOP != 0 */