Public Member Functions | Public Attributes | Protected Member Functions | Private Attributes

ACE_SSL_SOCK_Connector Class Reference

Defines a factory that creates new <ACE_SSL_SOCK_Stream>s actively. More...

#include <SSL_SOCK_Connector.h>

Collaboration diagram for ACE_SSL_SOCK_Connector:
Collaboration graph
[legend]

List of all members.

Public Types

typedef ACE_INET_Addr PEER_ADDR
 Meta-type info.
typedef ACE_SSL_SOCK_Stream PEER_STREAM
 Meta-type info.

Public Member Functions

 ACE_SSL_SOCK_Connector (void)
 Default constructor.
 ACE_SSL_SOCK_Connector (ACE_SSL_SOCK_Stream &new_stream, const ACE_Addr &remote_sap, const ACE_Time_Value *timeout=0, const ACE_Addr &local_sap=ACE_Addr::sap_any, int reuse_addr=0, int flags=0, int perms=0)
 ACE_SSL_SOCK_Connector (ACE_SSL_SOCK_Stream &new_stream, const ACE_Addr &remote_sap, ACE_QoS_Params qos_params, const ACE_Time_Value *timeout=0, const ACE_Addr &local_sap=ACE_Addr::sap_any, ACE_Protocol_Info *protocolinfo=0, ACE_SOCK_GROUP g=0, u_long flags=0, int reuse_addr=0, int perms=0)
 ~ACE_SSL_SOCK_Connector (void)
 Default dtor.
int connect (ACE_SSL_SOCK_Stream &new_stream, const ACE_Addr &remote_sap, const ACE_Time_Value *timeout=0, const ACE_Addr &local_sap=ACE_Addr::sap_any, int reuse_addr=0, int flags=0, int perms=0)
int connect (ACE_SSL_SOCK_Stream &new_stream, const ACE_Addr &remote_sap, ACE_QoS_Params qos_params, const ACE_Time_Value *timeout=0, const ACE_Addr &local_sap=ACE_Addr::sap_any, ACE_Protocol_Info *protocolinfo=0, ACE_SOCK_GROUP g=0, u_long flags=0, int reuse_addr=0, int perms=0)
int complete (ACE_SSL_SOCK_Stream &new_stream, ACE_Addr *remote_sap=0, const ACE_Time_Value *timeout=0)
bool reset_new_handle (ACE_HANDLE handle)
 Resets any event associations on this handle.
void dump (void) const
 Dump the state of an object.

Public Attributes

 ACE_ALLOC_HOOK_DECLARE
 Declare the dynamic allocation hooks.

Protected Member Functions

int ssl_connect (ACE_SSL_SOCK_Stream &new_stream, const ACE_Time_Value *timeout)
 Complete non-blocking SSL active connection.

Private Attributes

ACE_SOCK_Connector connector_

Detailed Description

Defines a factory that creates new <ACE_SSL_SOCK_Stream>s actively.

The ACE_SSL_SOCK_Connector doesn't have a socket of its own, i.e., it simply "borrows" the one from the ACE_SSL_SOCK_Stream that's being connected. The reason for this is that the underlying socket API doesn't use a "factory" socket to connect "data-mode" sockets. Therefore, there's no need to inherit ACE_SSL_SOCK_Connector from ACE_SSL_SOCK.

Since SSL is record-oriented, some additional work is done after the plain socket is connected.

Note:
The user must currently ensure that only one thread services a given SSL session at any given time since some underlying SSL implementations, such as OpenSSL, are not entirely thread-safe or reentrant.

Definition at line 56 of file SSL_SOCK_Connector.h.


Member Typedef Documentation

Meta-type info.

Definition at line 286 of file SSL_SOCK_Connector.h.

Meta-type info.

Definition at line 287 of file SSL_SOCK_Connector.h.


Constructor & Destructor Documentation

ACE_SSL_SOCK_Connector::ACE_SSL_SOCK_Connector ( void   ) 

Default constructor.

Definition at line 8 of file SSL_SOCK_Connector.inl.

  : connector_ ()
{
  ACE_TRACE ("ACE_SSL_SOCK_Connector::ACE_SSL_SOCK_Connector");
}

ACE_SSL_SOCK_Connector::ACE_SSL_SOCK_Connector ( ACE_SSL_SOCK_Stream new_stream,
const ACE_Addr remote_sap,
const ACE_Time_Value timeout = 0,
const ACE_Addr local_sap = ACE_Addr::sap_any,
int  reuse_addr = 0,
int  flags = 0,
int  perms = 0 
)

Actively connect to a peer, producing a connected ACE_SSL_SOCK_Stream object if the connection succeeds. This method performs both the initial socket connect and the SSL handshake.

Parameters:
new_stream The ACE_SSL_SOCK_Stream object that will be connected to the peer.
remote_sap The address that we are trying to connect to. The protocol family of remote_sap is used for the connected socket. That is, if remote_sap contains an IPv6 address, a socket with family PF_INET6 will be used, else it will be PF_INET.
timeout Pointer to an ACE_Time_Value object with amount of time to wait to connect. If the pointer is 0 then the call blocks until the connection attempt is complete, whether it succeeds or fails. If *timeout == {0, 0} then the connection is done using nonblocking mode. In this case, if the connection can't be made immediately, this method returns -1 and errno == EWOULDBLOCK. If *timeout > {0, 0} then this is the maximum amount of time to wait before timing out; if the specified amount of time passes before the connection is made, this method returns -1 and errno == ETIME. Note the difference between this case and when a blocking connect is attempted that TCP times out - in the latter case, errno will be ETIMEDOUT.
local_sap (optional) The local address to bind to. If it's the default value of ACE_Addr::sap_any then the OS will choose an unused port.
reuse_addr (optional) If the value is 1, the local address (local_sap) is reused, even if it hasn't been cleaned up yet.
flags Ignored.
perms Ignored.
Returns:
Returns 0 if the connection succeeds. If it fails, -1 is returned and errno contains a specific error code.

Definition at line 378 of file SSL_SOCK_Connector.cpp.

  : connector_ ()
{
  ACE_TRACE ("ACE_SSL_SOCK_Connector::ACE_SSL_SOCK_Connector");
  this->connect (new_stream,
                 remote_sap,
                 timeout,
                 local_sap,
                 reuse_addr,
                 flags,
                 perms);
}

ACE_SSL_SOCK_Connector::ACE_SSL_SOCK_Connector ( ACE_SSL_SOCK_Stream new_stream,
const ACE_Addr remote_sap,
ACE_QoS_Params  qos_params,
const ACE_Time_Value timeout = 0,
const ACE_Addr local_sap = ACE_Addr::sap_any,
ACE_Protocol_Info protocolinfo = 0,
ACE_SOCK_GROUP  g = 0,
u_long  flags = 0,
int  reuse_addr = 0,
int  perms = 0 
)

Actively connect to a peer, producing a connected ACE_SSL_SOCK_Stream object if the connection succeeds. This method performs both the initial socket connect and the SSL handshake.

Parameters:
new_stream The ACE_SSL_SOCK_Stream object that will be connected to the peer.
remote_sap The address that we are trying to connect to. The protocol family of remote_sap is used for the connected socket. That is, if remote_sap contains an IPv6 address, a socket with family PF_INET6 will be used, else it will be PF_INET.
qos_params Contains QoS parameters that are passed to the IntServ (RSVP) and DiffServ protocols.
See also:
ACE_QoS_Params.
Parameters:
timeout Pointer to an ACE_Time_Value object with amount of time to wait to connect. If the pointer is 0 then the call blocks until the connection attempt is complete, whether it succeeds or fails. If *timeout == {0, 0} then the connection is done using nonblocking mode. In this case, if the connection can't be made immediately, this method returns -1 and errno == EWOULDBLOCK. If *timeout > {0, 0} then this is the maximum amount of time to wait before timing out; if the specified amount of time passes before the connection is made, this method returns -1 and errno == ETIME. Note the difference between this case and when a blocking connect is attempted that TCP times out - in the latter case, errno will be ETIMEDOUT.
local_sap (optional) The local address to bind to. If it's the default value of ACE_Addr::sap_any then the OS will choose an unused port.
reuse_addr (optional) If the value is 1, the local address (local_sap) is reused, even if it hasn't been cleaned up yet.
flags Ignored.
perms Ignored.
Returns:
Returns 0 if the connection succeeds. If it fails, -1 is returned and errno contains a specific error code.

Definition at line 398 of file SSL_SOCK_Connector.cpp.

  : connector_ ()
{
  ACE_TRACE ("ACE_SSL_SOCK_Connector::ACE_SSL_SOCK_Connector");

  this->connect (new_stream,
                 remote_sap,
                 qos_params,
                 timeout,
                 local_sap,
                 protocolinfo,
                 g,
                 flags,
                 reuse_addr,
                 perms);
}

ACE_SSL_SOCK_Connector::~ACE_SSL_SOCK_Connector ( void   ) 

Default dtor.


Member Function Documentation

int ACE_SSL_SOCK_Connector::complete ( ACE_SSL_SOCK_Stream new_stream,
ACE_Addr remote_sap = 0,
const ACE_Time_Value timeout = 0 
)

Try to complete a non-blocking connection. If connection completion is successful then <new_stream> contains the connected ACE_SSL_SOCK_Stream. If <remote_sap> is non-NULL then it will contain the address of the connected peer.

Definition at line 330 of file SSL_SOCK_Connector.cpp.

{
  ACE_TRACE ("ACE_SSL_SOCK_Connector::complete");

  // Take into account the time to complete the basic TCP handshake
  // and the SSL handshake.
  ACE_Time_Value time_copy;
  ACE_Countdown_Time countdown (&time_copy);
  if (tv != 0)
    {
      time_copy += *tv;
      countdown.start ();
    }

  // Only attempt to complete the TCP connection if it that hasn't
  // already been done.
  ACE_INET_Addr raddr;
  if (new_stream.peer ().get_remote_addr (raddr) != 0
      && this->connector_.complete (new_stream.peer (),
                                    remote_sap,
                                    tv) == -1)
    return -1;

  // The handle in the SSL_SOCK_Stream should have already been set in
  // the connect() method.

  // If using a timeout, update the countdown timer to reflect the time
  // spent on the connect itself, then pass the remaining time to
  // ssl_connect to bound the time on the handshake.
  if (tv != 0)
    {
      countdown.update ();
      tv = &time_copy;
    }

  if (this->ssl_connect (new_stream, tv) == -1)
    {
      new_stream.close ();
      return -1;
    }

  return 0;

}

int ACE_SSL_SOCK_Connector::connect ( ACE_SSL_SOCK_Stream new_stream,
const ACE_Addr remote_sap,
ACE_QoS_Params  qos_params,
const ACE_Time_Value timeout = 0,
const ACE_Addr local_sap = ACE_Addr::sap_any,
ACE_Protocol_Info protocolinfo = 0,
ACE_SOCK_GROUP  g = 0,
u_long  flags = 0,
int  reuse_addr = 0,
int  perms = 0 
)

Actively connect to a peer, producing a connected ACE_SSL_SOCK_Stream object if the connection succeeds. This method performs both the initial socket connect and the SSL handshake.

Parameters:
new_stream The ACE_SSL_SOCK_Stream object that will be connected to the peer.
remote_sap The address that we are trying to connect to. The protocol family of remote_sap is used for the connected socket. That is, if remote_sap contains an IPv6 address, a socket with family PF_INET6 will be used, else it will be PF_INET.
qos_params Contains QoS parameters that are passed to the IntServ (RSVP) and DiffServ protocols.
See also:
ACE_QoS_Params.
Parameters:
timeout Pointer to an ACE_Time_Value object with amount of time to wait to connect. If the pointer is 0 then the call blocks until the connection attempt is complete, whether it succeeds or fails. If *timeout == {0, 0} then the connection is done using nonblocking mode. In this case, if the connection can't be made immediately, this method returns -1 and errno == EWOULDBLOCK. If *timeout > {0, 0} then this is the maximum amount of time to wait before timing out; if the specified amount of time passes before the connection is made, this method returns -1 and errno == ETIME. Note the difference between this case and when a blocking connect is attempted that TCP times out - in the latter case, errno will be ETIMEDOUT.
local_sap (optional) The local address to bind to. If it's the default value of ACE_Addr::sap_any then the OS will choose an unused port.
reuse_addr (optional) If the value is 1, the local address (local_sap) is reused, even if it hasn't been cleaned up yet.
flags Ignored.
perms Ignored.
Returns:
Returns 0 if the connection succeeds. If it fails, -1 is returned and errno contains a specific error code.

Definition at line 258 of file SSL_SOCK_Connector.cpp.

{
  ACE_TRACE ("ACE_SSL_SOCK_Connector::connect");

  // Take into account the time to complete the basic TCP handshake
  // and the SSL handshake.
  ACE_Time_Value time_copy;
  ACE_Countdown_Time countdown (&time_copy);
  if (timeout != 0)
    {
      time_copy += *timeout;
      countdown.start ();
    }

  int result = this->connector_.connect (new_stream.peer (),
                                         remote_sap,
                                         qos_params,
                                         timeout,
                                         local_sap,
                                         protocolinfo,
                                         g,
                                         flags,
                                         reuse_addr,
                                         perms);

  int error = 0;
  if (result == -1)
    error = errno;  // Save us some TSS accesses.

  // Obtain the handle from the underlying SOCK_Stream and set it in
  // the SSL_SOCK_Stream.  Note that the case where a connection is in
  // progress is also handled.  In that case, the handle must also be
  // set in the SSL_SOCK_Stream so that the correct handle is returned
  // when performing non-blocking connect()s.
  if (new_stream.get_handle () == ACE_INVALID_HANDLE
      && (result == 0
          || (result == -1 && (error == EWOULDBLOCK
                               || error == EINPROGRESS))))
    new_stream.set_handle (new_stream.peer ().get_handle ());

  if (result == -1)
    return result;

  // If using a timeout, update the countdown timer to reflect the time
  // spent on the connect itself, then pass the remaining time to
  // ssl_connect to bound the time on the handshake.
  if (timeout != 0)
    {
      countdown.update ();
      timeout = &time_copy;
    }

  result = this->ssl_connect (new_stream, timeout);

  if (result == -1)
    new_stream.close ();

  return result;
}

int ACE_SSL_SOCK_Connector::connect ( ACE_SSL_SOCK_Stream new_stream,
const ACE_Addr remote_sap,
const ACE_Time_Value timeout = 0,
const ACE_Addr local_sap = ACE_Addr::sap_any,
int  reuse_addr = 0,
int  flags = 0,
int  perms = 0 
)

Actively connect to a peer, producing a connected ACE_SSL_SOCK_Stream object if the connection succeeds. This method performs both the initial socket connect and the SSL handshake.

Parameters:
new_stream The ACE_SSL_SOCK_Stream object that will be connected to the peer.
remote_sap The address that we are trying to connect to. The protocol family of remote_sap is used for the connected socket. That is, if remote_sap contains an IPv6 address, a socket with family PF_INET6 will be used, else it will be PF_INET.
timeout Pointer to an ACE_Time_Value object with amount of time to wait to connect. If the pointer is 0 then the call blocks until the connection attempt is complete, whether it succeeds or fails. If *timeout == {0, 0} then the connection is done using nonblocking mode. In this case, if the connection can't be made immediately, this method returns -1 and errno == EWOULDBLOCK. If *timeout > {0, 0} then this is the maximum amount of time to wait before timing out; if the specified amount of time passes before the connection is made, this method returns -1 and errno == ETIME. Note the difference between this case and when a blocking connect is attempted that TCP times out - in the latter case, errno will be ETIMEDOUT.
local_sap (optional) The local address to bind to. If it's the default value of ACE_Addr::sap_any then the OS will choose an unused port.
reuse_addr (optional) If the value is 1, the local address (local_sap) is reused, even if it hasn't been cleaned up yet.
flags Ignored.
perms Ignored.
Returns:
Returns 0 if the connection succeeds. If it fails, -1 is returned and errno contains a specific error code.

Definition at line 193 of file SSL_SOCK_Connector.cpp.

{
  ACE_TRACE ("ACE_SSL_SOCK_Connector::connect");

  // Take into account the time to complete the basic TCP handshake
  // and the SSL handshake.
  ACE_Time_Value time_copy;
  ACE_Countdown_Time countdown (&time_copy);
  if (timeout != 0)
    {
      time_copy += *timeout;
      countdown.start ();
    }

  int result =
    this->connector_.connect (new_stream.peer (),
                              remote_sap,
                              timeout,
                              local_sap,
                              reuse_addr,
                              flags,
                              perms);

  int error = 0;
  if (result == -1)
    error = errno;  // Save us some TSS accesses.

  // Obtain the handle from the underlying SOCK_Stream and set it in
  // the SSL_SOCK_Stream.  Note that the case where a connection is in
  // progress is also handled.  In that case, the handle must also be
  // set in the SSL_SOCK_Stream so that the correct handle is returned
  // when performing non-blocking connect()s.
  if (new_stream.get_handle () == ACE_INVALID_HANDLE
      && (result == 0
          || (result == -1 && (error == EWOULDBLOCK
                               || error == EINPROGRESS))))
    new_stream.set_handle (new_stream.peer ().get_handle ());

  if (result == -1)
    return result;

  // If using a timeout, update the countdown timer to reflect the time
  // spent on the connect itself, then pass the remaining time to
  // ssl_connect to bound the time on the handshake.
  if (timeout != 0)
    {
      countdown.update ();
      timeout = &time_copy;
    }

  result = this->ssl_connect (new_stream, timeout);

  if (result == -1)
    new_stream.close ();

  return result;
}

void ACE_SSL_SOCK_Connector::dump ( void   )  const

Dump the state of an object.

Definition at line 22 of file SSL_SOCK_Connector.inl.

{
  ACE_TRACE ("ACE_SSL_SOCK_Connector::dump");
  this->connector_.dump ();
}

bool ACE_SSL_SOCK_Connector::reset_new_handle ( ACE_HANDLE  handle  ) 

Resets any event associations on this handle.

Definition at line 15 of file SSL_SOCK_Connector.inl.

{
  ACE_TRACE ("ACE_SSL_SOCK_Connector::reset_new_handle");
  return this->connector_.reset_new_handle (handle);
}

int ACE_SSL_SOCK_Connector::ssl_connect ( ACE_SSL_SOCK_Stream new_stream,
const ACE_Time_Value timeout 
) [protected]

Complete non-blocking SSL active connection.

Definition at line 34 of file SSL_SOCK_Connector.cpp.

{
  SSL *ssl = new_stream.ssl ();

  if (SSL_is_init_finished (ssl))
    return 0;

  // Check if a connection is already pending for the given SSL
  // structure.
  if (!SSL_in_connect_init (ssl))
    ::SSL_set_connect_state (ssl);

  ACE_HANDLE handle = new_stream.get_handle ();

  // We're going to call SSL_connect, optionally doing ACE::select and
  // retrying the SSL_connect, until the SSL handshake is done or
  // it fails.
  // To get the timeout affect, set the socket to nonblocking mode
  // before beginning if there is a timeout specified. If the timeout
  // is 0 (wait as long as it takes) then don't worry about the blocking
  // status; we'll block in SSL_connect if the socket is blocking, and
  // block in ACE::select if not.
  int reset_blocking_mode = 0;
  if (timeout != 0)
    {
      reset_blocking_mode = ACE_BIT_DISABLED (ACE::get_flags (handle),
                                              ACE_NONBLOCK);
          // Set the handle into non-blocking mode if it's not already
          // in it.
          if (reset_blocking_mode
              && ACE::set_flags (handle,
                                 ACE_NONBLOCK) == -1)
            return -1;
    }

  ACE_Time_Value t;
  if (timeout != 0)
    t = *timeout;   // Need a non-const copy.

  // Take into account the time between each select() call below.
  ACE_Countdown_Time countdown ((timeout == 0 ? 0 : &t));

  int status;
  
  do
    {
      // These handle sets are used to set up for whatever SSL_connect
      // says it wants next. They're reset on each pass around the loop.
      ACE_Handle_Set rd_handle;
      ACE_Handle_Set wr_handle;

      status = ::SSL_connect (ssl);
      switch (::SSL_get_error (ssl, status))
        {
        case SSL_ERROR_NONE:
          // Start out with non-blocking disabled on the SSL stream.
          new_stream.disable (ACE_NONBLOCK);
          status = 0;               // To tell caller about success
          break;                    // Done

        case SSL_ERROR_WANT_WRITE:
          wr_handle.set_bit (handle);
          status = 1;               // Wait for more activity
          break;

        case SSL_ERROR_WANT_READ:
          rd_handle.set_bit (handle);
          status = 1;               // Wait for more activity
          break;

        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.
          status = -1;
          break;

        case SSL_ERROR_SYSCALL:
          // On some platforms (e.g. MS Windows) OpenSSL does not
          // store the last error in errno so explicitly do so.
          //
          // Explicitly check for EWOULDBLOCK since it doesn't get
          // converted to an SSL_ERROR_WANT_{READ,WRITE} on some
          // platforms. If SSL_connect failed outright, though, don't
          // bother checking more. This can happen if the socket gets
          // closed during the handshake.
          if (ACE_OS::set_errno_to_last_error () == EWOULDBLOCK &&
              status == -1)
            {
              // Although the SSL_ERROR_WANT_READ/WRITE isn't getting
              // set correctly, the read/write state should be valid.
              // Use that to decide what to do.
              status = 1;               // Wait for more activity
              if (SSL_want_write (ssl))
                {
                  wr_handle.set_bit (handle);
                }
              else if (SSL_want_read (ssl))
                {
                  rd_handle.set_bit (handle);
                }
              else
                {
                  status = -1;            // Doesn't want anything - bail out
                }
            }
          else
            {
              status = -1;
            }
            
          break;

        default:
          ACE_SSL_Context::report_error ();
          status = -1;
          break;
        }

      if (status == 1)
        {
          // Must have at least one handle to wait for at this point.
          ACE_ASSERT (rd_handle.num_set () == 1 || wr_handle.num_set () == 1);

          // Block indefinitely if timeout pointer is zero.
          status = ACE::select (int (handle) + 1,
                                &rd_handle,
                                &wr_handle,
                                0,
                                (timeout == 0 ? 0 : &t));

          (void) countdown.update ();

          // 0 is timeout, so we're done.
          // -1 is error, so we're done.
          // Could be both handles set (same handle in both masks) so set to 1.
          if (status >= 1)
            {
              status = 1;
            }
          else                 // Timeout or socket failure
            {
              status = -1;
            }
        }

    } while (status == 1 && !SSL_is_init_finished (ssl));

  if (reset_blocking_mode)
    {
      ACE_Errno_Guard eguard (errno);
      ACE::clr_flags (handle, ACE_NONBLOCK);
    }

  return (status == -1 ? -1 : 0);
}


Member Data Documentation

Declare the dynamic allocation hooks.

Definition at line 294 of file SSL_SOCK_Connector.h.

The class that does all of the non-secure socket connection. It is default contructed, and subsequently used by connect().

Definition at line 306 of file SSL_SOCK_Connector.h.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines