IIOP_Connection_Handler.cpp

Go to the documentation of this file.
00001 #include "tao/IIOP_Connection_Handler.h"
00002 
00003 #if defined (TAO_HAS_IIOP) && (TAO_HAS_IIOP != 0)
00004 
00005 #include "tao/debug.h"
00006 #include "tao/ORB_Core.h"
00007 #include "tao/IIOP_Transport.h"
00008 #include "tao/IIOP_Endpoint.h"
00009 #include "tao/IIOPC.h"
00010 #include "tao/Thread_Lane_Resources.h"
00011 #include "tao/Base_Transport_Property.h"
00012 #include "tao/Protocols_Hooks.h"
00013 #include "tao/Wait_Strategy.h"
00014 
00015 #include "ace/os_include/netinet/os_tcp.h"
00016 #include "ace/os_include/os_netdb.h"
00017 
00018 ACE_RCSID (tao,
00019            IIOP_Connection_Handler,
00020            "IIOP_Connection_Handler.cpp,v 1.113 2006/05/16 06:10:47 mesnier_p Exp")
00021 
00022 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00023 
00024 TAO_IIOP_Connection_Handler::TAO_IIOP_Connection_Handler (ACE_Thread_Manager *t)
00025   : TAO_IIOP_SVC_HANDLER (t, 0 , 0),
00026     TAO_Connection_Handler (0),
00027     dscp_codepoint_ (IPDSFIELD_DSCP_DEFAULT << 2)
00028 {
00029   // This constructor should *never* get called, it is just here to
00030   // make the compiler happy: the default implementation of the
00031   // Creation_Strategy requires a constructor with that signature, we
00032   // don't use that implementation, but some (most?) compilers
00033   // instantiate it anyway.
00034   ACE_ASSERT (0);
00035 }
00036 
00037 
00038 TAO_IIOP_Connection_Handler::TAO_IIOP_Connection_Handler (
00039   TAO_ORB_Core *orb_core,
00040   CORBA::Boolean flag)
00041   : TAO_IIOP_SVC_HANDLER (orb_core->thr_mgr (), 0, 0),
00042     TAO_Connection_Handler (orb_core),
00043     dscp_codepoint_ (IPDSFIELD_DSCP_DEFAULT << 2)
00044 {
00045   TAO_IIOP_Transport* specific_transport = 0;
00046   ACE_NEW (specific_transport,
00047            TAO_IIOP_Transport (this, orb_core, flag));
00048 
00049   // store this pointer (indirectly increment ref count)
00050   this->transport (specific_transport);
00051 }
00052 
00053 TAO_IIOP_Connection_Handler::TAO_IIOP_Connection_Handler (TAO_ORB_Core *orb_core)
00054   : TAO_IIOP_SVC_HANDLER (orb_core->thr_mgr (), 0, 0),
00055     TAO_Connection_Handler (orb_core),
00056     dscp_codepoint_ (IPDSFIELD_DSCP_DEFAULT << 2)
00057 {
00058 }
00059 
00060 TAO_IIOP_Connection_Handler::~TAO_IIOP_Connection_Handler (void)
00061 {
00062   delete this->transport ();
00063 }
00064 
00065 /* Copy hook that copies over the concrete methods from this class
00066  * to the base Connection_Handler class as a part of the specialization
00067  * process. Add all concrete and virtual
00068  * methods implemented in this class within this hook.
00069  */
00070 //@@ CONNECTION_HANDLER_SPL_COPY_HOOK_START
00071 
00072 int
00073 TAO_IIOP_Connection_Handler::open_handler (void *v)
00074 {
00075   return this->open (v);
00076 }
00077 
00078 int
00079 TAO_IIOP_Connection_Handler::open (void*)
00080 {
00081   TAO_IIOP_Protocol_Properties protocol_properties;
00082 
00083   // Initialize values from ORB params.
00084   protocol_properties.send_buffer_size_ =
00085     this->orb_core ()->orb_params ()->sock_sndbuf_size ();
00086   protocol_properties.recv_buffer_size_ =
00087     this->orb_core ()->orb_params ()->sock_rcvbuf_size ();
00088   protocol_properties.no_delay_ =
00089     this->orb_core ()->orb_params ()->nodelay ();
00090   protocol_properties.keep_alive_ =
00091     this->orb_core ()->orb_params ()->sock_keepalive ();
00092   protocol_properties.dont_route_ =
00093    this->orb_core ()->orb_params ()->sock_dontroute ();
00094 
00095   TAO_Protocols_Hooks *tph =
00096     this->orb_core ()->get_protocols_hooks ();
00097 
00098   bool const client =
00099     this->transport ()->opened_as () == TAO::TAO_CLIENT_ROLE;
00100 
00101   ACE_DECLARE_NEW_CORBA_ENV;
00102 
00103   ACE_TRY
00104     {
00105       if (client)
00106         {
00107           tph->client_protocol_properties_at_orb_level (
00108             protocol_properties
00109             ACE_ENV_ARG_PARAMETER);
00110           ACE_TRY_CHECK;
00111         }
00112       else
00113         {
00114           tph->server_protocol_properties_at_orb_level (
00115             protocol_properties
00116             ACE_ENV_ARG_PARAMETER);
00117           ACE_TRY_CHECK;
00118         }
00119     }
00120   ACE_CATCHANY
00121     {
00122       return -1;
00123     }
00124   ACE_ENDTRY;
00125   ACE_CHECK_RETURN (-1);
00126 
00127   if (this->set_socket_option (this->peer (),
00128                                protocol_properties.send_buffer_size_,
00129                                protocol_properties.recv_buffer_size_) == -1)
00130     return -1;
00131 
00132 #if !defined (ACE_LACKS_TCP_NODELAY)
00133   if (this->peer ().set_option (ACE_IPPROTO_TCP,
00134                                 TCP_NODELAY,
00135                                 (void *) &protocol_properties.no_delay_,
00136                                 sizeof (protocol_properties.no_delay_)) == -1)
00137     return -1;
00138 #endif /* ! ACE_LACKS_TCP_NODELAY */
00139 
00140   if (protocol_properties.keep_alive_)
00141     {
00142       if (this->peer ().
00143           set_option (SOL_SOCKET,
00144                       SO_KEEPALIVE,
00145                       (void *) &protocol_properties.keep_alive_,
00146                       sizeof (protocol_properties.keep_alive_)) == -1
00147           && errno != ENOTSUP)
00148         {
00149           return -1;
00150         }
00151     }
00152 
00153 #if !defined (ACE_LACKS_SO_DONTROUTE)
00154   if (protocol_properties.dont_route_)
00155     {
00156       if (this->peer ().
00157           set_option (SOL_SOCKET,
00158                       SO_DONTROUTE,
00159                       (void *) &protocol_properties.dont_route_,
00160                       sizeof (protocol_properties.dont_route_)) == -1
00161           && errno != ENOTSUP)
00162         {
00163           return -1;
00164         }
00165     }
00166 #endif /* ! ACE_LACKS_SO_DONTROUTE */
00167 
00168   if (this->transport ()->wait_strategy ()->non_blocking ()
00169       || this->transport ()->opened_as () == TAO::TAO_SERVER_ROLE)
00170     {
00171       if (this->peer ().enable (ACE_NONBLOCK) == -1)
00172         return -1;
00173     }
00174 
00175   // Called by the <Strategy_Acceptor> when the handler is
00176   // completely connected.
00177 
00178   ACE_INET_Addr remote_addr;
00179   if (this->peer ().get_remote_addr (remote_addr) == -1)
00180     return -1;
00181 
00182   ACE_INET_Addr local_addr;
00183   if (this->peer ().get_local_addr (local_addr) == -1)
00184     return -1;
00185 
00186   if (TAO_debug_level > 2)
00187     ACE_DEBUG ((LM_DEBUG,
00188                 ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler::open, ")
00189                 ACE_TEXT("The local addr is <%s:%d> \n"),
00190                 local_addr.get_host_addr (),
00191                 local_addr.get_port_number()));
00192 
00193   if (local_addr == remote_addr)
00194     {
00195       if (TAO_debug_level > 0)
00196         {
00197           ACE_TCHAR remote_as_string[MAXHOSTNAMELEN + 16];
00198           ACE_TCHAR local_as_string[MAXHOSTNAMELEN + 16];
00199 
00200           (void) remote_addr.addr_to_string (remote_as_string,
00201                                              sizeof(remote_as_string));
00202           (void) local_addr.addr_to_string (local_as_string,
00203                                             sizeof(local_as_string));
00204           ACE_ERROR ((LM_ERROR,
00205                       ACE_TEXT("TAO(%P|%t) - IIOP_Connection_Handler::open, ")
00206                       ACE_TEXT("Holy Cow! The remote addr and ")
00207                       ACE_TEXT("local addr are identical (%s == %s)\n"),
00208                       remote_as_string, local_as_string));
00209         }
00210       return -1;
00211     }
00212 
00213 #if defined (ACE_HAS_IPV6) && !defined (ACE_HAS_IPV6_V6ONLY)
00214   // Check if we need to invalidate accepted connections
00215   // from IPv4 mapped IPv6 addresses
00216   if (this->orb_core ()->orb_params ()->connect_ipv6_only () &&
00217       remote_addr.is_ipv4_mapped_ipv6 ())
00218     {
00219       if (TAO_debug_level > 0)
00220         {
00221           ACE_TCHAR remote_as_string[MAXHOSTNAMELEN + 16];
00222 
00223           (void) remote_addr.addr_to_string (remote_as_string,
00224                                              sizeof(remote_as_string));
00225 
00226           ACE_ERROR ((LM_WARNING,
00227                       ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler::open, ")
00228                       ACE_TEXT("invalid connection from IPv4 mapped IPv6 interface <%s>!\n"),
00229                       remote_as_string));
00230         }
00231       return -1;
00232     }
00233 #endif /* ACE_HAS_IPV6 && ACE_HAS_IPV6_V6ONLY */
00234 
00235   if (TAO_debug_level > 0)
00236     {
00237       ACE_TCHAR client_addr[MAXHOSTNAMELEN + 16];
00238 
00239       // Verify that we can resolve the peer hostname.
00240       if (remote_addr.addr_to_string (client_addr, sizeof (client_addr)) == -1)
00241         return -1;
00242 
00243       ACE_DEBUG ((LM_DEBUG,
00244                   ACE_TEXT ("TAO (%P|%t) - IIOP_Connection_Handler::open, IIOP ")
00245                   ACE_TEXT ("connection to peer <%s> on %d\n"),
00246                   client_addr, this->peer ().get_handle ()));
00247     }
00248 
00249   // Set that the transport is now connected, if fails we return -1
00250   // Use C-style cast b/c otherwise we get warnings on lots of
00251   // compilers
00252   if (!this->transport ()->post_open ((size_t) this->get_handle ()))
00253     return -1;
00254 
00255   this->state_changed (TAO_LF_Event::LFS_SUCCESS,
00256                        this->orb_core ()->leader_follower ());
00257 
00258   return 0;
00259 }
00260 
00261 int
00262 TAO_IIOP_Connection_Handler::resume_handler (void)
00263 {
00264   return ACE_Event_Handler::ACE_APPLICATION_RESUMES_HANDLER;
00265 }
00266 
00267 int
00268 TAO_IIOP_Connection_Handler::close_connection (void)
00269 {
00270   // To maintain maximum compatibility, we only set this socket option
00271   // if the user has provided a linger timeout.
00272   int linger = this->orb_core()->orb_params()->linger ();
00273   if (linger != -1)
00274     {
00275       struct linger lval;
00276       lval.l_onoff = 1;
00277       lval.l_linger = (u_short)linger;
00278 
00279       if (this->peer ().set_option(SOL_SOCKET,
00280                                    SO_LINGER,
00281                                    (void*) &lval,
00282                                    sizeof (lval)) == -1)
00283         {
00284           if (TAO_debug_level)
00285             {
00286               ACE_DEBUG ((LM_DEBUG,
00287                           ACE_TEXT ("TAO (%P|%t) Unable to set ")
00288                           ACE_TEXT ("SO_LINGER on %d\n"),
00289                           this->peer ().get_handle ()));
00290             }
00291         }
00292     }
00293 
00294   return this->close_connection_eh (this);
00295 }
00296 
00297 int
00298 TAO_IIOP_Connection_Handler::handle_input (ACE_HANDLE h)
00299 {
00300   return this->handle_input_eh (h, this);
00301 }
00302 
00303 int
00304 TAO_IIOP_Connection_Handler::handle_output (ACE_HANDLE handle)
00305 {
00306   const int result =
00307     this->handle_output_eh (handle, this);
00308 
00309   if (result == -1)
00310     {
00311       this->close_connection ();
00312       return 0;
00313     }
00314 
00315   return result;
00316 }
00317 
00318 int
00319 TAO_IIOP_Connection_Handler::handle_timeout (const ACE_Time_Value &,
00320                                              const void *)
00321 {
00322   // We don't use this upcall for I/O.  This is only used by the
00323   // Connector to indicate that the connection timedout.  Therefore,
00324   // we should call close().
00325   return this->close ();
00326 }
00327 
00328 int
00329 TAO_IIOP_Connection_Handler::handle_close (ACE_HANDLE,
00330                                            ACE_Reactor_Mask)
00331 {
00332   ACE_ASSERT (0);
00333   return 0;
00334 }
00335 
00336 int
00337 TAO_IIOP_Connection_Handler::close (u_long)
00338 {
00339   return this->close_handler ();
00340 }
00341 
00342 int
00343 TAO_IIOP_Connection_Handler::release_os_resources (void)
00344 {
00345   return this->peer ().close ();
00346 }
00347 
00348 int
00349 TAO_IIOP_Connection_Handler::add_transport_to_cache (void)
00350 {
00351   ACE_INET_Addr addr;
00352 
00353   // Get the peername.
00354   if (this->peer ().get_remote_addr (addr) == -1)
00355     return -1;
00356 
00357   // Construct an  IIOP_Endpoint object
00358   TAO_IIOP_Endpoint endpoint (
00359       addr,
00360       this->orb_core()->orb_params()->cache_incoming_by_dotted_decimal_address ());
00361 
00362   // Construct a property object
00363   TAO_Base_Transport_Property prop (&endpoint);
00364 
00365   TAO::Transport_Cache_Manager &cache =
00366     this->orb_core ()->lane_resources ().transport_cache ();
00367 
00368   // Idle the transport..
00369   return cache.cache_idle_transport (&prop,
00370                                      this->transport ());
00371 }
00372 
00373 int
00374 TAO_IIOP_Connection_Handler::process_listen_point_list (
00375     IIOP::ListenPointList &listen_list)
00376 {
00377   // Get the size of the list
00378   const CORBA::ULong len = listen_list.length ();
00379 
00380   if (TAO_debug_level > 0 && len == 0)
00381     {
00382       ACE_ERROR ((LM_ERROR,
00383                   ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler::")
00384                   ACE_TEXT("process_listen_point_list, ")
00385                   ACE_TEXT("Received list of size 0, check client config.\n")));
00386     }
00387 
00388   for (CORBA::ULong i = 0; i < len; ++i)
00389     {
00390       IIOP::ListenPoint listen_point = listen_list[i];
00391       ACE_INET_Addr addr (listen_point.port,
00392                           listen_point.host.in ());
00393 
00394       if (TAO_debug_level > 0)
00395         {
00396           ACE_DEBUG ((LM_DEBUG,
00397                       ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler::")
00398                       ACE_TEXT("process_listen_point_list, ")
00399                       ACE_TEXT("Listening port [%d] on [%s]\n"),
00400                       listen_point.port,
00401                       ACE_TEXT_CHAR_TO_TCHAR(listen_point.host.in ())));
00402         }
00403 
00404       // Construct an  IIOP_Endpoint object using the host as provided
00405       // in the listen point list.  We must use host in that form because
00406       // that's also how the ORB on the other side will advertise the host
00407       // in an IOR.
00408       TAO_IIOP_Endpoint endpoint (listen_point.host.in (),
00409                                   listen_point.port, addr);
00410 
00411       // Construct a property object
00412       TAO_Base_Transport_Property prop (&endpoint);
00413 
00414       // Mark the connection as bidirectional
00415       prop.set_bidir_flag (1);
00416 
00417       // The property for this handler has changed. Recache the
00418       // handler with this property
00419       int retval =
00420         this->transport ()->recache_transport (&prop);
00421 
00422       if (retval == -1)
00423         return retval;
00424 
00425       // Make the handler idle and ready for use
00426       this->transport ()->make_idle ();
00427     }
00428 
00429   return 0;
00430 }
00431 
00432 int
00433 TAO_IIOP_Connection_Handler::set_dscp_codepoint (CORBA::Boolean set_network_priority)
00434 {
00435   int tos = IPDSFIELD_DSCP_DEFAULT << 2;
00436 
00437   if (set_network_priority)
00438     {
00439       TAO_Protocols_Hooks *tph =
00440         this->orb_core ()->get_protocols_hooks ();
00441 
00442       CORBA::Long codepoint =
00443         tph->get_dscp_codepoint ();
00444 
00445       tos = static_cast<int> (codepoint) << 2;
00446     }
00447 
00448   if (tos != this->dscp_codepoint_)
00449     {
00450       int result = 0;
00451 #if defined (ACE_HAS_IPV6)
00452       ACE_INET_Addr local_addr;
00453       if (this->peer ().get_local_addr (local_addr) == -1)
00454         return -1;
00455       else if (local_addr.get_type () == AF_INET6)
00456 # if !defined (IPV6_TCLASS)
00457       // IPv6 defines option IPV6_TCLASS for specifying traffic class/priority
00458       // but not many implementations yet (very new;-).
00459         {
00460           if (TAO_debug_level)
00461             {
00462               ACE_DEBUG ((LM_DEBUG,
00463                           "TAO (%P|%t) - IIOP_Connection_Handler::"
00464                           "set_dscp_codepoint -> IPV6_TCLASS not supported yet\n"));
00465             }
00466           return 0;
00467         }
00468 # else /* !IPV6_TCLASS */
00469         result = this->peer ().set_option (IPPROTO_IPV6,
00470                                            IPV6_TCLASS,
00471                                            (int *) &tos ,
00472                                            (int) sizeof (tos));
00473       else
00474 # endif /* IPV6_TCLASS */
00475 #endif /* ACE_HAS_IPV6 */
00476       result = this->peer ().set_option (IPPROTO_IP,
00477                                          IP_TOS,
00478                                          (int *) &tos ,
00479                                          (int) sizeof (tos));
00480 
00481       if (TAO_debug_level)
00482         {
00483           ACE_DEBUG ((LM_DEBUG,
00484                       "TAO (%P|%t) - IIOP_Connection_Handler::"
00485                       "set_dscp_codepoint -> dscp: %x; result: %d; %s\n",
00486                       tos,
00487                       result,
00488                       result == -1 ? "try running as superuser" : ""));
00489         }
00490 
00491       // On successful setting of TOS field.
00492       if (result == 0)
00493         this->dscp_codepoint_ = tos;
00494 
00495     }
00496 
00497   return 0;
00498 }
00499 
00500 void
00501 TAO_IIOP_Connection_Handler::abort (void)
00502 {
00503   struct linger lval;
00504   lval.l_onoff = 1;
00505   lval.l_linger = 0;
00506 
00507   if (this->peer ().set_option(SOL_SOCKET,
00508                                SO_LINGER,
00509                                (void*) &lval,
00510                                sizeof (lval)) == -1)
00511     {
00512       if (TAO_debug_level)
00513         {
00514           ACE_DEBUG ((LM_DEBUG,
00515                       ACE_TEXT ("TAO (%P|%t) Unable to set ")
00516                       ACE_TEXT ("SO_LINGER on %d\n"),
00517                       this->peer ().get_handle ()));
00518         }
00519     }
00520 }
00521 
00522 
00523 
00524 //@@ CONNECTION_HANDLER_SPL_COPY_HOOK_END
00525 /*
00526  * End copy hook
00527  */
00528 
00529 TAO_END_VERSIONED_NAMESPACE_DECL
00530 
00531 #endif /* TAO_HAS_IIOP && TAO_HAS_IIOP != 0 */

Generated on Thu Nov 9 11:54:13 2006 for TAO by doxygen 1.3.6