SSL_SOCK_Acceptor.cpp

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // $Id: SSL_SOCK_Acceptor.cpp 73790 2006-07-27 20:43:46Z wotte $
00004 
00005 
00006 #include "SSL_SOCK_Acceptor.h"
00007 
00008 #include "ace/Handle_Set.h"
00009 #include "ace/OS_Errno.h"
00010 #include "ace/OS_NS_errno.h"
00011 #include "ace/Log_Msg.h"
00012 #include "ace/Time_Value.h"
00013 #include "ace/Countdown_Time.h"
00014 
00015 #if !defined (__ACE_INLINE__)
00016 #include "SSL_SOCK_Acceptor.inl"
00017 #endif /* __ACE_INLINE__ */
00018 
00019 ACE_RCSID (ACE_SSL,
00020            SSL_SOCK_Acceptor,
00021            "$Id: SSL_SOCK_Acceptor.cpp 73790 2006-07-27 20:43:46Z wotte $")
00022 
00023 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00024 
00025 ACE_ALLOC_HOOK_DEFINE(ACE_SSL_SOCK_Acceptor)
00026 
00027 ACE_SSL_SOCK_Acceptor::~ACE_SSL_SOCK_Acceptor (void)
00028 {
00029   ACE_TRACE ("ACE_SSL_SOCK_Acceptor::~ACE_SSL_SOCK_Acceptor");
00030 }
00031 
00032 
00033 int
00034 ACE_SSL_SOCK_Acceptor::ssl_accept (ACE_SSL_SOCK_Stream &new_stream,
00035                                    ACE_Time_Value *timeout) const
00036 {
00037   SSL *ssl = new_stream.ssl ();
00038 
00039   if (SSL_is_init_finished (ssl))
00040     return 0;
00041 
00042   if (!SSL_in_accept_init (ssl))
00043     ::SSL_set_accept_state (ssl);
00044 
00045   ACE_HANDLE handle = new_stream.get_handle ();
00046 
00047   // We're going to call SSL_accept, optionally doing ACE::select and
00048   // retrying the SSL_accept, until the SSL handshake is done or
00049   // it fails.
00050   // To get the timeout affect, set the socket to nonblocking mode
00051   // before beginning if there is a timeout specified. If the timeout
00052   // is 0 (wait as long as it takes) then don't worry about the blocking
00053   // status; we'll block in SSL_accept if the socket is blocking, and
00054   // block in ACE::select if not.
00055   int reset_blocking_mode = 0;
00056   if (timeout != 0)
00057     {
00058       reset_blocking_mode = ACE_BIT_DISABLED (ACE::get_flags (handle),
00059                                               ACE_NONBLOCK);
00060           // Set the handle into non-blocking mode if it's not already
00061           // in it.
00062           if (reset_blocking_mode
00063               && ACE::set_flags (handle,
00064                                  ACE_NONBLOCK) == -1)
00065             return -1;
00066     }
00067 
00068   // Take into account the time between each select() call below.
00069   ACE_Countdown_Time countdown (timeout);
00070 
00071   int status;
00072   do
00073     {
00074       // These handle sets are used to set up for whatever SSL_accept
00075       // says it wants next. They're reset on each pass around the loop.
00076       ACE_Handle_Set rd_handle;
00077       ACE_Handle_Set wr_handle;
00078 
00079       status = ::SSL_accept (ssl);
00080       switch (::SSL_get_error (ssl, status))
00081         {
00082         case SSL_ERROR_NONE:
00083           status = 0;               // To tell caller about success
00084           break;                    // Done
00085 
00086         case SSL_ERROR_WANT_WRITE:
00087           wr_handle.set_bit (handle);
00088           status = 1;               // Wait for more activity
00089           break;
00090 
00091         case SSL_ERROR_WANT_READ:
00092           rd_handle.set_bit (handle);
00093           status = 1;               // Wait for more activity
00094           break;
00095 
00096         case SSL_ERROR_ZERO_RETURN:
00097           // The peer has notified us that it is shutting down via
00098           // the SSL "close_notify" message so we need to
00099           // shutdown, too.
00100           status = -1;
00101           break;
00102 
00103         case SSL_ERROR_SYSCALL:
00104           // On some platforms (e.g. MS Windows) OpenSSL does not
00105           // store the last error in errno so explicitly do so.
00106           //
00107           // Explicitly check for EWOULDBLOCK since it doesn't get
00108           // converted to an SSL_ERROR_WANT_{READ,WRITE} on some
00109           // platforms. If SSL_accept failed outright, though, don't
00110           // bother checking more. This can happen if the socket gets
00111           // closed during the handshake.
00112           if (ACE_OS::set_errno_to_last_error () == EWOULDBLOCK &&
00113               status == -1)
00114             {
00115               // Although the SSL_ERROR_WANT_READ/WRITE isn't getting
00116               // set correctly, the read/write state should be valid.
00117               // Use that to decide what to do.
00118               status = 1;               // Wait for more activity
00119               if (SSL_want_write (ssl))
00120                 wr_handle.set_bit (handle);
00121               else if (SSL_want_read (ssl))
00122                 rd_handle.set_bit (handle);
00123               else
00124                 status = -1;            // Doesn't want anything - bail out
00125             }
00126           else
00127             status = -1;
00128           break;
00129 
00130         default:
00131           ACE_SSL_Context::report_error ();
00132           status = -1;
00133           break;
00134         }
00135 
00136       if (status == 1)
00137         {
00138           // Must have at least one handle to wait for at this point.
00139           ACE_ASSERT (rd_handle.num_set() == 1 || wr_handle.num_set () == 1);
00140           status = ACE::select (int (handle) + 1,
00141                                 &rd_handle,
00142                                 &wr_handle,
00143                                 0,
00144                                 timeout);
00145 
00146           (void) countdown.update ();
00147 
00148           // 0 is timeout, so we're done.
00149           // -1 is error, so we're done.
00150           // Could be both handles set (same handle in both masks) so
00151           // set to 1.
00152           if (status >= 1)
00153             status = 1;
00154           else                   // Timeout or failure
00155             status = -1;
00156         }
00157 
00158     } while (status == 1 && !SSL_is_init_finished (ssl));
00159 
00160   if (reset_blocking_mode)
00161     {
00162       ACE_Errno_Guard eguard (errno);
00163       ACE::clr_flags (handle, ACE_NONBLOCK);
00164     }
00165 
00166   return (status == -1 ? -1 : 0);
00167 
00168 }
00169 
00170 // General purpose routine for accepting new connections.
00171 // Since our underlying acceptor is of the plain old ACE_SOCK_Acceptor
00172 // variety, get the basic socket setup done with it, then take care of
00173 // the SSL handshake if the socket is accepted.
00174 int
00175 ACE_SSL_SOCK_Acceptor::accept (ACE_SSL_SOCK_Stream &new_stream,
00176                                ACE_Addr *remote_addr,
00177                                ACE_Time_Value *timeout,
00178                                int restart,
00179                                int reset_new_handle) const
00180 {
00181   ACE_TRACE ("ACE_SSL_SOCK_Acceptor::accept");
00182 
00183   // Take into account the time to complete the basic TCP handshake
00184   // and the SSL handshake.
00185   ACE_Countdown_Time countdown (timeout);
00186 
00187   ACE_SOCK_Stream temp_stream;
00188   if (-1 == this->acceptor_.accept (temp_stream,
00189                                     remote_addr,
00190                                     timeout,
00191                                     restart,
00192                                     reset_new_handle))
00193     return -1;
00194 
00195   (void) countdown.update ();
00196 
00197   new_stream.set_handle (temp_stream.get_handle ());
00198   temp_stream.set_handle (ACE_INVALID_HANDLE);
00199 
00200   if (this->ssl_accept (new_stream, timeout) == -1)
00201     {
00202       new_stream.close ();
00203       new_stream.set_handle (ACE_INVALID_HANDLE);
00204       return -1;
00205     }
00206 
00207   return 0;
00208 
00209 }
00210 
00211 int
00212 ACE_SSL_SOCK_Acceptor::accept (ACE_SSL_SOCK_Stream &new_stream,
00213                                ACE_Accept_QoS_Params qos_params,
00214                                ACE_Addr *remote_addr,
00215                                ACE_Time_Value *timeout,
00216                                int restart,
00217                                int reset_new_handle) const
00218 {
00219   ACE_TRACE ("ACE_SSL_SOCK_Acceptor::accept");
00220 
00221   // Take into account the time to complete the basic TCP handshake
00222   // and the SSL handshake.
00223   ACE_Countdown_Time countdown (timeout);
00224 
00225   ACE_SOCK_Stream temp_stream;
00226   if (-1 == this->acceptor_.accept (temp_stream,
00227                                     qos_params,
00228                                     remote_addr,
00229                                     timeout,
00230                                     restart,
00231                                     reset_new_handle))
00232     return -1;
00233 
00234   (void) countdown.update ();
00235 
00236   new_stream.set_handle (temp_stream.get_handle ());
00237   temp_stream.set_handle (ACE_INVALID_HANDLE);
00238 
00239   if (this->ssl_accept (new_stream, timeout) == -1)
00240     {
00241       new_stream.close ();
00242       new_stream.set_handle (ACE_INVALID_HANDLE);
00243       return -1;
00244     }
00245 
00246   return 0;
00247 }
00248 
00249 ACE_END_VERSIONED_NAMESPACE_DECL

Generated on Sun Jan 27 13:03:21 2008 for ACE_SSL by doxygen 1.3.6