added ace + vcproj for win
--HG-- branch : trunk
This commit is contained in:
+330
@@ -0,0 +1,330 @@
|
||||
// -*- C++ -*-
|
||||
//
|
||||
// $Id: SSL_SOCK_Stream.inl 82579 2008-08-10 23:03:06Z mitza $
|
||||
|
||||
#include "ace/OS_NS_errno.h"
|
||||
#include "ace/Truncate.h"
|
||||
|
||||
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
|
||||
|
||||
ACE_INLINE void
|
||||
ACE_SSL_SOCK_Stream::set_handle (ACE_HANDLE fd)
|
||||
{
|
||||
if (this->ssl_ == 0 || fd == ACE_INVALID_HANDLE)
|
||||
{
|
||||
this->ACE_SSL_SOCK::set_handle (ACE_INVALID_HANDLE);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
(void) ::SSL_set_fd (this->ssl_, (int) fd);
|
||||
this->ACE_SSL_SOCK::set_handle (fd);
|
||||
this->stream_.set_handle (fd);
|
||||
}
|
||||
}
|
||||
|
||||
ACE_INLINE ssize_t
|
||||
ACE_SSL_SOCK_Stream::send_i (const void *buf,
|
||||
size_t n,
|
||||
int flags) const
|
||||
{
|
||||
ACE_TRACE ("ACE_SSL_SOCK_Stream::send_i");
|
||||
|
||||
// NOTE: Caller must provide thread-synchronization.
|
||||
|
||||
// No send flags are supported in SSL.
|
||||
if (flags != 0)
|
||||
{
|
||||
ACE_NOTSUP_RETURN (-1);
|
||||
}
|
||||
|
||||
int const bytes_sent = ::SSL_write (this->ssl_,
|
||||
static_cast<const char *> (buf),
|
||||
ACE_Utils::truncate_cast<int> (n));
|
||||
|
||||
switch (::SSL_get_error (this->ssl_, bytes_sent))
|
||||
{
|
||||
case SSL_ERROR_NONE:
|
||||
return bytes_sent;
|
||||
|
||||
case SSL_ERROR_WANT_READ:
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
errno = EWOULDBLOCK;
|
||||
|
||||
return -1;
|
||||
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
// The peer has notified us that it is shutting down via the SSL
|
||||
// "close_notify" message so we need to shutdown, too.
|
||||
(void) ::SSL_shutdown (this->ssl_);
|
||||
|
||||
return bytes_sent;
|
||||
|
||||
case SSL_ERROR_SYSCALL:
|
||||
if (bytes_sent == 0)
|
||||
// An EOF occured but the SSL "close_notify" message was not
|
||||
// sent. This is a protocol error, but we ignore it.
|
||||
return 0;
|
||||
|
||||
// If not an EOF, then fall through to "default" case.
|
||||
|
||||
// On some platforms (e.g. MS Windows) OpenSSL does not store
|
||||
// the last error in errno so explicitly do so.
|
||||
ACE_OS::set_errno_to_last_error ();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
// Reset errno to prevent previous values (e.g. EWOULDBLOCK)
|
||||
// from being associated with fatal SSL errors.
|
||||
errno = 0;
|
||||
|
||||
ACE_SSL_Context::report_error ();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
ACE_INLINE ssize_t
|
||||
ACE_SSL_SOCK_Stream::send (const void *buf,
|
||||
size_t n,
|
||||
int flags) const
|
||||
{
|
||||
return this->send_i (buf, n, flags);
|
||||
}
|
||||
|
||||
ACE_INLINE ssize_t
|
||||
ACE_SSL_SOCK_Stream::recv_i (void *buf,
|
||||
size_t n,
|
||||
int flags,
|
||||
const ACE_Time_Value *timeout) const
|
||||
{
|
||||
ACE_TRACE ("ACE_SSL_SOCK_Stream::recv_i");
|
||||
|
||||
// NOTE: Caller must provide thread-synchronization.
|
||||
|
||||
int bytes_read = 0;
|
||||
ACE_HANDLE const handle = this->get_handle ();
|
||||
|
||||
// Value for current I/O mode (blocking/non-blocking)
|
||||
int val = 0;
|
||||
|
||||
if (timeout != 0)
|
||||
ACE::record_and_set_non_blocking_mode (handle,
|
||||
val);
|
||||
|
||||
// Only block on select() with a timeout if no data in the
|
||||
// internal OpenSSL buffer is pending read completion for
|
||||
// the same reasons stated above, i.e. all data must be read
|
||||
// before blocking on select().
|
||||
if (timeout != 0
|
||||
&& !::SSL_pending (this->ssl_))
|
||||
{
|
||||
if (ACE::enter_recv_timedwait (handle,
|
||||
timeout,
|
||||
val) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags)
|
||||
{
|
||||
if (ACE_BIT_ENABLED (flags, MSG_PEEK))
|
||||
{
|
||||
bytes_read = ::SSL_peek (this->ssl_,
|
||||
static_cast<char *> (buf),
|
||||
ACE_Utils::truncate_cast<int> (n));
|
||||
}
|
||||
else
|
||||
{
|
||||
ACE_NOTSUP_RETURN (-1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes_read = ::SSL_read (this->ssl_,
|
||||
static_cast<char *> (buf),
|
||||
ACE_Utils::truncate_cast<int> (n));
|
||||
}
|
||||
|
||||
int const status = ::SSL_get_error (this->ssl_, bytes_read);
|
||||
switch (status)
|
||||
{
|
||||
case SSL_ERROR_NONE:
|
||||
if (timeout != 0)
|
||||
ACE::restore_non_blocking_mode (handle, val);
|
||||
|
||||
return bytes_read;
|
||||
|
||||
case SSL_ERROR_WANT_READ:
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
errno = EWOULDBLOCK;
|
||||
|
||||
return -1;
|
||||
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
if (timeout != 0)
|
||||
ACE::restore_non_blocking_mode (handle, val);
|
||||
|
||||
// The peer has notified us that it is shutting down via the SSL
|
||||
// "close_notify" message so we need to shutdown, too.
|
||||
(void) ::SSL_shutdown (this->ssl_);
|
||||
|
||||
return bytes_read;
|
||||
|
||||
case SSL_ERROR_SYSCALL:
|
||||
if (bytes_read == 0)
|
||||
// An EOF occured but the SSL "close_notify" message was not
|
||||
// sent. This is a protocol error, but we ignore it.
|
||||
return 0;
|
||||
|
||||
// If not an EOF, then fall through to "default" case.
|
||||
|
||||
// On some platforms (e.g. MS Windows) OpenSSL does not store
|
||||
// the last error in errno so explicitly do so.
|
||||
ACE_OS::set_errno_to_last_error ();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
// Reset errno to prevent previous values (e.g. EWOULDBLOCK)
|
||||
// from being associated with a fatal SSL error.
|
||||
errno = 0;
|
||||
|
||||
ACE_SSL_Context::report_error ();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
ACE_INLINE ssize_t
|
||||
ACE_SSL_SOCK_Stream::recv (void *buf,
|
||||
size_t n,
|
||||
int flags) const
|
||||
{
|
||||
return this->recv_i (buf, n, flags, 0);
|
||||
}
|
||||
|
||||
ACE_INLINE ssize_t
|
||||
ACE_SSL_SOCK_Stream::send (const void *buf,
|
||||
size_t n) const
|
||||
{
|
||||
ACE_TRACE ("ACE_SSL_SOCK_Stream::send");
|
||||
|
||||
return this->send_i (buf, n, 0);
|
||||
}
|
||||
|
||||
ACE_INLINE ssize_t
|
||||
ACE_SSL_SOCK_Stream::recv (void *buf,
|
||||
size_t n) const
|
||||
{
|
||||
ACE_TRACE ("ACE_SSL_SOCK_Stream::recv");
|
||||
|
||||
return this->recv_i (buf, n, 0, 0);
|
||||
}
|
||||
|
||||
ACE_INLINE ssize_t
|
||||
ACE_SSL_SOCK_Stream::send (const void *buf,
|
||||
size_t len,
|
||||
const ACE_Time_Value *timeout) const
|
||||
{
|
||||
ACE_TRACE ("ACE_SSL_SOCK_Stream::send");
|
||||
return this->send (buf, len, 0, timeout);
|
||||
}
|
||||
|
||||
ACE_INLINE ssize_t
|
||||
ACE_SSL_SOCK_Stream::recv (void *buf,
|
||||
size_t n,
|
||||
const ACE_Time_Value *timeout) const
|
||||
{
|
||||
ACE_TRACE ("ACE_SSL_SOCK_Stream::recv");
|
||||
return this->recv (buf, n, 0, timeout);
|
||||
}
|
||||
|
||||
ACE_INLINE ssize_t
|
||||
ACE_SSL_SOCK_Stream::recv_n (void *buf, int buf_size) const
|
||||
{
|
||||
ACE_TRACE ("ACE_SSL_SOCK_Stream::recv_n");
|
||||
return this->recv_n (buf, buf_size, 0);
|
||||
}
|
||||
|
||||
ACE_INLINE ssize_t
|
||||
ACE_SSL_SOCK_Stream::send_n (const void *buf, int len) const
|
||||
{
|
||||
ACE_TRACE ("ACE_SSL_SOCK_Stream::send_n");
|
||||
return this->send_n (buf, len, 0);
|
||||
}
|
||||
|
||||
ACE_INLINE int
|
||||
ACE_SSL_SOCK_Stream::close_reader (void)
|
||||
{
|
||||
ACE_TRACE ("ACE_SSL_SOCK_Stream::close_reader");
|
||||
return this->stream_.close_reader ();
|
||||
}
|
||||
|
||||
ACE_INLINE int
|
||||
ACE_SSL_SOCK_Stream::close_writer (void)
|
||||
{
|
||||
ACE_TRACE ("ACE_SSL_SOCK_Stream::close_writer");
|
||||
return this->stream_.close_writer ();
|
||||
}
|
||||
|
||||
ACE_INLINE int
|
||||
ACE_SSL_SOCK_Stream::close (void)
|
||||
{
|
||||
ACE_TRACE ("ACE_SSL_SOCK_Stream::close");
|
||||
|
||||
if (this->ssl_ == 0 || this->get_handle () == ACE_INVALID_HANDLE)
|
||||
return 0; // SSL_SOCK_Stream was never opened.
|
||||
|
||||
// SSL_shutdown() returns 1 on successful shutdown of the SSL
|
||||
// connection, not 0.
|
||||
int const status = ::SSL_shutdown (this->ssl_);
|
||||
|
||||
switch (::SSL_get_error (this->ssl_, status))
|
||||
{
|
||||
case SSL_ERROR_NONE:
|
||||
case SSL_ERROR_SYSCALL: // Ignore this error condition.
|
||||
|
||||
// Reset the SSL object to allow another connection to be made
|
||||
// using this ACE_SSL_SOCK_Stream instance. This prevents the
|
||||
// previous SSL session state from being associated with the new
|
||||
// SSL session/connection.
|
||||
(void) ::SSL_clear (this->ssl_);
|
||||
this->set_handle (ACE_INVALID_HANDLE);
|
||||
return this->stream_.close ();
|
||||
|
||||
case SSL_ERROR_WANT_READ:
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
errno = EWOULDBLOCK;
|
||||
break;
|
||||
|
||||
default:
|
||||
ACE_SSL_Context::report_error ();
|
||||
|
||||
ACE_Errno_Guard error (errno); // Save/restore errno
|
||||
(void) this->stream_.close ();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
ACE_INLINE ACE_SOCK_Stream &
|
||||
ACE_SSL_SOCK_Stream::peer (void)
|
||||
{
|
||||
ACE_TRACE ("ACE_SSL_SOCK_Stream::peer");
|
||||
return this->stream_;
|
||||
}
|
||||
|
||||
ACE_INLINE SSL *
|
||||
ACE_SSL_SOCK_Stream::ssl (void) const
|
||||
{
|
||||
return this->ssl_;
|
||||
}
|
||||
|
||||
ACE_END_VERSIONED_NAMESPACE_DECL
|
||||
Reference in New Issue
Block a user