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 80887 2008-03-10 08:03:12Z johnnyw $")
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 (), errno));
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 ACE_Time_Value const * timeout)
00092 {
00093
00094
00095
00096
00097
00098
00099 if (allocator == 0)
00100 return this->send (iov, iovcnt, bytes_transferred, timeout);
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, timeout);
00110 }
00111
00112 ssize_t retval = -1;
00113
00114 ACE_HANDLE const in_fd = allocator->handle ();
00115
00116 if (in_fd == ACE_INVALID_HANDLE)
00117 return retval;
00118
00119 ACE_HANDLE const out_fd =
00120 this->connection_handler_->peer ().get_handle ();
00121
00122 iovec * const begin = iov;
00123 iovec * const end = iov + iovcnt;
00124 for (iovec * i = begin; i != end; ++i)
00125 {
00126 off_t offset = allocator->offset (i->iov_base);
00127
00128 if (timeout)
00129 {
00130 int val = 0;
00131 if (ACE::enter_send_timedwait (out_fd, timeout, val) == -1)
00132 return retval;
00133 else
00134 {
00135 retval =
00136 ACE_OS::sendfile (out_fd, in_fd, &offset, i->iov_len);
00137 ACE::restore_non_blocking_mode (out_fd, val);
00138
00139 }
00140 }
00141 else
00142 {
00143 retval = ACE_OS::sendfile (out_fd, in_fd, &offset, i->iov_len);
00144 }
00145
00146 if (retval <= 0)
00147 break;
00148
00149 bytes_transferred += static_cast<size_t> (retval);
00150 }
00151
00152 if (retval <= 0 && TAO_debug_level > 4)
00153 {
00154 ACE_DEBUG ((LM_DEBUG,
00155 ACE_TEXT ("TAO (%P|%t) - IIOP_Transport[%d]::sendfile, ")
00156 ACE_TEXT ("sendfile failure - %m (errno: %d)\n"),
00157 this->id (),
00158 errno));
00159 }
00160
00161 return retval;
00162 }
00163 #endif
00164
00165 ssize_t
00166 TAO_IIOP_Transport::recv (char *buf,
00167 size_t len,
00168 const ACE_Time_Value *max_wait_time)
00169 {
00170 ssize_t const n = this->connection_handler_->peer ().recv (buf,
00171 len,
00172 max_wait_time);
00173
00174
00175
00176 if (n == -1 && TAO_debug_level > 4 && errno != ETIME)
00177 {
00178 ACE_DEBUG ((LM_DEBUG,
00179 ACE_TEXT ("TAO (%P|%t) - IIOP_Transport[%d]::recv, ")
00180 ACE_TEXT ("read failure - %m errno %d\n"),
00181 this->id (),
00182 errno));
00183 }
00184
00185
00186 if (n == -1)
00187 {
00188 if (errno == EWOULDBLOCK)
00189 return 0;
00190
00191 return -1;
00192 }
00193
00194
00195
00196
00197
00198 else if (n == 0)
00199 {
00200 return -1;
00201 }
00202
00203 return n;
00204 }
00205
00206 int
00207 TAO_IIOP_Transport::send_request (TAO_Stub *stub,
00208 TAO_ORB_Core *orb_core,
00209 TAO_OutputCDR &stream,
00210 TAO_Message_Semantics message_semantics,
00211 ACE_Time_Value *max_wait_time)
00212 {
00213 if (this->ws_->sending_request (orb_core, message_semantics) == -1)
00214 return -1;
00215
00216 if (this->send_message (stream,
00217 stub,
00218 message_semantics,
00219 max_wait_time) == -1)
00220 return -1;
00221
00222 this->first_request_sent();
00223
00224 return 0;
00225 }
00226
00227 int
00228 TAO_IIOP_Transport::send_message (TAO_OutputCDR &stream,
00229 TAO_Stub *stub,
00230 TAO_Message_Semantics message_semantics,
00231 ACE_Time_Value *max_wait_time)
00232 {
00233
00234 if (this->messaging_object_->format_message (stream) != 0)
00235 return -1;
00236
00237
00238 ssize_t const n = this->send_message_shared (stub,
00239 message_semantics,
00240 stream.begin (),
00241 max_wait_time);
00242
00243 if (n == -1)
00244 {
00245
00246
00247
00248
00249 if (TAO_debug_level)
00250 ACE_DEBUG ((LM_DEBUG,
00251 ACE_TEXT ("TAO (%P|%t) - IIOP_Transport[%d]::send_message, ")
00252 ACE_TEXT ("write failure - %m\n"),
00253 this->id ()));
00254 return -1;
00255 }
00256
00257 return 1;
00258 }
00259
00260 int
00261 TAO_IIOP_Transport::generate_request_header (TAO_Operation_Details &opdetails,
00262 TAO_Target_Specification &spec,
00263 TAO_OutputCDR &msg)
00264 {
00265
00266
00267
00268
00269 if (this->orb_core ()->bidir_giop_policy () &&
00270 this->messaging_object_->is_ready_for_bidirectional (msg) &&
00271 this->bidirectional_flag () < 0)
00272 {
00273 this->set_bidir_context_info (opdetails);
00274
00275
00276 this->bidirectional_flag (1);
00277
00278
00279
00280
00281
00282
00283 opdetails.request_id (this->tms ()->request_id ());
00284 }
00285
00286 return TAO_Transport::generate_request_header (opdetails, spec, msg);
00287 }
00288
00289 int
00290 TAO_IIOP_Transport::tear_listen_point_list (TAO_InputCDR &cdr)
00291 {
00292 CORBA::Boolean byte_order;
00293 if ((cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0)
00294 return -1;
00295
00296 cdr.reset_byte_order (static_cast<int> (byte_order));
00297
00298 IIOP::ListenPointList listen_list;
00299 if ((cdr >> listen_list) == 0)
00300 return -1;
00301
00302
00303
00304 this->bidirectional_flag (0);
00305
00306 return this->connection_handler_->process_listen_point_list (listen_list);
00307 }
00308
00309 void
00310 TAO_IIOP_Transport::set_bidir_context_info (TAO_Operation_Details &opdetails)
00311 {
00312
00313 TAO_Acceptor_Registry &ar =
00314 this->orb_core ()->lane_resources ().acceptor_registry ();
00315
00316 IIOP::ListenPointList listen_point_list;
00317
00318 const TAO_AcceptorSetIterator end = ar.end ();
00319
00320 for (TAO_AcceptorSetIterator acceptor = ar.begin ();
00321 acceptor != end;
00322 ++acceptor)
00323 {
00324
00325 if ((*acceptor)->tag () == IOP::TAG_INTERNET_IOP)
00326 {
00327 if (this->get_listen_point (listen_point_list, *acceptor) == -1)
00328 {
00329 if (TAO_debug_level > 0)
00330 ACE_ERROR ((LM_ERROR,
00331 "TAO (%P|%t) - IIOP_Transport::set_bidir_context_info, "
00332 "error getting listen_point\n"));
00333
00334 return;
00335 }
00336 }
00337 }
00338
00339 if (listen_point_list.length () == 0)
00340 {
00341 if (TAO_debug_level > 0)
00342 ACE_ERROR ((LM_ERROR,
00343 "TAO (%P|%t) - IIOP_Transport::set_bidir_context_info, "
00344 "listen_point list is empty, client should send a list "
00345 "with at least one point\n"));
00346
00347 return;
00348 }
00349
00350
00351
00352 TAO_OutputCDR cdr;
00353
00354
00355 if ((cdr << ACE_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER) == 0)
00356 || (cdr << listen_point_list) == 0)
00357 return;
00358
00359
00360 opdetails.request_service_context ().set_context (IOP::BI_DIR_IIOP, cdr);
00361
00362 return;
00363 }
00364
00365 int
00366 TAO_IIOP_Transport::get_listen_point (
00367 IIOP::ListenPointList &listen_point_list,
00368 TAO_Acceptor *acceptor)
00369 {
00370 TAO_IIOP_Acceptor *iiop_acceptor =
00371 dynamic_cast<TAO_IIOP_Acceptor *> (acceptor);
00372
00373 if (iiop_acceptor == 0)
00374 return -1;
00375
00376
00377 const ACE_INET_Addr *endpoint_addr =
00378 iiop_acceptor->endpoints ();
00379
00380
00381 size_t const count =
00382 iiop_acceptor->endpoint_count ();
00383
00384
00385 ACE_INET_Addr local_addr;
00386
00387 if (this->connection_handler_->peer ().get_local_addr (local_addr) == -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 address\n")),
00392 -1);
00393 }
00394
00395
00396
00397
00398 CORBA::String_var local_interface;
00399
00400
00401 if (iiop_acceptor->hostname (this->orb_core_,
00402 local_addr,
00403 local_interface.out ()) == -1)
00404 {
00405 ACE_ERROR_RETURN ((LM_ERROR,
00406 ACE_TEXT ("TAO (%P|%t) - IIOP_Transport::get_listen_point, ")
00407 ACE_TEXT ("could not resolve local host name\n")),
00408 -1);
00409 }
00410 #if defined (ACE_HAS_IPV6)
00411
00412
00413 const char *cp_scope = 0;
00414 if (local_addr.get_type () == PF_INET6 &&
00415 (cp_scope = ACE_OS::strchr (local_interface.in (), '%')) != 0)
00416 {
00417 CORBA::ULong len = cp_scope - local_interface.in ();
00418 local_interface[len] = '\0';
00419 }
00420 #endif
00421
00422 for (size_t index = 0;
00423 index < count;
00424 ++index)
00425 {
00426
00427
00428 local_addr.set_port_number (endpoint_addr[index].get_port_number ());
00429
00430 if (local_addr == endpoint_addr[index])
00431 {
00432
00433 const CORBA::ULong len = listen_point_list.length ();
00434
00435
00436 listen_point_list.length (len + 1);
00437
00438
00439
00440 IIOP::ListenPoint & point = listen_point_list[len];
00441 point.host = CORBA::string_dup (local_interface.in ());
00442 point.port = endpoint_addr[index].get_port_number ();
00443
00444 if (TAO_debug_level >= 5)
00445 {
00446 ACE_DEBUG ((LM_DEBUG,
00447 ACE_TEXT("TAO (%P|%t) - Listen_Point_List[%d] = <%s:%d>\n"),
00448 len,
00449 point.host.in (),
00450 point.port));
00451 }
00452
00453 }
00454 }
00455
00456 return 1;
00457 }
00458
00459
00460
00461
00462
00463 TAO_END_VERSIONED_NAMESPACE_DECL
00464
00465 #endif