ACE_SSL_SOCK_Stream Class Reference

Defines methods in the ACE_SSL_SOCK_Stream abstraction. More...

#include <SSL_SOCK_Stream.h>

Inheritance diagram for ACE_SSL_SOCK_Stream:

Inheritance graph
[legend]
Collaboration diagram for ACE_SSL_SOCK_Stream:

Collaboration graph
[legend]
List of all members.

Public Types

typedef ACE_INET_Addr PEER_ADDR
 Meta-type info.

Public Member Functions

 ACE_SSL_SOCK_Stream (ACE_SSL_Context *context=ACE_SSL_Context::instance())
 Constructor.
 ~ACE_SSL_SOCK_Stream (void)
 Destructor.
ssize_t send (const void *buf, size_t n, int flags) const
ssize_t recv (void *buf, size_t n, int flags) const
ssize_t send (const void *buf, size_t n) const
ssize_t recv (void *buf, size_t n) const
ssize_t sendv (const iovec iov[], size_t n, const ACE_Time_Value *timeout=0) const
 Send an iovec of size n to the ssl socket.
ssize_t recvv (iovec *io_vec, const ACE_Time_Value *timeout=0) const
ssize_t send (const void *buf, size_t n, int flags, const ACE_Time_Value *timeout) const
ssize_t recv (void *buf, size_t n, int flags, const ACE_Time_Value *timeout) const
ssize_t send (const void *buf, size_t n, const ACE_Time_Value *timeout) const
ssize_t recv (void *buf, size_t n, const ACE_Time_Value *timeout) const
ssize_t send (size_t n,...) const
 Send n varargs messages to the connected ssl socket.
ssize_t recv (size_t n,...) const
 Recv n varargs messages to the connected ssl socket.
ssize_t send_n (const void *buf, int n) const
 Send n bytes, keep trying until n are sent.
ssize_t recv_n (void *buf, int n) const
 Recv n bytes, keep trying until n are received.
ssize_t sendv_n (const iovec iov[], size_t n) const
ssize_t recvv_n (iovec iov[], size_t n) const
 Receive an iovec of size n to the connected socket.
int close (void)
 Close down the socket.
void set_handle (ACE_HANDLE fd)
 Overridden set_handle() method.
SSL * ssl (void) const
 Return a pointer to the underlying SSL structure.
int get_remote_addr (ACE_Addr &) const
ACE_SOCK_Streampeer (void)
 Return the underlying ACE_SOCK_Stream which ACE_SSL runs atop of.
ssize_t send_n (const void *buf, int n, int flags) const
 Send n bytes, keep trying until n are sent.
ssize_t recv_n (void *buf, int n, int flags) const
 Recv n bytes, keep trying until n are sent.
ssize_t send_n (const void *buf, size_t len, int flags, const ACE_Time_Value *timeout, size_t *bytes_transferred=0) const
ssize_t recv_n (void *buf, size_t len, int flags, const ACE_Time_Value *timeout, size_t *bytes_transferred=0) const
int close_reader (void)
 Close down the reader.
int close_writer (void)
 Close down the writer.

Public Attributes

 ACE_ALLOC_HOOK_DECLARE
 Declare the dynamic allocation hooks.

Protected Member Functions

ssize_t send_i (const void *buf, size_t n, int flags) const
ssize_t recv_i (void *buf, size_t n, int flags, const ACE_Time_Value *timeout) const

Private Attributes

ACE_UNIMPLEMENTED_FUNC(void
operator=(const ACE_SSL_SOCK_Stream
&)) ACE_UNIMPLEMENTED_FUNC(ACE_SSL_SOCK_Stream(const
ACE_SSL_SOCK_Stream &)) protected
ACE_SOCK_Stream 
stream_
 The stream which works under the ssl connection.

Detailed Description

Defines methods in the ACE_SSL_SOCK_Stream abstraction.

This class encapsulates the methods and functionality necessary to send and receive data over TLS/SSL.

Since SSL is record-oriented, some additional steps must be taken to make the ACE_SSL_SOCK_Stream interact properly with the Reactor (if one is used) when performing non-blocking IO. In particular, if SSL_pending (ssl), where "ssl" is a pointer to the SSL data structure returned from ACE_SSL_SOCK_Stream::ssl(), returns a non-zero value then the event handler that calls the IO methods in this class should return a value greater than zero to force the Reactor to invoke the event handler before polling for additional events (e.g. blocking on select()).
Note:
The user must currently ensure that only one thread services a given SSL session at any given time since underlying SSL implementations, such as OpenSSL, are not entirely thread-safe or reentrant.

Definition at line 62 of file SSL_SOCK_Stream.h.


Member Typedef Documentation

typedef ACE_INET_Addr ACE_SSL_SOCK_Stream::PEER_ADDR

Meta-type info.

Definition at line 253 of file SSL_SOCK_Stream.h.


Constructor & Destructor Documentation

ACE_SSL_SOCK_Stream::ACE_SSL_SOCK_Stream ( ACE_SSL_Context context = ACE_SSL_Context::instance()  ) 

Constructor.

Parameters:
context Pointer to ACE_SSL_Context instance containing the OpenSSL SSL data structure to be associated with this ACE_SSL_SOCK_Stream. The SSL data structure will be copied to make it at least logically independent of the supplied context.

ACE_SSL_SOCK_Stream::~ACE_SSL_SOCK_Stream ( void   ) 

Destructor.

Definition at line 46 of file SSL_SOCK_Stream.cpp.

References ACE_TRACE.

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 }


Member Function Documentation

ACE_INLINE int ACE_SSL_SOCK_Stream::close ( void   ) 

Close down the socket.

Reimplemented from ACE_SOCK.

Definition at line 269 of file SSL_SOCK_Stream.inl.

References ACE_TRACE, close(), ACE_SSL_Context::report_error(), set_handle(), and stream_.

Referenced by ACE_SSL_SOCK_Acceptor::accept(), close(), ACE_SSL_SOCK_Connector::complete(), and ACE_SSL_SOCK_Connector::connect().

00270 {
00271   ACE_TRACE ("ACE_SSL_SOCK_Stream::close");
00272 
00273   if (this->ssl_ == 0 || this->get_handle () == ACE_INVALID_HANDLE)
00274     return 0;  // SSL_SOCK_Stream was never opened.
00275 
00276   // SSL_shutdown() returns 1 on successful shutdown of the SSL
00277   // connection, not 0.
00278   int const status = ::SSL_shutdown (this->ssl_);
00279 
00280   switch (::SSL_get_error (this->ssl_, status))
00281     {
00282     case SSL_ERROR_NONE:
00283     case SSL_ERROR_SYSCALL:  // Ignore this error condition.
00284 
00285       // Reset the SSL object to allow another connection to be made
00286       // using this ACE_SSL_SOCK_Stream instance.  This prevents the
00287       // previous SSL session state from being associated with the new
00288       // SSL session/connection.
00289       (void) ::SSL_clear (this->ssl_);
00290       this->set_handle (ACE_INVALID_HANDLE);
00291       return this->stream_.close ();
00292 
00293     case SSL_ERROR_WANT_READ:
00294     case SSL_ERROR_WANT_WRITE:
00295       errno = EWOULDBLOCK;
00296       break;
00297 
00298     default:
00299       ACE_SSL_Context::report_error ();
00300 
00301       ACE_Errno_Guard error (errno);   // Save/restore errno
00302       (void) this->stream_.close ();
00303 
00304       return -1;
00305     }
00306 
00307   return -1;
00308 }

ACE_INLINE int ACE_SSL_SOCK_Stream::close_reader ( void   ) 

Close down the reader.

Selectively close endpoints.

Definition at line 255 of file SSL_SOCK_Stream.inl.

References ACE_TRACE, close_reader(), and stream_.

Referenced by close_reader().

00256 {
00257   ACE_TRACE ("ACE_SSL_SOCK_Stream::close_reader");
00258   return this->stream_.close_reader ();
00259 }

ACE_INLINE int ACE_SSL_SOCK_Stream::close_writer ( void   ) 

Close down the writer.

Definition at line 262 of file SSL_SOCK_Stream.inl.

References ACE_TRACE, close_writer(), and stream_.

Referenced by close_writer().

00263 {
00264   ACE_TRACE ("ACE_SSL_SOCK_Stream::close_writer");
00265   return this->stream_.close_writer ();
00266 }

int ACE_SSL_SOCK_Stream::get_remote_addr ( ACE_Addr  )  const

Return the address of the remotely connected peer (if there is one), in the referenced <ACE_Addr>. Returns 0 if successful, else -1.

Note:
If the TCP connection has been completed but the SSL connection has not been completed yet, -1 will be returned.

Reimplemented from ACE_SOCK.

Definition at line 563 of file SSL_SOCK_Stream.cpp.

References ACE_SOCK::get_remote_addr().

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 }

ACE_INLINE ACE_SOCK_Stream & ACE_SSL_SOCK_Stream::peer ( void   ) 

Return the underlying ACE_SOCK_Stream which ACE_SSL runs atop of.

Definition at line 311 of file SSL_SOCK_Stream.inl.

References ACE_TRACE, and stream_.

Referenced by ACE_SSL_SOCK_Connector::complete(), and ACE_SSL_SOCK_Connector::connect().

00312 {
00313   ACE_TRACE ("ACE_SSL_SOCK_Stream::peer");
00314   return this->stream_;
00315 }

ssize_t ACE_SSL_SOCK_Stream::recv ( size_t  n,
  ... 
) const

Recv n varargs messages to the connected ssl socket.

Definition at line 274 of file SSL_SOCK_Stream.cpp.

References ACE_TRACE, and recv().

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 }

ACE_INLINE ssize_t ACE_SSL_SOCK_Stream::recv ( void *  buf,
size_t  n,
const ACE_Time_Value timeout 
) const

Wait up to timeout amount of time to receive up to n bytes into buf (uses the recv() call). If recv() times out a -1 is returned with errno == ETIME. If it succeeds the number of bytes received is returned.

Definition at line 232 of file SSL_SOCK_Stream.inl.

References ACE_TRACE, and recv().

00235 {
00236   ACE_TRACE ("ACE_SSL_SOCK_Stream::recv");
00237   return this->recv (buf, n, 0, timeout);
00238 }

ssize_t ACE_SSL_SOCK_Stream::recv ( void *  buf,
size_t  n,
int  flags,
const ACE_Time_Value timeout 
) const

Wait up to timeout amount of time to receive up to n bytes into buf (uses the recv() call). If recv() times out -1 is returned with errno == ETIME. If it succeeds the number of bytes received is returned. MSG_PEEK is the only supported flag.

Definition at line 205 of file SSL_SOCK_Stream.cpp.

References ACE_TRACE, and recv_i().

00209 {
00210   ACE_TRACE ("ACE_SSL_SOCK_Stream::recv");
00211 
00212   return this->recv_i (buf, n, flags, timeout);
00213 }

ACE_INLINE ssize_t ACE_SSL_SOCK_Stream::recv ( void *  buf,
size_t  n 
) const

Recv an n byte buffer from the ssl socket using the semantics of read(2).

Definition at line 214 of file SSL_SOCK_Stream.inl.

References ACE_TRACE, and recv_i().

00216 {
00217   ACE_TRACE ("ACE_SSL_SOCK_Stream::recv");
00218 
00219   return this->recv_i (buf, n, 0, 0);
00220 }

ACE_INLINE ssize_t ACE_SSL_SOCK_Stream::recv ( void *  buf,
size_t  n,
int  flags 
) const

ACE_SSL supports MSG_PEEK, but no other flags at this time.

Definition at line 197 of file SSL_SOCK_Stream.inl.

References recv_i().

Referenced by recv(), and recvv().

00200 {
00201   return this->recv_i (buf, n, flags, 0);
00202 }

ACE_INLINE ssize_t ACE_SSL_SOCK_Stream::recv_i ( void *  buf,
size_t  n,
int  flags,
const ACE_Time_Value timeout 
) const [protected]

Underlying send() helper method common to all public send() methods.

Definition at line 96 of file SSL_SOCK_Stream.inl.

References ACE_BIT_ENABLED, ACE_NOTSUP_RETURN, ACE_TRACE, ACE::enter_recv_timedwait(), ACE_SSL_SOCK::get_handle(), MSG_PEEK, ACE::record_and_set_non_blocking_mode(), ACE_SSL_Context::report_error(), ACE::restore_non_blocking_mode(), and ACE_OS::set_errno_to_last_error().

Referenced by recv().

00100 {
00101   ACE_TRACE ("ACE_SSL_SOCK_Stream::recv_i");
00102 
00103   // NOTE: Caller must provide thread-synchronization.
00104 
00105   int bytes_read = 0;
00106   ACE_HANDLE const handle = this->get_handle ();
00107 
00108   // Value for current I/O mode (blocking/non-blocking)
00109   int val = 0;
00110 
00111   if (timeout != 0)
00112     ACE::record_and_set_non_blocking_mode (handle,
00113                                            val);
00114 
00115   // Only block on select() with a timeout if no data in the
00116   // internal OpenSSL buffer is pending read completion for
00117   // the same reasons stated above, i.e. all data must be read
00118   // before blocking on select().
00119   if (timeout != 0
00120       && !::SSL_pending (this->ssl_))
00121     {
00122       if (ACE::enter_recv_timedwait (handle,
00123                                      timeout,
00124                                      val) == -1)
00125         return -1;
00126     }
00127 
00128   if (flags)
00129     {
00130       if (ACE_BIT_ENABLED (flags, MSG_PEEK))
00131         bytes_read = ::SSL_peek (this->ssl_,
00132                                  static_cast<char *> (buf),
00133                                  n);
00134       else
00135         ACE_NOTSUP_RETURN (-1);
00136     }
00137   else
00138     {
00139       bytes_read = ::SSL_read (this->ssl_,
00140                                static_cast<char *> (buf),
00141                                n);
00142     }
00143 
00144   int const status = ::SSL_get_error (this->ssl_, bytes_read);
00145   switch (status)
00146     {
00147     case SSL_ERROR_NONE:
00148       if (timeout != 0)
00149         ACE::restore_non_blocking_mode (handle, val);
00150 
00151       return bytes_read;
00152 
00153     case SSL_ERROR_WANT_READ:
00154     case SSL_ERROR_WANT_WRITE:
00155       errno = EWOULDBLOCK;
00156 
00157       return -1;
00158 
00159     case SSL_ERROR_ZERO_RETURN:
00160       if (timeout != 0)
00161         ACE::restore_non_blocking_mode (handle, val);
00162 
00163       // The peer has notified us that it is shutting down via the SSL
00164       // "close_notify" message so we need to shutdown, too.
00165       (void) ::SSL_shutdown (this->ssl_);
00166 
00167       return bytes_read;
00168 
00169     case SSL_ERROR_SYSCALL:
00170       if (bytes_read == 0)
00171         // An EOF occured but the SSL "close_notify" message was not
00172         // sent.  This is a protocol error, but we ignore it.
00173         return 0;
00174 
00175       // If not an EOF, then fall through to "default" case.
00176 
00177       // On some platforms (e.g. MS Windows) OpenSSL does not store
00178       // the last error in errno so explicitly do so.
00179       ACE_OS::set_errno_to_last_error ();
00180 
00181       break;
00182 
00183     default:
00184       // Reset errno to prevent previous values (e.g. EWOULDBLOCK)
00185       // from being associated with a fatal SSL error.
00186       errno = 0;
00187 
00188       ACE_SSL_Context::report_error ();
00189 
00190       break;
00191     }
00192 
00193   return -1;
00194 }

ssize_t ACE_SSL_SOCK_Stream::recv_n ( void *  buf,
size_t  len,
int  flags,
const ACE_Time_Value timeout,
size_t *  bytes_transferred = 0 
) const

Try to receive exactly len bytes into buf (uses the recv() call). The ACE_Time_Value indicates how long to blocking trying to receive. If timeout == 0, the caller will block until action is possible, else will wait until the relative time specified in timeout elapses). If recv() blocks for longer than timeout the number of bytes actually read is returned with errno == ETIME. If a timeout does not occur, recv_n return len (i.e., the number of bytes requested to be read).

Definition at line 374 of file SSL_SOCK_Stream.cpp.

References ACE_NOTSUP_RETURN, ACE_TRACE, and MSG_PEEK.

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 }

ssize_t ACE_SSL_SOCK_Stream::recv_n ( void *  buf,
int  n,
int  flags 
) const

Recv n bytes, keep trying until n are sent.

Definition at line 421 of file SSL_SOCK_Stream.cpp.

References ACE_NOTSUP_RETURN, ACE_TRACE, and MSG_PEEK.

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 }

ACE_INLINE ssize_t ACE_SSL_SOCK_Stream::recv_n ( void *  buf,
int  n 
) const

Recv n bytes, keep trying until n are received.

Definition at line 241 of file SSL_SOCK_Stream.inl.

References ACE_TRACE.

00242 {
00243   ACE_TRACE ("ACE_SSL_SOCK_Stream::recv_n");
00244   return this->recv_n (buf, buf_size, 0);
00245 }

ssize_t ACE_SSL_SOCK_Stream::recvv ( iovec *  io_vec,
const ACE_Time_Value timeout = 0 
) const

Allows a client to read from a socket without having to provide a buffer to read. This method determines how much data is in the socket, allocates a buffer of this size, reads in the data, and returns the number of bytes read. The caller is responsible for deleting the member in the iov_base field of io_vec using delete [] io_vec->iov_base.

Definition at line 123 of file SSL_SOCK_Stream.cpp.

References ACE_NEW_RETURN, ACE_NOTSUP_RETURN, ACE_TRACE, ACE_OS::ioctl(), recv(), ACE_Handle_Set::reset(), ACE_OS::select(), and ACE_Handle_Set::set_bit().

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 }

ssize_t ACE_SSL_SOCK_Stream::recvv_n ( iovec  iov[],
size_t  n 
) const

Receive an iovec of size n to the connected socket.

Definition at line 532 of file SSL_SOCK_Stream.cpp.

References ACE_TRACE.

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 }

ssize_t ACE_SSL_SOCK_Stream::send ( size_t  n,
  ... 
) const

Send n varargs messages to the connected ssl socket.

Definition at line 217 of file SSL_SOCK_Stream.cpp.

References ACE_TRACE, and send().

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 }

ACE_INLINE ssize_t ACE_SSL_SOCK_Stream::send ( const void *  buf,
size_t  n,
const ACE_Time_Value timeout 
) const

Wait to to timeout amount of time to send up to n bytes into buf (uses the send() call). If send() times out a -1 is returned with errno == ETIME. If it succeeds the number of bytes sent is returned.

Definition at line 223 of file SSL_SOCK_Stream.inl.

References ACE_TRACE, and send().

00226 {
00227   ACE_TRACE ("ACE_SSL_SOCK_Stream::send");
00228   return this->send (buf, len, 0, timeout);
00229 }

ssize_t ACE_SSL_SOCK_Stream::send ( const void *  buf,
size_t  n,
int  flags,
const ACE_Time_Value timeout 
) const

Wait to timeout amount of time to send up to n bytes into buf (uses the send() call). If send() times out -1 is returned with errno == ETIME. If it succeeds the number of bytes sent is returned. No flags are supported.

Definition at line 179 of file SSL_SOCK_Stream.cpp.

References ACE_TRACE, ACE::enter_send_timedwait(), ACE::restore_non_blocking_mode(), and send().

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 }

ACE_INLINE ssize_t ACE_SSL_SOCK_Stream::send ( const void *  buf,
size_t  n 
) const

Send an n byte buffer to the ssl socket using the semantics of write(2).

Definition at line 205 of file SSL_SOCK_Stream.inl.

References ACE_TRACE, and send_i().

00207 {
00208   ACE_TRACE ("ACE_SSL_SOCK_Stream::send");
00209 
00210   return this->send_i (buf, n, 0);
00211 }

ACE_INLINE ssize_t ACE_SSL_SOCK_Stream::send ( const void *  buf,
size_t  n,
int  flags 
) const

ACE_SSL supports no flags for sending at this time.

Definition at line 88 of file SSL_SOCK_Stream.inl.

References send_i().

Referenced by send().

00091 {
00092   return this->send_i (buf, n, flags);
00093 }

ACE_INLINE ssize_t ACE_SSL_SOCK_Stream::send_i ( const void *  buf,
size_t  n,
int  flags 
) const [protected]

Underlying send() helper method common to all public send() methods.

Definition at line 26 of file SSL_SOCK_Stream.inl.

References ACE_NOTSUP_RETURN, ACE_TRACE, ACE_SSL_Context::report_error(), and ACE_OS::set_errno_to_last_error().

Referenced by send().

00029 {
00030   ACE_TRACE ("ACE_SSL_SOCK_Stream::send_i");
00031 
00032   // NOTE: Caller must provide thread-synchronization.
00033 
00034   // No send flags are supported in SSL.
00035   if (flags != 0)
00036     ACE_NOTSUP_RETURN (-1);
00037 
00038   int const bytes_sent = ::SSL_write (this->ssl_,
00039                                       static_cast<const char *> (buf),
00040                                       n);
00041 
00042   switch (::SSL_get_error (this->ssl_, bytes_sent))
00043     {
00044     case SSL_ERROR_NONE:
00045       return bytes_sent;
00046 
00047     case SSL_ERROR_WANT_READ:
00048     case SSL_ERROR_WANT_WRITE:
00049       errno = EWOULDBLOCK;
00050 
00051       return -1;
00052 
00053     case SSL_ERROR_ZERO_RETURN:
00054       // The peer has notified us that it is shutting down via the SSL
00055       // "close_notify" message so we need to shutdown, too.
00056       (void) ::SSL_shutdown (this->ssl_);
00057 
00058       return bytes_sent;
00059 
00060     case SSL_ERROR_SYSCALL:
00061       if (bytes_sent == 0)
00062         // An EOF occured but the SSL "close_notify" message was not
00063         // sent.  This is a protocol error, but we ignore it.
00064         return 0;
00065 
00066       // If not an EOF, then fall through to "default" case.
00067 
00068       // On some platforms (e.g. MS Windows) OpenSSL does not store
00069       // the last error in errno so explicitly do so.
00070       ACE_OS::set_errno_to_last_error ();
00071 
00072       break;
00073 
00074     default:
00075       // Reset errno to prevent previous values (e.g. EWOULDBLOCK)
00076       // from being associated with fatal SSL errors.
00077       errno = 0;
00078 
00079       ACE_SSL_Context::report_error ();
00080 
00081       break;
00082     }
00083 
00084   return -1;
00085 }

ssize_t ACE_SSL_SOCK_Stream::send_n ( const void *  buf,
size_t  len,
int  flags,
const ACE_Time_Value timeout,
size_t *  bytes_transferred = 0 
) const

Try to send exactly len bytes into buf (uses the send() call). If send() blocks for longer than timeout the number of bytes actually sent is returned with errno == ETIME. If a timeout does not occur, send_n() return len (i.e., the number of bytes requested to be sent).

Definition at line 326 of file SSL_SOCK_Stream.cpp.

References ACE_NOTSUP_RETURN, and ACE_TRACE.

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 }

ssize_t ACE_SSL_SOCK_Stream::send_n ( const void *  buf,
int  n,
int  flags 
) const

Send n bytes, keep trying until n are sent.

Note:
In the following four methods, only MSG_PEEK is supported for recv_n(), and no flags are supported for send_n().

Definition at line 461 of file SSL_SOCK_Stream.cpp.

References ACE_NOTSUP_RETURN, and ACE_TRACE.

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 }

ACE_INLINE ssize_t ACE_SSL_SOCK_Stream::send_n ( const void *  buf,
int  n 
) const

Send n bytes, keep trying until n are sent.

Definition at line 248 of file SSL_SOCK_Stream.inl.

References ACE_TRACE.

00249 {
00250   ACE_TRACE ("ACE_SSL_SOCK_Stream::send_n");
00251   return this->send_n (buf, len, 0);
00252 }

ssize_t ACE_SSL_SOCK_Stream::sendv ( const iovec  iov[],
size_t  n,
const ACE_Time_Value timeout = 0 
) const

Send an iovec of size n to the ssl socket.

Note that it is not possible to perform a "scattered" write with the underlying OpenSSL implementation. As such, the expected semantics are not fully reproduced with this implementation.

Definition at line 59 of file SSL_SOCK_Stream.cpp.

References ACE_TRACE, and ACE_Countdown_Time::update().

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 }

ssize_t ACE_SSL_SOCK_Stream::sendv_n ( const iovec  iov[],
size_t  n 
) const

Send an iovec of size n to the connected socket. Will block until all bytes are sent or an error occurs.

Definition at line 500 of file SSL_SOCK_Stream.cpp.

References ACE_TRACE.

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 }

ACE_BEGIN_VERSIONED_NAMESPACE_DECL ACE_INLINE void ACE_SSL_SOCK_Stream::set_handle ( ACE_HANDLE  fd  ) 

Overridden set_handle() method.

Only an ACE_SSL_SOCK_Acceptor or ACE_SSL_SOCK_Connector should access this method since some state in the underlying "ssl_" data structure is set during SSL connection establishment.

Reimplemented from ACE_SSL_SOCK.

Definition at line 10 of file SSL_SOCK_Stream.inl.

References set_handle(), ACE_SSL_SOCK::set_handle(), and stream_.

Referenced by ACE_SSL_SOCK_Acceptor::accept(), close(), ACE_SSL_SOCK_Connector::connect(), and set_handle().

00011 {
00012   if (this->ssl_ == 0 || fd == ACE_INVALID_HANDLE)
00013     {
00014       this->ACE_SSL_SOCK::set_handle (ACE_INVALID_HANDLE);
00015       return;
00016     }
00017   else
00018     {
00019       (void) ::SSL_set_fd (this->ssl_, (int) fd);
00020       this->ACE_SSL_SOCK::set_handle (fd);
00021       this->stream_.set_handle (fd);
00022     }
00023 }

ACE_INLINE SSL * ACE_SSL_SOCK_Stream::ssl ( void   )  const

Return a pointer to the underlying SSL structure.

Definition at line 318 of file SSL_SOCK_Stream.inl.

Referenced by ACE_SSL_SOCK_Acceptor::ssl_accept(), and ACE_SSL_SOCK_Connector::ssl_connect().

00319 {
00320   return this->ssl_;
00321 }


Member Data Documentation

ACE_SSL_SOCK_Stream::ACE_ALLOC_HOOK_DECLARE

Declare the dynamic allocation hooks.

Reimplemented from ACE_SOCK.

Definition at line 256 of file SSL_SOCK_Stream.h.

ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_SSL_SOCK_Stream &)) ACE_UNIMPLEMENTED_FUNC (ACE_SSL_SOCK_Stream ( const ACE_SSL_SOCK_Stream &)) protected ACE_SOCK_Stream ACE_SSL_SOCK_Stream::stream_ [private]

The stream which works under the ssl connection.

Definition at line 300 of file SSL_SOCK_Stream.h.

Referenced by close(), close_reader(), close_writer(), peer(), and set_handle().


The documentation for this class was generated from the following files:
Generated on Tue Feb 2 17:36:36 2010 for ACE_SSL by  doxygen 1.4.7