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

Generated on Tue Feb 2 17:37:52 2010 for TAO by  doxygen 1.4.7