1 #include "tao/Strategies/DIOP_Acceptor.h"
3 #if defined (TAO_HAS_DIOP) && (TAO_HAS_DIOP != 0)
5 #include "tao/Strategies/DIOP_Profile.h"
6 #include "tao/MProfile.h"
7 #include "tao/ORB_Core.h"
9 #include "tao/Protocols_Hooks.h"
10 #include "tao/Codeset_Manager.h"
13 #include "ace/OS_NS_string.h"
15 #if !defined(__ACE_INLINE__)
16 #include "tao/Strategies/DIOP_Acceptor.inl"
17 #endif /* __ACE_INLINE__ */
19 #include "ace/os_include/os_netdb.h"
23 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
25 TAO_DIOP_Acceptor::TAO_DIOP_Acceptor ()
26 : TAO_Acceptor (TAO_TAG_DIOP_PROFILE
),
31 version_ (TAO_DEF_GIOP_MAJOR
, TAO_DEF_GIOP_MINOR
),
33 #if defined (ACE_HAS_IPV6)
34 default_address_ (static_cast<unsigned short> (0), ACE_IPV6_ANY
, AF_INET6
),
36 default_address_ (static_cast<unsigned short> (0), static_cast<ACE_UINT32
> (INADDR_ANY
)),
37 #endif /* ACE_HAS_IPV6 */
38 connection_handler_ (0)
42 TAO_DIOP_Acceptor::~TAO_DIOP_Acceptor ()
44 // Make sure we are closed before we start destroying the
48 delete [] this->addrs_
;
50 for (CORBA::ULong i
= 0; i
< this->endpoint_count_
; ++i
)
51 CORBA::string_free (this->hosts_
[i
]);
53 delete [] this->hosts_
;
57 // 2) For V1.[1,2] there are tagged components
60 TAO_DIOP_Acceptor::create_profile (const TAO::ObjectKey
& object_key
,
61 TAO_MProfile
&mprofile
,
62 CORBA::Short priority
)
65 if (this->endpoint_count_
== 0)
68 // Check if multiple endpoints should be put in one profile or if
69 // they should be spread across multiple profiles.
70 if (priority
== TAO_INVALID_PRIORITY
&&
71 this->orb_core_
->orb_params ()->shared_profile () == 0)
72 return this->create_new_profile (object_key
, mprofile
, priority
);
74 return this->create_shared_profile (object_key
, mprofile
, priority
);
78 TAO_DIOP_Acceptor::create_new_profile (const TAO::ObjectKey
&object_key
,
79 TAO_MProfile
&mprofile
,
80 CORBA::Short priority
)
82 // Adding this->endpoint_count_ to the TAO_MProfile.
83 int count
= mprofile
.profile_count ();
84 if ((mprofile
.size () - count
) < this->endpoint_count_
85 && mprofile
.grow (count
+ this->endpoint_count_
) == -1)
88 // Create a profile for each acceptor endpoint.
89 for (CORBA::ULong i
= 0; i
< this->endpoint_count_
; ++i
)
91 // Skip if the host name
93 && (this->addrs_
[i
].get_port_number () == this->addrs_
[0].get_port_number ())
94 && ACE_OS::strcmp (this->hosts_
[i
], this->hosts_
[0]) == 0)
97 TAO_DIOP_Profile
*pfile
= 0;
98 ACE_NEW_RETURN (pfile
,
99 TAO_DIOP_Profile (this->hosts_
[i
],
100 this->addrs_
[i
].get_port_number (),
106 pfile
->endpoint ()->priority (priority
);
108 if (mprofile
.give_profile (pfile
) == -1)
110 pfile
->_decr_refcnt ();
115 // Do not add any tagged components to the profile if configured
116 // by the user not to do so, or if an IIOP 1.0 endpoint is being
117 // created (IIOP 1.0 did not support tagged components).
118 if (this->orb_core_
->orb_params ()->std_profile_components () == 0
119 || (this->version_
.major
== 1 && this->version_
.minor
== 0))
122 pfile
->tagged_components ().set_orb_type (TAO_ORB_TYPE
);
124 TAO_Codeset_Manager
*csm
= this->orb_core_
->codeset_manager ();
126 csm
->set_codeset (pfile
->tagged_components ());
133 TAO_DIOP_Acceptor::create_shared_profile (const TAO::ObjectKey
&object_key
,
134 TAO_MProfile
&mprofile
,
135 CORBA::Short priority
)
137 CORBA::ULong index
= 0;
138 TAO_DIOP_Profile
*diop_profile
= 0;
140 // First see if <mprofile> already contains a DIOP profile.
141 for (TAO_PHandle i
= 0; i
!= mprofile
.profile_count (); ++i
)
143 TAO_Profile
*pfile
= mprofile
.get_profile (i
);
144 if (pfile
->tag () == TAO_TAG_DIOP_PROFILE
)
146 diop_profile
= dynamic_cast<TAO_DIOP_Profile
*> (pfile
);
151 // If <mprofile> doesn't contain a DIOP_Profile, we need to create
153 if (diop_profile
== 0)
155 ACE_NEW_RETURN (diop_profile
,
156 TAO_DIOP_Profile (this->hosts_
[0],
157 this->addrs_
[0].get_port_number (),
163 diop_profile
->endpoint ()->priority (priority
);
165 if (mprofile
.give_profile (diop_profile
) == -1)
167 diop_profile
->_decr_refcnt ();
172 if (this->orb_core_
->orb_params ()->std_profile_components () != 0
173 && (this->version_
.major
>= 1 && this->version_
.minor
>= 1))
175 diop_profile
->tagged_components ().set_orb_type (TAO_ORB_TYPE
);
176 TAO_Codeset_Manager
*csm
= this->orb_core_
->codeset_manager ();
178 csm
->set_codeset (diop_profile
->tagged_components ());
184 // Add any remaining acceptor endpoints to the DIOP_Profile.
186 index
< this->endpoint_count_
;
190 this->addrs_
[index
].get_port_number () == this->addrs_
[0].get_port_number () &&
191 ACE_OS::strcmp (this->hosts_
[index
], this->hosts_
[0]) == 0)
194 TAO_DIOP_Endpoint
*endpoint
= 0;
195 ACE_NEW_RETURN (endpoint
,
196 TAO_DIOP_Endpoint (this->hosts_
[index
],
197 this->addrs_
[index
].get_port_number (),
198 this->addrs_
[index
]),
200 endpoint
->priority (priority
);
201 diop_profile
->add_endpoint (endpoint
);
208 TAO_DIOP_Acceptor::is_collocated (const TAO_Endpoint
*endpoint
)
210 const TAO_DIOP_Endpoint
*endp
=
211 dynamic_cast<const TAO_DIOP_Endpoint
*> (endpoint
);
213 // Make sure the dynamically cast pointer is valid.
217 for (CORBA::ULong i
= 0; i
< this->endpoint_count_
; ++i
)
219 // compare the port and host name. Please do *NOT* optimize
220 // this code by comparing the IP address instead. That would
221 // trigger the following bug:
223 // http://bugzilla.dre.vanderbilt.edu/show_bug.cgi?id=1220
225 if (endp
->port () == this->addrs_
[i
].get_port_number ()
226 && ACE_OS::strcmp (endp
->host (), this->hosts_
[i
]) == 0)
227 return 1; // Collocated
230 return 0; // Not collocated
234 TAO_DIOP_Acceptor::close ()
240 TAO_DIOP_Acceptor::open (TAO_ORB_Core
*orb_core
,
241 ACE_Reactor
*reactor
,
247 this->orb_core_
= orb_core
;
249 if (this->hosts_
!= 0)
251 // The hostname cache has already been set!
252 // This is bad mojo, i.e. an internal TAO error.
253 TAOLIB_ERROR_RETURN ((LM_ERROR
,
254 ACE_TEXT ("TAO (%P|%t) - ")
255 ACE_TEXT ("DIOP_Acceptor::open, ")
256 ACE_TEXT ("hostname already set\n\n")),
263 if (major
>=0 && minor
>= 0)
264 this->version_
.set_version (static_cast<CORBA::Octet
> (major
),
265 static_cast<CORBA::Octet
> (minor
));
267 if (this->parse_options (options
) == -1)
270 ACE_CString specified_hostname
;
272 int def_type
= AF_UNSPEC
;
274 if (this->parse_address (address
,
280 if (specified_hostname
.length () == 0)
282 // The address is a port number or port name. No hostname was
283 // specified. The hostname for each network interface and the
284 // fully qualified domain name must be obtained.
286 // Check for multiple network interfaces.
287 if (this->probe_interfaces (orb_core
, def_type
) == -1)
290 // Probe interfaces has a side effect of potentially modifying
291 // the default address, since that is where the address family
293 addr
.set (this->default_address_
);
295 return this->open_i (addr
,
299 #if defined (ACE_HAS_IPV6)
300 // Check for violation of ORBConnectIPV6Only option
301 if (this->orb_core_
->orb_params ()->connect_ipv6_only () &&
302 (addr
.get_type () != AF_INET6
||
303 addr
.is_ipv4_mapped_ipv6 ()))
305 TAOLIB_ERROR_RETURN ((LM_ERROR
,
306 ACE_TEXT ("TAO (%P|%t) - ")
307 ACE_TEXT ("DIOP_Acceptor::open, ")
308 ACE_TEXT ("non-IPv6 endpoints not allowed when ")
309 ACE_TEXT ("connect_ipv6_only is set\n\n")),
312 #endif /* ACE_HAS_IPV6 */
314 if (TAO_debug_level
> 2)
316 TAOLIB_DEBUG ((LM_DEBUG
,
317 ACE_TEXT ("TAO (%P|%t) - ")
318 ACE_TEXT ("DIOP_Acceptor::open, specified host=%C:%d\n"),
319 (specified_hostname
.length () == 0 ? "<null>" : specified_hostname
.c_str ()),
320 addr
.get_port_number ()));
323 this->endpoint_count_
= 1; // Only one hostname to store
325 ACE_NEW_RETURN (this->addrs_
,
326 ACE_INET_Addr
[this->endpoint_count_
],
329 ACE_NEW_RETURN (this->hosts_
,
330 char *[this->endpoint_count_
],
335 if (this->hostname (orb_core
,
338 specified_hostname
.c_str ()) != 0)
341 // Copy the addr. The port is (re)set in
342 // TAO_DIOP_Acceptor::open_i().
343 if (this->addrs_
[0].set (addr
) != 0)
346 return this->open_i (addr
,
351 TAO_DIOP_Acceptor::open_default (TAO_ORB_Core
*orb_core
,
352 ACE_Reactor
*reactor
,
357 this->orb_core_
= orb_core
;
359 if (this->hosts_
!= 0)
361 // The hostname cache has already been set!
362 // This is bad mojo, i.e. an internal TAO error.
363 TAOLIB_ERROR_RETURN ((LM_ERROR
,
364 ACE_TEXT ("TAO (%P|%t) - ")
365 ACE_TEXT ("DIOP_Acceptor::open_default, ")
366 ACE_TEXT ("hostname already set\n\n")),
370 if (major
>= 0 && minor
>= 0)
371 this->version_
.set_version (static_cast<CORBA::Octet
> (major
),
372 static_cast<CORBA::Octet
> (minor
));
375 if (this->parse_options (options
) == -1)
378 // Check for multiple network interfaces.
379 if (this->probe_interfaces (orb_core
) == -1)
382 // Now that each network interface's hostname has been cached, open
383 // an endpoint on each network interface using the INADDR_ANY
387 if (addr
.set (this->default_address_
) != 0)
390 return this->open_i (addr
, reactor
);
394 TAO_DIOP_Acceptor::open_i (const ACE_INET_Addr
& addr
,
395 ACE_Reactor
*reactor
)
397 unsigned short const requested_port
= addr
.get_port_number ();
398 ACE_UINT32
const last_port
= ACE_MIN (requested_port
+ this->port_span_
- 1,
399 ACE_MAX_DEFAULT_PORT
);
401 ACE_INET_Addr
a(addr
);
402 bool found_a_port
= false;
403 for (ACE_UINT32 p
= requested_port
; p
<= last_port
; p
++)
405 ACE_NEW_RETURN (this->connection_handler_
,
406 TAO_DIOP_Connection_Handler (this->orb_core_
),
409 if (TAO_debug_level
> 5)
410 TAOLIB_DEBUG ((LM_DEBUG
,
411 ACE_TEXT ("TAO (%P|%t) - DIOP_Acceptor::open_i, ")
412 ACE_TEXT ("trying to listen on port %d\n"), p
));
413 // Now try to actually open on that port
414 a
.set_port_number ((u_short
)p
);
415 this->connection_handler_
->local_addr (a
);
416 int result
= this->connection_handler_
->open_server ();
419 delete this->connection_handler_
;
423 // Register only with a valid handle
425 reactor
->register_handler (this->connection_handler_
,
426 ACE_Event_Handler::READ_MASK
);
429 // Close the handler (this will also delete connection_handler_).
430 this->connection_handler_
->close ();
440 if (TAO_debug_level
> 0)
441 TAOLIB_DEBUG ((LM_DEBUG
,
442 ACE_TEXT ("TAO (%P|%t) - DIOP_Acceptor::open_i, ")
443 ACE_TEXT ("cannot open acceptor in port range (%d,%d)")
445 requested_port
, last_port
, ACE_TEXT("")));
449 // Connection handler ownership now belongs to the Reactor.
450 this->connection_handler_
->remove_reference ();
452 ACE_INET_Addr address
;
454 // We do this make sure the port number the endpoint is listening on
455 // gets set in the addr.
456 if (this->connection_handler_
->peer ().get_local_addr (address
) != 0)
458 if (TAO_debug_level
> 0)
459 TAOLIB_ERROR ((LM_ERROR
,
460 ACE_TEXT ("TAO (%P|%t) DIOP_Acceptor::open_i, ")
462 ACE_TEXT ("cannot get local addr\n\n")));
466 // Set the port for each addr. If there is more than one network
467 // interface then the endpoint created on each interface will be on
468 // the same port. This is how a wildcard socket bind() is supposed
470 unsigned short port
= address
.get_port_number ();
471 for (CORBA::ULong j
= 0; j
< this->endpoint_count_
; ++j
)
472 this->addrs_
[j
].set_port_number (port
, 1);
474 this->default_address_
.set_port_number (port
);
476 if (TAO_debug_level
> 5)
478 for (CORBA::ULong i
= 0; i
< this->endpoint_count_
; ++i
)
480 TAOLIB_DEBUG ((LM_DEBUG
,
481 ACE_TEXT ("TAO (%P|%t) - DIOP_Acceptor::open_i, ")
482 ACE_TEXT ("listening on: <%C:%u>\n"),
484 this->addrs_
[i
].get_port_number ()));
492 TAO_DIOP_Acceptor::hostname (TAO_ORB_Core
*orb_core
,
495 const char *specified_hostname
)
497 if (orb_core
->orb_params ()->use_dotted_decimal_addresses ())
499 // If dotted decimal addresses are enabled,
501 return this->dotted_decimal_address (addr
, host
);
503 else if (specified_hostname
!= 0)
505 // If the user specified a hostname, pass it back
506 // blindly as it overrides our choice of hostname.
507 host
= CORBA::string_dup (specified_hostname
);
511 char tmp_host
[MAXHOSTNAMELEN
+ 1];
513 // Get the hostname associated with our address
514 #if defined (ACE_HAS_IPV6)
515 // If we have a IPv4-compatible IPv6 address don't do hostname lookup
516 // because that gets us into trouble. Most likely we get the same hostname
517 // returned as for the actual IPv4 address but resolving that into an IPv6
518 // address at the client will fail.
519 if (addr
.is_ipv4_compat_ipv6 () ||
520 addr
.get_host_name (tmp_host
, sizeof (tmp_host
)) != 0)
521 #else /* ACE_HAS_IPV6 */
522 if (addr
.get_host_name (tmp_host
, sizeof (tmp_host
)) != 0)
523 #endif /* !ACE_HAS_IPV6 */
525 // On failure, just return the decimal address.
526 return this->dotted_decimal_address (addr
, host
);
530 host
= CORBA::string_dup (tmp_host
);
538 TAO_DIOP_Acceptor::parse_address (const char *address
,
540 ACE_CString
&specified_hostname
,
546 specified_hostname
.clear();
549 const char *port_separator_loc
= std::strchr (address
, ':');
550 char tmp_host
[MAXHOSTNAMELEN
+ 1];
552 bool host_defaulted
= port_separator_loc
== address
;
553 bool ipv6_in_host
= false;
555 *def_type
= AF_UNSPEC
;
557 #if defined (ACE_HAS_IPV6)
558 // Check if this is a (possibly) IPv6 supporting profile containing a
559 // numeric IPv6 address representation.
560 if ((this->version_
.major
> TAO_MIN_IPV6_IIOP_MAJOR
||
561 this->version_
.minor
>= TAO_MIN_IPV6_IIOP_MINOR
) &&
564 // In this case we have to find the end of the numeric address and
565 // start looking for the port separator from there.
566 char const * const cp_pos
= std::strchr (address
, ']');
569 // No valid IPv6 address specified.
570 TAOLIB_ERROR_RETURN ((LM_ERROR
,
571 ACE_TEXT ("TAO (%P|%t) - ")
572 ACE_TEXT ("DIOP_Acceptor::open, ")
573 ACE_TEXT ("invalid IPv6 decimal address specified\n\n")),
578 // Extract out just the host part of the address.
579 size_t const len
= cp_pos
- (address
+ 1);
581 if (len
>= sizeof (tmp_host
))
585 host_defaulted
= (cp_pos
== address
+1) ||
586 (cp_pos
== address
+3 && address
[1] == ':' && address
[2] == ':');
587 if (cp_pos
[1] == ':') // Look for a port
588 port_separator_loc
= cp_pos
+ 1;
590 port_separator_loc
= 0;
592 *def_type
= AF_INET6
;
594 ACE_OS::memcpy (tmp_host
, address
+ 1, len
);
595 tmp_host
[len
] = '\0';
599 #endif /* ACE_HAS_IPV6 */
602 if (port_separator_loc
!= 0)
604 // Extract out just the host part of the address.
605 size_t const len
= port_separator_loc
- address
;
607 if (len
>= sizeof (tmp_host
))
610 ACE_OS::memcpy (tmp_host
, address
, len
);
611 tmp_host
[len
] = '\0';
614 ACE_OS::strcpy (tmp_host
, address
);
617 if (!ipv6_in_host
&& !host_defaulted
)
619 if (addr
.set ((unsigned short) 0, tmp_host
) != 0)
621 this->default_address_
.set (addr
);
622 host_defaulted
= addr
.is_any ();
629 // First convert the port into a usable form.
630 unsigned short portno
= 0;
631 if (port_separator_loc
!= 0)
634 static_cast<u_short
> (ACE_OS::atoi (port_separator_loc
+
637 this->default_address_
.set_port_number (portno
);
639 // Now reset the port and set the host.
640 if (addr
.set (this->default_address_
) != 0)
643 else if (port_separator_loc
== 0)
645 // The address is a hostname. No port was specified, so assume
646 // port zero (port will be chosen for us).
647 specified_hostname
= tmp_host
[0] == '\0' ? address
: tmp_host
;
648 if (addr
.set ((unsigned short) 0,
649 specified_hostname
.c_str ()) != 0)
654 // Host and port were specified.
655 if (addr
.set (address
) != 0)
657 if (tmp_host
[0] == '\0')
659 // Extract out just the host part of the address.
660 size_t const len
= port_separator_loc
- address
;
662 if (len
>= sizeof (tmp_host
))
665 ACE_OS::memcpy (tmp_host
, address
, len
);
666 tmp_host
[len
] = '\0';
668 specified_hostname
= tmp_host
;
675 TAO_DIOP_Acceptor::dotted_decimal_address (ACE_INET_Addr
&addr
,
681 // If the IP address in the INET_Addr is the IN(6)ADDR_ANY address,
682 // then force the actual IP address to be used by initializing a new
683 // INET_Addr with the hostname from the original one. If that fails
684 // then something is seriously wrong with the systems networking
688 ACE_INET_Addr new_addr
;
689 #if defined (ACE_HAS_IPV6)
690 result
= new_addr
.set (addr
.get_port_number (),
691 addr
.get_host_name (),
694 #else /* ACE_HAS_IPV6 */
695 result
= new_addr
.set (addr
.get_port_number (),
696 addr
.get_host_name ());
697 #endif /* !ACE_HAS_IPV6 */
698 tmp
= new_addr
.get_host_addr ();
701 tmp
= addr
.get_host_addr ();
703 if (tmp
== 0 || result
!= 0)
705 if (TAO_debug_level
> 0)
706 TAOLIB_DEBUG ((LM_DEBUG
,
707 ACE_TEXT ("TAO (%P|%t) - ")
708 ACE_TEXT ("DIOP_Acceptor::dotted_decimal_address, ")
710 ACE_TEXT ("cannot determine hostname")));
714 host
= CORBA::string_dup (tmp
);
719 TAO_DIOP_Acceptor::probe_interfaces (TAO_ORB_Core
*orb_core
, int def_type
)
721 // Extract the hostname for each network interface, and then cache
722 // it. The hostnames will then be used when creating a
723 // TAO_DIOP_Profile for each endpoint setup on the probed
724 // network interfaces.
725 ACE_INET_Addr
*if_addrs
= 0;
728 if (ACE::get_ip_interfaces (if_cnt
,
732 // In the case where errno == ENOTSUP, if_cnt and if_addrs will
733 // not be modified, and will each remain equal to zero. This
734 // causes the default interface to be used.
738 if (if_cnt
== 0 || if_addrs
== 0)
740 if (TAO_debug_level
> 0)
742 TAOLIB_DEBUG ((LM_WARNING
,
743 ACE_TEXT ("TAO (%P|%t) - Unable to probe network ")
744 ACE_TEXT ("interfaces. Using default.")));
747 if_cnt
= 1; // Force the network interface count to be one.
749 ACE_NEW_RETURN (if_addrs
,
750 ACE_INET_Addr
[if_cnt
],
754 // Scan for the loopback interface since it shouldn't be included in
755 // the list of cached hostnames unless it is the only interface.
756 size_t lo_cnt
= 0; // Loopback interface count
757 for (size_t j
= 0; j
< if_cnt
; ++j
)
758 if (if_addrs
[j
].is_loopback ())
761 #if defined (ACE_HAS_IPV6)
763 size_t ipv4_lo_cnt
= 0;
765 bool ipv6_non_ll
= false;
766 // Scan for IPv4 interfaces since these should not be included
767 // when IPv6-only is selected.
768 for (size_t j
= 0; j
< if_cnt
; ++j
)
769 if (if_addrs
[j
].get_type () != AF_INET6
||
770 if_addrs
[j
].is_ipv4_mapped_ipv6 ())
773 if (if_addrs
[j
].is_loopback ())
774 ++ipv4_lo_cnt
; // keep track of IPv4 loopback ifs
776 else if (!if_addrs
[j
].is_linklocal () &&
777 !if_addrs
[j
].is_loopback())
779 ipv6_non_ll
= true; // we have at least 1 non-local IPv6 if
781 else if (!orb_core
->orb_params ()->use_ipv6_link_local () &&
782 if_addrs
[j
].is_linklocal ())
784 ++ipv6_ll
; // count link local addrs to exclude them afterwards
786 #endif /* ACE_HAS_IPV6 */
788 // The instantiation for this template is in
789 // tao/DIOP_Connector.cpp.
790 std::unique_ptr
<ACE_INET_Addr
[]> safe_if_addrs (if_addrs
);
792 #if defined (ACE_HAS_IPV6)
793 bool ipv4_only
= def_type
== AF_INET
;
794 bool ipv6_only
= (def_type
== AF_INET6
) ||
795 orb_core
->orb_params ()->connect_ipv6_only ();
796 #if defined (ACE_WIN32)
797 if (this->default_address_
.get_type () == AF_INET
)
801 #endif /* ACE_WIN32 */
802 // If the loopback interface is the only interface then include it
803 // in the list of interfaces to query for a hostname, otherwise
804 // exclude it from the list.
807 // only exclude loopback if non-local if exists
808 ignore_lo
= ipv6_non_ll
;
810 ignore_lo
= ipv4_cnt
!= ipv4_lo_cnt
;
812 ignore_lo
= if_cnt
!= lo_cnt
;
814 // Adjust counts for IPv6 only if required
815 size_t if_ok_cnt
= if_cnt
;
818 if_ok_cnt
-= ipv4_cnt
;
819 lo_cnt
-= ipv4_lo_cnt
;
824 if_ok_cnt
= ipv4_cnt
;
825 lo_cnt
= ipv4_lo_cnt
;
828 // In case there are no non-local IPv6 ifs in the list only exclude
830 // IPv6 loopback will be needed to successfully connect IPv6 clients
831 // in a localhost environment.
832 if (!ipv4_only
&& !ipv6_non_ll
)
833 lo_cnt
= ipv4_lo_cnt
;
836 this->endpoint_count_
= static_cast<CORBA::ULong
> (if_ok_cnt
- ipv6_ll
);
838 this->endpoint_count_
= static_cast<CORBA::ULong
> (if_ok_cnt
- ipv6_ll
- lo_cnt
);
839 #else /* ACE_HAS_IPV6 */
840 // If the loopback interface is the only interface then include it
841 // in the list of interfaces to query for a hostname, otherwise
842 // exclude it from the list.
844 ignore_lo
= if_cnt
!= lo_cnt
;
846 this->endpoint_count_
= static_cast<CORBA::ULong
> (if_cnt
);
848 this->endpoint_count_
= static_cast<CORBA::ULong
> (if_cnt
- lo_cnt
);
849 #endif /* !ACE_HAS_IPV6 */
851 if (this->endpoint_count_
== 0)
853 if (TAO_debug_level
> 0)
854 TAOLIB_DEBUG ((LM_DEBUG
,
855 ACE_TEXT("(%P|%t) - DIOP_Acceptor::probe_interfaces, ")
856 ACE_TEXT("found no usable addresses, def_type = %d\n"),
861 ACE_NEW_RETURN (this->addrs_
,
862 ACE_INET_Addr
[this->endpoint_count_
],
865 ACE_NEW_RETURN (this->hosts_
,
866 char *[this->endpoint_count_
],
869 ACE_OS::memset (this->hosts_
, 0, sizeof (char*) * this->endpoint_count_
);
871 // The number of hosts/interfaces we want to cache may not be the
872 // same as the number of detected interfaces so keep a separate
876 for (size_t i
= 0; i
< if_cnt
; ++i
)
878 #if defined (ACE_HAS_IPV6)
879 // Ignore any loopback interface if there are other
880 // non-loopback interfaces.
882 if_addrs
[i
].is_loopback () &&
885 if_addrs
[i
].get_type () != AF_INET6
))
888 // Ignore any non-IPv4 interfaces when so required.
890 (if_addrs
[i
].get_type () != AF_INET
))
893 // Ignore any non-IPv6 interfaces when so required.
895 (if_addrs
[i
].get_type () != AF_INET6
||
896 if_addrs
[i
].is_ipv4_mapped_ipv6 ()))
899 // Ignore all IPv6 link local interfaces when so required.
900 if (!orb_core
->orb_params ()->use_ipv6_link_local () &&
901 if_addrs
[i
].is_linklocal ())
903 #else /* ACE_HAS_IPV6 */
904 // Ignore any loopback interface if there are other
905 // non-loopback interfaces.
907 if_addrs
[i
].is_loopback ())
909 #endif /* !ACE_HAS_IPV6 */
911 if (this->hostname (orb_core
,
913 this->hosts_
[host_cnt
]) != 0)
916 // Copy the addr. The port is (re)set in
917 // TAO_DIOP_Acceptor::open_i().
918 if (this->addrs_
[host_cnt
].set (if_addrs
[i
]) != 0)
928 TAO_DIOP_Acceptor::endpoint_count ()
930 return this->endpoint_count_
;
934 TAO_DIOP_Acceptor::object_key (IOP::TaggedProfile
&profile
,
935 TAO::ObjectKey
&object_key
)
937 // Create the decoding stream from the encapsulation in the buffer,
938 #if (TAO_NO_COPY_OCTET_SEQUENCES == 1)
939 TAO_InputCDR
cdr (profile
.profile_data
.mb ());
941 TAO_InputCDR
cdr (reinterpret_cast<char*> (profile
.profile_data
.get_buffer ()),
942 profile
.profile_data
.length ());
943 #endif /* TAO_NO_COPY_OCTET_SEQUENCES == 1 */
945 CORBA::Octet major
= 0;
946 CORBA::Octet minor
= 0;
948 // Read the version. We just read it here. We don't*do any*
950 if (!(cdr
.read_octet (major
)
951 && cdr
.read_octet (minor
)))
953 if (TAO_debug_level
> 0)
955 TAOLIB_DEBUG ((LM_DEBUG
,
956 ACE_TEXT ("TAO (%P|%t) - DIOP_Profile::object_key, v%d.%d\n"),
963 CORBA::String_var host
;
964 CORBA::UShort port
= 0;
966 // Get host and port. No processing here too..
967 if (cdr
.read_string (host
.out ()) == 0
968 || cdr
.read_ushort (port
) == 0)
970 if (TAO_debug_level
> 0)
972 TAOLIB_DEBUG ((LM_DEBUG
,
973 ACE_TEXT ("TAO (%P|%t) - DIOP_Acceptor::object_key, ")
974 ACE_TEXT ("error while decoding host/port")));
979 // ... and object key.
980 if ((cdr
>> object_key
) == 0)
983 // We are NOT bothered about the rest.
989 TAO_DIOP_Acceptor::parse_options (const char *str
)
992 return 0; // No options to parse. Not a problem.
994 // Use an option format similar to the one used for CGI scripts in
996 // e.g.: option1=foo&option2=bar
998 const ACE_CString
options (str
);
1000 const size_t len
= options
.length ();
1002 static const char option_delimiter
= '&';
1004 // Count the number of options.
1005 CORBA::ULong option_count
= 1;
1007 // Only check for endpoints after the protocol specification and
1008 // before the object key.
1009 for (size_t i
= 0; i
< len
; ++i
)
1010 if (options
[i
] == option_delimiter
)
1013 // The idea behind the following loop is to split the options into
1014 // (option, name) pairs.
1016 // `option1=foo&option2=bar'
1017 // will be parsed into:
1021 ACE_CString::size_type begin
= 0;
1022 ACE_CString::size_type end
= 0;
1024 for (CORBA::ULong j
= 0; j
< option_count
;)
1026 if (j
< option_count
- 1)
1027 end
= options
.find (option_delimiter
, begin
);
1031 ++j
; // In this way we fight MS VS warning about unreachable code.
1035 TAOLIB_ERROR_RETURN ((LM_ERROR
,
1036 ACE_TEXT ("TAO (%P|%t) - Zero length DIOP option.\n")),
1039 else if (end
!= ACE_CString::npos
)
1041 ACE_CString opt
= options
.substring (begin
, end
- begin
);
1043 ACE_CString::size_type
const slot
= opt
.find ("=");
1046 || slot
== ACE_CString::npos
)
1047 TAOLIB_ERROR_RETURN ((LM_ERROR
,
1048 ACE_TEXT ("TAO (%P|%t) - DIOP option <%C> is ")
1049 ACE_TEXT ("missing a value.\n"),
1053 ACE_CString name
= opt
.substring (0, slot
);
1054 ACE_CString value
= opt
.substring (slot
+ 1);
1058 if (name
.length () == 0)
1059 TAOLIB_ERROR_RETURN ((LM_ERROR
,
1060 ACE_TEXT ("TAO (%P|%t) - Zero length DIOP ")
1061 ACE_TEXT ("option name.\n")),
1064 if (name
== "priority")
1066 TAOLIB_ERROR_RETURN ((LM_ERROR
,
1067 ACE_TEXT ("TAO (%P|%t) - Invalid DIOP endpoint format: ")
1068 ACE_TEXT ("endpoint priorities no longer supported.\n")),
1071 else if (name
== "portspan")
1073 int const range
= ACE_OS::atoi (value
.c_str ());
1074 // @@ What's the lower bound on the range? zero, or one?
1075 if (range
< 1 || range
> ACE_MAX_DEFAULT_PORT
)
1076 TAOLIB_ERROR_RETURN ((LM_ERROR
,
1077 ACE_TEXT ("TAO (%P|%t) Invalid DIOP endpoint ")
1078 ACE_TEXT ("portspan: <%C>\n")
1079 ACE_TEXT ("Valid range 1 -- %d\n"),
1080 value
.c_str (), ACE_MAX_DEFAULT_PORT
),
1083 this->port_span_
= static_cast <u_short
> (range
);
1087 TAOLIB_ERROR_RETURN ((LM_ERROR
,
1088 ACE_TEXT ("TAO (%P|%t) - Invalid DIOP option: <%C>\n"),
1095 break; // No other options.
1101 TAO_END_VERSIONED_NAMESPACE_DECL
1103 #endif /* TAO_HAS_DIOP && TAO_HAS_DIOP != 0 */