Revert "Minor modernization of DynamicAny code"
[ACE_TAO.git] / TAO / tao / IIOP_Connection_Handler.cpp
bloba5734c7d8d3ff3ba7a26d4c7e2984aa1714434e7
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 ()
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;
39 ACE_Event_Handler::Reference_Count
40 TAO_IIOP_Connection_Handler::remove_reference ()
42 TAO_Transport *tport = this->transport ();
43 Reference_Count rc = TAO_IIOP_SVC_HANDLER::remove_reference ();
44 if (TAO_debug_level > 9)
46 TAOLIB_DEBUG ((LM_DEBUG,
47 ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler[%d]::")
48 ACE_TEXT("remove_reference, down to %d\n"),
49 tport != 0 ? tport->id () : 0,
50 rc));
52 return rc;
54 #endif /*TAO_LOG_CH_REF_COUNTS*/
57 TAO_IIOP_Connection_Handler::TAO_IIOP_Connection_Handler (ACE_Thread_Manager *t)
58 : TAO_IIOP_SVC_HANDLER (t, nullptr , nullptr),
59 TAO_Connection_Handler (nullptr),
60 dscp_codepoint_ (IPDSFIELD_DSCP_DEFAULT << 2)
62 // This constructor should *never* get called, it is just here to
63 // make the compiler happy: the default implementation of the
64 // Creation_Strategy requires a constructor with that signature, we
65 // don't use that implementation, but some (most?) compilers
66 // instantiate it anyway.
67 ACE_ASSERT (0);
71 TAO_IIOP_Connection_Handler::TAO_IIOP_Connection_Handler (
72 TAO_ORB_Core *orb_core)
73 : TAO_IIOP_SVC_HANDLER (orb_core->thr_mgr (), nullptr, nullptr),
74 TAO_Connection_Handler (orb_core),
75 dscp_codepoint_ (IPDSFIELD_DSCP_DEFAULT << 2)
77 TAO_IIOP_Transport* specific_transport = nullptr;
78 ACE_NEW (specific_transport,
79 TAO_IIOP_Transport (this, orb_core));
81 if (TAO_debug_level > 9)
83 TAO_Transport *tport = static_cast<TAO_Transport *> (specific_transport);
84 TAOLIB_DEBUG ((LM_DEBUG,
85 ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler[%d]::")
86 ACE_TEXT("IIOP_Connection_Handler, ")
87 ACE_TEXT("this=%@\n"),
88 tport != nullptr ? tport->id () : 0,
89 this));
92 // store this pointer (indirectly increment ref count)
93 this->transport (specific_transport);
96 TAO_IIOP_Connection_Handler::~TAO_IIOP_Connection_Handler ()
98 if (TAO_debug_level > 9)
100 TAO_Transport *tport = this->transport ();
101 TAOLIB_DEBUG ((LM_DEBUG,
102 ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler[%d]::")
103 ACE_TEXT("~IIOP_Connection_Handler, ")
104 ACE_TEXT("this=%@, transport=%@\n"),
105 tport != nullptr ? tport->id () : 0,
106 this,
107 tport));
109 delete this->transport ();
110 int const result =
111 this->release_os_resources ();
113 if (result == -1 && TAO_debug_level)
115 TAOLIB_ERROR ((LM_ERROR,
116 ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler::")
117 ACE_TEXT("~IIOP_Connection_Handler, ")
118 ACE_TEXT("release_os_resources() failed %m\n")));
123 TAO_IIOP_Connection_Handler::open_handler (void *v)
125 return this->open (v);
129 TAO_IIOP_Connection_Handler::open (void*)
131 if (this->shared_open() == -1)
132 return -1;
134 TAO_IIOP_Protocol_Properties protocol_properties;
136 // Initialize values from ORB params.
137 protocol_properties.send_buffer_size_ =
138 this->orb_core ()->orb_params ()->sock_sndbuf_size ();
139 protocol_properties.recv_buffer_size_ =
140 this->orb_core ()->orb_params ()->sock_rcvbuf_size ();
141 protocol_properties.no_delay_ =
142 this->orb_core ()->orb_params ()->nodelay ();
143 protocol_properties.keep_alive_ =
144 this->orb_core ()->orb_params ()->sock_keepalive ();
145 protocol_properties.dont_route_ =
146 this->orb_core ()->orb_params ()->sock_dontroute ();
147 protocol_properties.hop_limit_ =
148 this->orb_core ()->orb_params ()->ip_hoplimit ();
150 TAO_Protocols_Hooks *tph = this->orb_core ()->get_protocols_hooks ();
152 if (tph != nullptr)
156 if (this->transport ()->opened_as () == TAO::TAO_CLIENT_ROLE)
158 tph->client_protocol_properties_at_orb_level (protocol_properties);
160 else
162 tph->server_protocol_properties_at_orb_level (protocol_properties);
165 catch (const ::CORBA::Exception&)
167 return -1;
171 if (this->set_socket_option (this->peer (),
172 protocol_properties.send_buffer_size_,
173 protocol_properties.recv_buffer_size_) == -1)
175 return -1;
178 #if !defined (ACE_LACKS_TCP_NODELAY)
179 if (this->peer ().set_option (ACE_IPPROTO_TCP,
180 TCP_NODELAY,
181 (void *) &protocol_properties.no_delay_,
182 sizeof (protocol_properties.no_delay_)) == -1)
183 return -1;
184 #endif /* ! ACE_LACKS_TCP_NODELAY */
186 if (protocol_properties.keep_alive_)
188 if (this->peer ().
189 set_option (SOL_SOCKET,
190 SO_KEEPALIVE,
191 (void *) &protocol_properties.keep_alive_,
192 sizeof (protocol_properties.keep_alive_)) == -1
193 && errno != ENOTSUP)
195 return -1;
199 #if !defined (ACE_LACKS_SO_DONTROUTE)
200 if (protocol_properties.dont_route_)
202 if (this->peer ().
203 set_option (SOL_SOCKET,
204 SO_DONTROUTE,
205 (void *) &protocol_properties.dont_route_,
206 sizeof (protocol_properties.dont_route_)) == -1
207 && errno != ENOTSUP)
209 return -1;
212 #endif /* ! ACE_LACKS_SO_DONTROUTE */
214 if (protocol_properties.hop_limit_ >= 0)
216 int result = 0;
217 #if defined (ACE_HAS_IPV6)
218 ACE_INET_Addr local_addr;
219 if (this->peer ().get_local_addr (local_addr) == -1)
221 result = -1;
223 else if (local_addr.get_type () == AF_INET6)
225 #if defined (ACE_WIN32)
226 DWORD hop_limit =
227 static_cast<DWORD> (protocol_properties.hop_limit_);
228 #else
229 int hop_limit =
230 static_cast<int> (protocol_properties.hop_limit_);
231 #endif
232 result = this->peer ().set_option (
233 IPPROTO_IPV6,
234 IPV6_UNICAST_HOPS,
235 (void *) &hop_limit,
236 sizeof (hop_limit));
238 else
239 #endif /* ACE_HAS_IPV6 */
241 #if defined (ACE_WIN32)
242 DWORD hop_limit =
243 static_cast<DWORD> (protocol_properties.hop_limit_);
244 #else
245 int hop_limit =
246 static_cast<int> (protocol_properties.hop_limit_);
247 #endif
248 result = this->peer ().set_option (
249 IPPROTO_IP,
250 IP_TTL,
251 (void *) &hop_limit,
252 sizeof (hop_limit));
255 if (result != 0)
257 if (TAO_debug_level)
259 TAOLIB_ERROR ((LM_ERROR,
260 ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler::open, ")
261 ACE_TEXT("couldn't set hop limit\n\n")));
263 return -1;
267 if (this->transport ()->wait_strategy ()->non_blocking ()
268 || this->transport ()->opened_as () == TAO::TAO_SERVER_ROLE)
270 if (this->peer ().enable (ACE_NONBLOCK) == -1)
271 return -1;
274 // Called by the <Strategy_Acceptor> when the handler is
275 // completely connected.
277 ACE_INET_Addr remote_addr;
278 if (this->peer ().get_remote_addr (remote_addr) == -1)
279 return -1;
281 ACE_INET_Addr local_addr;
282 if (this->peer ().get_local_addr (local_addr) == -1)
283 return -1;
285 if (TAO_debug_level > 2)
286 TAOLIB_DEBUG ((LM_DEBUG,
287 ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler::open, ")
288 ACE_TEXT("The local addr is <%C:%d>\n"),
289 local_addr.get_host_addr (),
290 local_addr.get_port_number()));
292 if (local_addr == remote_addr)
294 if (TAO_debug_level > 0)
296 ACE_TCHAR remote_as_string[MAXHOSTNAMELEN + 16];
297 ACE_TCHAR local_as_string[MAXHOSTNAMELEN + 16];
299 (void) remote_addr.addr_to_string (remote_as_string,
300 sizeof(remote_as_string));
301 (void) local_addr.addr_to_string (local_as_string,
302 sizeof(local_as_string));
303 TAOLIB_ERROR ((LM_ERROR,
304 ACE_TEXT("TAO(%P|%t) - IIOP_Connection_Handler::open, ")
305 ACE_TEXT("Holy Cow! The remote addr and ")
306 ACE_TEXT("local addr are identical (%s == %s)\n"),
307 remote_as_string, local_as_string));
309 return -1;
312 #if defined (ACE_HAS_IPV6) && !defined (ACE_HAS_IPV6_V6ONLY)
313 // Check if we need to invalidate accepted connections
314 // from IPv4 mapped IPv6 addresses
315 if (this->orb_core ()->orb_params ()->connect_ipv6_only () &&
316 remote_addr.is_ipv4_mapped_ipv6 ())
318 if (TAO_debug_level > 0)
320 ACE_TCHAR remote_as_string[MAXHOSTNAMELEN + 16];
322 (void) remote_addr.addr_to_string (remote_as_string,
323 sizeof(remote_as_string));
325 TAOLIB_ERROR ((LM_ERROR,
326 ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler::open, ")
327 ACE_TEXT("invalid connection from IPv4 mapped IPv6 interface <%s>!\n"),
328 remote_as_string));
330 return -1;
332 #endif /* ACE_HAS_IPV6 && ACE_HAS_IPV6_V6ONLY */
334 if (TAO_debug_level > 0)
336 ACE_TCHAR client_addr[MAXHOSTNAMELEN + 16];
338 // Verify that we can resolve the peer hostname.
339 if (remote_addr.addr_to_string (client_addr, sizeof (client_addr)) == -1)
340 return -1;
342 TAOLIB_DEBUG ((LM_DEBUG,
343 ACE_TEXT ("TAO (%P|%t) - IIOP_Connection_Handler::open, IIOP ")
344 ACE_TEXT ("connection to peer <%s> on [%d]\n"),
345 client_addr, this->peer ().get_handle ()));
348 // Set that the transport is now connected, if fails we return -1
349 // Use C-style cast b/c otherwise we get warnings on lots of
350 // compilers
351 if (!this->transport ()->post_open ((size_t) this->get_handle ()))
352 return -1;
353 this->state_changed (TAO_LF_Event::LFS_SUCCESS,
354 this->orb_core ()->leader_follower ());
356 return 0;
360 TAO_IIOP_Connection_Handler::resume_handler ()
362 return ACE_Event_Handler::ACE_APPLICATION_RESUMES_HANDLER;
366 TAO_IIOP_Connection_Handler::close_connection ()
368 // To maintain maximum compatibility, we only set this socket option
369 // if the user has provided a linger timeout.
370 int const linger = this->orb_core()->orb_params()->linger ();
371 if (linger != -1)
373 struct linger lval;
374 lval.l_onoff = 1;
375 #if defined(ACE_HAS_LINGER_MS)
376 lval.l_linger_ms = linger * 1000;
377 #else
378 lval.l_linger = (u_short)linger;
379 #endif
380 if (this->peer ().set_option(SOL_SOCKET,
381 SO_LINGER,
382 (void*) &lval,
383 sizeof (lval)) == -1)
385 if (TAO_debug_level)
387 TAOLIB_DEBUG ((LM_DEBUG,
388 ACE_TEXT ("TAO (%P|%t) Unable to set ")
389 ACE_TEXT ("SO_LINGER on %d\n"),
390 this->peer ().get_handle ()));
395 return this->close_connection_eh (this);
399 TAO_IIOP_Connection_Handler::handle_input (ACE_HANDLE h)
401 return this->handle_input_eh (h, this);
405 TAO_IIOP_Connection_Handler::handle_output (ACE_HANDLE handle)
407 int const result = this->handle_output_eh (handle, this);
409 if (result == -1)
411 this->close_connection ();
412 return 0;
415 return result;
420 TAO_IIOP_Connection_Handler::handle_timeout (const ACE_Time_Value &,
421 const void *)
423 // Using this to ensure this instance will be deleted (if necessary)
424 // only after reset_state(). Without this, when this refcount==1 -
425 // the call to close() will cause a call to remove_reference() which
426 // will delete this. At that point this->reset_state() is in no
427 // man's territory and that causes SEGV on some platforms (Windows!)
429 TAO_Auto_Reference<TAO_IIOP_Connection_Handler> safeguard (*this);
431 // NOTE: Perhaps not the best solution, as it feels like the upper
432 // layers should be responsible for this?
434 // We don't use this upcall for I/O. This is only used by the
435 // Connector to indicate that the connection timedout. Therefore,
436 // we should call close()
438 int const ret = this->close ();
439 this->reset_state (TAO_LF_Event::LFS_TIMEOUT);
440 if (TAO_debug_level > 9)
442 TAOLIB_DEBUG ((LM_DEBUG, "TAO (%P|%t) - TAO_IIOP_Connection_Handler[%d]::"
443 "handle_timeout reset state to LFS_TIMEOUT\n",
444 this->transport ()-> id()));
446 return ret;
450 TAO_IIOP_Connection_Handler::handle_close (ACE_HANDLE, ACE_Reactor_Mask)
452 return 0;
456 TAO_IIOP_Connection_Handler::close (u_long flags)
458 return this->close_handler (flags);
462 TAO_IIOP_Connection_Handler::release_os_resources ()
464 return this->peer ().close ();
468 TAO_IIOP_Connection_Handler::add_transport_to_cache ()
470 ACE_INET_Addr addr;
472 // Get the peername.
473 if (this->peer ().get_remote_addr (addr) == -1)
474 return -1;
476 // Construct an IIOP_Endpoint object
477 TAO_IIOP_Endpoint endpoint (
478 addr,
479 this->orb_core()->orb_params()->cache_incoming_by_dotted_decimal_address ());
481 // Construct a property object
482 TAO_Base_Transport_Property prop (&endpoint);
484 TAO::Transport_Cache_Manager &cache =
485 this->orb_core ()->lane_resources ().transport_cache ();
487 // Idle the transport..
488 return cache.cache_transport (&prop, this->transport ());
492 TAO_IIOP_Connection_Handler::process_listen_point_list (
493 IIOP::ListenPointList &listen_list)
495 // Get the size of the list
496 CORBA::ULong len = listen_list.length ();
498 if (TAO_debug_level > 0 && len == 0)
500 TAOLIB_ERROR ((LM_ERROR,
501 ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler::")
502 ACE_TEXT("process_listen_point_list, ")
503 ACE_TEXT("Received list of size 0, check client config.\n")));
506 // @@ We can only handle a single endpoint for now because the
507 // transport is recached for each endpoint, loosing older
508 // information. This means that when more than one listen_point is
509 // sent, the cache will end up only being associated with the last
510 // address. This poses a problem at invocation time because the
511 // default endpoint selector steps through the profiles/endpoints
512 // sequentially and will try and possibly succeed in connecting to
513 // one of the earlier endpoints. My assumption is that when this
514 // method is called, it is before the first attempt to connect to
515 // any object in the target process, thus the first listen point in
516 // the list will correspond with the first profile and thus that
517 // should match the cache.
519 // Probably what needs to be done to make this model work well is to
520 // allow the transport cache to have multiple keys reference the
521 // same transport so that rather than recaching, we simply add a
522 // key.
523 len = 1;
524 for (CORBA::ULong i = 0; i < len; ++i)
526 IIOP::ListenPoint listen_point = listen_list[i];
528 // since the supplied host/port could be unresolvable, the assigning
529 // constructor of the INET addr should not be as it will emit an error
530 // if the underlying set fails. An unresolvable address in this case
531 // is OK, as it will only be used to find an already cached transport.
532 ACE_INET_Addr addr;
533 (void)addr.set(listen_point.port, listen_point.host.in ());
535 if (TAO_debug_level > 0)
537 TAOLIB_DEBUG ((LM_DEBUG,
538 ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler::")
539 ACE_TEXT("process_listen_point_list, ")
540 ACE_TEXT("Listening port [%d] on [%C]\n"),
541 listen_point.port,
542 listen_point.host.in ()));
545 // Construct an IIOP_Endpoint object using the host as provided
546 // in the listen point list. We must use host in that form because
547 // that's also how the ORB on the other side will advertise the host
548 // in an IOR.
549 TAO_IIOP_Endpoint endpoint (listen_point.host.in (),
550 listen_point.port, addr);
552 // Construct a property object
553 TAO_Base_Transport_Property prop (&endpoint);
555 // Mark the connection as bidirectional
556 prop.set_bidir_flag (1);
558 // The property for this handler has changed. Recache the
559 // handler with this property
560 if (this->transport ()->recache_transport (&prop) == -1)
561 return -1;
563 // Make the handler idle and ready for use
564 this->transport ()->make_idle ();
567 return 0;
571 TAO_IIOP_Connection_Handler::set_tos (int tos)
573 if (tos != this->dscp_codepoint_)
575 int result = 0;
576 #if defined (ACE_HAS_IPV6)
577 ACE_INET_Addr local_addr;
578 if (this->peer ().get_local_addr (local_addr) == -1)
579 return -1;
580 else if (local_addr.get_type () == AF_INET6)
581 # if !defined (IPV6_TCLASS)
582 // IPv6 defines option IPV6_TCLASS for specifying traffic class/priority
583 // but not many implementations yet (very new;-).
585 if (TAO_debug_level)
587 TAOLIB_DEBUG ((LM_DEBUG,
588 ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler::")
589 ACE_TEXT("set_dscp_codepoint -> IPV6_TCLASS not supported yet\n")));
591 return 0;
593 # else /* !IPV6_TCLASS */
594 result = this->peer ().set_option (IPPROTO_IPV6,
595 IPV6_TCLASS,
596 (int *) &tos ,
597 (int) sizeof (tos));
598 else
599 # endif /* IPV6_TCLASS */
600 #endif /* ACE_HAS_IPV6 */
601 result = this->peer ().set_option (IPPROTO_IP,
602 IP_TOS,
603 (int *) &tos ,
604 (int) sizeof (tos));
606 if (TAO_debug_level)
608 TAOLIB_DEBUG ((LM_DEBUG,
609 ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler::")
610 ACE_TEXT("set_dscp_codepoint -> dscp: %x; result: %d; %C\n"),
611 tos,
612 result,
613 result == -1 ? "try running as superuser" : ""));
616 // On successful setting of TOS field.
617 if (result == 0)
618 this->dscp_codepoint_ = tos;
620 return 0;
624 TAO_IIOP_Connection_Handler::set_dscp_codepoint (CORBA::Long dscp_codepoint)
626 int tos = IPDSFIELD_DSCP_DEFAULT << 2;
628 CORBA::Long codepoint = dscp_codepoint;
630 tos = static_cast<int> (codepoint) << 2;
632 this->set_tos (tos);
634 return 0;
638 TAO_IIOP_Connection_Handler::set_dscp_codepoint (CORBA::Boolean set_network_priority)
640 int tos = IPDSFIELD_DSCP_DEFAULT << 2;
642 if (set_network_priority)
644 TAO_Protocols_Hooks *tph = this->orb_core ()->get_protocols_hooks ();
646 if (tph != nullptr)
648 CORBA::Long codepoint = tph->get_dscp_codepoint ();
650 tos = static_cast<int> (codepoint) << 2;
651 this->set_tos (tos);
655 return 0;
658 void
659 TAO_IIOP_Connection_Handler::abort ()
661 struct linger lval = { 0, 0 };
662 lval.l_onoff = 1;
664 if (this->peer ().set_option(SOL_SOCKET,
665 SO_LINGER,
666 (void*) &lval,
667 sizeof (lval)) == -1)
669 if (TAO_debug_level)
671 TAOLIB_DEBUG ((LM_DEBUG,
672 ACE_TEXT ("TAO (%P|%t) Unable to set ")
673 ACE_TEXT ("SO_LINGER on %d\n"),
674 this->peer ().get_handle ()));
680 TAO_IIOP_Connection_Handler::handle_write_ready (const ACE_Time_Value *timeout)
682 return ACE::handle_write_ready (this->peer ().get_handle (), timeout);
685 TAO_END_VERSIONED_NAMESPACE_DECL
687 #endif /* TAO_HAS_IIOP && TAO_HAS_IIOP != 0 */