SSLIOP_Transport.cpp

Go to the documentation of this file.
00001 #include "orbsvcs/SSLIOP/SSLIOP_Connection_Handler.h"
00002 #include "orbsvcs/SSLIOP/SSLIOP_Transport.h"
00003 #include "orbsvcs/SSLIOP/SSLIOP_Profile.h"
00004 #include "orbsvcs/SSLIOP/SSLIOP_Acceptor.h"
00005 
00006 #include "tao/debug.h"
00007 
00008 #include "tao/Timeprobe.h"
00009 #include "tao/CDR.h"
00010 #include "tao/Transport_Mux_Strategy.h"
00011 #include "tao/Wait_Strategy.h"
00012 #include "tao/Stub.h"
00013 #include "tao/ORB_Core.h"
00014 #include "tao/debug.h"
00015 #include "tao/GIOP_Message_Base.h"
00016 #include "tao/Acceptor_Registry.h"
00017 #include "tao/Thread_Lane_Resources.h"
00018 
00019 ACE_RCSID (SSLIOP,
00020            SSLIOP_Transport,
00021            "$Id: SSLIOP_Transport.cpp 79267 2007-08-08 15:51:45Z mesnier_p $")
00022 
00023 
00024 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00025 
00026 TAO::SSLIOP::Transport::Transport (
00027   TAO::SSLIOP::Connection_Handler *handler,
00028   TAO_ORB_Core *orb_core)
00029   : TAO_Transport (IOP::TAG_INTERNET_IOP, orb_core),
00030     connection_handler_ (handler),
00031     messaging_object_ (0)
00032 {
00033   // Use the normal GIOP object
00034   ACE_NEW (this->messaging_object_,
00035            TAO_GIOP_Message_Base (orb_core, this));
00036 }
00037 
00038 TAO::SSLIOP::Transport::~Transport (void)
00039 {
00040   delete this->messaging_object_;
00041 }
00042 
00043 ACE_Event_Handler *
00044 TAO::SSLIOP::Transport::event_handler_i (void)
00045 {
00046   return this->connection_handler_;
00047 }
00048 
00049 TAO_Connection_Handler *
00050 TAO::SSLIOP::Transport::connection_handler_i (void)
00051 {
00052   return this->connection_handler_;
00053 }
00054 
00055 TAO_Pluggable_Messaging *
00056 TAO::SSLIOP::Transport::messaging_object (void)
00057 {
00058   return this->messaging_object_;
00059 }
00060 
00061 int
00062 TAO::SSLIOP::Transport::handle_input (TAO_Resume_Handle &rh,
00063                                       ACE_Time_Value *max_wait_time)
00064 {
00065   int result = 0;
00066 
00067   // Set up the SSLIOP::Current object.
00068   TAO::SSLIOP::State_Guard ssl_state_guard (this->connection_handler_,
00069                                             result);
00070 
00071   if (result == -1)
00072     return -1;
00073 
00074   return TAO_Transport::handle_input (rh, max_wait_time);
00075 }
00076 
00077 ssize_t
00078 TAO::SSLIOP::Transport::send (iovec *iov,
00079                               int iovcnt,
00080                               size_t &bytes_transferred,
00081                               const ACE_Time_Value *max_wait_time)
00082 {
00083   const ssize_t retval =
00084     this->connection_handler_->peer ().sendv (iov, iovcnt, max_wait_time);
00085 
00086   if (retval > 0)
00087     bytes_transferred = retval;
00088 
00089   return retval;
00090 }
00091 
00092 ssize_t
00093 TAO::SSLIOP::Transport::recv (char *buf,
00094                               size_t len,
00095                               const ACE_Time_Value *max_wait_time)
00096 {
00097   const ssize_t n = this->connection_handler_->peer ().recv (buf,
00098                                                              len,
00099                                                              max_wait_time);
00100 
00101   // Most of the errors handling is common for
00102   // Now the message has been read
00103   if (n == -1
00104       && TAO_debug_level > 4
00105       && errno != ETIME)
00106     {
00107       ACE_DEBUG ((LM_DEBUG,
00108                   ACE_TEXT ("TAO (%P|%t) - %p \n"),
00109                   ACE_TEXT ("TAO - read message failure ")
00110                   ACE_TEXT ("recv_i () \n")));
00111     }
00112 
00113   // Error handling
00114   if (n == -1)
00115     {
00116       if (errno == EWOULDBLOCK)
00117         return 0;
00118 
00119       return -1;
00120     }
00121   // @@ What are the other error handling here??
00122   else if (n == 0)
00123     {
00124       return -1;
00125     }
00126 
00127   return n;
00128 }
00129 
00130 int
00131 TAO::SSLIOP::Transport::send_request (TAO_Stub *stub,
00132                                       TAO_ORB_Core *orb_core,
00133                                       TAO_OutputCDR &stream,
00134                                       int message_semantics,
00135                                       ACE_Time_Value *max_wait_time)
00136 {
00137   if (this->ws_->sending_request (orb_core, message_semantics) == -1)
00138     return -1;
00139 
00140   if (this->send_message (stream,
00141                           stub,
00142                           message_semantics,
00143                           max_wait_time) == -1)
00144 
00145     return -1;
00146 
00147   return 0;
00148 }
00149 
00150 int
00151 TAO::SSLIOP::Transport::send_message (TAO_OutputCDR &stream,
00152                                       TAO_Stub *stub,
00153                                       int message_semantics,
00154                                       ACE_Time_Value *max_wait_time)
00155 {
00156   // Format the message in the stream first
00157   if (this->messaging_object_->format_message (stream) != 0)
00158     return -1;
00159 
00160   // Strictly speaking, should not need to loop here because the
00161   // socket never gets set to a nonblocking mode ... some Linux
00162   // versions seem to need it though.  Leaving it costs little.
00163 
00164   // This guarantees to send all data (bytes) or return an error.
00165   const ssize_t n = this->send_message_shared (stub,
00166                                                message_semantics,
00167                                                stream.begin (),
00168                                                max_wait_time);
00169 
00170   if (n == -1)
00171     {
00172       if (TAO_debug_level)
00173         ACE_DEBUG ((LM_DEBUG,
00174                     ACE_TEXT ("TAO: (%P|%t|%N|%l) closing transport ")
00175                     ACE_TEXT ("%d after fault %p\n"),
00176                     this->id (),
00177                     ACE_TEXT ("send_message ()\n")));
00178 
00179       return -1;
00180     }
00181 
00182   return 1;
00183 }
00184 
00185 
00186 int
00187 TAO::SSLIOP::Transport::generate_request_header (
00188   TAO_Operation_Details &opdetails,
00189   TAO_Target_Specification &spec,
00190   TAO_OutputCDR &msg)
00191 {
00192   // Check whether we have a Bi Dir IIOP policy set, whether the
00193   // messaging objects are ready to handle bidirectional connections
00194   // and also make sure that we have not recd. or sent any information
00195   // regarding this before...
00196   if (this->orb_core ()->bidir_giop_policy ()
00197       && this->messaging_object_->is_ready_for_bidirectional (msg)
00198       && this->bidirectional_flag () < 0)
00199     {
00200       this->set_bidir_context_info (opdetails);
00201 
00202       // Set the flag to 1
00203       this->bidirectional_flag (1);
00204 
00205       // At the moment we enable BiDIR giop we have to get a new
00206       // request id to make sure that we follow the even/odd rule
00207       // for request id's. We only need to do this when enabled
00208       // it, after that the Transport Mux Strategy will make sure
00209       // that the rule is followed
00210       opdetails.request_id (this->tms ()->request_id ());
00211     }
00212 
00213   // We are going to pass on this request to the underlying messaging
00214   // layer. It should take care of this request
00215   return TAO_Transport::generate_request_header (opdetails,
00216                                                  spec,
00217                                                  msg);
00218 }
00219 
00220 int
00221 TAO::SSLIOP::Transport::messaging_init (CORBA::Octet major,
00222                                         CORBA::Octet minor)
00223 {
00224   this->messaging_object_->init (major,
00225                                  minor);
00226   return 1;
00227 }
00228 
00229 
00230 int
00231 TAO::SSLIOP::Transport::tear_listen_point_list (TAO_InputCDR &cdr)
00232 {
00233   CORBA::Boolean byte_order;
00234   if ((cdr >> ACE_InputCDR::to_boolean (byte_order)) == 0)
00235     return -1;
00236 
00237   cdr.reset_byte_order (static_cast<int> (byte_order));
00238 
00239   IIOP::ListenPointList listen_list;
00240   if ((cdr >> listen_list) == 0)
00241     return -1;
00242 
00243   // As we have received a bidirectional information, set the flag to
00244   // 0
00245   this->bidirectional_flag (0);
00246 
00247   return this->connection_handler_->process_listen_point_list (listen_list);
00248 }
00249 
00250 
00251 
00252 void
00253 TAO::SSLIOP::Transport::set_bidir_context_info (
00254   TAO_Operation_Details &opdetails)
00255 {
00256   // Get a handle on to the acceptor registry
00257   TAO_Acceptor_Registry &ar =
00258     this->orb_core ()->lane_resources ().acceptor_registry ();
00259 
00260   // Get the first acceptor in the registry
00261   TAO_AcceptorSetIterator acceptor = ar.begin ();
00262 
00263   IIOP::ListenPointList listen_point_list;
00264 
00265   for (;
00266        acceptor != ar.end ();
00267        acceptor++)
00268     {
00269       // Check whether it is a IIOP acceptor
00270       if ((*acceptor)->tag () == IOP::TAG_INTERNET_IOP)
00271         {
00272           if (this->get_listen_point (listen_point_list,
00273                                       *acceptor) == -1)
00274             {
00275               ACE_ERROR ((LM_ERROR,
00276                           "TAO (%P|%t) - SSLIOP_Transport::set_bidir_info, ",
00277                           "error getting listen_point \n"));
00278 
00279               return;
00280             }
00281         }
00282     }
00283 
00284   // We have the ListenPointList at this point. Create a output CDR
00285   // stream at this point
00286   TAO_OutputCDR cdr;
00287 
00288   // Marshall the information into the stream
00289   if ((cdr << ACE_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER) == 0)
00290       || (cdr << listen_point_list) == 0)
00291     return;
00292 
00293   // Add this info in to the svc_list
00294   opdetails.request_service_context ().set_context (IOP::BI_DIR_IIOP,
00295                                                     cdr);
00296   return;
00297 }
00298 
00299 
00300 int
00301 TAO::SSLIOP::Transport::get_listen_point (
00302   IIOP::ListenPointList &listen_point_list,
00303   TAO_Acceptor *acceptor)
00304 {
00305   TAO::SSLIOP::Acceptor *ssliop_acceptor =
00306     dynamic_cast<TAO::SSLIOP::Acceptor *> (acceptor);
00307 
00308   if (ssliop_acceptor == 0)
00309     return -1;
00310 
00311   // Get the array of IIOP (not SSLIOP!) endpoints serviced by the
00312   // SSLIOP_Acceptor.
00313   const ACE_INET_Addr *endpoint_addr =
00314     ssliop_acceptor->endpoints ();
00315 
00316   // Get the count
00317   const size_t count =
00318     ssliop_acceptor->endpoint_count ();
00319 
00320   // The SSL port is stored in the SSLIOP::SSL component associated
00321   // with the SSLIOP_Acceptor.
00322   const ::SSLIOP::SSL &ssl = ssliop_acceptor->ssl_component ();
00323 
00324   // Get the local address of the connection
00325   ACE_INET_Addr local_addr;
00326   {
00327     if (this->connection_handler_->peer ().get_local_addr (local_addr)
00328         == -1)
00329       {
00330         ACE_ERROR_RETURN ((LM_ERROR,
00331                            ACE_TEXT ("(%P|%t) Could not resolve local host")
00332                            ACE_TEXT (" address in get_listen_point()\n")),
00333                         -1);
00334     }
00335 
00336   }
00337 
00338   // Note: Looks like there is no point in sending the list of
00339   // endpoints on interfaces on which this connection has not
00340   // been established. If this is wrong, please correct me.
00341   CORBA::String_var local_interface;
00342 
00343   // Get the hostname for the local address
00344   if (ssliop_acceptor->hostname (this->orb_core_,
00345                                  local_addr,
00346                                  local_interface.out ()) == -1)
00347     {
00348       ACE_ERROR_RETURN ((LM_ERROR,
00349                          ACE_TEXT ("(%P|%t) Could not resolve local host")
00350                          ACE_TEXT (" name \n")),
00351                         -1);
00352     }
00353 
00354 #if defined (ACE_HAS_IPV6)
00355   // If this is an IPv6 decimal linklocal address containing a scopeid than
00356   // remove the scopeid from the information being sent.
00357   const char *cp_scope = 0;
00358   if (local_addr.get_type () == PF_INET6 &&
00359         (cp_scope = ACE_OS::strchr (local_interface.in (), '%')) != 0)
00360     {
00361       CORBA::ULong len = cp_scope - local_interface.in ();
00362       local_interface[len] = '\0';
00363     }
00364 #endif /* ACE_HAS_IPV6 */
00365 
00366   for (size_t index = 0; index < count; ++index)
00367     {
00368       // Make sure port numbers are equal so the following comparison
00369       // only concerns the IP(v4/v6) address.
00370       local_addr.set_port_number (endpoint_addr[index].get_port_number ());
00371 
00372       if (local_addr == endpoint_addr[index])
00373         {
00374           // Get the count of the number of elements
00375           const CORBA::ULong len = listen_point_list.length ();
00376 
00377           // Increase the length by 1
00378           listen_point_list.length (len + 1);
00379 
00380           // We have the connection and the acceptor endpoint on the
00381           // same interface
00382           IIOP::ListenPoint & point = listen_point_list[len];
00383           point.host = CORBA::string_dup (local_interface.in ());
00384 
00385           // All endpoints, if more than one, serviced by the
00386           // SSLIOP_Acceptor should be listening on the same port (due
00387           // to the bind to the INADDR_ANY address).
00388           point.port = ssl.port;
00389         }
00390     }
00391 
00392   return 1;
00393 }
00394 
00395 TAO_END_VERSIONED_NAMESPACE_DECL

Generated on Sun Jan 27 16:12:24 2008 for TAO_SSLIOP by doxygen 1.3.6