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
00030
00031
00032
00033
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
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
00068
00069
00070
00071
00072
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
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
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
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
00172
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
00211
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
00230
00231 if (TAO_debug_level > 0)
00232 {
00233 ACE_TCHAR client_addr[MAXHOSTNAMELEN + 16];
00234
00235
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
00246
00247
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
00266
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
00317
00318
00319
00320
00321
00322 TAO_Auto_Reference<TAO_IIOP_Connection_Handler> safeguard (*this);
00323
00324
00325
00326
00327
00328
00329
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
00362 if (this->peer ().get_remote_addr (addr) == -1)
00363 return -1;
00364
00365
00366 TAO_IIOP_Endpoint endpoint (
00367 addr,
00368 this->orb_core()->orb_params()->cache_incoming_by_dotted_decimal_address ());
00369
00370
00371 TAO_Base_Transport_Property prop (&endpoint);
00372
00373 TAO::Transport_Cache_Manager &cache =
00374 this->orb_core ()->lane_resources ().transport_cache ();
00375
00376
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
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
00412
00413
00414
00415 TAO_IIOP_Endpoint endpoint (listen_point.host.in (),
00416 listen_point.port, addr);
00417
00418
00419 TAO_Base_Transport_Property prop (&endpoint);
00420
00421
00422 prop.set_bidir_flag (1);
00423
00424
00425
00426 if (this->transport ()->recache_transport (&prop) == -1)
00427 return -1;
00428
00429
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
00449
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
00460 result = this->peer ().set_option (IPPROTO_IPV6,
00461 IPV6_TCLASS,
00462 (int *) &tos ,
00463 (int) sizeof (tos));
00464 else
00465 # endif
00466 #endif
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
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
00549
00550
00551
00552
00553 TAO_END_VERSIONED_NAMESPACE_DECL
00554
00555 #endif