2 #include "tao/IIOP_Connection_Handler.h"
4 #if defined (TAO_HAS_IIOP) && (TAO_HAS_IIOP != 0)
7 #include "tao/ORB_Core.h"
8 #include "tao/IIOP_Transport.h"
9 #include "tao/IIOP_Endpoint.h"
10 #include "tao/IIOPC.h"
11 #include "tao/Thread_Lane_Resources.h"
12 #include "tao/Base_Transport_Property.h"
13 #include "tao/Protocols_Hooks.h"
14 #include "tao/Wait_Strategy.h"
16 #include "ace/os_include/netinet/os_tcp.h"
17 #include "ace/os_include/os_netdb.h"
19 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
22 #ifdef TAO_LOG_CH_REF_COUNTS
23 ACE_Event_Handler::Reference_Count
24 TAO_IIOP_Connection_Handler::add_reference (void)
26 Reference_Count rc
= TAO_IIOP_SVC_HANDLER::add_reference ();
27 if (TAO_debug_level
> 9)
29 TAO_Transport
*tport
= this->transport ();
30 TAOLIB_DEBUG ((LM_DEBUG
,
31 ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler[%d]::")
32 ACE_TEXT("add_reference, up to %d\n"),
33 tport
!= 0 ? tport
->id () : 0,
40 ACE_Event_Handler::Reference_Count
41 TAO_IIOP_Connection_Handler::remove_reference (void)
43 TAO_Transport
*tport
= this->transport ();
44 Reference_Count rc
= TAO_IIOP_SVC_HANDLER::remove_reference ();
45 if (TAO_debug_level
> 9)
47 TAOLIB_DEBUG ((LM_DEBUG
,
48 ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler[%d]::")
49 ACE_TEXT("remove_reference, down to %d\n"),
50 tport
!= 0 ? tport
->id () : 0,
55 #endif /*TAO_LOG_CH_REF_COUNTS*/
58 TAO_IIOP_Connection_Handler::TAO_IIOP_Connection_Handler (ACE_Thread_Manager
*t
)
59 : TAO_IIOP_SVC_HANDLER (t
, nullptr , nullptr),
60 TAO_Connection_Handler (nullptr),
61 dscp_codepoint_ (IPDSFIELD_DSCP_DEFAULT
<< 2)
63 // This constructor should *never* get called, it is just here to
64 // make the compiler happy: the default implementation of the
65 // Creation_Strategy requires a constructor with that signature, we
66 // don't use that implementation, but some (most?) compilers
67 // instantiate it anyway.
72 TAO_IIOP_Connection_Handler::TAO_IIOP_Connection_Handler (
73 TAO_ORB_Core
*orb_core
)
74 : TAO_IIOP_SVC_HANDLER (orb_core
->thr_mgr (), nullptr, nullptr),
75 TAO_Connection_Handler (orb_core
),
76 dscp_codepoint_ (IPDSFIELD_DSCP_DEFAULT
<< 2)
78 TAO_IIOP_Transport
* specific_transport
= nullptr;
79 ACE_NEW (specific_transport
,
80 TAO_IIOP_Transport (this, orb_core
));
82 if (TAO_debug_level
> 9)
84 TAO_Transport
*tport
= static_cast<TAO_Transport
*> (specific_transport
);
85 TAOLIB_DEBUG ((LM_DEBUG
,
86 ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler[%d]::")
87 ACE_TEXT("IIOP_Connection_Handler, ")
88 ACE_TEXT("this=%@\n"),
89 tport
!= nullptr ? tport
->id () : 0,
93 // store this pointer (indirectly increment ref count)
94 this->transport (specific_transport
);
97 TAO_IIOP_Connection_Handler::~TAO_IIOP_Connection_Handler ()
99 if (TAO_debug_level
> 9)
101 TAO_Transport
*tport
= this->transport ();
102 TAOLIB_DEBUG ((LM_DEBUG
,
103 ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler[%d]::")
104 ACE_TEXT("~IIOP_Connection_Handler, ")
105 ACE_TEXT("this=%@, transport=%@\n"),
106 tport
!= nullptr ? tport
->id () : 0,
110 delete this->transport ();
112 this->release_os_resources ();
114 if (result
== -1 && TAO_debug_level
)
116 TAOLIB_ERROR ((LM_ERROR
,
117 ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler::")
118 ACE_TEXT("~IIOP_Connection_Handler, ")
119 ACE_TEXT("release_os_resources() failed %m\n")));
124 TAO_IIOP_Connection_Handler::open_handler (void *v
)
126 return this->open (v
);
130 TAO_IIOP_Connection_Handler::open (void*)
132 if (this->shared_open() == -1)
135 TAO_IIOP_Protocol_Properties protocol_properties
;
137 // Initialize values from ORB params.
138 protocol_properties
.send_buffer_size_
=
139 this->orb_core ()->orb_params ()->sock_sndbuf_size ();
140 protocol_properties
.recv_buffer_size_
=
141 this->orb_core ()->orb_params ()->sock_rcvbuf_size ();
142 protocol_properties
.no_delay_
=
143 this->orb_core ()->orb_params ()->nodelay ();
144 protocol_properties
.keep_alive_
=
145 this->orb_core ()->orb_params ()->sock_keepalive ();
146 protocol_properties
.dont_route_
=
147 this->orb_core ()->orb_params ()->sock_dontroute ();
148 protocol_properties
.hop_limit_
=
149 this->orb_core ()->orb_params ()->ip_hoplimit ();
151 TAO_Protocols_Hooks
*tph
= this->orb_core ()->get_protocols_hooks ();
157 if (this->transport ()->opened_as () == TAO::TAO_CLIENT_ROLE
)
159 tph
->client_protocol_properties_at_orb_level (protocol_properties
);
163 tph
->server_protocol_properties_at_orb_level (protocol_properties
);
166 catch (const ::CORBA::Exception
&)
172 if (this->set_socket_option (this->peer (),
173 protocol_properties
.send_buffer_size_
,
174 protocol_properties
.recv_buffer_size_
) == -1)
179 #if !defined (ACE_LACKS_TCP_NODELAY)
180 if (this->peer ().set_option (ACE_IPPROTO_TCP
,
182 (void *) &protocol_properties
.no_delay_
,
183 sizeof (protocol_properties
.no_delay_
)) == -1)
185 #endif /* ! ACE_LACKS_TCP_NODELAY */
187 if (protocol_properties
.keep_alive_
)
190 set_option (SOL_SOCKET
,
192 (void *) &protocol_properties
.keep_alive_
,
193 sizeof (protocol_properties
.keep_alive_
)) == -1
200 #if !defined (ACE_LACKS_SO_DONTROUTE)
201 if (protocol_properties
.dont_route_
)
204 set_option (SOL_SOCKET
,
206 (void *) &protocol_properties
.dont_route_
,
207 sizeof (protocol_properties
.dont_route_
)) == -1
213 #endif /* ! ACE_LACKS_SO_DONTROUTE */
215 if (protocol_properties
.hop_limit_
>= 0)
218 #if defined (ACE_HAS_IPV6)
219 ACE_INET_Addr local_addr
;
220 if (this->peer ().get_local_addr (local_addr
) == -1)
224 else if (local_addr
.get_type () == AF_INET6
)
226 #if defined (ACE_WIN32)
228 static_cast<DWORD
> (protocol_properties
.hop_limit_
);
231 static_cast<int> (protocol_properties
.hop_limit_
);
233 result
= this->peer ().set_option (
240 #endif /* ACE_HAS_IPV6 */
242 #if defined (ACE_WIN32)
244 static_cast<DWORD
> (protocol_properties
.hop_limit_
);
247 static_cast<int> (protocol_properties
.hop_limit_
);
249 result
= this->peer ().set_option (
260 TAOLIB_ERROR ((LM_ERROR
,
261 ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler::open, ")
262 ACE_TEXT("couldn't set hop limit\n\n")));
268 if (this->transport ()->wait_strategy ()->non_blocking ()
269 || this->transport ()->opened_as () == TAO::TAO_SERVER_ROLE
)
271 if (this->peer ().enable (ACE_NONBLOCK
) == -1)
275 // Called by the <Strategy_Acceptor> when the handler is
276 // completely connected.
278 ACE_INET_Addr remote_addr
;
279 if (this->peer ().get_remote_addr (remote_addr
) == -1)
282 ACE_INET_Addr local_addr
;
283 if (this->peer ().get_local_addr (local_addr
) == -1)
286 if (TAO_debug_level
> 2)
287 TAOLIB_DEBUG ((LM_DEBUG
,
288 ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler::open, ")
289 ACE_TEXT("The local addr is <%C:%d>\n"),
290 local_addr
.get_host_addr (),
291 local_addr
.get_port_number()));
293 if (local_addr
== remote_addr
)
295 if (TAO_debug_level
> 0)
297 ACE_TCHAR remote_as_string
[MAXHOSTNAMELEN
+ 16];
298 ACE_TCHAR local_as_string
[MAXHOSTNAMELEN
+ 16];
300 (void) remote_addr
.addr_to_string (remote_as_string
,
301 sizeof(remote_as_string
));
302 (void) local_addr
.addr_to_string (local_as_string
,
303 sizeof(local_as_string
));
304 TAOLIB_ERROR ((LM_ERROR
,
305 ACE_TEXT("TAO(%P|%t) - IIOP_Connection_Handler::open, ")
306 ACE_TEXT("Holy Cow! The remote addr and ")
307 ACE_TEXT("local addr are identical (%s == %s)\n"),
308 remote_as_string
, local_as_string
));
313 #if defined (ACE_HAS_IPV6) && !defined (ACE_HAS_IPV6_V6ONLY)
314 // Check if we need to invalidate accepted connections
315 // from IPv4 mapped IPv6 addresses
316 if (this->orb_core ()->orb_params ()->connect_ipv6_only () &&
317 remote_addr
.is_ipv4_mapped_ipv6 ())
319 if (TAO_debug_level
> 0)
321 ACE_TCHAR remote_as_string
[MAXHOSTNAMELEN
+ 16];
323 (void) remote_addr
.addr_to_string (remote_as_string
,
324 sizeof(remote_as_string
));
326 TAOLIB_ERROR ((LM_ERROR
,
327 ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler::open, ")
328 ACE_TEXT("invalid connection from IPv4 mapped IPv6 interface <%s>!\n"),
333 #endif /* ACE_HAS_IPV6 && ACE_HAS_IPV6_V6ONLY */
335 if (TAO_debug_level
> 0)
337 ACE_TCHAR client_addr
[MAXHOSTNAMELEN
+ 16];
339 // Verify that we can resolve the peer hostname.
340 if (remote_addr
.addr_to_string (client_addr
, sizeof (client_addr
)) == -1)
343 TAOLIB_DEBUG ((LM_DEBUG
,
344 ACE_TEXT ("TAO (%P|%t) - IIOP_Connection_Handler::open, IIOP ")
345 ACE_TEXT ("connection to peer <%s> on [%d]\n"),
346 client_addr
, this->peer ().get_handle ()));
349 // Set that the transport is now connected, if fails we return -1
350 // Use C-style cast b/c otherwise we get warnings on lots of
352 if (!this->transport ()->post_open ((size_t) this->get_handle ()))
354 this->state_changed (TAO_LF_Event::LFS_SUCCESS
,
355 this->orb_core ()->leader_follower ());
361 TAO_IIOP_Connection_Handler::resume_handler ()
363 return ACE_Event_Handler::ACE_APPLICATION_RESUMES_HANDLER
;
367 TAO_IIOP_Connection_Handler::close_connection ()
369 // To maintain maximum compatibility, we only set this socket option
370 // if the user has provided a linger timeout.
371 int const linger
= this->orb_core()->orb_params()->linger ();
376 #if defined(ACE_HAS_LINGER_MS)
377 lval
.l_linger_ms
= linger
* 1000;
379 lval
.l_linger
= (u_short
)linger
;
381 if (this->peer ().set_option(SOL_SOCKET
,
384 sizeof (lval
)) == -1)
388 TAOLIB_DEBUG ((LM_DEBUG
,
389 ACE_TEXT ("TAO (%P|%t) Unable to set ")
390 ACE_TEXT ("SO_LINGER on %d\n"),
391 this->peer ().get_handle ()));
396 return this->close_connection_eh (this);
400 TAO_IIOP_Connection_Handler::handle_input (ACE_HANDLE h
)
402 return this->handle_input_eh (h
, this);
406 TAO_IIOP_Connection_Handler::handle_output (ACE_HANDLE handle
)
408 int const result
= this->handle_output_eh (handle
, this);
412 this->close_connection ();
421 TAO_IIOP_Connection_Handler::handle_timeout (const ACE_Time_Value
&,
424 // Using this to ensure this instance will be deleted (if necessary)
425 // only after reset_state(). Without this, when this refcount==1 -
426 // the call to close() will cause a call to remove_reference() which
427 // will delete this. At that point this->reset_state() is in no
428 // man's territory and that causes SEGV on some platforms (Windows!)
430 TAO_Auto_Reference
<TAO_IIOP_Connection_Handler
> safeguard (*this);
432 // NOTE: Perhaps not the best solution, as it feels like the upper
433 // layers should be responsible for this?
435 // We don't use this upcall for I/O. This is only used by the
436 // Connector to indicate that the connection timedout. Therefore,
437 // we should call close()
439 int const ret
= this->close ();
440 this->reset_state (TAO_LF_Event::LFS_TIMEOUT
);
441 if (TAO_debug_level
> 9)
443 TAOLIB_DEBUG ((LM_DEBUG
, "TAO (%P|%t) - TAO_IIOP_Connection_Handler[%d]::"
444 "handle_timeout reset state to LFS_TIMEOUT\n",
445 this->transport ()-> id()));
451 TAO_IIOP_Connection_Handler::handle_close (ACE_HANDLE
, ACE_Reactor_Mask
)
457 TAO_IIOP_Connection_Handler::close (u_long flags
)
459 return this->close_handler (flags
);
463 TAO_IIOP_Connection_Handler::release_os_resources ()
465 return this->peer ().close ();
469 TAO_IIOP_Connection_Handler::add_transport_to_cache ()
474 if (this->peer ().get_remote_addr (addr
) == -1)
477 // Construct an IIOP_Endpoint object
478 TAO_IIOP_Endpoint
endpoint (
480 this->orb_core()->orb_params()->cache_incoming_by_dotted_decimal_address ());
482 // Construct a property object
483 TAO_Base_Transport_Property
prop (&endpoint
);
485 TAO::Transport_Cache_Manager
&cache
=
486 this->orb_core ()->lane_resources ().transport_cache ();
488 // Idle the transport..
489 return cache
.cache_transport (&prop
, this->transport ());
493 TAO_IIOP_Connection_Handler::process_listen_point_list (
494 IIOP::ListenPointList
&listen_list
)
496 // Get the size of the list
497 CORBA::ULong len
= listen_list
.length ();
499 if (TAO_debug_level
> 0 && len
== 0)
501 TAOLIB_ERROR ((LM_ERROR
,
502 ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler::")
503 ACE_TEXT("process_listen_point_list, ")
504 ACE_TEXT("Received list of size 0, check client config.\n")));
507 // @@ We can only handle a single endpoint for now because the
508 // transport is recached for each endpoint, loosing older
509 // information. This means that when more than one listen_point is
510 // sent, the cache will end up only being associated with the last
511 // address. This poses a problem at invocation time because the
512 // default endpoint selector steps through the profiles/endpoints
513 // sequentially and will try and possibly succeed in connecting to
514 // one of the earlier endpoints. My assumption is that when this
515 // method is called, it is before the first attempt to connect to
516 // any object in the target process, thus the first listen point in
517 // the list will correspond with the first profile and thus that
518 // should match the cache.
520 // Probably what needs to be done to make this model work well is to
521 // allow the transport cache to have multiple keys reference the
522 // same transport so that rather than recaching, we simply add a
525 for (CORBA::ULong i
= 0; i
< len
; ++i
)
527 IIOP::ListenPoint listen_point
= listen_list
[i
];
529 // since the supplied host/port could be unresolvable, the assigning
530 // constructor of the INET addr should not be as it will emit an error
531 // if the underlying set fails. An unresolvable address in this case
532 // is OK, as it will only be used to find an already cached transport.
534 (void)addr
.set(listen_point
.port
, listen_point
.host
.in ());
536 if (TAO_debug_level
> 0)
538 TAOLIB_DEBUG ((LM_DEBUG
,
539 ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler::")
540 ACE_TEXT("process_listen_point_list, ")
541 ACE_TEXT("Listening port [%d] on [%C]\n"),
543 listen_point
.host
.in ()));
546 // Construct an IIOP_Endpoint object using the host as provided
547 // in the listen point list. We must use host in that form because
548 // that's also how the ORB on the other side will advertise the host
550 TAO_IIOP_Endpoint
endpoint (listen_point
.host
.in (),
551 listen_point
.port
, addr
);
553 // Construct a property object
554 TAO_Base_Transport_Property
prop (&endpoint
);
556 // Mark the connection as bidirectional
557 prop
.set_bidir_flag (1);
559 // The property for this handler has changed. Recache the
560 // handler with this property
561 if (this->transport ()->recache_transport (&prop
) == -1)
564 // Make the handler idle and ready for use
565 this->transport ()->make_idle ();
572 TAO_IIOP_Connection_Handler::set_tos (int tos
)
574 if (tos
!= this->dscp_codepoint_
)
577 #if defined (ACE_HAS_IPV6)
578 ACE_INET_Addr local_addr
;
579 if (this->peer ().get_local_addr (local_addr
) == -1)
581 else if (local_addr
.get_type () == AF_INET6
)
582 # if !defined (IPV6_TCLASS)
583 // IPv6 defines option IPV6_TCLASS for specifying traffic class/priority
584 // but not many implementations yet (very new;-).
588 TAOLIB_DEBUG ((LM_DEBUG
,
589 ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler::")
590 ACE_TEXT("set_dscp_codepoint -> IPV6_TCLASS not supported yet\n")));
594 # else /* !IPV6_TCLASS */
595 result
= this->peer ().set_option (IPPROTO_IPV6
,
600 # endif /* IPV6_TCLASS */
601 #endif /* ACE_HAS_IPV6 */
602 result
= this->peer ().set_option (IPPROTO_IP
,
609 TAOLIB_DEBUG ((LM_DEBUG
,
610 ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler::")
611 ACE_TEXT("set_dscp_codepoint -> dscp: %x; result: %d; %C\n"),
614 result
== -1 ? "try running as superuser" : ""));
617 // On successful setting of TOS field.
619 this->dscp_codepoint_
= tos
;
625 TAO_IIOP_Connection_Handler::set_dscp_codepoint (CORBA::Long dscp_codepoint
)
627 int tos
= IPDSFIELD_DSCP_DEFAULT
<< 2;
629 CORBA::Long codepoint
= dscp_codepoint
;
631 tos
= static_cast<int> (codepoint
) << 2;
639 TAO_IIOP_Connection_Handler::set_dscp_codepoint (CORBA::Boolean set_network_priority
)
641 int tos
= IPDSFIELD_DSCP_DEFAULT
<< 2;
643 if (set_network_priority
)
645 TAO_Protocols_Hooks
*tph
= this->orb_core ()->get_protocols_hooks ();
649 CORBA::Long codepoint
= tph
->get_dscp_codepoint ();
651 tos
= static_cast<int> (codepoint
) << 2;
660 TAO_IIOP_Connection_Handler::abort ()
662 struct linger lval
= { 0, 0 };
665 if (this->peer ().set_option(SOL_SOCKET
,
668 sizeof (lval
)) == -1)
672 TAOLIB_DEBUG ((LM_DEBUG
,
673 ACE_TEXT ("TAO (%P|%t) Unable to set ")
674 ACE_TEXT ("SO_LINGER on %d\n"),
675 this->peer ().get_handle ()));
681 TAO_IIOP_Connection_Handler::handle_write_ready (const ACE_Time_Value
*timeout
)
683 return ACE::handle_write_ready (this->peer ().get_handle (), timeout
);
686 TAO_END_VERSIONED_NAMESPACE_DECL
688 #endif /* TAO_HAS_IIOP && TAO_HAS_IIOP != 0 */