SSL_SOCK_Stream.cpp

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

Generated on Thu Nov 9 11:41:56 2006 for ACE_SSL by doxygen 1.3.6