summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOssama Othman <ossama-othman@users.noreply.github.com>2002-05-16 22:28:53 +0000
committerOssama Othman <ossama-othman@users.noreply.github.com>2002-05-16 22:28:53 +0000
commit5350c7859446ece7cc220cc5835c0068e598ead0 (patch)
treea275cad2b132367d85b3863e1aa84145d56ec892
parent3c425bf43a64707275dee4dc971eb9d96688a1e8 (diff)
downloadATCD-5350c7859446ece7cc220cc5835c0068e598ead0.tar.gz
ChangeLogTag:Thu May 16 15:28:24 2002 Ossama Othman <ossama@uci.edu>
-rw-r--r--ChangeLog50
-rw-r--r--ChangeLogs/ChangeLog-02a50
-rw-r--r--ChangeLogs/ChangeLog-03a50
-rw-r--r--ace/SSL/SSL_Connector.cpp196
-rw-r--r--ace/SSL/SSL_Connector.h137
-rw-r--r--ace/SSL/SSL_SOCK_Connector.cpp112
-rw-r--r--ace/SSL/SSL_SOCK_Stream.cpp16
-rw-r--r--ace/SSL/SSL_SOCK_Stream.h15
8 files changed, 583 insertions, 43 deletions
diff --git a/ChangeLog b/ChangeLog
index ea447b63511..8bd63d78ec5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,53 @@
+Thu May 16 15:28:24 2002 Ossama Othman <ossama@uci.edu>
+
+ * ace/SSL/SSL_Connector.h:
+ * ace/SSL/SSL_Connector.cpp:
+
+ New ACE_SSL-specific subclasses of the standard
+ ACE_{Strategy_}Connector classes. The standard ACE_Connector
+ class assumes that a connection is established once the stream
+ handle becomes writable. However, that only holds for protocols
+ with a single handshake, such as TCP. Protocols with multiple
+ handshakes, such as SSL, require special handling to prevent the
+ connection from being considered completed once the stream
+ handle becomes writable. The subclasses simply override the
+ handle_input() and handle_output() methods for each of base
+ classes that were subclassed. If possible, these changes will
+ be generalized and merged into ACE proper. When that occurs,
+ these classes will be deprecated. As such, these classes are
+ only intended to be an interim solution.
+
+ * ace/SSL/SSL_SOCK_Connector.cpp (connect):
+
+ Fixed bug where the handle in the SSL_SOCK_Stream was not set if
+ a connection is in progress. In that case, the handle must also
+ be set in the SSL_SOCK_Stream so that the correct handle is
+ returned from SSL_SOCK_Stream::get_handle() when performing
+ non-blocking connect()s via the SSL_SOCK_Connector.
+
+ (complete):
+
+ No need to set the handle in SSL_SOCK_Stream since it is
+ already set in the connect() method.
+
+ Only attempt to complete the TCP connection if that hasn't
+ already been done.
+
+ * ace/SSL/SSL_SOCK_Stream.h (peer):
+
+ Made this method public so that it can be called by the new
+ SSL_{Strategy_}Connector classes.
+
+ * ace/SSL/SSL_SOCK_Stream.cpp (get_remote_addr):
+
+ Overrode the base class implementations of this method. Some
+ applications use get_remote_addr() as a way of determining
+ whether or not a connection has been established. In SSL's
+ case, the remote addr will be available once the TCP handshake
+ has been complete. Despite that fact, the SSL connection may
+ not have been completed. In such a case, a successful return
+ from get_remote_addr() would be misleading.
+
Thu May 16 13:34:19 2002 Nanbor Wang <nanbor@cs.wustl.edu>
* ACEXML/examples/SAXPrint/main.cpp: Added constness to
diff --git a/ChangeLogs/ChangeLog-02a b/ChangeLogs/ChangeLog-02a
index ea447b63511..8bd63d78ec5 100644
--- a/ChangeLogs/ChangeLog-02a
+++ b/ChangeLogs/ChangeLog-02a
@@ -1,3 +1,53 @@
+Thu May 16 15:28:24 2002 Ossama Othman <ossama@uci.edu>
+
+ * ace/SSL/SSL_Connector.h:
+ * ace/SSL/SSL_Connector.cpp:
+
+ New ACE_SSL-specific subclasses of the standard
+ ACE_{Strategy_}Connector classes. The standard ACE_Connector
+ class assumes that a connection is established once the stream
+ handle becomes writable. However, that only holds for protocols
+ with a single handshake, such as TCP. Protocols with multiple
+ handshakes, such as SSL, require special handling to prevent the
+ connection from being considered completed once the stream
+ handle becomes writable. The subclasses simply override the
+ handle_input() and handle_output() methods for each of base
+ classes that were subclassed. If possible, these changes will
+ be generalized and merged into ACE proper. When that occurs,
+ these classes will be deprecated. As such, these classes are
+ only intended to be an interim solution.
+
+ * ace/SSL/SSL_SOCK_Connector.cpp (connect):
+
+ Fixed bug where the handle in the SSL_SOCK_Stream was not set if
+ a connection is in progress. In that case, the handle must also
+ be set in the SSL_SOCK_Stream so that the correct handle is
+ returned from SSL_SOCK_Stream::get_handle() when performing
+ non-blocking connect()s via the SSL_SOCK_Connector.
+
+ (complete):
+
+ No need to set the handle in SSL_SOCK_Stream since it is
+ already set in the connect() method.
+
+ Only attempt to complete the TCP connection if that hasn't
+ already been done.
+
+ * ace/SSL/SSL_SOCK_Stream.h (peer):
+
+ Made this method public so that it can be called by the new
+ SSL_{Strategy_}Connector classes.
+
+ * ace/SSL/SSL_SOCK_Stream.cpp (get_remote_addr):
+
+ Overrode the base class implementations of this method. Some
+ applications use get_remote_addr() as a way of determining
+ whether or not a connection has been established. In SSL's
+ case, the remote addr will be available once the TCP handshake
+ has been complete. Despite that fact, the SSL connection may
+ not have been completed. In such a case, a successful return
+ from get_remote_addr() would be misleading.
+
Thu May 16 13:34:19 2002 Nanbor Wang <nanbor@cs.wustl.edu>
* ACEXML/examples/SAXPrint/main.cpp: Added constness to
diff --git a/ChangeLogs/ChangeLog-03a b/ChangeLogs/ChangeLog-03a
index ea447b63511..8bd63d78ec5 100644
--- a/ChangeLogs/ChangeLog-03a
+++ b/ChangeLogs/ChangeLog-03a
@@ -1,3 +1,53 @@
+Thu May 16 15:28:24 2002 Ossama Othman <ossama@uci.edu>
+
+ * ace/SSL/SSL_Connector.h:
+ * ace/SSL/SSL_Connector.cpp:
+
+ New ACE_SSL-specific subclasses of the standard
+ ACE_{Strategy_}Connector classes. The standard ACE_Connector
+ class assumes that a connection is established once the stream
+ handle becomes writable. However, that only holds for protocols
+ with a single handshake, such as TCP. Protocols with multiple
+ handshakes, such as SSL, require special handling to prevent the
+ connection from being considered completed once the stream
+ handle becomes writable. The subclasses simply override the
+ handle_input() and handle_output() methods for each of base
+ classes that were subclassed. If possible, these changes will
+ be generalized and merged into ACE proper. When that occurs,
+ these classes will be deprecated. As such, these classes are
+ only intended to be an interim solution.
+
+ * ace/SSL/SSL_SOCK_Connector.cpp (connect):
+
+ Fixed bug where the handle in the SSL_SOCK_Stream was not set if
+ a connection is in progress. In that case, the handle must also
+ be set in the SSL_SOCK_Stream so that the correct handle is
+ returned from SSL_SOCK_Stream::get_handle() when performing
+ non-blocking connect()s via the SSL_SOCK_Connector.
+
+ (complete):
+
+ No need to set the handle in SSL_SOCK_Stream since it is
+ already set in the connect() method.
+
+ Only attempt to complete the TCP connection if that hasn't
+ already been done.
+
+ * ace/SSL/SSL_SOCK_Stream.h (peer):
+
+ Made this method public so that it can be called by the new
+ SSL_{Strategy_}Connector classes.
+
+ * ace/SSL/SSL_SOCK_Stream.cpp (get_remote_addr):
+
+ Overrode the base class implementations of this method. Some
+ applications use get_remote_addr() as a way of determining
+ whether or not a connection has been established. In SSL's
+ case, the remote addr will be available once the TCP handshake
+ has been complete. Despite that fact, the SSL connection may
+ not have been completed. In such a case, a successful return
+ from get_remote_addr() would be misleading.
+
Thu May 16 13:34:19 2002 Nanbor Wang <nanbor@cs.wustl.edu>
* ACEXML/examples/SAXPrint/main.cpp: Added constness to
diff --git a/ace/SSL/SSL_Connector.cpp b/ace/SSL/SSL_Connector.cpp
new file mode 100644
index 00000000000..0cfe8cc878b
--- /dev/null
+++ b/ace/SSL/SSL_Connector.cpp
@@ -0,0 +1,196 @@
+#include "SSL_Connector.h"
+
+ACE_RCSID (ACE_SSL,
+ SSL_Connector,
+ "$Id$")
+
+
+// Shorthand names.
+#define SVH SVC_HANDLER
+#define PR_CO_1 ACE_PEER_CONNECTOR_1
+#define PR_CO_2 ACE_PEER_CONNECTOR_2
+#define PR_AD ACE_PEER_CONNECTOR_ADDR
+
+
+template <class SVH, PR_CO_1>
+ACE_SSL_Connector<SVH, PR_CO_2>::ACE_SSL_Connector (ACE_Reactor *r,
+ int flags)
+ : ACE_Connector<SVH, PR_CO_2> (r, flags)
+{
+}
+
+template <class SVH, PR_CO_1> int
+ACE_SSL_Connector<SVH, PR_CO_2>::handle_input (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_SSL_Connector<SVH, PR_CO_2>::handle_input");
+
+ // The TCP connection has either failed or it was previously
+ // completed. If it was previously completed then complete the SSL
+ // connection/handshake.
+
+ // @@ It doesn't look like we'll ever get here since the
+ // ACE_SSL_SOCK_Connector::ssl_connect() method doesn't return
+ // until the SSL connection/handshake is completed. In case its
+ // implementation ever changes, this method may be needed.
+
+ int result = 0;
+ AST * ast = 0;
+
+ if (this->handler_map_.find (handle, ast) == 0)
+ {
+ ACE_SSL_SOCK_Stream & new_stream = ast->svc_handler ()->peer ();
+
+ PR_AD raddr;
+
+ // Check to see if the TCP connection was previously completed.
+ if (new_stream.peer ().get_remote_addr (raddr) == -1)
+ {
+ ACE_Timer_Queue * tq = this->reactor ()->timer_queue ();
+
+ ACE_Time_Value timer_buf (0);
+ ACE_Time_Value * tv = tq->calculate_timeout (0, &timer_buf);
+
+ if (this->connector ().complete (new_stream, 0, tv) == 0)
+ return this->ACE_Connector<SVH, PR_CO_2>::handle_output (handle);
+ }
+
+ if (errno != EWOULDBLOCK)
+ // Connection failed. Cleanup resources.
+ return this->ACE_Connector<SVH, PR_CO_2>::handle_input (handle);
+ }
+
+ return result;
+}
+
+template <class SVH, PR_CO_1> int
+ACE_SSL_Connector<SVH, PR_CO_2>::handle_output (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_SSL_Connector<SVH, PR_CO_2>::handle_output");
+
+ // The TCP connection has completed. Now complete the SSL
+ // connection/handshake.
+
+ AST * ast = 0;
+ if (this->handler_map_.find (handle, ast) == 0)
+ {
+ ACE_SSL_SOCK_Stream & new_stream = ast->svc_handler ()->peer ();
+
+ ACE_Timer_Queue * tq = this->reactor ()->timer_queue ();
+
+ ACE_Time_Value timer_buf (0);
+ ACE_Time_Value * tv = tq->calculate_timeout (0, &timer_buf);
+
+ // Delegate completion to the underlying connector.
+ if (this->connector ().complete (new_stream, 0, tv) == 0)
+ return this->ACE_Connector<SVH, PR_CO_2>::handle_output (handle);
+ else if (errno != EWOULDBLOCK)
+ // Connection failed. Cleanup resources.
+ return this->ACE_Connector<SVH, PR_CO_2>::handle_input (handle);
+ }
+
+ return 0;
+}
+
+// ------------------------------------------------------------
+
+template <class SVH, PR_CO_1>
+ACE_SSL_Strategy_Connector<SVH, PR_CO_2>::ACE_SSL_Strategy_Connector
+ (ACE_Reactor *reactor,
+ ACE_Creation_Strategy<SVC_HANDLER> *cre_s,
+ ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> *conn_s,
+ ACE_Concurrency_Strategy<SVC_HANDLER> *con_s,
+ int flags)
+ : ACE_Strategy_Connector<SVH, PR_CO_2> (reactor,
+ cre_s,
+ conn_s,
+ con_s,
+ flags)
+{
+ ACE_TRACE ("ACE_SSL_Strategy_Connector<SVH, PR_CO_2>::ACE_SSL_Strategy_Connector");
+}
+
+template <class SVH, PR_CO_1> int
+ACE_SSL_Strategy_Connector<SVH, PR_CO_2>::handle_input (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_SSL_Strategy_Connector<SVH, PR_CO_2>::handle_input");
+
+
+ // @@ Mucho code duplication here, but I couldn't get around the
+ // multiple inheritance issues introduced when inheriting from
+ // both ACE_Strategy_Connector and ACE_SSL_Connector.
+ // -Ossama
+
+
+ // The TCP connection has either failed or it was previously
+ // completed. If it was previously completed then complete the SSL
+ // connection/handshake.
+
+ // @@ It doesn't look like we'll ever get here since the
+ // ACE_SSL_SOCK_Connector::ssl_connect() method doesn't return
+ // until the SSL connection/handshake is completed. In case its
+ // implementation ever changes, this method may be needed.
+
+ int result = 0;
+ AST * ast = 0;
+
+ if (this->handler_map_.find (handle, ast) == 0)
+ {
+ ACE_SSL_SOCK_Stream & new_stream = ast->svc_handler ()->peer ();
+
+ PR_AD raddr;
+
+ // Check to see if the TCP connection was previously completed.
+ if (new_stream.peer ().get_remote_addr (raddr) == -1)
+ {
+ ACE_Timer_Queue * tq = this->reactor ()->timer_queue ();
+
+ ACE_Time_Value timer_buf (0);
+ ACE_Time_Value * tv = tq->calculate_timeout (0, &timer_buf);
+
+ if (this->connector ().complete (new_stream, 0, tv) == 0)
+ return this->ACE_Connector<SVH, PR_CO_2>::handle_output (handle);
+ }
+
+ if (errno != EWOULDBLOCK)
+ // Connection failed. Cleanup resources.
+ return this->ACE_Connector<SVH, PR_CO_2>::handle_input (handle);
+ }
+
+ return result;
+}
+
+template <class SVH, PR_CO_1> int
+ACE_SSL_Strategy_Connector<SVH, PR_CO_2>::handle_output (ACE_HANDLE handle)
+{
+ ACE_TRACE ("ACE_SSL_Strategy_Connector<SVH, PR_CO_2>::handle_output");
+
+
+ // @@ Mucho code duplication here, but I couldn't get around the
+ // multiple inheritance issues introduced when inheriting from
+ // both ACE_Strategy_Connector and ACE_SSL_Connector.
+ // -Ossama
+
+
+ // The TCP connection has completed. Now complete the SSL
+ // connection/handshake.
+
+ AST * ast = 0;
+ if (this->handler_map_.find (handle, ast) == 0)
+ {
+ ACE_SSL_SOCK_Stream & new_stream = ast->svc_handler ()->peer ();
+
+ ACE_Timer_Queue * tq = this->reactor ()->timer_queue ();
+
+ ACE_Time_Value timer_buf (0);
+ ACE_Time_Value * tv = tq->calculate_timeout (0, &timer_buf);
+
+ // Delegate completion to the underlying connector.
+ if (this->connector ().complete (new_stream, 0, tv) == 0)
+ return this->ACE_Connector<SVH, PR_CO_2>::handle_output (handle);
+ else if (errno != EWOULDBLOCK)
+ // Connection failed. Cleanup resources.
+ return this->ACE_Connector<SVH, PR_CO_2>::handle_input (handle);
+ }
+
+ return 0;
+}
diff --git a/ace/SSL/SSL_Connector.h b/ace/SSL/SSL_Connector.h
new file mode 100644
index 00000000000..378ae2780dd
--- /dev/null
+++ b/ace/SSL/SSL_Connector.h
@@ -0,0 +1,137 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file SSL_Connector.h
+ *
+ * $Id$
+ *
+ * ACE_SSL-specific implementations of the core classes in
+ * ace/Connector.h.
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=============================================================================
+
+#ifndef ACE_SSL_CONNECTOR_H
+#define ACE_SSL_CONNECTOR_H
+
+#include "ace/pre.h"
+
+#include "ace/Connector.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+
+/**
+ * @class ACE_SSL_Connector
+ *
+ * @brief Class that facilitates non-blocking SSL connections by use
+ * of the Template Method design pattern.
+ *
+ * The standard ACE_Connector class assumes that a connection is
+ * established once the stream handle becomes writable. However, that
+ * only holds for protocols with a single handshake, such as TCP.
+ * Protocols with multiple handshakes, such as SSL, require special
+ * handling to prevent the connection from being considered completed
+ * once the stream handle becomes writable.
+ */
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1>
+class ACE_SSL_Connector
+ : public ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>
+{
+public:
+
+ /// Constructor.
+ /**
+ * @note See the ACE_Connector constructor documentation for
+ * details.
+ */
+ ACE_SSL_Connector (ACE_Reactor *r = ACE_Reactor::instance (),
+ int flags = 0);
+
+protected:
+
+ /**
+ * handle_input() is normally called when a non-blocking connection
+ * fails, i.e. when the stream handle becomes readable. However,
+ * once the first (TCP) handshake is completed, the second (SSL)
+ * handshake may need to perform reads. In that case, the stream
+ * handle becoming readable should not be considered a connection
+ * failure.
+ */
+ virtual int handle_input (ACE_HANDLE);
+
+ /**
+ * handle_output() is normally called when a non-blocking connection
+ * succeeds, i.e. when the stream handle becomes writable. However,
+ * this only applies for single handshake protocols, such as TCP.
+ * Multi-handshake protocols, such as SSL, require additional
+ * handling once the initial handshake is completed.
+ */
+ virtual int handle_output (ACE_HANDLE);
+
+};
+
+// ------------------------------------------------------------
+
+/**
+ * @class ACE_SSL_Strategy_Connector
+ *
+ * @brief Class that facilitates non-blocking SSL connections by use
+ * of the Template Method design pattern.
+ *
+ * This class is analogous to the ACE_Strategy_Connector class, but
+ * utilizes the functionality introduced by the ACE_SSL_Connector
+ * class to handle non-blocking SSL connections correctly.
+ */
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1>
+class ACE_SSL_Strategy_Connector
+ : public ACE_Strategy_Connector <SVC_HANDLER, ACE_PEER_CONNECTOR_2>
+{
+public:
+
+ ACE_SSL_Strategy_Connector (ACE_Reactor *r = ACE_Reactor::instance (),
+ ACE_Creation_Strategy<SVC_HANDLER> * = 0,
+ ACE_Connect_Strategy<SVC_HANDLER, ACE_PEER_CONNECTOR_2> * = 0,
+ ACE_Concurrency_Strategy<SVC_HANDLER> * = 0,
+ int flags = 0);
+
+protected:
+
+ /**
+ * handle_input() is normally called when a non-blocking connection
+ * fails, i.e. when the stream handle becomes readable. However,
+ * once the first (TCP) handshake is completed, the second (SSL)
+ * handshake may need to perform reads. In that case, the stream
+ * handle becoming readable should not be considered a connection
+ * failure.
+ */
+ virtual int handle_input (ACE_HANDLE);
+
+ /**
+ * handle_output() is normally called when a non-blocking connection
+ * succeeds, i.e. when the stream handle becomes writable. However,
+ * this only applies for single handshake protocols, such as TCP.
+ * Multi-handshake protocols, such as SSL, require additional
+ * handling once the initial handshake is completed.
+ */
+ virtual int handle_output (ACE_HANDLE);
+
+};
+
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "SSL_Connector.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("SSL_Connector.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+
+#include "ace/post.h"
+
+#endif /* ACE_SSL_CONNECTOR_H */
diff --git a/ace/SSL/SSL_SOCK_Connector.cpp b/ace/SSL/SSL_SOCK_Connector.cpp
index ec50bdc6710..d7de02c7cbb 100644
--- a/ace/SSL/SSL_SOCK_Connector.cpp
+++ b/ace/SSL/SSL_SOCK_Connector.cpp
@@ -66,7 +66,7 @@ ACE_SSL_SOCK_Connector::ssl_connect (ACE_SSL_SOCK_Stream &new_stream,
int status;
do
{
- // These handle sets are used to set up for whatever SSL_accept
+ // 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;
@@ -103,7 +103,7 @@ ACE_SSL_SOCK_Connector::ssl_connect (ACE_SSL_SOCK_Stream &new_stream,
//
// Explicitly check for EWOULDBLOCK since it doesn't get
// converted to an SSL_ERROR_WANT_{READ,WRITE} on some
- // platforms. If SSL_accept failed outright, though, don't
+ // 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 &&
@@ -181,17 +181,33 @@ ACE_SSL_SOCK_Connector::connect (ACE_SSL_SOCK_Stream &new_stream,
countdown.start ();
}
- if (this->connector_.connect (new_stream.peer (),
- remote_sap,
- timeout,
- local_sap,
- reuse_addr,
- flags,
- perms) == -1)
- return -1;
- else if (new_stream.get_handle () == ACE_INVALID_HANDLE)
+ 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.
@@ -201,14 +217,12 @@ ACE_SSL_SOCK_Connector::connect (ACE_SSL_SOCK_Stream &new_stream,
timeout = &time_copy;
}
- if (this->ssl_connect (new_stream, timeout) == -1)
- {
- new_stream.close ();
- return -1;
- }
+ result = this->ssl_connect (new_stream, timeout);
- return 0;
+ if (result == -1)
+ new_stream.close ();
+ return result;
}
int
@@ -235,20 +249,35 @@ ACE_SSL_SOCK_Connector::connect (ACE_SSL_SOCK_Stream &new_stream,
countdown.start ();
}
- if (this->connector_.connect (new_stream.peer (),
- remote_sap,
- qos_params,
- timeout,
- local_sap,
- protocolinfo,
- g,
- flags,
- reuse_addr,
- perms) == -1)
- return -1;
- else if (new_stream.get_handle () == ACE_INVALID_HANDLE)
+ 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.
@@ -258,14 +287,12 @@ ACE_SSL_SOCK_Connector::connect (ACE_SSL_SOCK_Stream &new_stream,
timeout = &time_copy;
}
- if (this->ssl_connect (new_stream, timeout) == -1)
- {
- new_stream.close ();
- return -1;
- }
+ result = this->ssl_connect (new_stream, timeout);
- return 0;
+ if (result == -1)
+ new_stream.close ();
+ return result;
}
// Try to complete a non-blocking connection.
@@ -287,12 +314,17 @@ ACE_SSL_SOCK_Connector::complete (ACE_SSL_SOCK_Stream &new_stream,
countdown.start ();
}
- if (this->connector_.complete (new_stream.peer (),
- remote_sap,
- tv) == -1)
+ // 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;
- else if (new_stream.get_handle () == ACE_INVALID_HANDLE)
- new_stream.set_handle (new_stream.peer ().get_handle ());
+
+ // 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
diff --git a/ace/SSL/SSL_SOCK_Stream.cpp b/ace/SSL/SSL_SOCK_Stream.cpp
index 5030e37ae3a..b2904d04bd1 100644
--- a/ace/SSL/SSL_SOCK_Stream.cpp
+++ b/ace/SSL/SSL_SOCK_Stream.cpp
@@ -542,3 +542,19 @@ ACE_SSL_SOCK_Stream::recvv_n (iovec iov[], size_t iovcnt) const
return bytes_read;
}
+
+int
+ACE_SSL_SOCK_Stream::get_remote_addr (ACE_Addr &addr) const
+{
+ // Some applications use get_remote_addr() as a way of determining
+ // whether or not a connection has been established. In SSL's case,
+ // the remote addr will be available once the TCP handshake has been
+ // complete. Despite that fact, the SSL connection may not have
+ // been completed. In such a case, a successful return from
+ // get_remote_addr() would be misleading.
+
+ if (SSL_is_init_finished (this->ssl_))
+ return this->ACE_SOCK::get_remote_addr (addr);
+
+ return -1;
+}
diff --git a/ace/SSL/SSL_SOCK_Stream.h b/ace/SSL/SSL_SOCK_Stream.h
index 1438451e6f5..981b931655d 100644
--- a/ace/SSL/SSL_SOCK_Stream.h
+++ b/ace/SSL/SSL_SOCK_Stream.h
@@ -258,13 +258,22 @@ public:
/// Return a pointer to the underlying SSL structure.
SSL *ssl (void) const;
- //@}
-
-protected:
+ /**
+ * 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.
+ */
+ int get_remote_addr (ACE_Addr &) const;
/// Return the underlying ACE_SOCK_Stream which ACE_SSL runs atop of.
ACE_SOCK_Stream & peer (void);
+protected:
+
/// Underlying send() helper method common to all public send()
/// methods.
ssize_t send_i (const void *buf,