00001 #include "tao/IIOP_Transport.h"
00002
00003 #if defined (TAO_HAS_IIOP) && (TAO_HAS_IIOP != 0)
00004
00005 #include "tao/IIOP_Acceptor.h"
00006 #include "tao/IIOPC.h"
00007 #include "tao/Acceptor_Registry.h"
00008 #include "tao/operation_details.h"
00009 #include "tao/Wait_Strategy.h"
00010 #include "tao/debug.h"
00011 #include "tao/GIOP_Message_Base.h"
00012 #include "tao/Protocols_Hooks.h"
00013 #include "tao/ORB_Core.h"
00014 #include "tao/Thread_Lane_Resources.h"
00015 #include "tao/Transport_Mux_Strategy.h"
00016 #include "tao/MMAP_Allocator.h"
00017
00018 #include "ace/OS_NS_sys_sendfile.h"
00019
00020 ACE_RCSID (tao,
00021 IIOP_Transport,
00022 "$Id: IIOP_Transport.cpp 79159 2007-08-01 16:41:24Z wilsond $")
00023
00024 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00025
00026 TAO_IIOP_Transport::TAO_IIOP_Transport (TAO_IIOP_Connection_Handler *handler,
00027 TAO_ORB_Core *orb_core)
00028 : TAO_Transport (IOP::TAG_INTERNET_IOP,
00029 orb_core)
00030 , connection_handler_ (handler)
00031 , messaging_object_ (0)
00032 {
00033
00034 ACE_NEW (this->messaging_object_,
00035 TAO_GIOP_Message_Base (orb_core, this));
00036 }
00037
00038 TAO_IIOP_Transport::~TAO_IIOP_Transport (void)
00039 {
00040 delete this->messaging_object_;
00041 }
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 ACE_Event_Handler *
00054 TAO_IIOP_Transport::event_handler_i (void)
00055 {
00056 return this->connection_handler_;
00057 }
00058
00059 TAO_Connection_Handler *
00060 TAO_IIOP_Transport::connection_handler_i (void)
00061 {
00062 return this->connection_handler_;
00063 }
00064
00065 TAO_Pluggable_Messaging *
00066 TAO_IIOP_Transport::messaging_object (void)
00067 {
00068 return this->messaging_object_;
00069 }
00070
00071 ssize_t
00072 TAO_IIOP_Transport::send (iovec *iov, int iovcnt,
00073 size_t &bytes_transferred,
00074 const ACE_Time_Value *max_wait_time)
00075 {
00076 ssize_t const retval =
00077 this->connection_handler_->peer ().sendv (iov,
00078 iovcnt,
00079 max_wait_time);
00080
00081 if (retval > 0)
00082 bytes_transferred = retval;
00083 else
00084 {
00085 if (TAO_debug_level > 4)
00086 {
00087 ACE_DEBUG ((LM_DEBUG,
00088 ACE_TEXT ("TAO (%P|%t) - IIOP_Transport[%d]::send, ")
00089 ACE_TEXT ("send failure - %m (errno: %d)\n"),
00090 this->id (), errno));
00091 }
00092 }
00093
00094 return retval;
00095 }
00096
00097 #if TAO_HAS_SENDFILE == 1
00098 ssize_t
00099 TAO_IIOP_Transport::sendfile (TAO_MMAP_Allocator * allocator,
00100 iovec * iov,
00101 int iovcnt,
00102 size_t &bytes_transferred,
00103 ACE_Time_Value const * timeout)
00104 {
00105
00106
00107
00108
00109
00110
00111 if (allocator == 0)
00112 return this->send (iov, iovcnt, bytes_transferred, timeout);
00113
00114
00115
00116 iovec * const off_check_begin = iov;
00117 iovec * const off_check_end = iov + iovcnt;
00118 for (iovec * index = off_check_begin; index != off_check_end; ++index)
00119 {
00120 if (-1 == allocator->offset (index->iov_base))
00121 return this->send (iov, iovcnt, bytes_transferred, timeout);
00122 }
00123
00124 ssize_t retval = -1;
00125
00126 ACE_HANDLE const in_fd = allocator->handle ();
00127
00128 if (in_fd == ACE_INVALID_HANDLE)
00129 return retval;
00130
00131 ACE_HANDLE const out_fd =
00132 this->connection_handler_->peer ().get_handle ();
00133
00134 iovec * const begin = iov;
00135 iovec * const end = iov + iovcnt;
00136 for (iovec * i = begin; i != end; ++i)
00137 {
00138 off_t offset = allocator->offset (i->iov_base);
00139
00140 if (timeout)
00141 {
00142 int val = 0;
00143 if (ACE::enter_send_timedwait (out_fd, timeout, val) == -1)
00144 return retval;
00145 else
00146 {
00147 retval =
00148 ACE_OS::sendfile (out_fd, in_fd, &offset, i->iov_len);
00149 ACE::restore_non_blocking_mode (out_fd, val);
00150
00151 }
00152 }
00153 else
00154 {
00155 retval = ACE_OS::sendfile (out_fd, in_fd, &offset, i->iov_len);
00156 }
00157
00158 if (retval <= 0)
00159 break;
00160
00161 bytes_transferred += static_cast<size_t> (retval);
00162 }
00163
00164 if (retval <= 0 && TAO_debug_level > 4)
00165 {
00166 ACE_DEBUG ((LM_DEBUG,
00167 ACE_TEXT ("TAO (%P|%t) - IIOP_Transport[%d]::sendfile, ")
00168 ACE_TEXT ("sendfile failure - %m (errno: %d)\n"),
00169 this->id (),
00170 errno));
00171 }
00172
00173 return retval;
00174 }
00175 #endif
00176
00177 ssize_t
00178 TAO_IIOP_Transport::recv (char *buf,
00179 size_t len,
00180 const ACE_Time_Value *max_wait_time)
00181 {
00182 ssize_t const n = this->connection_handler_->peer ().recv (buf,
00183 len,
00184 max_wait_time);
00185
00186
00187
00188 if (n == -1 &&
00189 TAO_debug_level > 4 &&
00190 errno != ETIME)
00191 {
00192
00193 ACE_DEBUG ((LM_DEBUG,
00194 ACE_TEXT ("TAO (%P|%t) - IIOP_Transport[%d]::recv, ")
00195 ACE_TEXT ("read failure - %m errno %d\n"),
00196 this->id (),
00197 errno));
00198 }
00199
00200
00201 if (n == -1)
00202 {
00203 if (errno == EWOULDBLOCK)
00204 return 0;
00205
00206 return -1;
00207 }
00208
00209
00210
00211
00212
00213 else if (n == 0)
00214 {
00215 return -1;
00216 }
00217
00218 return n;
00219 }
00220
00221 int
00222 TAO_IIOP_Transport::send_request (TAO_Stub *stub,
00223 TAO_ORB_Core *orb_core,
00224 TAO_OutputCDR &stream,
00225 int message_semantics,
00226 ACE_Time_Value *max_wait_time)
00227 {
00228 if (this->ws_->sending_request (orb_core,
00229 message_semantics) == -1)
00230
00231 return -1;
00232
00233 if (this->send_message (stream,
00234 stub,
00235 message_semantics,
00236 max_wait_time) == -1)
00237 return -1;
00238
00239 this->first_request_sent();
00240
00241 return 0;
00242 }
00243
00244 int
00245 TAO_IIOP_Transport::send_message (TAO_OutputCDR &stream,
00246 TAO_Stub *stub,
00247 int message_semantics,
00248 ACE_Time_Value *max_wait_time)
00249 {
00250
00251 if (this->messaging_object_->format_message (stream) != 0)
00252 return -1;
00253
00254
00255 ssize_t const n = this->send_message_shared (stub,
00256 message_semantics,
00257 stream.begin (),
00258 max_wait_time);
00259
00260 if (n == -1)
00261 {
00262
00263
00264
00265
00266 if (TAO_debug_level)
00267 ACE_DEBUG ((LM_DEBUG,
00268 ACE_TEXT ("TAO (%P|%t) - IIOP_Transport[%d]::send_message, ")
00269 ACE_TEXT ("write failure - %m\n"),
00270 this->id ()));
00271 return -1;
00272 }
00273
00274 return 1;
00275 }
00276
00277 int
00278 TAO_IIOP_Transport::send_message_shared (
00279 TAO_Stub *stub,
00280 int message_semantics,
00281 const ACE_Message_Block *message_block,
00282 ACE_Time_Value *max_wait_time)
00283 {
00284 int r;
00285
00286 {
00287 ACE_GUARD_RETURN (ACE_Lock, ace_mon, *this->handler_lock_, -1);
00288
00289 r = this->send_message_shared_i (stub, message_semantics,
00290 message_block, max_wait_time);
00291 }
00292
00293 if (r == -1)
00294 {
00295 this->close_connection ();
00296 }
00297
00298 return r;
00299 }
00300
00301 int
00302 TAO_IIOP_Transport::generate_request_header (TAO_Operation_Details &opdetails,
00303 TAO_Target_Specification &spec,
00304 TAO_OutputCDR &msg)
00305 {
00306
00307
00308
00309
00310 if (this->orb_core ()->bidir_giop_policy () &&
00311 this->messaging_object_->is_ready_for_bidirectional (msg) &&
00312 this->bidirectional_flag () < 0)
00313 {
00314 this->set_bidir_context_info (opdetails);
00315
00316
00317 this->bidirectional_flag (1);
00318
00319
00320
00321
00322
00323
00324 opdetails.request_id (this->tms ()->request_id ());
00325 }
00326
00327 return TAO_Transport::generate_request_header (opdetails,
00328 spec,
00329 msg);
00330 }
00331
00332 int
00333 TAO_IIOP_Transport::messaging_init (CORBA::Octet major,
00334 CORBA::Octet minor)
00335 {
00336 this->messaging_object_->init (major, minor);
00337
00338 return 1;
00339 }
00340
00341 int
00342 TAO_IIOP_Transport::tear_listen_point_list (TAO_InputCDR &cdr)
00343 {
00344 CORBA::Boolean byte_order;
00345 if ((cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0)
00346 return -1;
00347
00348 cdr.reset_byte_order (static_cast<int> (byte_order));
00349
00350 IIOP::ListenPointList listen_list;
00351 if ((cdr >> listen_list) == 0)
00352 return -1;
00353
00354
00355
00356 this->bidirectional_flag (0);
00357
00358 return this->connection_handler_->process_listen_point_list (listen_list);
00359 }
00360
00361 void
00362 TAO_IIOP_Transport::set_bidir_context_info (TAO_Operation_Details &opdetails)
00363 {
00364
00365 TAO_Acceptor_Registry &ar =
00366 this->orb_core ()->lane_resources ().acceptor_registry ();
00367
00368 IIOP::ListenPointList listen_point_list;
00369
00370 const TAO_AcceptorSetIterator end = ar.end ();
00371
00372 for (TAO_AcceptorSetIterator acceptor = ar.begin ();
00373 acceptor != end;
00374 ++acceptor)
00375 {
00376
00377 if ((*acceptor)->tag () == IOP::TAG_INTERNET_IOP)
00378 {
00379 if (this->get_listen_point (listen_point_list, *acceptor) == -1)
00380 {
00381 if (TAO_debug_level > 0)
00382 ACE_ERROR ((LM_ERROR,
00383 "TAO (%P|%t) - IIOP_Transport::set_bidir_context_info, "
00384 "error getting listen_point\n"));
00385
00386 return;
00387 }
00388 }
00389 }
00390
00391 if (listen_point_list.length () == 0)
00392 {
00393 if (TAO_debug_level > 0)
00394 ACE_ERROR ((LM_ERROR,
00395 "TAO (%P|%t) - IIOP_Transport::set_bidir_context_info, "
00396 "listen_point list is empty, client should send a list "
00397 "with at least one point\n"));
00398
00399 return;
00400 }
00401
00402
00403
00404 TAO_OutputCDR cdr;
00405
00406
00407 if ((cdr << ACE_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER) == 0)
00408 || (cdr << listen_point_list) == 0)
00409 return;
00410
00411
00412 opdetails.request_service_context ().set_context (IOP::BI_DIR_IIOP,
00413 cdr);
00414
00415 return;
00416 }
00417
00418 int
00419 TAO_IIOP_Transport::get_listen_point (
00420 IIOP::ListenPointList &listen_point_list,
00421 TAO_Acceptor *acceptor)
00422 {
00423 TAO_IIOP_Acceptor *iiop_acceptor =
00424 dynamic_cast<TAO_IIOP_Acceptor *> (acceptor);
00425
00426 if (iiop_acceptor == 0)
00427 return -1;
00428
00429
00430 const ACE_INET_Addr *endpoint_addr =
00431 iiop_acceptor->endpoints ();
00432
00433
00434 size_t const count =
00435 iiop_acceptor->endpoint_count ();
00436
00437
00438 ACE_INET_Addr local_addr;
00439
00440 if (this->connection_handler_->peer ().get_local_addr (local_addr)
00441 == -1)
00442 {
00443 ACE_ERROR_RETURN ((LM_ERROR,
00444 ACE_TEXT ("TAO (%P|%t) - IIOP_Transport::get_listen_point, ")
00445 ACE_TEXT ("could not resolve local host address\n")),
00446 -1);
00447 }
00448
00449
00450
00451
00452 CORBA::String_var local_interface;
00453
00454
00455 if (iiop_acceptor->hostname (this->orb_core_,
00456 local_addr,
00457 local_interface.out ()) == -1)
00458 {
00459 ACE_ERROR_RETURN ((LM_ERROR,
00460 ACE_TEXT ("TAO (%P|%t) - IIOP_Transport::get_listen_point, ")
00461 ACE_TEXT ("could not resolve local host name\n")),
00462 -1);
00463 }
00464 #if defined (ACE_HAS_IPV6)
00465
00466
00467 const char *cp_scope = 0;
00468 if (local_addr.get_type () == PF_INET6 &&
00469 (cp_scope = ACE_OS::strchr (local_interface.in (), '%')) != 0)
00470 {
00471 CORBA::ULong len = cp_scope - local_interface.in ();
00472 local_interface[len] = '\0';
00473 }
00474 #endif
00475
00476 for (size_t index = 0;
00477 index < count;
00478 ++index)
00479 {
00480
00481
00482 local_addr.set_port_number (endpoint_addr[index].get_port_number ());
00483
00484 if (local_addr == endpoint_addr[index])
00485 {
00486
00487 const CORBA::ULong len = listen_point_list.length ();
00488
00489
00490 listen_point_list.length (len + 1);
00491
00492
00493
00494 IIOP::ListenPoint & point = listen_point_list[len];
00495 point.host = CORBA::string_dup (local_interface.in ());
00496 point.port = endpoint_addr[index].get_port_number ();
00497
00498 if (TAO_debug_level >= 5)
00499 {
00500 ACE_DEBUG ((LM_DEBUG,
00501 ACE_TEXT("TAO (%P|%t) - Listen_Point_List[%d] = <%s:%d>\n"),
00502 len,
00503 point.host.in (),
00504 point.port));
00505 }
00506
00507 }
00508 }
00509
00510 return 1;
00511 }
00512
00513
00514
00515
00516
00517 TAO_END_VERSIONED_NAMESPACE_DECL
00518
00519 #endif