1 #include "tao/Acceptor_Registry.h"
2 #include "tao/Profile.h"
3 #include "tao/Transport_Acceptor.h"
4 #include "tao/Protocol_Factory.h"
5 #include "tao/ORB_Core.h"
6 #include "tao/params.h"
7 #include "tao/MProfile.h"
9 #include "tao/Acceptor_Filter.h"
10 #include "tao/Endpoint.h"
11 #include "tao/ORB_Constants.h"
12 #include "tao/SystemException.h"
13 #if defined (ACE_WIN32) && defined (ACE_HAS_IPV6)
14 # include "tao/IIOP_Acceptor.h"
15 #endif /* ACE_WIN32 && ACE_HAS_IPV6 */
18 #include "ace/OS_NS_string.h"
19 #include "ace/OS_NS_ctype.h"
22 #if !defined(__ACE_INLINE__)
23 #include "tao/Acceptor_Registry.inl"
24 #endif /* __ACE_INLINE__ */
26 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
28 TAO_Acceptor_Registry::~TAO_Acceptor_Registry ()
32 delete [] this->acceptors_
;
36 TAO_Acceptor_Registry::endpoint_count ()
39 const TAO_AcceptorSetIterator end
= this->end ();
41 for (TAO_AcceptorSetIterator i
= this->begin (); i
!= end
; ++i
)
43 count
+= (*i
)->endpoint_count ();
50 TAO_Acceptor_Registry::is_collocated (const TAO_MProfile
&mprofile
)
52 TAO_AcceptorSetIterator
const end
= this->end ();
53 CORBA::ULong
const count
= mprofile
.profile_count ();
55 // If at least one endpoint in one of the profiles matches one of
56 // the acceptors, we are collocated.
57 for (TAO_AcceptorSetIterator i
= this->begin (); i
!= end
; ++i
)
59 for (TAO_PHandle j
= 0; j
!= count
; ++j
)
61 const TAO_Profile
*profile
= mprofile
.get_profile (j
);
63 // @@ We need to invoke a nonconst <endpoint> method on
64 // <profile>. The content of profile/endpoint will not
66 TAO_Profile
*pf
= const_cast<TAO_Profile
*> (profile
);
68 // Check all endpoints for address equality.
69 if ((*i
)->tag () == pf
->tag ())
71 // @note This can be a potentially expensive (O(n^2))
72 // operation if the below is_collocated() call
73 // also executes a loop.
74 for (TAO_Endpoint
*endp
= pf
->endpoint ();
78 if ((*i
)->is_collocated (endp
))
91 TAO_Acceptor_Registry::get_acceptor (CORBA::ULong tag
)
93 TAO_AcceptorSetIterator
const end
= this->end ();
94 TAO_AcceptorSetIterator acceptor
= this->begin ();
96 for (; acceptor
!= end
; ++acceptor
)
98 if ((*acceptor
)->tag () == tag
)
108 TAO_Acceptor_Registry::open (TAO_ORB_Core
*orb_core
,
109 ACE_Reactor
*reactor
,
110 const TAO_EndpointSet
&endpoint_set
,
113 if (endpoint_set
.is_empty ()
114 // No endpoints were specified, we let each protocol pick its
117 // All TAO pluggable protocols are expected to have the ability
118 // to create a default endpoint.
119 && this->open_default (orb_core
, reactor
, nullptr) == -1)
121 throw ::CORBA::INTERNAL (
122 CORBA::SystemException::_tao_minor_code (
123 TAO_ACCEPTOR_REGISTRY_OPEN_LOCATION_CODE
,
125 CORBA::COMPLETED_NO
);
128 // Count the maximum number of endpoints in the set. This will be
129 // the maximum number of acceptors that need to be created.
130 size_t acceptor_count
= 0;
131 TAO_EndpointSetIterator
endpts (endpoint_set
);
133 for (ACE_CString
*ep
= nullptr;
134 endpts
.next (ep
) != 0;
137 const ACE_CString
&iop
= (*ep
);
139 // IOP://address1,address2
141 ACE_CString::size_type
const slot
= iop
.find ("://", 0);
143 if (slot
== iop
.npos
)
145 if (TAO_debug_level
> 0)
147 TAOLIB_ERROR ((LM_ERROR
,
148 ACE_TEXT ("(%P|%t) Invalid endpoint ")
149 ACE_TEXT ("specification: <%C>.\n"),
153 throw ::CORBA::BAD_PARAM (
154 CORBA::SystemException::_tao_minor_code (
155 TAO_ACCEPTOR_REGISTRY_OPEN_LOCATION_CODE
,
157 CORBA::COMPLETED_NO
);
160 ++acceptor_count
; // We've got at least one acceptor so far.
161 #if defined (ACE_WIN32) && defined (ACE_HAS_IPV6)
162 // Since Win32 has single-stack IPv4/IPv6 we need an additional
163 // acceptor if an iiop protocol without endpoints is specified
164 // to open explicitly on IPv6 ANY *and* IPv4 ANY.
166 // Now get the list of available protocol factories.
167 const TAO_ProtocolFactorySetItor end
=
168 orb_core
->protocol_factories ()->end ();
170 // extract the protocol prefix
171 const ACE_CString
prefix (iop
.substring (0, slot
));
173 for (TAO_ProtocolFactorySetItor factory
=
174 orb_core
->protocol_factories ()->begin ();
178 if ((*factory
)->factory ()->match_prefix (prefix
))
180 if ((*factory
)->factory ()->tag () == IOP::TAG_INTERNET_IOP
)
182 // just add additional space to cover for possibility
185 break; // we found the protocol, no need to go on
188 #endif /* ACE_WIN32 && ACE_HAS_IPV6 */
190 // Now count the number of commas. That number will be the
191 // remaining number of endpoints in the current endpoint
194 ep
->c_str () + std::strlen (ep
->c_str ());
196 for (const char *e
= std::strchr (ep
->c_str (), ',');
197 e
!= nullptr && e
!= ep_end
;
198 e
= std::strchr (e
, ','))
205 // The array containing the TAO_Acceptors will never contain more
206 // than the number of endpoints stored in TAO_ORB_Parameters.
207 if (this->acceptors_
== nullptr)
209 ACE_NEW_THROW_EX (this->acceptors_
,
210 TAO_Acceptor
*[acceptor_count
],
212 CORBA::SystemException::_tao_minor_code (
213 TAO_ACCEPTOR_REGISTRY_OPEN_LOCATION_CODE
,
215 CORBA::COMPLETED_NO
));
218 TAO_EndpointSetIterator
endpoints (endpoint_set
);
220 for (ACE_CString
*endpoint
= nullptr;
221 endpoints
.next (endpoint
) != 0;
222 endpoints
.advance ())
224 const ACE_CString
&iop
= (*endpoint
);
226 // IOP://address1,address2
228 ACE_CString::size_type
const slot
= iop
.find ("://", 0);
230 if (slot
== iop
.npos
)
232 if (TAO_debug_level
> 0)
234 TAOLIB_ERROR ((LM_ERROR
,
235 ACE_TEXT ("(%P|%t) Invalid endpoint ")
236 ACE_TEXT ("specification: <%C>.\n"),
240 throw ::CORBA::BAD_PARAM (
241 CORBA::SystemException::_tao_minor_code (
242 TAO_ACCEPTOR_REGISTRY_OPEN_LOCATION_CODE
,
244 CORBA::COMPLETED_NO
);
247 const ACE_CString
prefix (iop
.substring (0, slot
));
249 // @@ We could move the protocol factory loop to the outermost
250 // level but for now we leave it inside the endpoint loop
251 // under the assumption that there will be more endpoints
254 // Now get the list of available protocol factories.
255 const TAO_ProtocolFactorySetItor end
=
256 orb_core
->protocol_factories ()->end ();
259 // If usable protocol (factory) is found then this will be
260 // set equal to true.
262 for (TAO_ProtocolFactorySetItor factory
=
263 orb_core
->protocol_factories ()->begin ();
267 if ((*factory
)->factory ()->match_prefix (prefix
))
269 // increment slot past the "://" (i.e. add 3)
270 ACE_CString addrs
= iop
.substring (slot
+ 3);
272 int const result
= this->open_i (orb_core
,
283 found
= true; // A usable protocol was found.
293 TAOLIB_ERROR ((LM_ERROR
,
294 ACE_TEXT ("TAO (%P|%t) ")
295 ACE_TEXT ("no usable transport protocol ")
296 ACE_TEXT ("was found.\n")));
298 throw ::CORBA::BAD_PARAM (
299 CORBA::SystemException::_tao_minor_code (
300 TAO_ACCEPTOR_REGISTRY_OPEN_LOCATION_CODE
,
302 CORBA::COMPLETED_NO
);
309 // Iterate through the loaded transport protocols and create a default
310 // server for each protocol.
311 int TAO_Acceptor_Registry::open_default (TAO_ORB_Core
*orb_core
,
312 ACE_Reactor
*reactor
,
315 // Flag that indicates at least one endpoint was opened. If one
316 // wasn't opened then there is a problem.
317 bool opened_endpoint
= false;
319 #if defined (ACE_WIN32) && defined (ACE_HAS_IPV6)
321 vinfo
.dwOSVersionInfoSize
= sizeof (vinfo
);
322 int vres
= GetVersionEx (&vinfo
);
323 if ((vres
== 0 || vinfo
.dwMajorVersion
< 6) &&
324 !orb_core
->orb_params ()->connect_ipv6_only () && this->acceptors_
== 0)
326 // Since Win32 has single-stack IPv4/IPv6 we need an additional
327 // acceptor to open explicitly on IPv6 ANY *and* IPv4 ANY.
328 // This code takes care of that.
330 TAO_ProtocolFactorySet
*pfs
= orb_core
->protocol_factories ();
332 // Number of acceptors to set up
333 size_t acceptor_count
= 0;
335 const TAO_ProtocolFactorySetItor end
= pfs
->end ();
337 // Loop through all the loaded protocols...
338 for (TAO_ProtocolFactorySetItor i
= pfs
->begin (); i
!= end
; ++i
)
340 if (!(*i
)->factory ()->requires_explicit_endpoint ())
342 if ((*i
)->factory ()->tag () == IOP::TAG_INTERNET_IOP
)
343 acceptor_count
+= 2; // IPv4 AND IPv6 endpoints
349 // Allocate TAO_Acceptor array
350 ACE_NEW_RETURN (this->acceptors_
,
351 TAO_Acceptor
*[acceptor_count
],
354 // Loop through all the loaded protocols...
355 for (TAO_ProtocolFactorySetItor i
= pfs
->begin (); i
!= end
; ++i
)
357 // If the protocol requires an explicit -ORBEndpoint option then
358 // don't use it, otherwise open a default endpoint for that
359 // protocol, this solves the problem with persistent endpoints
360 // (such as UNIX domain rendesvouz points) that are not cleaned
361 // up if the server crashes.
362 if (!(*i
)->factory ()->requires_explicit_endpoint ())
365 TAO_Acceptor
*acceptor
=
366 (*i
)->factory ()->make_acceptor ();
370 if (TAO_debug_level
> 0)
374 ACE_TEXT ("TAO (%P|%t) unable to create ")
375 ACE_TEXT ("an acceptor for <%C>\n"),
376 (*i
)->protocol_name ().c_str ()
383 if ((*i
)->factory ()->tag () == IOP::TAG_INTERNET_IOP
)
385 // Open first acceptor on IPv4 ANY
386 ACE_INET_Addr
addr(static_cast<unsigned short> (0));
388 TAO_IIOP_Acceptor
* iiop_acceptor
=
389 dynamic_cast<TAO_IIOP_Acceptor
*> (acceptor
);
394 iiop_acceptor
->set_default_address (addr
);
396 if (this->open_default_i (orb_core
,
407 // record the port chosen for the IPv4 acceptor
409 iiop_acceptor
->default_address ().get_port_number ();
411 // Create second acceptor for IPV6 traffic
413 (*i
)->factory ()->make_acceptor ();
417 if (TAO_debug_level
> 0)
421 ACE_TEXT ("TAO (%P|%t) unable to create ")
422 ACE_TEXT ("an acceptor for <%C>\n"),
423 (*i
)->protocol_name ().c_str ()
430 if (ACE::ipv6_enabled() &&
431 addr
.set (port
, ACE_IPV6_ANY
, 1, AF_INET6
) == 0)
434 dynamic_cast<TAO_IIOP_Acceptor
*> (acceptor
);
439 iiop_acceptor
->set_default_address (addr
);
441 if (this->open_default_i (orb_core
,
455 if (this->open_default_i (orb_core
,
467 opened_endpoint
= true;
473 #endif /* ACE_WIN32 && ACE_HAS_IPV6 */
474 TAO_ProtocolFactorySet
*pfs
= orb_core
->protocol_factories ();
476 // If the TAO_Acceptor array is zero by the time we get here then no
477 // endpoints were specified by the user, meaning that the number of
478 // acceptors will never be more than the number of loaded protocols
480 if (this->acceptors_
== nullptr)
482 ACE_NEW_RETURN (this->acceptors_
,
483 TAO_Acceptor
*[pfs
->size ()],
487 const TAO_ProtocolFactorySetItor end
= pfs
->end ();
489 // Loop through all the loaded protocols...
490 for (TAO_ProtocolFactorySetItor i
= pfs
->begin (); i
!= end
; ++i
)
492 // If the protocol requires an explicit -ORBEndpoint option then
493 // don't use it, otherwise open a default endpoint for that
494 // protocol, this solves the problem with persistent endpoints
495 // (such as UNIX domain rendesvouz points) that are not cleaned
496 // up if the server crashes.
497 if (!(*i
)->factory ()->requires_explicit_endpoint ())
499 if (this->open_default (orb_core
,
501 TAO_DEF_GIOP_MAJOR
, // default major
502 TAO_DEF_GIOP_MINOR
, // default minor
509 opened_endpoint
= true;
512 #if defined (ACE_WIN32) && defined (ACE_HAS_IPV6)
514 #endif /* ACE_WIN32) && ACE_HAS_IPV6 */
516 if (!opened_endpoint
)
518 if (TAO_debug_level
> 0)
520 TAOLIB_ERROR ((LM_ERROR
,
521 ACE_TEXT ("TAO (%P|%t) No default endpoints ")
522 ACE_TEXT ("opened.\n")
523 ACE_TEXT ("Please specify one or more using ")
524 ACE_TEXT ("the \"-ORBListenEndpoints\" ")
525 ACE_TEXT ("option.\n")));
534 // Used when no endpoints were specified. Open a default server for
535 // the indicated protocol.
537 TAO_Acceptor_Registry::open_default (TAO_ORB_Core
*orb_core
,
538 ACE_Reactor
*reactor
,
541 TAO_ProtocolFactorySetItor
&factory
,
544 // No endpoints were specified, we let each protocol pick its own
548 TAO_Acceptor
*acceptor
= (*factory
)->factory ()->make_acceptor ();
550 if (acceptor
== nullptr)
552 if (TAO_debug_level
> 0)
556 ACE_TEXT ("TAO (%P|%t) unable to create ")
557 ACE_TEXT ("an acceptor for <%C>\n"),
558 (*factory
)->protocol_name ().c_str ()
565 return this->open_default_i (orb_core
,
574 // Open a default server.
576 TAO_Acceptor_Registry::open_default_i (TAO_ORB_Core
*orb_core
,
577 ACE_Reactor
*reactor
,
580 TAO_ProtocolFactorySetItor
&factory
,
581 TAO_Acceptor
* acceptor
,
584 // Initialize the acceptor to listen on a default endpoint.
585 if (acceptor
->open_default (orb_core
, reactor
, major
, minor
, options
) == -1)
589 if (TAO_debug_level
> 0)
593 ACE_TEXT ("TAO (%P|%t) - Unable to open ")
594 ACE_TEXT ("default acceptor for <%C>%p\n"),
595 (*factory
)->protocol_name ().c_str (),
603 this->acceptors_
[this->size_
++] = acceptor
;
609 TAO_Acceptor_Registry::close_all ()
611 const TAO_AcceptorSetIterator end
= this->end ();
613 for (TAO_AcceptorSetIterator i
= this->begin (); i
!= end
; ++i
)
627 TAO_Acceptor_Registry::extract_endpoint_options (ACE_CString
&addrs
,
628 ACE_CString
&options
,
629 TAO_Protocol_Factory
*factory
)
631 ACE_CString::size_type
const options_index
=
632 addrs
.find (factory
->options_delimiter ());
634 if (options_index
== addrs
.length () - 1)
636 // Get rid of trailing option delimiter.
637 addrs
= addrs
.substring (0, addrs
.length () - 1);
639 else if (options_index
!= ACE_CString::npos
)
641 options
= addrs
.substring (options_index
+ 1);
642 addrs
= addrs
.substring (0, options_index
);
647 TAO_Acceptor_Registry::extract_endpoint_version (ACE_CString
&address
,
651 // Check if an "N.n@" version prefix was
653 major
= TAO_DEF_GIOP_MAJOR
;
654 minor
= TAO_DEF_GIOP_MINOR
;
656 if (ACE_OS::ace_isdigit (address
[0])
658 && ACE_OS::ace_isdigit (address
[2])
659 && address
[3] == '@')
661 major
= address
[0] - '0';
662 minor
= address
[2] - '0';
663 address
= address
.substring (4);
668 TAO_Acceptor_Registry::open_i (TAO_ORB_Core
*orb_core
,
669 ACE_Reactor
*reactor
,
671 TAO_ProtocolFactorySetItor
&factory
,
674 ACE_CString options_tmp
;
675 this->extract_endpoint_options (addrs
, options_tmp
, (*factory
)->factory ());
677 const char *options
= nullptr;
679 if (options_tmp
.length () > 0)
681 options
= options_tmp
.c_str ();
684 char *last_addr
= nullptr;
685 std::unique_ptr
<char[]> addr_str (addrs
.rep ());
687 const char *astr
= ACE_OS::strtok_r (addr_str
.get (), ",", &last_addr
);
689 // Iterate over the addrs specified in the endpoint.
693 // For the first time only through the loop, it is
694 // possible for astr to be 0. This indicates that
695 // the user is requesting the default endpoint for
696 // the specified protocol.
697 ACE_CString
address (astr
== nullptr ? "" : astr
);
699 TAO_Acceptor
*acceptor
= (*factory
)->factory ()->make_acceptor ();
701 if (acceptor
!= nullptr)
703 // Extract the desired endpoint/protocol version if one
705 int major
= TAO_DEF_GIOP_MAJOR
;
706 int minor
= TAO_DEF_GIOP_MINOR
;
707 this->extract_endpoint_version (address
, major
, minor
);
709 // Check for existence of endpoint.
710 if (ignore_address
|| address
.length () == 0)
712 // Protocol prefix was specified without any endpoints.
713 // All TAO pluggable protocols are expected to have the
714 // ability to create a default endpoint.
715 #if defined (ACE_WIN32) && defined (ACE_HAS_IPV6)
716 if ((*factory
)->factory ()->tag () == IOP::TAG_INTERNET_IOP
)
718 // Open first acceptor on IPv4 ANY
719 ACE_INET_Addr
addr(static_cast<unsigned short> (0)); // IPv4 ANY
721 TAO_IIOP_Acceptor
* iiop_acceptor
= dynamic_cast<TAO_IIOP_Acceptor
*> (acceptor
);
726 iiop_acceptor
->set_default_address (addr
);
728 if (this->open_default_i (orb_core
,
736 // record the port chosen for the IPv4 acceptor
737 u_short port
= iiop_acceptor
->default_address ().get_port_number ();
739 // Create second acceptor for IPV6 traffic
741 (*factory
)->factory ()->make_acceptor ();
745 if (TAO_debug_level
> 0)
749 ACE_TEXT ("TAO (%P|%t) unable to create ")
750 ACE_TEXT ("an acceptor for <%C>\n"),
751 (*factory
)->protocol_name ().c_str ()
755 throw ::CORBA::NO_MEMORY (
756 CORBA::SystemException::_tao_minor_code (
757 TAO_ACCEPTOR_REGISTRY_OPEN_LOCATION_CODE
,
759 CORBA::COMPLETED_NO
);
762 addr
.set (port
, ACE_IPV6_ANY
, AF_INET6
); // IPv6 ANY on specified port
764 iiop_acceptor
= dynamic_cast<TAO_IIOP_Acceptor
*> (acceptor
);
768 iiop_acceptor
->set_default_address (addr
);
770 if (this->open_default_i (orb_core
,
785 if (this->open_default_i (orb_core
,
797 // Could not open a default endpoint, nor an explicit
799 throw ::CORBA::INTERNAL (
800 CORBA::SystemException::_tao_minor_code (
801 TAO_ACCEPTOR_REGISTRY_OPEN_LOCATION_CODE
,
803 CORBA::COMPLETED_NO
);
804 #else /* ACE_WIN32 && ACE_HAS_IPV6 */
805 if (this->open_default_i (orb_core
,
814 // Could not open a default endpoint, nor an explicit
818 throw ::CORBA::INTERNAL (
819 CORBA::SystemException::_tao_minor_code (
820 TAO_ACCEPTOR_REGISTRY_OPEN_LOCATION_CODE
,
822 CORBA::COMPLETED_NO
);
824 #endif /* !ACE_WIN32 || !ACE_HAS_IPV6 */
826 // An explicit endpoint was provided.
827 else if (acceptor
->open (orb_core
,
834 /* Need to save the errno value from the acceptor->open(),
835 * because errno will get reset when we delete acceptor */
836 int const errno_value
= errno
;
839 if (TAO_debug_level
> 0)
841 TAOLIB_ERROR ((LM_ERROR
,
842 ACE_TEXT ("TAO (%P|%t) - ")
843 ACE_TEXT ("Unable to open acceptor ")
844 ACE_TEXT ("for <%C>%p\n"),
849 throw ::CORBA::BAD_PARAM (
850 CORBA::SystemException::_tao_minor_code (
851 TAO_ACCEPTOR_REGISTRY_OPEN_LOCATION_CODE
,
853 CORBA::COMPLETED_NO
);
856 // add acceptor to list
857 this->acceptors_
[this->size_
++] = acceptor
;
861 if (TAO_debug_level
> 0)
863 TAOLIB_ERROR ((LM_ERROR
,
864 ACE_TEXT ("TAO (%P|%t) unable to create ")
865 ACE_TEXT ("an acceptor for <%C>.\n"),
869 throw ::CORBA::NO_MEMORY (
870 CORBA::SystemException::_tao_minor_code (
871 TAO_ACCEPTOR_REGISTRY_OPEN_LOCATION_CODE
,
873 CORBA::COMPLETED_NO
);
876 while (astr
!= nullptr && (astr
= ACE_OS::strtok_r (nullptr, ",", &last_addr
)) != nullptr);
881 TAO_END_VERSIONED_NAMESPACE_DECL