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 85441 2009-05-26 17:02:14Z coryan $")
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 {
00032 }
00033
00034 TAO_IIOP_Transport::~TAO_IIOP_Transport (void)
00035 {
00036 }
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 ACE_Event_Handler *
00049 TAO_IIOP_Transport::event_handler_i (void)
00050 {
00051 return this->connection_handler_;
00052 }
00053
00054 TAO_Connection_Handler *
00055 TAO_IIOP_Transport::connection_handler_i (void)
00056 {
00057 return this->connection_handler_;
00058 }
00059
00060 ssize_t
00061 TAO_IIOP_Transport::send (iovec *iov, int iovcnt,
00062 size_t &bytes_transferred,
00063 const ACE_Time_Value *max_wait_time)
00064 {
00065 ssize_t const retval =
00066 this->connection_handler_->peer ().sendv (iov,
00067 iovcnt,
00068 max_wait_time);
00069 if (retval > 0)
00070 bytes_transferred = retval;
00071 else
00072 {
00073 if (TAO_debug_level > 4)
00074 {
00075 ACE_DEBUG ((LM_DEBUG,
00076 ACE_TEXT ("TAO (%P|%t) - IIOP_Transport[%d]::send, ")
00077 ACE_TEXT ("send failure (errno: %d) - %m\n"),
00078 this->id (), ACE_ERRNO_GET));
00079 }
00080 }
00081
00082 return retval;
00083 }
00084
00085 #if TAO_HAS_SENDFILE == 1
00086 ssize_t
00087 TAO_IIOP_Transport::sendfile (TAO_MMAP_Allocator * allocator,
00088 iovec * iov,
00089 int iovcnt,
00090 size_t &bytes_transferred,
00091 TAO::Transport::Drain_Constraints const & dc)
00092 {
00093
00094
00095
00096
00097
00098
00099 if (allocator == 0)
00100 return this->send (iov, iovcnt, bytes_transferred, this->io_timeout(dc));
00101
00102
00103
00104 iovec * const off_check_begin = iov;
00105 iovec * const off_check_end = iov + iovcnt;
00106 for (iovec * index = off_check_begin; index != off_check_end; ++index)
00107 {
00108 if (-1 == allocator->offset (index->iov_base))
00109 return this->send (iov, iovcnt, bytes_transferred,
00110 this->io_timeout(dc));
00111 }
00112
00113 ssize_t retval = -1;
00114
00115 ACE_HANDLE const in_fd = allocator->handle ();
00116
00117 if (in_fd == ACE_INVALID_HANDLE)
00118 return retval;
00119
00120 ACE_HANDLE const out_fd =
00121 this->connection_handler_->peer ().get_handle ();
00122
00123 iovec * const begin = iov;
00124 iovec * const end = iov + iovcnt;
00125 for (iovec * i = begin; i != end; ++i)
00126 {
00127 off_t offset = allocator->offset (i->iov_base);
00128
00129 if (this->io_timeout(dc))
00130 {
00131 int val = 0;
00132 if (ACE::enter_send_timedwait (out_fd,
00133 this->io_timeout(dc), val) == -1)
00134 return retval;
00135 else
00136 {
00137 retval =
00138 ACE_OS::sendfile (out_fd, in_fd, &offset, i->iov_len);
00139 ACE::restore_non_blocking_mode (out_fd, val);
00140 }
00141 }
00142 else
00143 {
00144 retval = ACE_OS::sendfile (out_fd, in_fd, &offset, i->iov_len);
00145 }
00146
00147 if (retval <= 0)
00148 break;
00149
00150 bytes_transferred += static_cast<size_t> (retval);
00151 }
00152
00153 if (retval <= 0 && TAO_debug_level > 4)
00154 {
00155 ACE_DEBUG ((LM_DEBUG,
00156 ACE_TEXT ("TAO (%P|%t) - IIOP_Transport[%d]::sendfile, ")
00157 ACE_TEXT ("sendfile failure - %m (errno: %d)\n"),
00158 this->id (),
00159 ACE_ERRNO_GET));
00160 }
00161
00162 return retval;
00163 }
00164 #endif
00165
00166 ssize_t
00167 TAO_IIOP_Transport::recv (char *buf,
00168 size_t len,
00169 const ACE_Time_Value *max_wait_time)
00170 {
00171 ssize_t const n = this->connection_handler_->peer ().recv (buf,
00172 len,
00173 max_wait_time);
00174
00175
00176
00177 if (n == -1 && TAO_debug_level > 4 && errno != ETIME)
00178 {
00179 ACE_DEBUG ((LM_DEBUG,
00180 ACE_TEXT ("TAO (%P|%t) - IIOP_Transport[%d]::recv, ")
00181 ACE_TEXT ("read failure - %m errno %d\n"),
00182 this->id (),
00183 ACE_ERRNO_GET));
00184 }
00185
00186
00187 if (n == -1)
00188 {
00189 if (errno == EWOULDBLOCK)
00190 return 0;
00191
00192 return -1;
00193 }
00194
00195
00196
00197
00198
00199 else if (n == 0)
00200 {
00201 return -1;
00202 }
00203
00204 return n;
00205 }
00206
00207 int
00208 TAO_IIOP_Transport::send_request (TAO_Stub *stub,
00209 TAO_ORB_Core *orb_core,
00210 TAO_OutputCDR &stream,
00211 TAO_Message_Semantics message_semantics,
00212 ACE_Time_Value *max_wait_time)
00213 {
00214 if (this->ws_->sending_request (orb_core, message_semantics) == -1)
00215 return -1;
00216
00217 if (this->send_message (stream,
00218 stub,
00219 message_semantics,
00220 max_wait_time) == -1)
00221 return -1;
00222
00223 this->first_request_sent();
00224
00225 return 0;
00226 }
00227
00228 int
00229 TAO_IIOP_Transport::send_message (TAO_OutputCDR &stream,
00230 TAO_Stub *stub,
00231 TAO_Message_Semantics message_semantics,
00232 ACE_Time_Value *max_wait_time)
00233 {
00234
00235 if (this->messaging_object ()->format_message (stream, stub) != 0)
00236 return -1;
00237
00238
00239 ssize_t const n = this->send_message_shared (stub,
00240 message_semantics,
00241 stream.begin (),
00242 max_wait_time);
00243
00244 if (n == -1)
00245 {
00246
00247
00248
00249
00250 if (TAO_debug_level)
00251 ACE_DEBUG ((LM_DEBUG,
00252 ACE_TEXT ("TAO (%P|%t) - IIOP_Transport[%d]::send_message, ")
00253 ACE_TEXT ("write failure - %m\n"),
00254 this->id ()));
00255 return -1;
00256 }
00257
00258 return 1;
00259 }
00260
00261 int
00262 TAO_IIOP_Transport::tear_listen_point_list (TAO_InputCDR &cdr)
00263 {
00264 CORBA::Boolean byte_order;
00265 if (!(cdr >> ACE_InputCDR::to_boolean (byte_order)))
00266 return -1;
00267
00268 cdr.reset_byte_order (static_cast<int> (byte_order));
00269
00270 IIOP::ListenPointList listen_list;
00271 if (!(cdr >> listen_list))
00272 return -1;
00273
00274
00275
00276 this->bidirectional_flag (0);
00277
00278 return this->connection_handler_->process_listen_point_list (listen_list);
00279 }
00280
00281 void
00282 TAO_IIOP_Transport::set_bidir_context_info (TAO_Operation_Details &opdetails)
00283 {
00284
00285 TAO_Acceptor_Registry &ar =
00286 this->orb_core ()->lane_resources ().acceptor_registry ();
00287
00288 IIOP::ListenPointList listen_point_list;
00289
00290 TAO_AcceptorSetIterator const end = ar.end ();
00291
00292 for (TAO_AcceptorSetIterator acceptor = ar.begin ();
00293 acceptor != end;
00294 ++acceptor)
00295 {
00296
00297 if ((*acceptor)->tag () == this->tag ())
00298 {
00299 if (this->get_listen_point (listen_point_list, *acceptor) == -1)
00300 {
00301 if (TAO_debug_level > 0)
00302 ACE_ERROR ((LM_ERROR,
00303 "TAO (%P|%t) - IIOP_Transport::set_bidir_context_info, "
00304 "error getting listen_point\n"));
00305
00306 return;
00307 }
00308 }
00309 }
00310
00311 if (listen_point_list.length () == 0)
00312 {
00313 if (TAO_debug_level > 0)
00314 ACE_ERROR ((LM_ERROR,
00315 "TAO (%P|%t) - IIOP_Transport::set_bidir_context_info, "
00316 "listen_point list is empty, client should send a list "
00317 "with at least one point\n"));
00318
00319 return;
00320 }
00321
00322
00323
00324 TAO_OutputCDR cdr;
00325
00326
00327 if (!(cdr << ACE_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER))
00328 || (!(cdr << listen_point_list)))
00329 return;
00330
00331
00332 opdetails.request_service_context ().set_context (IOP::BI_DIR_IIOP, cdr);
00333
00334 return;
00335 }
00336
00337 int
00338 TAO_IIOP_Transport::get_listen_point (
00339 IIOP::ListenPointList &listen_point_list,
00340 TAO_Acceptor *acceptor)
00341 {
00342 TAO_IIOP_Acceptor *iiop_acceptor =
00343 dynamic_cast<TAO_IIOP_Acceptor *> (acceptor);
00344
00345 if (iiop_acceptor == 0)
00346 return -1;
00347
00348
00349 const ACE_INET_Addr *endpoint_addr =
00350 iiop_acceptor->endpoints ();
00351 size_t count = iiop_acceptor->endpoint_count ();
00352
00353 #if defined (TAO_USE_BROKEN_BIDIR)
00354
00355
00356
00357
00358
00359 ACE_INET_Addr local_addr;
00360 if (this->connection_handler_->peer ().get_local_addr (local_addr)
00361 == -1)
00362 {
00363 ACE_ERROR_RETURN ((LM_ERROR,
00364 ACE_TEXT ("TAO (%P|%t) - IIOP_Transport::get_listen_point, ")
00365 ACE_TEXT ("could not resolve local host address\n")),
00366 -1);
00367 }
00368 #endif
00369
00370 for (size_t index = 0; index < count; index++)
00371 {
00372 #if defined (TAO_USE_BROKEN_BIDIR)
00373
00374
00375 local_addr.set_port_number (endpoint_addr[index].get_port_number ());
00376
00377 if (local_addr != endpoint_addr[index])
00378 continue;
00379 #endif
00380
00381
00382 CORBA::String_var interface_name;
00383
00384
00385 if (iiop_acceptor->hostname (this->orb_core_,
00386 endpoint_addr[index],
00387 interface_name.out ()) == -1)
00388 {
00389 ACE_ERROR_RETURN ((LM_ERROR,
00390 ACE_TEXT ("TAO (%P|%t) - IIOP_Transport::get_listen_point, ")
00391 ACE_TEXT ("could not resolve local host name\n")),
00392 -1);
00393 }
00394
00395 #if defined (ACE_HAS_IPV6)
00396
00397
00398 const char *cp_scope = 0;
00399 if (endpoint_addr[index].get_type () == PF_INET6 &&
00400 (cp_scope = ACE_OS::strchr (interface_name.in (), '%')) != 0)
00401 {
00402 CORBA::ULong len = cp_scope - interface_name.in ();
00403 interface_name[len] = '\0';
00404 }
00405 #endif
00406
00407
00408 CORBA::ULong const len = listen_point_list.length ();
00409
00410
00411 listen_point_list.length (len + 1);
00412
00413
00414
00415 IIOP::ListenPoint & point = listen_point_list[len];
00416 point.host = CORBA::string_dup (interface_name.in ());
00417 point.port = endpoint_addr[index].get_port_number ();
00418
00419 if (TAO_debug_level >= 5)
00420 {
00421 ACE_DEBUG ((LM_DEBUG,
00422 ACE_TEXT("TAO (%P|%t) - Listen_Point_List[%d] = <%C:%d>\n"),
00423 len,
00424 point.host.in (),
00425 point.port));
00426 }
00427 }
00428 return 1;
00429 }
00430
00431
00432
00433
00434
00435 TAO_END_VERSIONED_NAMESPACE_DECL
00436
00437 #endif