s/Uint/UInt/g
[ACE_TAO.git] / TAO / tao / IIOP_Connection_Handler.cpp
blob55126126816ff438309de09ea6d04a1ef26efd8f
1 // -*- C++ -*-
2 #include "tao/IIOP_Connection_Handler.h"
4 #if defined (TAO_HAS_IIOP) && (TAO_HAS_IIOP != 0)
6 #include "tao/debug.h"
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,
34 rc));
36 return rc;
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,
51 rc));
53 return rc;
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.
68 ACE_ASSERT (0);
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,
90 this));
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,
107 this,
108 tport));
110 delete this->transport ();
111 int const result =
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)
133 return -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 ();
153 if (tph != nullptr)
157 if (this->transport ()->opened_as () == TAO::TAO_CLIENT_ROLE)
159 tph->client_protocol_properties_at_orb_level (protocol_properties);
161 else
163 tph->server_protocol_properties_at_orb_level (protocol_properties);
166 catch (const ::CORBA::Exception&)
168 return -1;
172 if (this->set_socket_option (this->peer (),
173 protocol_properties.send_buffer_size_,
174 protocol_properties.recv_buffer_size_) == -1)
176 return -1;
179 #if !defined (ACE_LACKS_TCP_NODELAY)
180 if (this->peer ().set_option (ACE_IPPROTO_TCP,
181 TCP_NODELAY,
182 (void *) &protocol_properties.no_delay_,
183 sizeof (protocol_properties.no_delay_)) == -1)
184 return -1;
185 #endif /* ! ACE_LACKS_TCP_NODELAY */
187 if (protocol_properties.keep_alive_)
189 if (this->peer ().
190 set_option (SOL_SOCKET,
191 SO_KEEPALIVE,
192 (void *) &protocol_properties.keep_alive_,
193 sizeof (protocol_properties.keep_alive_)) == -1
194 && errno != ENOTSUP)
196 return -1;
200 #if !defined (ACE_LACKS_SO_DONTROUTE)
201 if (protocol_properties.dont_route_)
203 if (this->peer ().
204 set_option (SOL_SOCKET,
205 SO_DONTROUTE,
206 (void *) &protocol_properties.dont_route_,
207 sizeof (protocol_properties.dont_route_)) == -1
208 && errno != ENOTSUP)
210 return -1;
213 #endif /* ! ACE_LACKS_SO_DONTROUTE */
215 if (protocol_properties.hop_limit_ >= 0)
217 int result = 0;
218 #if defined (ACE_HAS_IPV6)
219 ACE_INET_Addr local_addr;
220 if (this->peer ().get_local_addr (local_addr) == -1)
222 result = -1;
224 else if (local_addr.get_type () == AF_INET6)
226 #if defined (ACE_WIN32)
227 DWORD hop_limit =
228 static_cast<DWORD> (protocol_properties.hop_limit_);
229 #else
230 int hop_limit =
231 static_cast<int> (protocol_properties.hop_limit_);
232 #endif
233 result = this->peer ().set_option (
234 IPPROTO_IPV6,
235 IPV6_UNICAST_HOPS,
236 (void *) &hop_limit,
237 sizeof (hop_limit));
239 else
240 #endif /* ACE_HAS_IPV6 */
242 #if defined (ACE_WIN32)
243 DWORD hop_limit =
244 static_cast<DWORD> (protocol_properties.hop_limit_);
245 #else
246 int hop_limit =
247 static_cast<int> (protocol_properties.hop_limit_);
248 #endif
249 result = this->peer ().set_option (
250 IPPROTO_IP,
251 IP_TTL,
252 (void *) &hop_limit,
253 sizeof (hop_limit));
256 if (result != 0)
258 if (TAO_debug_level)
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")));
264 return -1;
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)
272 return -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)
280 return -1;
282 ACE_INET_Addr local_addr;
283 if (this->peer ().get_local_addr (local_addr) == -1)
284 return -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));
310 return -1;
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"),
329 remote_as_string));
331 return -1;
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)
341 return -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
351 // compilers
352 if (!this->transport ()->post_open ((size_t) this->get_handle ()))
353 return -1;
354 this->state_changed (TAO_LF_Event::LFS_SUCCESS,
355 this->orb_core ()->leader_follower ());
357 return 0;
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 ();
372 if (linger != -1)
374 struct linger lval;
375 lval.l_onoff = 1;
376 #if defined(ACE_HAS_LINGER_MS)
377 lval.l_linger_ms = linger * 1000;
378 #else
379 lval.l_linger = (u_short)linger;
380 #endif
381 if (this->peer ().set_option(SOL_SOCKET,
382 SO_LINGER,
383 (void*) &lval,
384 sizeof (lval)) == -1)
386 if (TAO_debug_level)
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);
410 if (result == -1)
412 this->close_connection ();
413 return 0;
416 return result;
421 TAO_IIOP_Connection_Handler::handle_timeout (const ACE_Time_Value &,
422 const void *)
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()));
447 return ret;
451 TAO_IIOP_Connection_Handler::handle_close (ACE_HANDLE, ACE_Reactor_Mask)
453 return 0;
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 ()
471 ACE_INET_Addr addr;
473 // Get the peername.
474 if (this->peer ().get_remote_addr (addr) == -1)
475 return -1;
477 // Construct an IIOP_Endpoint object
478 TAO_IIOP_Endpoint endpoint (
479 addr,
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
523 // key.
524 len = 1;
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.
533 ACE_INET_Addr addr;
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"),
542 listen_point.port,
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
549 // in an IOR.
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)
562 return -1;
564 // Make the handler idle and ready for use
565 this->transport ()->make_idle ();
568 return 0;
572 TAO_IIOP_Connection_Handler::set_tos (int tos)
574 if (tos != this->dscp_codepoint_)
576 int result = 0;
577 #if defined (ACE_HAS_IPV6)
578 ACE_INET_Addr local_addr;
579 if (this->peer ().get_local_addr (local_addr) == -1)
580 return -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;-).
586 if (TAO_debug_level)
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")));
592 return 0;
594 # else /* !IPV6_TCLASS */
595 result = this->peer ().set_option (IPPROTO_IPV6,
596 IPV6_TCLASS,
597 (int *) &tos ,
598 (int) sizeof (tos));
599 else
600 # endif /* IPV6_TCLASS */
601 #endif /* ACE_HAS_IPV6 */
602 result = this->peer ().set_option (IPPROTO_IP,
603 IP_TOS,
604 (int *) &tos ,
605 (int) sizeof (tos));
607 if (TAO_debug_level)
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"),
612 tos,
613 result,
614 result == -1 ? "try running as superuser" : ""));
617 // On successful setting of TOS field.
618 if (result == 0)
619 this->dscp_codepoint_ = tos;
621 return 0;
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;
633 this->set_tos (tos);
635 return 0;
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 ();
647 if (tph != nullptr)
649 CORBA::Long codepoint = tph->get_dscp_codepoint ();
651 tos = static_cast<int> (codepoint) << 2;
652 this->set_tos (tos);
656 return 0;
659 void
660 TAO_IIOP_Connection_Handler::abort ()
662 struct linger lval = { 0, 0 };
663 lval.l_onoff = 1;
665 if (this->peer ().set_option(SOL_SOCKET,
666 SO_LINGER,
667 (void*) &lval,
668 sizeof (lval)) == -1)
670 if (TAO_debug_level)
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 */