1 #include "tao/IIOP_Acceptor.h"
3 #if defined (TAO_HAS_IIOP) && (TAO_HAS_IIOP != 0)
5 #include "tao/IIOP_Profile.h"
6 #include "tao/MProfile.h"
8 #include "tao/Protocols_Hooks.h"
9 #include "tao/Codeset_Manager.h"
10 #include "tao/Transport.h"
11 #include "tao/ORB_Core.h"
14 #if !defined(__ACE_INLINE__)
15 #include "tao/IIOP_Acceptor.inl"
16 #endif /* __ACE_INLINE__ */
18 #include "ace/OS_NS_string.h"
19 #include "ace/os_include/os_netdb.h"
22 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
24 TAO_IIOP_Acceptor::TAO_IIOP_Acceptor ()
25 : TAO_Acceptor (IOP::TAG_INTERNET_IOP
),
29 hostname_in_ior_ (nullptr),
31 version_ (TAO_DEF_GIOP_MAJOR
, TAO_DEF_GIOP_MINOR
),
34 #if defined (ACE_HAS_IPV6) && !defined (ACE_USES_IPV4_IPV6_MIGRATION)
35 default_address_ (static_cast<unsigned short> (0), ACE_IPV6_ANY
, AF_INET6
),
37 default_address_ (static_cast<unsigned short> (0), static_cast<ACE_UINT32
> (INADDR_ANY
)),
38 #endif /* ACE_HAS_IPV6 && !ACE_USES_IPV4_IPV6_MIGRATION */
39 base_acceptor_ (this),
40 creation_strategy_ (nullptr),
41 concurrency_strategy_ (nullptr),
42 accept_strategy_ (nullptr)
44 #if defined (ACE_HAS_IPV6) && defined (ACE_USES_IPV4_IPV6_MIGRATION)
45 if (ACE::ipv6_enabled())
46 default_address_
.set (
47 static_cast<unsigned short> (0),
50 #endif /* ACE_HAS_IPV6 && ACE_USES_IPV4_IPV6_MIGRATION */
53 TAO_IIOP_Acceptor::~TAO_IIOP_Acceptor ()
55 // Make sure we are closed before we start destroying the
59 delete this->creation_strategy_
;
60 delete this->concurrency_strategy_
;
61 delete this->accept_strategy_
;
63 delete [] this->addrs_
;
65 for (CORBA::ULong i
= 0; i
< this->endpoint_count_
; ++i
)
66 CORBA::string_free (this->hosts_
[i
]);
68 delete [] this->hosts_
;
70 delete [] this->hostname_in_ior_
;
74 // 2) For V1.[1,2] there are tagged components
76 TAO_IIOP_Acceptor::create_profile (const TAO::ObjectKey
&object_key
,
77 TAO_MProfile
&mprofile
,
78 CORBA::Short priority
)
81 if (this->endpoint_count_
== 0)
84 // Check if multiple endpoints should be put in one profile or
85 // if they should be spread across multiple profiles.
86 if (priority
== TAO_INVALID_PRIORITY
&&
87 this->orb_core_
->orb_params ()->shared_profile () == 0)
88 return this->create_new_profile (object_key
, mprofile
, priority
);
90 return this->create_shared_profile (object_key
, mprofile
, priority
);
94 TAO_IIOP_Acceptor::create_new_profile (const TAO::ObjectKey
&object_key
,
95 TAO_MProfile
&mprofile
,
96 CORBA::Short priority
)
98 // Adding this->endpoint_count_ to the TAO_MProfile.
99 int const count
= mprofile
.profile_count ();
100 if ((mprofile
.size () - count
) < this->endpoint_count_
101 && mprofile
.grow (count
+ this->endpoint_count_
) == -1)
104 // Create a profile for each acceptor endpoint.
105 for (CORBA::ULong i
= 0; i
< this->endpoint_count_
; ++i
)
107 // Skip if the host name
109 && (this->addrs_
[i
].get_port_number() == this->addrs_
[0].get_port_number())
110 && ACE_OS::strcmp(this->hosts_
[i
], this->hosts_
[0]) == 0)
113 TAO_IIOP_Profile
*pfile
= nullptr;
114 ACE_NEW_RETURN (pfile
,
115 TAO_IIOP_Profile (this->hosts_
[i
],
116 this->addrs_
[i
].get_port_number (),
122 pfile
->endpoint ()->priority (priority
);
124 if (mprofile
.give_profile (pfile
) == -1)
126 pfile
->_decr_refcnt ();
131 // Do not add any tagged components to the profile if configured
132 // by the user not to do so, or if an IIOP 1.0 endpoint is being
133 // created (IIOP 1.0 did not support tagged components).
134 if (!this->orb_core_
->orb_params ()->std_profile_components ()
135 || (this->version_
.major
== 1 && this->version_
.minor
== 0))
138 pfile
->tagged_components ().set_orb_type (TAO_ORB_TYPE
);
140 TAO_Codeset_Manager
*csm
= this->orb_core_
->codeset_manager();
142 csm
->set_codeset(pfile
->tagged_components());
149 TAO_IIOP_Acceptor::create_shared_profile (const TAO::ObjectKey
&object_key
,
150 TAO_MProfile
&mprofile
,
151 CORBA::Short priority
)
153 CORBA::ULong index
= 0;
154 TAO_Profile
*pfile
= nullptr;
155 TAO_IIOP_Profile
*iiop_profile
= nullptr;
157 // First see if @a mprofile already contains a IIOP profile.
158 for (TAO_PHandle i
= 0; i
!= mprofile
.profile_count (); ++i
)
160 pfile
= mprofile
.get_profile (i
);
161 if (pfile
->tag () == IOP::TAG_INTERNET_IOP
)
163 iiop_profile
= dynamic_cast<TAO_IIOP_Profile
*> (pfile
);
168 // If <mprofile> doesn't contain a IIOP_Profile, we need to create
170 if (iiop_profile
== nullptr)
172 ACE_NEW_RETURN (iiop_profile
,
173 TAO_IIOP_Profile (this->hosts_
[0],
174 this->addrs_
[0].get_port_number (),
181 iiop_profile
->endpoint ()->priority (priority
);
183 if (mprofile
.give_profile (iiop_profile
) == -1)
185 iiop_profile
->_decr_refcnt ();
186 iiop_profile
= nullptr;
190 // Do not add any tagged components to the profile if configured
191 // by the user not to do so, or if an IIOP 1.0 endpoint is being
192 // created (IIOP 1.0 did not support tagged components).
193 if (this->orb_core_
->orb_params ()->std_profile_components ()
194 && (this->version_
.major
>= 1 && this->version_
.minor
>= 1))
196 iiop_profile
->tagged_components ().set_orb_type (TAO_ORB_TYPE
);
197 TAO_Codeset_Manager
*csm
= this->orb_core_
->codeset_manager();
199 csm
->set_codeset(iiop_profile
->tagged_components());
205 // Add any remaining acceptor endpoints to the IIOP_Profile.
207 index
< this->endpoint_count_
;
211 this->addrs_
[index
].get_port_number() == this->addrs_
[0].get_port_number() &&
212 ACE_OS::strcmp(this->hosts_
[index
], this->hosts_
[0]) == 0)
215 TAO_IIOP_Endpoint
*endpoint
= nullptr;
216 ACE_NEW_RETURN (endpoint
,
217 TAO_IIOP_Endpoint (this->hosts_
[index
],
218 this->addrs_
[index
].get_port_number (),
219 this->addrs_
[index
]),
221 endpoint
->priority (priority
);
222 iiop_profile
->add_endpoint (endpoint
);
229 TAO_IIOP_Acceptor::is_collocated (const TAO_Endpoint
*endpoint
)
231 const TAO_IIOP_Endpoint
*endp
=
232 dynamic_cast<const TAO_IIOP_Endpoint
*> (endpoint
);
234 // Make sure the dynamically cast pointer is valid.
238 for (CORBA::ULong i
= 0; i
< this->endpoint_count_
; ++i
)
240 // compare the port and host name. Please do *NOT* optimize
241 // this code by comparing the IP address instead. That would
242 // trigger the following bug:
244 // http://bugzilla.dre.vanderbilt.edu/show_bug.cgi?id=1220
246 if (endp
->port() == this->addrs_
[i
].get_port_number()
247 && ACE_OS::strcmp(endp
->host(), this->hosts_
[i
]) == 0)
255 TAO_IIOP_Acceptor::close ()
257 return this->base_acceptor_
.close ();
261 TAO_IIOP_Acceptor::open (TAO_ORB_Core
*orb_core
,
262 ACE_Reactor
*reactor
,
268 if (TAO_debug_level
> 2)
270 TAOLIB_DEBUG ((LM_DEBUG
,
271 ACE_TEXT ("TAO (%P|%t) - ")
272 ACE_TEXT ("IIOP_Acceptor::open, address==%C, options=%C\n"),
276 this->orb_core_
= orb_core
;
278 if (this->hosts_
!= nullptr)
280 // The hostname cache has already been set!
281 // This is bad mojo, i.e. an internal TAO error.
282 TAOLIB_ERROR_RETURN ((LM_ERROR
,
283 ACE_TEXT ("TAO (%P|%t) - ")
284 ACE_TEXT ("IIOP_Acceptor::open, ")
285 ACE_TEXT ("hostname already set\n\n")),
289 if (address
== nullptr)
292 if (major
>=0 && minor
>= 0)
293 this->version_
.set_version (static_cast<CORBA::Octet
> (major
),
294 static_cast<CORBA::Octet
> (minor
));
296 if (this->parse_options (options
) == -1)
299 ACE_CString specified_hostname
;
301 int def_type
= AF_UNSPEC
;
303 if (this->parse_address (address
,
309 if (specified_hostname
.length() == 0)
311 // The address is a port number or port name. No hostname was
312 // specified. The hostname for each network interface and the
313 // fully qualified domain name must be obtained.
315 // Check for multiple network interfaces.
316 if (this->probe_interfaces (orb_core
, def_type
) == -1)
319 // Probe interfaces has a side effect of potentially modifying
320 // the default address, since that is where the address family
322 addr
.set(this->default_address_
);
324 return this->open_i (addr
, reactor
);
327 #if defined (ACE_HAS_IPV6)
328 // Check for violation of ORBConnectIPV6Only option
329 if (this->orb_core_
->orb_params ()->connect_ipv6_only () &&
330 (addr
.get_type () != AF_INET6
||
331 addr
.is_ipv4_mapped_ipv6 ()))
333 TAOLIB_ERROR_RETURN ((LM_ERROR
,
334 ACE_TEXT ("TAO (%P|%t) - ")
335 ACE_TEXT ("IIOP_Acceptor::open, ")
336 ACE_TEXT ("non-IPv6 endpoints not allowed when ")
337 ACE_TEXT ("connect_ipv6_only is set\n\n")),
340 #endif /* ACE_HAS_IPV6 */
342 if (TAO_debug_level
> 2)
344 TAOLIB_DEBUG ((LM_DEBUG
,
345 ACE_TEXT ("TAO (%P|%t) - ")
346 ACE_TEXT ("IIOP_Acceptor::open, specified host=%C:%d\n"),
347 (specified_hostname
.length() == 0 ? "<null>" : specified_hostname
.c_str()),
348 addr
.get_port_number ()));
351 this->endpoint_count_
= 1; // Only one hostname to store
353 ACE_NEW_RETURN (this->addrs_
,
354 ACE_INET_Addr
[this->endpoint_count_
],
357 ACE_NEW_RETURN (this->hosts_
,
358 char *[this->endpoint_count_
],
361 this->hosts_
[0] = nullptr;
363 if (this->hostname_in_ior_
!= nullptr)
365 if (TAO_debug_level
> 2)
367 TAOLIB_DEBUG ((LM_DEBUG
,
368 ACE_TEXT ("TAO (%P|%t) - ")
369 ACE_TEXT ("IIOP_Acceptor::open, ")
370 ACE_TEXT ("overriding address in IOR with %C\n"),
371 this->hostname_in_ior_
));
373 specified_hostname
= this->hostname_in_ior_
;
376 if (this->hostname (orb_core
,
379 specified_hostname
.c_str()) != 0)
382 // Copy the addr. The port is (re)set in
383 // TAO_IIOP_Acceptor::open_i().
384 if (this->addrs_
[0].set (addr
) != 0)
387 return this->open_i (addr
, reactor
);
391 TAO_IIOP_Acceptor::open_default (TAO_ORB_Core
*orb_core
,
392 ACE_Reactor
*reactor
,
397 this->orb_core_
= orb_core
;
399 if (this->hosts_
!= nullptr)
401 // The hostname cache has already been set!
402 // This is bad mojo, i.e. an internal TAO error.
403 TAOLIB_ERROR_RETURN ((LM_ERROR
,
404 ACE_TEXT ("TAO (%P|%t) - ")
405 ACE_TEXT ("IIOP_Acceptor::open_default, ")
406 ACE_TEXT ("hostname already set\n\n")),
410 if (major
>= 0 && minor
>= 0)
411 this->version_
.set_version (static_cast<CORBA::Octet
> (major
),
412 static_cast<CORBA::Octet
> (minor
));
415 if (this->parse_options (options
) == -1)
418 // Check for multiple network interfaces.
419 if (this->probe_interfaces (orb_core
) == -1)
422 // Now that each network interface's hostname has been cached, open
423 // an endpoint on each network interface using the INADDR_ANY
427 if (addr
.set (this->default_address_
) != 0)
430 return this->open_i (addr
, reactor
);
434 TAO_IIOP_Acceptor::open_i (const ACE_INET_Addr
& addr
,
435 ACE_Reactor
*reactor
)
437 ACE_NEW_RETURN (this->creation_strategy_
,
438 CREATION_STRATEGY (this->orb_core_
),
441 ACE_NEW_RETURN (this->concurrency_strategy_
,
442 CONCURRENCY_STRATEGY (this->orb_core_
),
445 ACE_NEW_RETURN (this->accept_strategy_
,
446 ACCEPT_STRATEGY (this->orb_core_
),
449 unsigned short const requested_port
= addr
.get_port_number ();
450 if (requested_port
== 0)
452 // don't care, i.e., let the OS choose an ephemeral port
453 if (this->base_acceptor_
.open (addr
,
455 this->creation_strategy_
,
456 this->accept_strategy_
,
457 this->concurrency_strategy_
,
458 nullptr, nullptr, nullptr, ACE_DEFAULT_ACCEPTOR_USE_SELECT
,
459 this->reuse_addr_
) == -1)
461 if (TAO_debug_level
> 0)
462 TAOLIB_ERROR ((LM_ERROR
,
463 ACE_TEXT ("TAO (%P|%t) - IIOP_Acceptor::open_i, ")
465 ACE_TEXT ("cannot open acceptor")));
471 ACE_INET_Addr
a(addr
);
473 bool found_a_port
= false;
474 ACE_UINT32
const last_port
= ACE_MIN (requested_port
+ this->port_span_
- 1,
475 ACE_MAX_DEFAULT_PORT
);
477 for (ACE_UINT32 p
= requested_port
; p
<= last_port
; p
++)
479 if (TAO_debug_level
> 5)
480 TAOLIB_DEBUG ((LM_DEBUG
,
481 ACE_TEXT ("TAO (%P|%t) - IIOP_Acceptor::open_i, ")
482 ACE_TEXT ("trying to listen on port %d\n"), p
));
484 // Now try to actually open on that port
485 a
.set_port_number ((u_short
)p
);
486 if (this->base_acceptor_
.open (a
,
488 this->creation_strategy_
,
489 this->accept_strategy_
,
490 this->concurrency_strategy_
,
491 nullptr, nullptr, nullptr, ACE_DEFAULT_ACCEPTOR_USE_SELECT
,
492 this->reuse_addr_
) != -1)
499 // Now, if we couldn't locate a port, we punt
502 if (TAO_debug_level
> 0)
503 TAOLIB_DEBUG ((LM_DEBUG
,
504 ACE_TEXT ("TAO (%P|%t) - IIOP_Acceptor::open_i, ")
505 ACE_TEXT ("cannot open acceptor in port range (%d,%d)")
507 requested_port
, last_port
, ACE_TEXT("")));
512 #if defined (ACE_HAS_IPV6) && defined (ACE_HAS_IPV6_V6ONLY)
513 // Check if need to prevent this acceptor from accepting connections
514 // from IPv4 mapped IPv6 addresses
515 if (this->orb_core_
->orb_params ()->connect_ipv6_only () &&
518 if (TAO_debug_level
> 5)
519 TAOLIB_DEBUG ((LM_DEBUG
,
520 ACE_TEXT("TAO (%P|%t) - IIOP_Acceptor::open_i, ")
521 ACE_TEXT("setting IPV6_V6ONLY\n")));
523 // Prevent server from accepting connections from IPv4-mapped addresses.
525 if (this->base_acceptor_
.acceptor ().set_option (IPPROTO_IPV6
,
530 TAOLIB_ERROR ((LM_ERROR
,
531 ACE_TEXT ("TAO (%P|%t) - IIOP_Acceptor::open_i, ")
533 ACE_TEXT ("cannot set IPV6_V6ONLY")));
536 #endif /* ACE_HAS_IPV6 && ACE_HAS_IPV6_V6ONLY */
538 ACE_INET_Addr address
;
540 // We do this make sure the port number the endpoint is listening on
541 // gets set in the addr.
542 if (this->base_acceptor_
.acceptor ().get_local_addr (address
) != 0)
544 if (TAO_debug_level
> 0)
545 TAOLIB_ERROR ((LM_ERROR
,
546 ACE_TEXT ("TAO (%P|%t) - IIOP_Acceptor::open_i, ")
548 ACE_TEXT ("cannot get local addr")));
552 // Set the port for each addr. If there is more than one network
553 // interface then the endpoint created on each interface will be on
554 // the same port. This is how a wildcard socket bind() is supposed
556 unsigned short port
= address
.get_port_number ();
557 for (CORBA::ULong j
= 0; j
< this->endpoint_count_
; ++j
)
558 this->addrs_
[j
].set_port_number (port
, 1);
560 this->default_address_
.set_port_number (port
);
562 (void) this->base_acceptor_
.acceptor().enable (ACE_CLOEXEC
);
563 // This avoids having child processes acquire the listen socket thereby
564 // denying the server the opportunity to restart on a well-known endpoint.
565 // This does not affect the aberrent behavior on Win32 platforms.
567 if (TAO_debug_level
> 5)
569 for (CORBA::ULong i
= 0; i
< this->endpoint_count_
; ++i
)
571 TAOLIB_DEBUG ((LM_DEBUG
,
572 ACE_TEXT ("TAO (%P|%t) - IIOP_Acceptor::open_i, ")
573 ACE_TEXT ("listening on: <%C:%u>\n"),
575 this->addrs_
[i
].get_port_number ()));
579 // In the event that an accept() fails, we can examine the reason. If
580 // the reason warrants it, we can try accepting again at a later time.
581 // The amount of time we wait to accept again is governed by this orb
583 this->set_error_retry_delay (
584 this->orb_core_
->orb_params ()->accept_error_delay());
590 TAO_IIOP_Acceptor::hostname (TAO_ORB_Core
*orb_core
,
591 const ACE_INET_Addr
&addr
,
593 const char *specified_hostname
)
595 if (this->hostname_in_ior_
!= nullptr)
597 if (TAO_debug_level
>= 5)
598 TAOLIB_DEBUG ((LM_DEBUG
,
599 ACE_TEXT ("TAO (%P|%t) - IIOP_Acceptor::hostname, ")
600 ACE_TEXT ("overriding the hostname with <%C>\n"),
601 this->hostname_in_ior_
));
603 host
= CORBA::string_dup (this->hostname_in_ior_
);
605 else if (orb_core
->orb_params ()->use_dotted_decimal_addresses ())
607 // If dotted decimal addresses are enabled,
609 return this->dotted_decimal_address (addr
, host
);
611 else if (specified_hostname
!= nullptr)
613 // If the user specified a hostname, pass it back
614 // blindly as it overrides our choice of hostname.
615 host
= CORBA::string_dup (specified_hostname
);
619 char tmp_host
[MAXHOSTNAMELEN
+ 1];
621 // Get the hostname associated with our address
622 #if defined (ACE_HAS_IPV6)
623 // If we have a IPv4-compatible IPv6 address don't do hostname lookup
624 // because that gets us into trouble. Most likely we get the same hostname
625 // returned as for the actual IPv4 address but resolving that into an IPv6
626 // address at the client will fail.
627 if (addr
.is_ipv4_compat_ipv6 () ||
628 addr
.get_host_name (tmp_host
, sizeof (tmp_host
)) != 0)
629 #else /* ACE_HAS_IPV6 */
630 if (addr
.get_host_name (tmp_host
, sizeof (tmp_host
)) != 0)
631 #endif /* !ACE_HAS_IPV6 */
633 // On failure, just return the decimal address.
634 return this->dotted_decimal_address (addr
, host
);
638 host
= CORBA::string_dup (tmp_host
);
647 TAO_IIOP_Acceptor::parse_address (const char *address
,
649 ACE_CString
&specified_hostname
,
655 specified_hostname
.clear();
658 const char *port_separator_loc
= std::strchr (address
, ':');
659 char tmp_host
[MAXHOSTNAMELEN
+ 1];
661 bool host_defaulted
= port_separator_loc
== address
;
662 bool ipv6_in_host
= false;
664 *def_type
= AF_UNSPEC
;
666 #if defined (ACE_HAS_IPV6)
667 // Check if this is a (possibly) IPv6 supporting profile containing a
668 // numeric IPv6 address representation.
669 if ((this->version_
.major
> TAO_MIN_IPV6_IIOP_MAJOR
||
670 this->version_
.minor
>= TAO_MIN_IPV6_IIOP_MINOR
) &&
673 // In this case we have to find the end of the numeric address and
674 // start looking for the port separator from there.
675 char const * const cp_pos
= std::strchr (address
, ']');
678 // No valid IPv6 address specified.
679 TAOLIB_ERROR_RETURN ((LM_ERROR
,
680 ACE_TEXT ("TAO (%P|%t) - ")
681 ACE_TEXT ("IIOP_Acceptor::open, ")
682 ACE_TEXT ("Invalid IPv6 decimal address specified\n\n")),
687 // Extract out just the host part of the address.
688 size_t const len
= cp_pos
- (address
+ 1);
690 if (len
>= sizeof (tmp_host
))
694 host_defaulted
= (cp_pos
== address
+1) ||
695 (cp_pos
== address
+3 && address
[1] == ':' && address
[2] == ':');
696 if (cp_pos
[1] == ':') // Look for a port
697 port_separator_loc
= cp_pos
+ 1;
699 port_separator_loc
= 0;
701 *def_type
= AF_INET6
;
703 ACE_OS::memcpy (tmp_host
, address
+ 1, len
);
704 tmp_host
[len
] = '\0';
708 #endif /* ACE_HAS_IPV6 */
711 if (port_separator_loc
!= nullptr)
713 // Extract out just the host part of the address.
714 size_t const len
= port_separator_loc
- address
;
716 if (len
>= sizeof (tmp_host
))
719 ACE_OS::memcpy (tmp_host
, address
, len
);
720 tmp_host
[len
] = '\0';
723 ACE_OS::strcpy (tmp_host
, address
);
726 if (!ipv6_in_host
&& !host_defaulted
)
728 if (addr
.set((unsigned short)0,tmp_host
) != 0)
730 this->default_address_
.set(addr
);
731 host_defaulted
= addr
.is_any();
738 // First convert the port into a usable form.
739 unsigned short portno
= 0;
740 if (port_separator_loc
!= nullptr)
743 static_cast<u_short
> (ACE_OS::atoi (port_separator_loc
+
746 this->default_address_
.set_port_number (portno
);
748 // Now reset the port and set the host.
749 if (addr
.set (this->default_address_
) != 0)
752 else if (port_separator_loc
== nullptr)
754 // The address is a hostname. No port was specified, so assume
755 // port zero (port will be chosen for us).
756 specified_hostname
= tmp_host
[0] == '\0' ? address
: tmp_host
;
757 if (addr
.set ((unsigned short) 0,
758 specified_hostname
.c_str()) != 0)
763 // Host and port were specified.
764 if (addr
.set (address
) != 0)
766 if (tmp_host
[0] == '\0')
768 // Extract out just the host part of the address.
769 size_t const len
= port_separator_loc
- address
;
771 if (len
>= sizeof (tmp_host
))
774 ACE_OS::memcpy (tmp_host
, address
, len
);
775 tmp_host
[len
] = '\0';
777 specified_hostname
= tmp_host
;
785 TAO_IIOP_Acceptor::dotted_decimal_address (const ACE_INET_Addr
&addr
,
789 const char *tmp
= nullptr;
791 // If the IP address in the INET_Addr is the IN(6)ADDR_ANY address,
792 // then force the actual IP address to be used by initializing a new
793 // INET_Addr with the hostname from the original one. If that fails
794 // then something is seriously wrong with the systems networking
798 ACE_INET_Addr new_addr
;
799 #if defined (ACE_HAS_IPV6)
800 result
= new_addr
.set (addr
.get_port_number (),
801 addr
.get_host_name (),
804 #else /* ACE_HAS_IPV6 */
805 result
= new_addr
.set (addr
.get_port_number (),
806 addr
.get_host_name ());
807 #endif /* !ACE_HAS_IPV6 */
808 tmp
= new_addr
.get_host_addr ();
811 tmp
= addr
.get_host_addr ();
813 if (tmp
== nullptr || result
!= 0)
815 if (TAO_debug_level
> 0)
816 TAOLIB_ERROR ((LM_ERROR
,
817 ACE_TEXT ("TAO (%P|%t) - ")
818 ACE_TEXT ("IIOP_Acceptor::dotted_decimal_address, ")
820 ACE_TEXT ("cannot determine hostname")));
824 host
= CORBA::string_dup (tmp
);
829 TAO_IIOP_Acceptor::probe_interfaces (TAO_ORB_Core
*orb_core
, int def_type
)
831 // Extract the hostname for each network interface, and then cache
832 // it. The hostnames will then be used when creating a
833 // TAO_IIOP_Profile for each endpoint setup on the probed
834 // network interfaces.
835 ACE_INET_Addr
*if_addrs
= nullptr;
838 if (ACE::get_ip_interfaces (if_cnt
, if_addrs
) != 0
841 // In the case where errno == ENOTSUP, if_cnt and if_addrs will
842 // not be modified, and will each remain equal to zero. This
843 // causes the default interface to be used.
847 if (if_cnt
== 0 || if_addrs
== nullptr)
849 if (TAO_debug_level
> 0)
851 TAOLIB_DEBUG ((LM_WARNING
,
852 ACE_TEXT ("TAO (%P|%t) - Unable to probe network ")
853 ACE_TEXT ("interfaces. Using default.\n")));
856 if_cnt
= 1; // Force the network interface count to be one.
858 ACE_NEW_RETURN (if_addrs
,
859 ACE_INET_Addr
[if_cnt
],
863 // Scan for the loopback interface since it shouldn't be included in
864 // the list of cached hostnames unless it is the only interface.
865 size_t lo_cnt
= 0; // Loopback interface count
866 for (size_t j
= 0; j
< if_cnt
; ++j
)
867 if (if_addrs
[j
].is_loopback ())
870 #if defined (ACE_HAS_IPV6)
872 size_t ipv4_lo_cnt
= 0;
874 bool ipv4_non_lo
= false;
875 bool ipv6_non_ll
= false;
876 // Scan for IPv4 interfaces since these should not be included
877 // when IPv6-only is selected.
878 for (size_t j
= 0; j
< if_cnt
; ++j
)
879 if (if_addrs
[j
].get_type () != AF_INET6
||
880 if_addrs
[j
].is_ipv4_mapped_ipv6 ())
883 if (if_addrs
[j
].is_loopback ())
884 ++ipv4_lo_cnt
; // keep track of IPv4 loopback ifs
888 else if (!if_addrs
[j
].is_linklocal () &&
889 !if_addrs
[j
].is_loopback())
891 ipv6_non_ll
= true; // we have at least 1 non-local IPv6 if
893 else if (!orb_core
->orb_params ()->use_ipv6_link_local () &&
894 if_addrs
[j
].is_linklocal ())
896 ++ipv6_ll
; // count link local addrs to exclude them afterwards
898 #endif /* ACE_HAS_IPV6 */
900 // The instantiation for this template is in
901 // tao/IIOP_Connector.cpp.
902 ACE_Auto_Basic_Array_Ptr
<ACE_INET_Addr
> safe_if_addrs (if_addrs
);
904 #if defined (ACE_HAS_IPV6)
905 bool ipv4_only
= def_type
== AF_INET
;
906 bool ipv6_only
= (def_type
== AF_INET6
) ||
907 orb_core
->orb_params ()->connect_ipv6_only ();
908 #if defined (ACE_WIN32)
910 vinfo
.dwOSVersionInfoSize
= sizeof (vinfo
);
911 int vres
= GetVersionEx (&vinfo
);
912 if (vres
== 0 || vinfo
.dwMajorVersion
< 6)
914 if (this->default_address_
.get_type () == AF_INET
)
919 #endif /* ACE_WIN32 */
920 // If the loopback interface is the only interface then include it
921 // in the list of interfaces to query for a hostname, otherwise
922 // exclude it from the list.
925 // only exclude loopback if non-local if exists
926 ignore_lo
= ipv6_non_ll
;
928 ignore_lo
= ipv4_cnt
!= ipv4_lo_cnt
;
931 ipv6_non_ll
|= ipv4_non_lo
;
932 ignore_lo
= ipv6_non_ll
;
935 // Adjust counts for IPv6 only if required
936 size_t if_ok_cnt
= if_cnt
;
939 if_ok_cnt
-= ipv4_cnt
;
940 lo_cnt
-= ipv4_lo_cnt
;
945 if_ok_cnt
= ipv4_cnt
;
946 lo_cnt
= ipv4_lo_cnt
;
950 // In case there are no non-local IPv6 ifs in the list only exclude
952 // IPv6 loopback will be needed to successfully connect IPv6 clients
953 // in a localhost environment.
954 if (!ipv4_only
&& !ipv6_non_ll
)
955 lo_cnt
= ipv4_lo_cnt
;
958 this->endpoint_count_
= static_cast<CORBA::ULong
> (if_ok_cnt
- ipv6_ll
);
960 this->endpoint_count_
= static_cast<CORBA::ULong
> (if_ok_cnt
- ipv6_ll
- lo_cnt
);
961 #else /* ACE_HAS_IPV6 */
962 // If the loopback interface is the only interface then include it
963 // in the list of interfaces to query for a hostname, otherwise
964 // exclude it from the list.
966 ignore_lo
= if_cnt
!= lo_cnt
;
968 this->endpoint_count_
= static_cast<CORBA::ULong
> (if_cnt
);
970 this->endpoint_count_
= static_cast<CORBA::ULong
> (if_cnt
- lo_cnt
);
971 #endif /* !ACE_HAS_IPV6 */
973 if (this->endpoint_count_
== 0)
975 if (TAO_debug_level
> 0)
976 TAOLIB_DEBUG ((LM_DEBUG
,
977 ACE_TEXT("(%P|%t) TAO_IIOP_Acceptor::probe_interfaces ")
978 ACE_TEXT("found no usable addresses, def_type = %d\n"),
983 ACE_NEW_RETURN (this->addrs_
,
984 ACE_INET_Addr
[this->endpoint_count_
],
987 ACE_NEW_RETURN (this->hosts_
,
988 char *[this->endpoint_count_
],
991 ACE_OS::memset (this->hosts_
, 0, sizeof (char*) * this->endpoint_count_
);
993 // The number of hosts/interfaces we want to cache may not be the
994 // same as the number of detected interfaces so keep a separate
998 for (size_t i
= 0; i
< if_cnt
; ++i
)
1000 #if defined (ACE_HAS_IPV6)
1001 // Ignore any loopback interface if there are other
1002 // non-loopback interfaces.
1004 if_addrs
[i
].is_loopback () &&
1007 if_addrs
[i
].get_type () != AF_INET6
))
1010 // Ignore any non-IPv4 interfaces when so required.
1012 (if_addrs
[i
].get_type () != AF_INET
))
1015 // Ignore any non-IPv6 interfaces when so required.
1017 (if_addrs
[i
].get_type () != AF_INET6
||
1018 if_addrs
[i
].is_ipv4_mapped_ipv6 ()))
1021 // Ignore all IPv6 link local interfaces when so required.
1022 if (!orb_core
->orb_params ()->use_ipv6_link_local () &&
1023 if_addrs
[i
].is_linklocal ())
1025 #else /* ACE_HAS_IPV6 */
1026 // Ignore any loopback interface if there are other
1027 // non-loopback interfaces.
1029 if_addrs
[i
].is_loopback ())
1031 #endif /* !ACE_HAS_IPV6 */
1033 if (this->hostname (orb_core
,
1035 this->hosts_
[host_cnt
]) != 0)
1038 // Copy the addr. The port is (re)set in
1039 // TAO_IIOP_Acceptor::open_i().
1040 if (this->addrs_
[host_cnt
].set (if_addrs
[i
]) != 0)
1050 TAO_IIOP_Acceptor::endpoint_count ()
1052 return this->endpoint_count_
;
1056 TAO_IIOP_Acceptor::object_key (IOP::TaggedProfile
&profile
,
1057 TAO::ObjectKey
&object_key
)
1059 // Create the decoding stream from the encapsulation in the buffer,
1060 #if (TAO_NO_COPY_OCTET_SEQUENCES == 1)
1061 TAO_InputCDR
cdr (profile
.profile_data
.mb ());
1063 TAO_InputCDR
cdr (reinterpret_cast<char*> (profile
.profile_data
.get_buffer ()),
1064 profile
.profile_data
.length ());
1065 #endif /* TAO_NO_COPY_OCTET_SEQUENCES == 1 */
1067 CORBA::Octet major
= 0;
1068 CORBA::Octet minor
= 0;
1070 // Read the version. We just read it here. We don't*do any*
1072 if (!(cdr
.read_octet (major
)
1073 && cdr
.read_octet (minor
)))
1075 if (TAO_debug_level
> 0)
1077 TAOLIB_DEBUG ((LM_DEBUG
,
1078 ACE_TEXT ("TAO (%P|%t) - TAO_IIOP_Acceptor::object_key, v%d.%d\n"),
1085 CORBA::String_var host
;
1086 CORBA::UShort port
= 0;
1088 // Get host and port. No processing here too..
1089 if (cdr
.read_string (host
.out ()) == 0
1090 || cdr
.read_ushort (port
) == 0)
1092 if (TAO_debug_level
> 0)
1094 TAOLIB_DEBUG ((LM_DEBUG
,
1095 ACE_TEXT ("TAO (%P|%t) - TAO_IIOP_Acceptor::object_key, ")
1096 ACE_TEXT ("error while decoding host/port\n")));
1101 // ... and object key.
1102 if ((cdr
>> object_key
) == 0)
1105 // We are NOT bothered about the rest.
1111 TAO_IIOP_Acceptor::parse_options (const char *str
)
1114 return 0; // No options to parse. Not a problem.
1116 // Use an option format similar to the one used for CGI scripts in
1118 // e.g.: option1=foo&option2=bar
1120 const ACE_CString
options (str
);
1122 const size_t len
= options
.length ();
1124 static const char option_delimiter
= '&';
1126 // Count the number of options.
1129 for (size_t i
= 0; i
< len
; ++i
)
1130 if (options
[i
] == option_delimiter
)
1133 // The idea behind the following loop is to split the options into
1134 // (option, name) pairs.
1136 // `option1=foo&option2=bar'
1137 // will be parsed into:
1141 ACE_CString
*argv_base
= nullptr;
1142 ACE_NEW_RETURN (argv_base
, ACE_CString
[argc
],-1);
1143 ACE_CString
**argv
= nullptr;
1144 ACE_NEW_RETURN (argv
, ACE_CString
*[argc
],-1);
1146 ACE_CString::size_type begin
= 0;
1147 ACE_CString::size_type end
= 0;
1149 for (int j
= 0; j
< argc
; ++j
)
1152 end
= options
.find (option_delimiter
, begin
);
1158 TAOLIB_ERROR ((LM_ERROR
,
1159 ACE_TEXT ("TAO (%P|%t) - Zero length IIOP option.\n")));
1163 else if (end
!= options
.npos
)
1165 argv_base
[j
] = options
.substring (begin
, end
- begin
);
1166 argv
[j
] = &argv_base
[j
];
1171 break; // No other options.
1176 result
= this->parse_options_i (argc
,argv
);
1180 TAOLIB_ERROR ((LM_ERROR
,
1181 ACE_TEXT ("TAO (%P|%t) - IIOP")
1182 ACE_TEXT (" endpoint has %d unknown options:\n"),
1184 for (int i
= 0; i
< argc
; i
++)
1185 TAOLIB_ERROR ((LM_ERROR
,
1191 delete [] argv_base
;
1196 TAO_IIOP_Acceptor::parse_options_i (int &argc
,
1202 ACE_CString::size_type
const len
= argv
[i
]->length ();
1203 ACE_CString::size_type
const slot
= argv
[i
]->find ('=');
1206 || slot
== ACE_CString::npos
)
1207 TAOLIB_ERROR_RETURN ((LM_ERROR
,
1208 ACE_TEXT ("TAO (%P|%t) - IIOP option <%C> is ")
1209 ACE_TEXT ("missing a value.\n"),
1213 ACE_CString name
= argv
[i
]->substring (0, slot
);
1214 ACE_CString value
= argv
[i
]->substring (slot
+ 1);
1216 if (name
.length () == 0)
1217 TAOLIB_ERROR_RETURN ((LM_ERROR
,
1218 ACE_TEXT ("TAO (%P|%t) Zero length IIOP ")
1219 ACE_TEXT ("option name.\n")),
1221 if (name
== "portspan")
1223 int const range
= ACE_OS::atoi (value
.c_str ());
1224 // @@ What's the lower bound on the range? zero, or one?
1225 if (range
< 1 || range
> ACE_MAX_DEFAULT_PORT
)
1226 TAOLIB_ERROR_RETURN ((LM_ERROR
,
1227 ACE_TEXT ("TAO (%P|%t) Invalid IIOP endpoint ")
1228 ACE_TEXT ("portspan: <%C>\n")
1229 ACE_TEXT ("Valid range 1 -- %d\n"),
1230 value
.c_str (), ACE_MAX_DEFAULT_PORT
),
1233 this->port_span_
= static_cast <u_short
> (range
);
1235 else if (name
== "hostname_in_ior")
1237 this->hostname_in_ior_
= value
.rep ();
1239 else if (name
== "reuse_addr")
1241 this->reuse_addr_
= ACE_OS::atoi (value
.c_str ());
1245 // the name is not known, skip to the next option
1249 // at the end, we've consumed this argument. Shift the list and
1250 // put this one on the end. This technique has the effect of
1251 // putting them in reverse order, but that doesn't matter, since
1252 // these arguments are only whole strings.
1254 ACE_CString
*temp
= argv
[i
];
1255 for (int j
= i
; j
<= argc
-1; ++j
)
1256 argv
[j
] = argv
[j
+1];
1262 TAO_END_VERSIONED_NAMESPACE_DECL
1264 #endif /* TAO_HAS_IIOP && TAO_HAS_IIOP != 0 */