diff options
Diffstat (limited to 'ACE/ace/SSL/SSL_Asynch_Stream.h')
-rw-r--r-- | ACE/ace/SSL/SSL_Asynch_Stream.h | 425 |
1 files changed, 425 insertions, 0 deletions
diff --git a/ACE/ace/SSL/SSL_Asynch_Stream.h b/ACE/ace/SSL/SSL_Asynch_Stream.h new file mode 100644 index 00000000000..671cca46c24 --- /dev/null +++ b/ACE/ace/SSL/SSL_Asynch_Stream.h @@ -0,0 +1,425 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file SSL_Asynch_Stream.h + * + * $Id$ + * + * @author Alexander Libman <alibman@baltimore.com> + */ +//============================================================================= + +#ifndef ACE_SSL_ASYNCH_STREAM_H +#define ACE_SSL_ASYNCH_STREAM_H + +#include /**/ "ace/pre.h" +#include "SSL_Context.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +#pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#if OPENSSL_VERSION_NUMBER > 0x0090581fL && ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS))) + +#include "SSL_Asynch_BIO.h" + +#include "ace/Asynch_IO_Impl.h" +#include "ace/Message_Block.h" +#include "ace/Synch_Traits.h" +#include "ace/Thread_Mutex.h" + +/* + * This facility doesn't follow the normal ACE asynch I/O support classes' + * interface/implementation arrangement. It's not needed because rather than + * branching off to platform-specific APIs, all platforms use the OpenSSL + * API. Thus, you can think of this class as the implementation class (for + * OpenSSL) and there's no separate interface class. + * Also, since both read and write operations are defined in one I/O + * factory, there's no single Result class defined as there is for + * ACE_Asynch_Read_Stream, et al. There are separate result classes defined + * for read and write operations. + */ + +#if defined (ACE_WIN32) +# include "ace/WIN32_Asynch_IO.h" +typedef ACE_WIN32_Asynch_Result A_RESULT; +typedef ACE_WIN32_Asynch_Read_Stream_Result ARS_RESULT; +typedef ACE_WIN32_Asynch_Write_Stream_Result AWS_RESULT; + +# define ERR_CANCELED ERROR_OPERATION_ABORTED + +#else +# include "ace/POSIX_Asynch_IO.h" +typedef ACE_POSIX_Asynch_Result A_RESULT; +typedef ACE_POSIX_Asynch_Read_Stream_Result ARS_RESULT; +typedef ACE_POSIX_Asynch_Write_Stream_Result AWS_RESULT; + +# define ERR_CANCELED ECANCELED + +#endif /* ACE_WIN32 */ + + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +class ACE_SSL_Asynch_Stream; // Forward decl for use in result class def. + +/** + * @class ACE_SSL_Asynch_Read_Stream_Result + * + * Result class that communicates result of read operations initiated on + * an ACE_SSL_Asynch_Stream object. + */ +class ACE_SSL_Asynch_Read_Stream_Result : public ARS_RESULT +{ + /// Factory class will have special permissions. + friend class ACE_SSL_Asynch_Stream; + +protected: + ACE_SSL_Asynch_Read_Stream_Result (ACE_Handler &handler, + ACE_HANDLE handle, + ACE_Message_Block &message_block, + size_t bytes_to_read, + const void* act, + ACE_HANDLE event, + int priority, + int signal_number); +}; + +/** + * @class ACE_SSL_Asynch_Write_Stream_Result + * + * Result class that communicates result of write operations initiated on + * an ACE_SSL_Asynch_Stream object. + */ +class ACE_SSL_Asynch_Write_Stream_Result : public AWS_RESULT +{ + /// Factory class will have special permissions. + friend class ACE_SSL_Asynch_Stream; + +protected: + ACE_SSL_Asynch_Write_Stream_Result (ACE_Handler &handler, + ACE_HANDLE handle, + ACE_Message_Block &message_block, + size_t bytes_to_read, + const void* act, + ACE_HANDLE event, + int priority, + int signal_number); +}; + + +/** + * @class ACE_SSL_Asynch_Result + * + * Result class that is used internally for socket close notifications. + */ +class ACE_SSL_Asynch_Result : public A_RESULT +{ +public: + ACE_SSL_Asynch_Result (ACE_Handler &handler); + + void complete (size_t bytes_transferred, + int success, + const void * completion_key, + u_long error); +}; + + +// Only provide forward declarations to prevent possible abuse of the +// friend declarations in ACE_SSL_Asynch_Stream. +struct ACE_SSL_Asynch_Stream_Accessor; + +/** + * @class ACE_SSL_Asynch_Stream + * + * @brief This class is a factory for initiating asynchronous reads + * and writes on an SSL stream. + * + * Once open() is called, multiple asynchronous read and write operations + * can be started using this class. The handler object (derived from + * ACE_Handler) specified in open() will receive completion events for the + * operations initiated via this class. + */ +class ACE_SSL_Export ACE_SSL_Asynch_Stream + : public ACE_Asynch_Operation, + public ACE_Handler +{ +public: + + // Use a class/struct to work around scoping + // problems for extern "C" free functions with some compilers. For + // example, some can't handle + // + // friend ::some_extern_c_free_function (...) + // + // Note that we could use a straight C++ (i.e. not extern "C") free + // function, but using a class or struct allows us to hide the + // interface from the user, which prevents abuse of this friend + // relationship. + friend struct ACE_SSL_Asynch_Stream_Accessor; + + enum Stream_Type + { + ST_CLIENT = 0x0001, + ST_SERVER = 0x0002 + }; + + /// Constructor. + /** + * @arg context Pointer to an ACE_SSL_Context instance containing + * the OpenSSL information to be associated with this + * ACE_SSL_Asynch_Stream. The needed SSL data will be + * copied before return. Therefore, this object can be + * reused, modified, or deleted upon return. If a 0 pointer + * is passed, the ACE_SSL_Context::instance() method will + * be called to get access to a singleton. + */ + ACE_SSL_Asynch_Stream (Stream_Type s_type = ST_SERVER, + ACE_SSL_Context * context = 0); + + /// Destructor + virtual ~ACE_SSL_Asynch_Stream (void); + + int cancel (void); + + int close (void); + + /** + * Initializes the factory with information which will be used with + * each asynchronous call. + * + * @arg handler The ACE_Handler that will be called to handle completions + * for operations initiated using this factory. + * @arg handle The handle that future read/write operations will use. + * + * @retval 0 for success. + * @retval -1 for failure; consult @c errno for further information. + */ + int open (ACE_Handler &handler, + ACE_HANDLE handle = ACE_INVALID_HANDLE, + const void *completion_key = 0, + ACE_Proactor *proactor = 0); + + /** + * Initiates an asynchronous read. If the operation is successfully + * initiated, the handle_read_stream() method will be called on the + * ACE_Handler object passed to open() when the operation completes. + * Data is read into the specified ACE_Message_Block beginning at its + * write pointer; the block's write pointer is updated to reflect any + * added data when the operation completes. + * + * @arg message_block The specified ACE_Message_Block will receive any + * data that is read. Data will be read into the + * block beginning at the block's write pointer. + * @arg num_bytes_to_read The maximum number of bytes to read. The actual + * amount read may be less. + * @arg act ACT which is passed to the completion handler in + * the result object. + * @arg priority Specifies the operation priority. This has an + * affect on POSIX only. Works like @i nice in Unix. + * Negative values are not allowed. 0 means priority + * of the operation same as the process priority. + * 1 means priority of the operation is one less than + * process, and so forth. This parameter has no + * affect on Win32. + * @arg signal_number The POSIX4 real-time signal number to be used + * for the operation. signal_number ranges from + * ACE_SIGRTMIN to ACE_SIGRTMAX. This argument is + * unused on non-POSIX4 systems. + * + * @retval 0 for success. + * @retval -1 for failure; consult @c errno for further information. + */ + int read (ACE_Message_Block &message_block, + size_t num_bytes_to_read, + const void *act = 0, + int priority = 0, + int signal_number = ACE_SIGRTMIN); + + /** + * Initiates an asynchronous write. If the operation is successfully + * initiated, the handle_write_stream() method will be called on the + * ACE_Handler object passed to open() when the operation completes. + * Data is taken from the specified ACE_Message_Block beginning at its + * read pointer; the block's read pointer is updated to reflect any + * data successfully sent when the operation completes. + * + * @arg message_block The specified ACE_Message_Block is the source of + * data that is written. Data will be taken from the + * block beginning at the block's read pointer. + * @arg bytes_to_write The maximum number of bytes to write. The actual + * amount written may be less. + * @arg act ACT which is passed to the completion handler in + * the result object. + * @arg priority Specifies the operation priority. This has an + * affect on POSIX only. Works like @i nice in Unix. + * Negative values are not allowed. 0 means priority + * of the operation same as the process priority. + * 1 means priority of the operation is one less than + * process, and so forth. This parameter has no + * affect on Win32. + * @arg signal_number The POSIX4 real-time signal number to be used + * for the operation. signal_number ranges from + * ACE_SIGRTMIN to ACE_SIGRTMAX. This argument is + * unused on non-POSIX4 systems. + * + * @retval 0 for success. + * @retval -1 for failure; consult @c errno for further information. + */ + int write (ACE_Message_Block &message_block, + size_t bytes_to_write, + const void *act = 0, + int priority = 0, + int signal_number = ACE_SIGRTMIN); + +protected: + /// Virtual from ACE_Asynch_Operation. Since this class is essentially an + /// implementation class, simply return 0. + virtual ACE_Asynch_Operation_Impl *implementation (void) const { return 0; } + + /// virtual from ACE_Handler + + /// This method is called when BIO write request is completed. It + /// processes the IO completion and calls do_SSL_state_machine(). + virtual void handle_write_stream + (const ACE_Asynch_Write_Stream::Result &result); + + /// This method is called when BIO read request is completed. It + /// processes the IO completion and calls do_SSL_state_machine(). + virtual void handle_read_stream + (const ACE_Asynch_Read_Stream::Result &result); + + /// This method is called when all SSL sessions are closed and no + /// more pending AIOs exist. It also calls users handle_wakeup(). + virtual void handle_wakeup (void); + + /** + * @name SSL State Machine + */ + //@{ + int do_SSL_state_machine (void); + int do_SSL_handshake (void); + int do_SSL_read (void); + int do_SSL_write(void); + int do_SSL_shutdown(void); + //@} + + void print_error (int err_ssl, + const ACE_TCHAR *pText); + + int pending_BIO_count (void); + + /// This method is called to notify user handler when user's read in + /// done. + int notify_read (int bytes_transferred, int error); + + /// This method is called to notify user handler when user's write + /// in done. + int notify_write (int bytes_transferred, int error); + + /// This method is called to notify ourself that SSL session is + /// shutdown and that there is no more I/O activity now and in the + /// future. + int notify_close(void); + + /** + * @name BIO Helpers + */ + //@{ + int ssl_bio_read (char * buf, size_t len, int & errval); + int ssl_bio_write (const char * buf, size_t len, int & errval); + //@} + +private: + + // Preventing copying through construction or assignment. + ACE_SSL_Asynch_Stream (ACE_SSL_Asynch_Stream const &); + ACE_SSL_Asynch_Stream & operator= (ACE_SSL_Asynch_Stream const &); + +protected: + + /// Stream Type ST_CLIENT/ST_SERVER + Stream_Type type_; + + /// The real file/socket handle + ACE_HANDLE handle_; + + /// The proactor + ACE_Proactor * proactor_; + + /// External,i.e user handler + ACE_Handler * ext_handler_; + + /// External, i.e. read result faked for user + ACE_SSL_Asynch_Read_Stream_Result * ext_read_result_ ; + + /// External, i.e. write result faked for user + ACE_SSL_Asynch_Write_Stream_Result * ext_write_result_ ; + + /// Stream state/flags + enum Stream_Flag + { + /// istream_ open OK + SF_STREAM_OPEN = 0x0001, + /// request to SSL shutdown + SF_REQ_SHUTDOWN = 0x0002, + /// SSL shutdown finished + SF_SHUTDOWN_DONE = 0x0004, + /// Close notification sent + SF_CLOSE_NTF_SENT = 0x0008, + /// Stream can be safely destroyed + SF_DELETE_ENABLE = 0x0010 + }; + + int flags_; + + /// The SSL session. + SSL * ssl_; + + /// The BIO implementation + BIO * bio_; + + /// The real streams which work under the ssl connection. + /// BIO performs I/O via this streams + enum BIO_Flag // internal IO flags + { + /// End of stream + BF_EOS = 0x01, + /// Real AIO in progress + BF_AIO = 0x02 + }; + + /** + * @name Internal stream, buffer and info for BIO read + */ + //@{ + ACE_Asynch_Read_Stream bio_istream_; + ACE_Message_Block bio_inp_msg_; + int bio_inp_errno_; + int bio_inp_flag_; + //@} + + /** + * @name Internal stream, buffer and info for BIO write + */ + //@{ + ACE_Asynch_Write_Stream bio_ostream_; + ACE_Message_Block bio_out_msg_; + int bio_out_errno_; + int bio_out_flag_; + //@} + + /// Mutex to protect work + ACE_SYNCH_MUTEX mutex_; + +}; + +ACE_END_VERSIONED_NAMESPACE_DECL + +#endif /* OPENSSL_VERSION_NUMBER > 0x0090581fL && (ACE_WIN32 || + ACE_HAS_AIO_CALLS) */ + +#include /**/ "ace/post.h" + +#endif /* ACE_SSL_ASYNCH_STREAM_H */ |