diff options
author | Ossama Othman <ossama-othman@users.noreply.github.com> | 2002-05-16 22:28:53 +0000 |
---|---|---|
committer | Ossama Othman <ossama-othman@users.noreply.github.com> | 2002-05-16 22:28:53 +0000 |
commit | 5350c7859446ece7cc220cc5835c0068e598ead0 (patch) | |
tree | a275cad2b132367d85b3863e1aa84145d56ec892 | |
parent | 3c425bf43a64707275dee4dc971eb9d96688a1e8 (diff) | |
download | ATCD-5350c7859446ece7cc220cc5835c0068e598ead0.tar.gz |
ChangeLogTag:Thu May 16 15:28:24 2002 Ossama Othman <ossama@uci.edu>
-rw-r--r-- | ChangeLog | 50 | ||||
-rw-r--r-- | ChangeLogs/ChangeLog-02a | 50 | ||||
-rw-r--r-- | ChangeLogs/ChangeLog-03a | 50 | ||||
-rw-r--r-- | ace/SSL/SSL_Connector.cpp | 196 | ||||
-rw-r--r-- | ace/SSL/SSL_Connector.h | 137 | ||||
-rw-r--r-- | ace/SSL/SSL_SOCK_Connector.cpp | 112 | ||||
-rw-r--r-- | ace/SSL/SSL_SOCK_Stream.cpp | 16 | ||||
-rw-r--r-- | ace/SSL/SSL_SOCK_Stream.h | 15 |
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, |