SCIOP_Transport.cpp

Go to the documentation of this file.
00001 // $Id: SCIOP_Transport.cpp 78931 2007-07-18 09:59:36Z johnnyw $
00002 
00003 #include "tao/Strategies/SCIOP_Transport.h"
00004 
00005 #if TAO_HAS_SCIOP == 1
00006 
00007 #include "tao/Strategies/SCIOP_Connection_Handler.h"
00008 #include "tao/Strategies/SCIOP_Acceptor.h"
00009 #include "tao/Strategies/SCIOP_Profile.h"
00010 #include "tao/Acceptor_Registry.h"
00011 #include "tao/Thread_Lane_Resources.h"
00012 #include "tao/operation_details.h"
00013 #include "tao/Timeprobe.h"
00014 #include "tao/CDR.h"
00015 #include "tao/Transport_Mux_Strategy.h"
00016 #include "tao/Wait_Strategy.h"
00017 #include "tao/Stub.h"
00018 #include "tao/ORB_Core.h"
00019 #include "tao/debug.h"
00020 #include "tao/GIOP_Message_Base.h"
00021 #include "tao/Protocols_Hooks.h"
00022 #include "tao/Adapter.h"
00023 
00024 ACE_RCSID (tao,
00025            SCIOP_Transport,
00026            "$Id: SCIOP_Transport.cpp 78931 2007-07-18 09:59:36Z johnnyw $")
00027 
00028 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00029 
00030 TAO_SCIOP_Transport::TAO_SCIOP_Transport (TAO_SCIOP_Connection_Handler *handler,
00031                                           TAO_ORB_Core *orb_core)
00032   : TAO_Transport (TAO_TAG_SCIOP_PROFILE,
00033                    orb_core)
00034   , connection_handler_ (handler)
00035   , messaging_object_ (0)
00036 {
00037   ACE_NEW (this->messaging_object_,
00038             TAO_GIOP_Message_Base (orb_core, this));
00039 }
00040 
00041 TAO_SCIOP_Transport::~TAO_SCIOP_Transport (void)
00042 {
00043   delete this->messaging_object_;
00044 }
00045 
00046 ACE_Event_Handler *
00047 TAO_SCIOP_Transport::event_handler_i (void)
00048 {
00049   return this->connection_handler_;
00050 }
00051 
00052 TAO_Connection_Handler *
00053 TAO_SCIOP_Transport::connection_handler_i (void)
00054 {
00055   return this->connection_handler_;
00056 }
00057 
00058 TAO_Pluggable_Messaging *
00059 TAO_SCIOP_Transport::messaging_object (void)
00060 {
00061   return this->messaging_object_;
00062 }
00063 
00064 ssize_t
00065 TAO_SCIOP_Transport::send (iovec *iov, int iovcnt,
00066                            size_t &bytes_transferred,
00067                            const ACE_Time_Value *max_wait_time)
00068 {
00069   ssize_t retval = this->connection_handler_->peer ().sendv (iov, iovcnt,
00070                                                              max_wait_time);
00071   if (retval > 0)
00072     bytes_transferred = retval;
00073 
00074   return retval;
00075 }
00076 
00077 ssize_t
00078 TAO_SCIOP_Transport::recv (char *buf,
00079                            size_t len,
00080                            const ACE_Time_Value *max_wait_time)
00081 {
00082   ssize_t n = this->connection_handler_->peer ().recv (buf,
00083                                                        len,
00084                                                        max_wait_time);
00085 
00086   // Do not print the error message if it is a timeout, which could
00087   // occur in thread-per-connection.
00088   if (n == -1 &&
00089       TAO_debug_level > 4 &&
00090       errno != ETIME)
00091     {
00092       ACE_DEBUG ((LM_DEBUG,
00093                   ACE_TEXT ("TAO (%P|%t) - SCIOP_Transport[%d]::recv, ")
00094                   ACE_TEXT ("read failure - %m\n"),
00095                   this->id ()));
00096     }
00097 
00098   // Error handling
00099   if (n == -1)
00100     {
00101       if (errno == EWOULDBLOCK)
00102         return 0;
00103 
00104 
00105       return -1;
00106     }
00107 
00108   // Most of the errors handling is common for
00109   // Now the message has been read
00110 
00111   // @@ What are the other error handling here??
00112   else if (n == 0)
00113     {
00114       return -1;
00115     }
00116 
00117   return n;
00118 }
00119 
00120 int
00121 TAO_SCIOP_Transport::send_request (TAO_Stub *stub,
00122                                   TAO_ORB_Core *orb_core,
00123                                   TAO_OutputCDR &stream,
00124                                   int message_semantics,
00125                                   ACE_Time_Value *max_wait_time)
00126 {
00127   if (this->ws_->sending_request (orb_core,
00128                                   message_semantics) == -1)
00129 
00130     return -1;
00131 
00132   if (this->send_message (stream,
00133                           stub,
00134                           message_semantics,
00135                           max_wait_time) == -1)
00136     return -1;
00137 
00138   this->first_request_sent();
00139 
00140   return 0;
00141 }
00142 
00143 int
00144 TAO_SCIOP_Transport::send_message (TAO_OutputCDR &stream,
00145                                   TAO_Stub *stub,
00146                                   int message_semantics,
00147                                   ACE_Time_Value *max_wait_time)
00148 {
00149   // Format the message in the stream first
00150   if (this->messaging_object_->format_message (stream) != 0)
00151     return -1;
00152 
00153   // This guarantees to send all data (bytes) or return an error.
00154   ssize_t n = this->send_message_shared (stub,
00155                                          message_semantics,
00156                                          stream.begin (),
00157                                          max_wait_time);
00158 
00159   if (n == -1)
00160     {
00161       if (TAO_debug_level)
00162         ACE_DEBUG ((LM_DEBUG,
00163                     ACE_TEXT ("TAO (%P|%t) - SCIOP_Transport[%d]::send_message, ")
00164                     ACE_TEXT (" write failure - %m\n"),
00165                     this->id ()));
00166       return -1;
00167     }
00168 
00169   return 1;
00170 }
00171 
00172 int
00173 TAO_SCIOP_Transport::send_message_shared (TAO_Stub *stub,
00174                                          int message_semantics,
00175                                          const ACE_Message_Block *message_block,
00176                                          ACE_Time_Value *max_wait_time)
00177 {
00178   int r;
00179 
00180   {
00181     ACE_GUARD_RETURN (ACE_Lock, ace_mon, *this->handler_lock_, -1);
00182 
00183     r = this->send_message_shared_i (stub, message_semantics,
00184                                      message_block, max_wait_time);
00185   }
00186 
00187   if (r == -1)
00188     {
00189       this->close_connection ();
00190     }
00191 
00192   return r;
00193 }
00194 
00195 int
00196 TAO_SCIOP_Transport::generate_request_header (TAO_Operation_Details &opdetails,
00197                                              TAO_Target_Specification &spec,
00198                                              TAO_OutputCDR &msg)
00199 {
00200   // Check whether we have a Bi Dir SCIOP policy set, whether the
00201   // messaging objects are ready to handle bidirectional connections
00202   // and also make sure that we have not recd. or sent any information
00203   // regarding this before...
00204   if (this->orb_core ()->bidir_giop_policy () &&
00205       this->messaging_object_->is_ready_for_bidirectional (msg) &&
00206       this->bidirectional_flag () < 0)
00207     {
00208       this->set_bidir_context_info (opdetails);
00209 
00210       // Set the flag to 1  (i.e., originating side)
00211       this->bidirectional_flag (1);
00212 
00213       // At the moment we enable BiDIR giop we have to get a new
00214       // request id to make sure that we follow the even/odd rule
00215       // for request id's. We only need to do this when enabled
00216       // it, after that the Transport Mux Strategy will make sure
00217       // that the rule is followed
00218       opdetails.request_id (this->tms ()->request_id ());
00219     }
00220 
00221   return TAO_Transport::generate_request_header (opdetails,
00222                                                  spec,
00223                                                  msg);
00224 }
00225 
00226 int
00227 TAO_SCIOP_Transport::messaging_init (CORBA::Octet major,
00228                                     CORBA::Octet minor)
00229 {
00230   this->messaging_object_->init (major, minor);
00231 
00232   return 1;
00233 }
00234 
00235 int
00236 TAO_SCIOP_Transport::tear_listen_point_list (TAO_InputCDR &cdr)
00237 {
00238   CORBA::Boolean byte_order;
00239   if ((cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0)
00240     return -1;
00241 
00242   cdr.reset_byte_order (static_cast<int> (byte_order));
00243 
00244   IIOP::ListenPointList listen_list;
00245   if ((cdr >> listen_list) == 0)
00246     return -1;
00247 
00248   // As we have received a bidirectional information, set the flag to
00249   // 1 (i.e., non-originating side)
00250   this->bidirectional_flag (0);
00251 
00252   return this->connection_handler_->process_listen_point_list (listen_list);
00253 }
00254 
00255 void
00256 TAO_SCIOP_Transport::set_bidir_context_info (TAO_Operation_Details &opdetails)
00257 {
00258   // Get a handle to the acceptor registry
00259   TAO_Acceptor_Registry &ar =
00260     this->orb_core ()->lane_resources ().acceptor_registry ();
00261 
00262   // Get the first acceptor in the registry
00263   TAO_AcceptorSetIterator acceptor = ar.begin ();
00264 
00265   IIOP::ListenPointList listen_point_list;
00266 
00267   for (;
00268        acceptor != ar.end ();
00269        acceptor++)
00270     {
00271       // Check whether it is a SCIOP acceptor
00272       if ((*acceptor)->tag () == TAO_TAG_SCIOP_PROFILE)
00273         {
00274           if (this->get_listen_point (listen_point_list,
00275                                       *acceptor) == -1)
00276             {
00277               ACE_ERROR ((LM_ERROR,
00278                           "TAO (%P|%t) - SCIOP_Transport::set_bidir_info, "
00279                           "error getting listen_point \n"));
00280 
00281               return;
00282             }
00283         }
00284     }
00285 
00286   // We have the ListenPointList at this point. Create a output CDR
00287   // stream at this point
00288   TAO_OutputCDR cdr;
00289 
00290   // Marshall the information into the stream
00291   if ((cdr << ACE_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER) == 0)
00292       || (cdr << listen_point_list) == 0)
00293     return;
00294 
00295   // Add this info in to the svc_list
00296   opdetails.request_service_context ().set_context (IOP::BI_DIR_IIOP,
00297                                                     cdr);
00298 
00299   return;
00300 }
00301 
00302 int
00303 TAO_SCIOP_Transport::get_listen_point (
00304     IIOP::ListenPointList &listen_point_list,
00305     TAO_Acceptor *acceptor)
00306 {
00307   TAO_SCIOP_Acceptor *sciop_acceptor =
00308     dynamic_cast<TAO_SCIOP_Acceptor *> (acceptor );
00309 
00310   // Get the array of endpoints serviced by TAO_SCIOP_Acceptor
00311   const ACE_INET_Addr *endpoint_addr =
00312     sciop_acceptor->endpoints ();
00313 
00314   // Get the endpoint count
00315   size_t count =
00316     sciop_acceptor->endpoint_count ();
00317 
00318   // Get the local address of the connection
00319   ACE_INET_Addr local_addr;
00320 
00321   if (this->connection_handler_->peer ().get_local_addr (local_addr) == -1)
00322     {
00323       ACE_ERROR_RETURN ((LM_ERROR,
00324                          ACE_TEXT ("(%P|%t) Could not resolve local ")
00325                          ACE_TEXT ("host address in ")
00326                          ACE_TEXT ("get_listen_point()\n")),
00327                         -1);
00328     }
00329 
00330   // Note: Looks like there is no point in sending the list of
00331   // endpoints on interfaces on which this connection has not
00332   // been established. If this is wrong, please correct me.
00333   CORBA::String_var local_interface;
00334 
00335   // Get the hostname for the local address
00336   if (sciop_acceptor->hostname (this->orb_core_,
00337                                local_addr,
00338                                local_interface.out ()) == -1)
00339     {
00340       ACE_ERROR_RETURN ((LM_ERROR,
00341                          ACE_TEXT ("(%P|%t) Could not resolve local host")
00342                          ACE_TEXT (" name \n")),
00343                         -1);
00344     }
00345 
00346   for (size_t index = 0; index != count; index++)
00347     {
00348       if (local_addr.get_ip_address() == endpoint_addr[index].get_ip_address())
00349         {
00350           // Get the count of the number of elements
00351           CORBA::ULong const len = listen_point_list.length ();
00352 
00353           // Increase the length by 1
00354           listen_point_list.length (len + 1);
00355 
00356           // We have the connection and the acceptor endpoint on the
00357           // same interface
00358           IIOP::ListenPoint &point = listen_point_list[len];
00359           point.host = CORBA::string_dup (local_interface.in ());
00360           point.port = endpoint_addr[index].get_port_number ();
00361         }
00362     }
00363 
00364   return 1;
00365 }
00366 
00367 TAO_END_VERSIONED_NAMESPACE_DECL
00368 
00369 #endif /* TAO_HAS_SCIOP == 1 */

Generated on Sun Jan 27 15:59:49 2008 for TAO_Strategies by doxygen 1.3.6