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 78931 2007-07-18 09:59:36Z 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 <%s:%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   const int result =
00301     this->handle_output_eh (handle, this);
00302 
00303   if (result == -1)
00304     {
00305       this->close_connection ();
00306       return 0;
00307     }
00308 
00309   return result;
00310 }
00311 
00312 
00313 int
00314 TAO_IIOP_Connection_Handler::handle_timeout (const ACE_Time_Value &,
00315                                              const void *)
00316 {
00317   // Using this to ensure this instance will be deleted (if necessary)
00318   // only after reset_state(). Without this, when this refcount==1 -
00319   // the call to close() will cause a call to remove_reference() which
00320   // will delete this. At that point this->reset_state() is in no
00321   // man's territory and that causes SEGV on some platforms (Windows!)
00322 
00323   TAO_Auto_Reference<TAO_IIOP_Connection_Handler> safeguard (*this);
00324 
00325   // NOTE: Perhaps not the best solution, as it feels like the upper
00326   // layers should be responsible for this?
00327 
00328   // We don't use this upcall for I/O.  This is only used by the
00329   // Connector to indicate that the connection timedout.  Therefore,
00330   // we should call close()
00331 
00332   int const ret = this->close ();
00333   this->reset_state (TAO_LF_Event::LFS_TIMEOUT);
00334 
00335   return ret;
00336 }
00337 
00338 int
00339 TAO_IIOP_Connection_Handler::handle_close (ACE_HANDLE,
00340                                            ACE_Reactor_Mask)
00341 {
00342   ACE_ASSERT (0);
00343   return 0;
00344 }
00345 
00346 int
00347 TAO_IIOP_Connection_Handler::close (u_long)
00348 {
00349   return this->close_handler ();
00350 }
00351 
00352 int
00353 TAO_IIOP_Connection_Handler::release_os_resources (void)
00354 {
00355   return this->peer ().close ();
00356 }
00357 
00358 int
00359 TAO_IIOP_Connection_Handler::add_transport_to_cache (void)
00360 {
00361   ACE_INET_Addr addr;
00362 
00363   // Get the peername.
00364   if (this->peer ().get_remote_addr (addr) == -1)
00365     return -1;
00366 
00367   // Construct an  IIOP_Endpoint object
00368   TAO_IIOP_Endpoint endpoint (
00369       addr,
00370       this->orb_core()->orb_params()->cache_incoming_by_dotted_decimal_address ());
00371 
00372   // Construct a property object
00373   TAO_Base_Transport_Property prop (&endpoint);
00374 
00375   TAO::Transport_Cache_Manager &cache =
00376     this->orb_core ()->lane_resources ().transport_cache ();
00377 
00378   // Idle the transport..
00379   return cache.cache_idle_transport (&prop,
00380                                      this->transport ());
00381 }
00382 
00383 int
00384 TAO_IIOP_Connection_Handler::process_listen_point_list (
00385     IIOP::ListenPointList &listen_list)
00386 {
00387   // Get the size of the list
00388   const CORBA::ULong len = listen_list.length ();
00389 
00390   if (TAO_debug_level > 0 && len == 0)
00391     {
00392       ACE_ERROR ((LM_ERROR,
00393                   ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler::")
00394                   ACE_TEXT("process_listen_point_list, ")
00395                   ACE_TEXT("Received list of size 0, check client config.\n")));
00396     }
00397 
00398   for (CORBA::ULong i = 0; i < len; ++i)
00399     {
00400       IIOP::ListenPoint listen_point = listen_list[i];
00401       ACE_INET_Addr addr (listen_point.port,
00402                           listen_point.host.in ());
00403 
00404       if (TAO_debug_level > 0)
00405         {
00406           ACE_DEBUG ((LM_DEBUG,
00407                       ACE_TEXT("TAO (%P|%t) - IIOP_Connection_Handler::")
00408                       ACE_TEXT("process_listen_point_list, ")
00409                       ACE_TEXT("Listening port [%d] on [%s]\n"),
00410                       listen_point.port,
00411                       ACE_TEXT_CHAR_TO_TCHAR(listen_point.host.in ())));
00412         }
00413 
00414       // Construct an  IIOP_Endpoint object using the host as provided
00415       // in the listen point list.  We must use host in that form because
00416       // that's also how the ORB on the other side will advertise the host
00417       // in an IOR.
00418       TAO_IIOP_Endpoint endpoint (listen_point.host.in (),
00419                                   listen_point.port, addr);
00420 
00421       // Construct a property object
00422       TAO_Base_Transport_Property prop (&endpoint);
00423 
00424       // Mark the connection as bidirectional
00425       prop.set_bidir_flag (1);
00426 
00427       // The property for this handler has changed. Recache the
00428       // handler with this property
00429       int retval =
00430         this->transport ()->recache_transport (&prop);
00431 
00432       if (retval == -1)
00433         return retval;
00434 
00435       // Make the handler idle and ready for use
00436       this->transport ()->make_idle ();
00437     }
00438 
00439   return 0;
00440 }
00441 
00442 int
00443 TAO_IIOP_Connection_Handler::set_tos (int tos)
00444 {
00445   if (tos != this->dscp_codepoint_)
00446     {
00447       int result = 0;
00448 #if defined (ACE_HAS_IPV6)
00449       ACE_INET_Addr local_addr;
00450       if (this->peer ().get_local_addr (local_addr) == -1)
00451         return -1;
00452       else if (local_addr.get_type () == AF_INET6)
00453 # if !defined (IPV6_TCLASS)
00454       // IPv6 defines option IPV6_TCLASS for specifying traffic class/priority
00455       // but not many implementations yet (very new;-).
00456         {
00457           if (TAO_debug_level)
00458             {
00459               ACE_DEBUG ((LM_DEBUG,
00460                           "TAO (%P|%t) - IIOP_Connection_Handler::"
00461                           "set_dscp_codepoint -> IPV6_TCLASS not supported yet\n"));
00462             }
00463           return 0;
00464         }
00465 # else /* !IPV6_TCLASS */
00466         result = this->peer ().set_option (IPPROTO_IPV6,
00467                                            IPV6_TCLASS,
00468                                            (int *) &tos ,
00469                                            (int) sizeof (tos));
00470       else
00471 # endif /* IPV6_TCLASS */
00472 #endif /* ACE_HAS_IPV6 */
00473       result = this->peer ().set_option (IPPROTO_IP,
00474                                          IP_TOS,
00475                                          (int *) &tos ,
00476                                          (int) sizeof (tos));
00477 
00478       if (TAO_debug_level)
00479         {
00480           ACE_DEBUG ((LM_DEBUG,
00481                       "TAO (%P|%t) - IIOP_Connection_Handler::"
00482                       "set_dscp_codepoint -> dscp: %x; result: %d; %s\n",
00483                       tos,
00484                       result,
00485                       result == -1 ? "try running as superuser" : ""));
00486         }
00487 
00488       // On successful setting of TOS field.
00489       if (result == 0)
00490         this->dscp_codepoint_ = tos;
00491     }
00492   return 0;
00493 }
00494 
00495 int
00496 TAO_IIOP_Connection_Handler::set_dscp_codepoint (CORBA::Long dscp_codepoint)
00497 {
00498   int tos = IPDSFIELD_DSCP_DEFAULT << 2;
00499 
00500   CORBA::Long codepoint = dscp_codepoint;
00501 
00502   tos = static_cast<int> (codepoint) << 2;
00503 
00504   this->set_tos (tos);
00505 
00506   return 0;
00507 }
00508 
00509 int
00510 TAO_IIOP_Connection_Handler::set_dscp_codepoint (CORBA::Boolean set_network_priority)
00511 {
00512   int tos = IPDSFIELD_DSCP_DEFAULT << 2;
00513 
00514   if (set_network_priority)
00515     {
00516       TAO_Protocols_Hooks *tph = this->orb_core ()->get_protocols_hooks ();
00517 
00518       if (tph != 0)
00519         {
00520           CORBA::Long codepoint =
00521             tph->get_dscp_codepoint ();
00522 
00523           tos = static_cast<int> (codepoint) << 2;
00524           this->set_tos (tos);
00525         }
00526     }
00527 
00528   return 0;
00529 }
00530 
00531 void
00532 TAO_IIOP_Connection_Handler::abort (void)
00533 {
00534   struct linger lval;
00535   lval.l_onoff = 1;
00536   lval.l_linger = 0;
00537 
00538   if (this->peer ().set_option(SOL_SOCKET,
00539                                SO_LINGER,
00540                                (void*) &lval,
00541                                sizeof (lval)) == -1)
00542     {
00543       if (TAO_debug_level)
00544         {
00545           ACE_DEBUG ((LM_DEBUG,
00546                       ACE_TEXT ("TAO (%P|%t) Unable to set ")
00547                       ACE_TEXT ("SO_LINGER on %d\n"),
00548                       this->peer ().get_handle ()));
00549         }
00550     }
00551 }
00552 
00553 
00554 
00555 //@@ CONNECTION_HANDLER_SPL_COPY_HOOK_END
00556 /*
00557  * End copy hook
00558  */
00559 
00560 TAO_END_VERSIONED_NAMESPACE_DECL
00561 
00562 #endif /* TAO_HAS_IIOP && TAO_HAS_IIOP != 0 */

Generated on Sun Jan 27 13:07:33 2008 for TAO by doxygen 1.3.6