Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

SSL_SOCK_Stream.cpp

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

Generated on Mon Jun 16 13:15:56 2003 for ACE_SSL by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002