SSL_SOCK_Stream.cpp

Go to the documentation of this file.
00001 // $Id: SSL_SOCK_Stream.cpp 80826 2008-03-04 14:51:23Z wotte $
00002 
00003 #include "ace/Handle_Set.h"
00004 #include "ace/Log_Msg.h"
00005 #include "ace/Countdown_Time.h"
00006 #include "ace/OS_NS_string.h"
00007 #include "ace/OS_NS_sys_select.h"
00008 #include "ace/OS_Memory.h"
00009 
00010 #include <openssl/err.h>
00011 
00012 #include "SSL_SOCK_Stream.h"
00013 
00014 #if !defined (__ACE_INLINE__)
00015 #include "SSL_SOCK_Stream.inl"
00016 #endif /* __ACE_INLINE__ */
00017 
00018 ACE_RCSID (ACE_SSL,
00019            SSL_SOCK_Stream,
00020            "$Id: SSL_SOCK_Stream.cpp 80826 2008-03-04 14:51:23Z wotte $")
00021 
00022 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00023 
00024 ACE_ALLOC_HOOK_DEFINE(ACE_SSL_SOCK_Stream)
00025 
00026 ACE_SSL_SOCK_Stream::ACE_SSL_SOCK_Stream (ACE_SSL_Context *context)
00027   : ssl_ (0),
00028     stream_ ()
00029 {
00030   ACE_TRACE ("ACE_SSL_SOCK_Stream::ACE_SSL_SOCK_Stream");
00031 
00032   ACE_SSL_Context * ctx =
00033     (context == 0 ? ACE_SSL_Context::instance () : context);
00034 
00035   this->ssl_ = ::SSL_new (ctx->context ());
00036 
00037   if (this->ssl_ == 0)
00038     {
00039       ACE_ERROR ((LM_ERROR,
00040                   "(%P|%t) ACE_SSL_SOCK_Stream "
00041                   "- cannot allocate new SSL structure %p\n",
00042                   ACE_TEXT ("")));
00043     }
00044 }
00045 
00046 ACE_SSL_SOCK_Stream::~ACE_SSL_SOCK_Stream (void)
00047 {
00048   ACE_TRACE ("ACE_SSL_SOCK_Stream::~ACE_SSL_SOCK_Stream");
00049 
00050   ::SSL_free (this->ssl_);
00051 
00052   // @@ Question: should we reference count the Context object or
00053   // leave that to the application developer? We do not reference
00054   // count reactors (for example) and following some simple rules
00055   // seems to work fine!
00056 }
00057 
00058 ssize_t
00059 ACE_SSL_SOCK_Stream::sendv (const iovec iov[],
00060                             size_t n,
00061                             const ACE_Time_Value *max_wait_time) const
00062 {
00063   ACE_TRACE ("ACE_SSL_SOCK_Stream::sendv");
00064 
00065   // There is subtle problem in this method that occurs when using
00066   // non-blocking IO.  The semantics of a non-blocking scatter write
00067   // (sendv()) are not possible to retain with the emulation in this
00068   // method.
00069 
00070   ssize_t bytes_sent = 0;
00071 
00072   ACE_Time_Value t;
00073   ACE_Time_Value *timeout = const_cast<ACE_Time_Value *> (max_wait_time);
00074 
00075   if (max_wait_time != 0)
00076     {
00077       // Make a copy since ACE_Countdown_Time modifies the
00078       // ACE_Time_Value.
00079       t = *max_wait_time;
00080       timeout = &t;
00081     }
00082 
00083   // Take into account the time between each send.
00084   ACE_Countdown_Time countdown (timeout);
00085 
00086   for (size_t i = 0; i < n; ++i)
00087     {
00088       ssize_t const result = this->send (iov[i].iov_base,
00089                                          iov[i].iov_len,
00090                                          timeout);
00091 
00092       if (result == -1)
00093         {
00094           // There is a subtle difference in behaviour depending on
00095           // whether or not any data was sent.  If no data was sent,
00096           // then always return -1.  Otherwise return bytes_sent.
00097           // This gives the caller an opportunity to keep track of
00098           if (bytes_sent > 0)
00099             break;
00100           else
00101             return -1;
00102         }
00103       else
00104         {
00105           bytes_sent += result;
00106 
00107           // Do not continue on to the next loop iteration if the
00108           // amount of data sent was less than the amount data given.
00109           // This avoids a subtle problem where "holes" in the data
00110           // stream would occur if partial sends of a given buffer in
00111           // the iovec array occured.
00112           if (static_cast<size_t> (result) < static_cast<size_t> (iov[i].iov_len))
00113             break;
00114         }
00115 
00116       (void) countdown.update ();
00117     }
00118 
00119   return bytes_sent;
00120 }
00121 
00122 ssize_t
00123 ACE_SSL_SOCK_Stream::recvv (iovec *io_vec,
00124                             const ACE_Time_Value *timeout) const
00125 {
00126   ACE_TRACE ("ACE_SSL_SOCK_Stream::recvv");
00127 
00128   // From ACE_SOCK_IO::recvv().
00129 #if defined (FIONREAD)
00130   ACE_Handle_Set handle_set;
00131   handle_set.reset ();
00132   handle_set.set_bit (this->get_handle ());
00133 
00134   io_vec->iov_base = 0;
00135 
00136   // Check the status of the current socket.
00137   switch (ACE_OS::select (int (this->get_handle ()) + 1,
00138                           handle_set,
00139                           0, 0,
00140                           timeout))
00141     {
00142     case -1:
00143       return -1;
00144       /* NOTREACHED */
00145     case 0:
00146       errno = ETIME;
00147       return -1;
00148       /* NOTREACHED */
00149     default:
00150       // Goes fine, fallthrough to get data
00151       break;
00152     }
00153 
00154   int inlen;
00155 
00156   if (ACE_OS::ioctl (this->get_handle (),
00157                      FIONREAD,
00158                      &inlen) == -1)
00159     return -1;
00160   else if (inlen > 0)
00161     {
00162       ACE_NEW_RETURN (io_vec->iov_base,
00163                       char[inlen],
00164                       -1);
00165       io_vec->iov_len = this->recv (io_vec->iov_base,
00166                                     inlen);
00167       return io_vec->iov_len;
00168     }
00169   else
00170     return 0;
00171 #else
00172   ACE_UNUSED_ARG (io_vec);
00173   ACE_UNUSED_ARG (timeout);
00174   ACE_NOTSUP_RETURN (-1);
00175 #endif /* FIONREAD */
00176 }
00177 
00178 ssize_t
00179 ACE_SSL_SOCK_Stream::send (const void *buf,
00180                            size_t len,
00181                            int flags,
00182                            const ACE_Time_Value *timeout) const
00183 {
00184   ACE_TRACE ("ACE_SSL_SOCK_Stream::send");
00185 
00186   // If SSL has data in the buffer, i.e. SSL_pending() returns a
00187   // non-zero value, then don't block on select().
00188   if (timeout == 0 || ::SSL_pending (this->ssl_))
00189     return this->send (buf, len, flags);
00190 
00191   int val = 0;
00192   if (ACE::enter_send_timedwait (this->get_handle (),
00193                                  timeout,
00194                                  val) == -1)
00195     return -1;
00196 
00197   ssize_t const bytes_transferred = this->send (buf, len, flags);
00198 
00199   ACE::restore_non_blocking_mode (this->get_handle (), val);
00200 
00201   return bytes_transferred;
00202 }
00203 
00204 ssize_t
00205 ACE_SSL_SOCK_Stream::recv (void *buf,
00206                            size_t n,
00207                            int flags,
00208                            const ACE_Time_Value *timeout) const
00209 {
00210   ACE_TRACE ("ACE_SSL_SOCK_Stream::recv");
00211 
00212   return this->recv_i (buf, n, flags, timeout);
00213 }
00214 
00215 
00216 ssize_t
00217 ACE_SSL_SOCK_Stream::send (size_t n, ...) const
00218 {
00219   ACE_TRACE ("ACE_SSL_SOCK_Stream::send");
00220 
00221   size_t const total_tuples = n / 2;
00222 
00223   va_list argp;
00224   va_start (argp, n);
00225 
00226   ssize_t bytes_sent = 0;
00227 
00228   // NOTE: This method used to fill an IO vector (e.g. iovec) and then
00229   //       send it using a scatter write (sendv()).  However, it is
00230   //       not possible to emulate a non-blocking scatter write over
00231   //       SSL.  As such, there is no point in attempting to use
00232   //       scatter writes over SSL.
00233   for (size_t i = 0; i < total_tuples; ++i)
00234     {
00235       ssize_t const data_len = va_arg (argp, ssize_t);
00236       ssize_t const result = this->send (va_arg (argp, char *), data_len);
00237 
00238       if (result == -1)
00239         {
00240           // There is a subtle difference in behaviour depending on
00241           // whether or not any data was sent.  If no data was sent,
00242           // then always return -1.  Otherwise return bytes_sent.
00243           // This gives the caller an opportunity to keep track of
00244           // which data was actually sent.
00245           if (bytes_sent > 0)
00246             break;
00247           else
00248             {
00249               va_end (argp);
00250               return -1;
00251             }
00252         }
00253       else
00254         {
00255           bytes_sent += result;
00256 
00257           // Do not continue on to the next loop iteration if the
00258           // amount of data sent was less than the amount of data
00259           // given.  This avoids a subtle problem where "holes" in the
00260           // data stream would occur if partial sends of a given
00261           // buffer in the varargs occured.
00262           if (result < data_len)
00263             break;
00264 
00265         }
00266     }
00267 
00268   va_end (argp);
00269 
00270   return bytes_sent;
00271 }
00272 
00273 ssize_t
00274 ACE_SSL_SOCK_Stream::recv (size_t n, ...) const
00275 {
00276   ACE_TRACE ("ACE_SSL_SOCK_Stream::recv");
00277 
00278   size_t const total_tuples = n / 2;
00279 
00280   va_list argp;
00281   va_start (argp, n);
00282 
00283   ssize_t bytes_recv = 0;
00284 
00285   for (size_t i = 0; i < total_tuples; ++i)
00286     {
00287       ssize_t const data_len = va_arg (argp, ssize_t);
00288       ssize_t const result = this->recv (va_arg (argp, char *), data_len);
00289 
00290       if (result == -1)
00291         {
00292           // There is a subtle difference in behaviour depending on
00293           // whether or not any data was received.  If no data was
00294           // received, then always return -1.  Otherwise return
00295           // bytes_received.  This gives the caller an opportunity to
00296           // keep track of which data was actually received.
00297           if (bytes_recv > 0)
00298             break;
00299           else
00300             {
00301               va_end (argp);
00302               return -1;
00303             }
00304         }
00305       else
00306         {
00307           bytes_recv += result;
00308 
00309           // Do not continue on to the next loop iteration if the
00310           // amount of data received was less than the amount of data
00311           // desired.  This avoids a subtle problem where "holes" in
00312           // the data stream would occur if partial receives of a
00313           // given buffer in the varargs occured.
00314           if (result < data_len)
00315             break;
00316 
00317         }
00318     }
00319 
00320   va_end (argp);
00321 
00322   return bytes_recv;
00323 }
00324 
00325 ssize_t
00326 ACE_SSL_SOCK_Stream::send_n (const void *buf,
00327                              size_t len,
00328                              int flags,
00329                              const ACE_Time_Value *timeout,
00330                              size_t *bt) const
00331 {
00332   ACE_TRACE ("ACE_SSL_SOCK_Stream::send_n");
00333 
00334   // No support for send flags in SSL.
00335   if (flags != 0)
00336     ACE_NOTSUP_RETURN (-1);
00337 
00338   /* This code mimics ACE::send_n */
00339   // Total number of bytes written.
00340   size_t temp = 0;
00341   size_t &bytes_transferred = ((bt == 0) ? temp : *bt);
00342 
00343   // Actual number of bytes written in each <send> attempt
00344   ssize_t n = 0;
00345 
00346   for (bytes_transferred = 0;
00347        bytes_transferred < len;
00348        bytes_transferred += n)
00349     {
00350       n = this->send ((const char*) buf + bytes_transferred,
00351                       len - bytes_transferred,
00352                       flags,
00353                       timeout);
00354 
00355       if (n < 0)
00356         {
00357           if (errno == EWOULDBLOCK)
00358             {
00359               // If blocked, try again.
00360               n = 0;
00361               continue;
00362             }
00363           else
00364             return -1;
00365         }
00366       else if (n == 0)
00367         break;
00368     }
00369 
00370   return bytes_transferred;
00371 }
00372 
00373 ssize_t
00374 ACE_SSL_SOCK_Stream::recv_n (void *buf,
00375                              size_t len,
00376                              int flags,
00377                              const ACE_Time_Value *timeout,
00378                              size_t *bt) const
00379 {
00380   ACE_TRACE ("ACE_SSL_SOCK_Stream::recv_n");
00381 
00382   if (flags != 0)
00383     {
00384        if ((flags | MSG_PEEK) != MSG_PEEK)
00385         ACE_NOTSUP_RETURN (-1);
00386     }
00387 
00388   size_t temp = 0;
00389   size_t &bytes_transferred = ((bt == 0) ? temp : *bt);
00390 
00391   ssize_t n = 0;
00392 
00393   for (bytes_transferred = 0;
00394        bytes_transferred < len;
00395        bytes_transferred += n)
00396     {
00397       n = this->recv ((char*) buf + bytes_transferred,
00398                       len - bytes_transferred,
00399                       flags,
00400                       timeout);
00401 
00402       if (n < 0)
00403         {
00404           if (errno == EWOULDBLOCK)
00405             {
00406               // If blocked, try again.
00407               n = 0;
00408               continue;
00409             }
00410           else
00411             return -1;
00412         }
00413       else if (n == 0)
00414         break;
00415     }
00416 
00417   return bytes_transferred;
00418 }
00419 
00420 ssize_t
00421 ACE_SSL_SOCK_Stream::recv_n (void *buf, int len, int flags) const
00422 {
00423   ACE_TRACE ("ACE_SSL_SOCK_Stream::recv_n");
00424 
00425   if (flags != 0)
00426     {
00427       if ((flags | MSG_PEEK) != MSG_PEEK)
00428         ACE_NOTSUP_RETURN (-1);
00429     }
00430 
00431   ssize_t bytes_transferred = 0;
00432   ssize_t n = 0;
00433 
00434   for (bytes_transferred = 0;
00435        bytes_transferred < len;
00436        bytes_transferred += n)
00437     {
00438       n = this->recv ((char*) buf + bytes_transferred,
00439                       len - bytes_transferred,
00440                       flags);
00441 
00442       if (n < 0)
00443         {
00444           if (errno == EWOULDBLOCK)
00445             {
00446               // If blocked, try again.
00447               n = 0;
00448               continue;
00449             }
00450           else
00451             return -1;
00452         }
00453       else if (n == 0)
00454         break;
00455     }
00456 
00457   return bytes_transferred;
00458 }
00459 
00460 ssize_t
00461 ACE_SSL_SOCK_Stream::send_n (const void *buf, int len, int flags) const
00462 {
00463   ACE_TRACE ("ACE_SSL_SOCK_Stream::send_n");
00464 
00465   // Send flags are unsupported in SSL
00466   if (flags != 0)
00467     ACE_NOTSUP_RETURN (-1);
00468 
00469   /*  The following code mimics <ACE::send_n> */
00470   size_t bytes_transferred = 0;
00471   ssize_t n = 0;
00472 
00473   for (bytes_transferred = 0;
00474        bytes_transferred < (size_t) len;
00475        bytes_transferred += n)
00476     {
00477       n = this->send ((const char*) buf + bytes_transferred,
00478                       len - bytes_transferred,
00479                       flags);
00480 
00481       if (n < 0)
00482         {
00483           if (errno == EWOULDBLOCK)
00484             {
00485               // If blocked, try again.
00486               n = 0;
00487               continue;
00488             }
00489           else
00490             return -1;
00491         }
00492       else if (n == 0)
00493         break;
00494     }
00495 
00496   return bytes_transferred;
00497 }
00498 
00499 ssize_t
00500 ACE_SSL_SOCK_Stream::sendv_n (const iovec iov[], size_t iovcnt) const
00501 {
00502   ACE_TRACE ("ACE_SSL_SOCK_Stream::sendv_n");
00503 
00504   ssize_t bytes_sent = 0;
00505 
00506   for (size_t i = 0; i < iovcnt; ++i)
00507     {
00508       ssize_t result = this->send_n (iov[i].iov_base,
00509                                      iov[i].iov_len);
00510 
00511 
00512       if (result == -1)
00513         {
00514           // There is a subtle difference in behaviour depending on
00515           // whether or not any data was sent.  If no data was sent,
00516           // then always return -1.  Otherwise return bytes_sent.
00517           // This gives the caller an opportunity to keep track of
00518           // which data was actually sent.
00519           if (bytes_sent > 0)
00520             break;
00521           else
00522             return -1;
00523         }
00524       else
00525         bytes_sent += result;
00526     }
00527 
00528   return bytes_sent;
00529 }
00530 
00531 ssize_t
00532 ACE_SSL_SOCK_Stream::recvv_n (iovec iov[], size_t iovcnt) const
00533 {
00534   ACE_TRACE ("ACE_SSL_SOCK_Stream::recvv_n");
00535 
00536   ssize_t bytes_read = 0;
00537 
00538   for (size_t i = 0; i < iovcnt; ++i)
00539     {
00540       ssize_t const result = this->recv_n (iov[i].iov_base,
00541                                            iov[i].iov_len);
00542 
00543       if (result == -1)
00544         {
00545           // There is a subtle difference in behaviour depending on
00546           // whether or not any data was read.  If no data was read,
00547           // then always return -1.  Otherwise return bytes_read.
00548           // This gives the caller an opportunity to keep track of
00549           // which data was actually read.
00550           if (bytes_read > 0)
00551             break;
00552           else
00553             return -1;
00554         }
00555       else
00556         bytes_read += result;
00557     }
00558 
00559   return bytes_read;
00560 }
00561 
00562 int
00563 ACE_SSL_SOCK_Stream::get_remote_addr (ACE_Addr &addr) const
00564 {
00565   // Some applications use get_remote_addr() as a way of determining
00566   // whether or not a connection has been established.  In SSL's case,
00567   // the remote addr will be available once the TCP handshake has been
00568   // complete.  Despite that fact, the SSL connection may not have
00569   // been completed.  In such a case, a successful return from
00570   // get_remote_addr() would be misleading.
00571 
00572   if (SSL_is_init_finished (this->ssl_))
00573     return this->ACE_SSL_SOCK::get_remote_addr (addr);
00574 
00575   if (this->get_handle () == ACE_INVALID_HANDLE)
00576     errno = EBADF;
00577   else
00578     errno = ENOTCONN;
00579 
00580   return -1;
00581 }
00582 
00583 ACE_END_VERSIONED_NAMESPACE_DECL

Generated on Tue Feb 2 17:36:34 2010 for ACE_SSL by  doxygen 1.4.7