SCIOP_Transport.cpp

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

Generated on Tue Feb 2 17:47:18 2010 for TAO_Strategies by  doxygen 1.4.7