diff --git a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj index ebe6f0fe0b..6b28e276ae 100644 --- a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj +++ b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj @@ -72,19 +72,20 @@ + - - - + + + + + - - - + @@ -308,13 +309,7 @@ true - - true - true - true - true - - + true true true diff --git a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters index a29fdd4db9..c9094c3bbc 100644 --- a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters +++ b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters @@ -152,15 +152,15 @@ {422da6a1-e57e-4a96-9fce-e5958c16026e} - - {c4a7b6bb-88ec-4ff1-bc56-7c432a467500} - {ccdc0c8e-f77a-486e-ba2f-29c10ec97f18} {dfa79046-33ef-4653-a6f9-83954b76a10f} + + {4856837a-fa72-4252-8e8f-a112c1dbb3d2} + @@ -767,15 +767,9 @@ beast_asio\sockets - - beast_asio\sockets - beast_asio\sockets - - beast_asio\sockets - beast_asio\system @@ -815,9 +809,6 @@ beast_asio\tests - - beast_asio\protocol - beast_asio\tests @@ -842,15 +833,27 @@ beast_core\memory - - beast_asio\protocol - - - beast_asio\protocol - - + beast_asio\streams + + beast_asio\handshake + + + beast_asio\handshake + + + beast_asio\basics + + + beast_asio\handshake + + + beast_asio\handshake + + + beast_asio\handshake + @@ -1303,17 +1306,14 @@ beast_asio\tests - - beast_asio\protocol - beast_asio\tests beast_asio\basics - - beast_asio\protocol + + beast_asio\handshake diff --git a/Subtrees/beast/modules/beast_asio/basics/beast_FixedInputBuffer.h b/Subtrees/beast/modules/beast_asio/basics/beast_FixedInputBuffer.h new file mode 100644 index 0000000000..ce0a968052 --- /dev/null +++ b/Subtrees/beast/modules/beast_asio/basics/beast_FixedInputBuffer.h @@ -0,0 +1,112 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_FIXEDINPUTBUFFER_H_INCLUDED +#define BEAST_FIXEDINPUTBUFFER_H_INCLUDED + +/** Represents a small, fixed size buffer. + This provides a convenient interface for doing a bytewise + verification/reject test on a handshake protocol. +*/ +template +struct FixedInputBuffer +{ + template + explicit FixedInputBuffer (ConstBufferSequence const& buffer) + : m_buffer (boost::asio::buffer (m_storage)) + , m_size (boost::asio::buffer_copy (m_buffer, buffer)) + , m_data (boost::asio::buffer_cast (m_buffer)) + { + } + + uint8 operator[] (std::size_t index) const noexcept + { + bassert (index >= 0 && index < m_size); + return m_data [index]; + } + + bool peek (std::size_t bytes) const noexcept + { + if (m_size >= bytes) + return true; + return false; + } + + template + bool peek (T* t) noexcept + { + std::size_t const bytes = sizeof (T); + if (m_size >= bytes) + { + std::copy (m_data, m_data + bytes, t); + return true; + } + return false; + } + + bool consume (std::size_t bytes) noexcept + { + if (m_size >= bytes) + { + m_data += bytes; + m_size -= bytes; + return true; + } + return false; + } + + template + bool read (T* t) noexcept + { + std::size_t const bytes = sizeof (T); + if (m_size >= bytes) + { + //this causes a stack corruption. + //std::copy (m_data, m_data + bytes, t); + + memcpy (t, m_data, bytes); + m_data += bytes; + m_size -= bytes; + return true; + } + return false; + } + + // Reads an integraltype in network byte order + template + bool readNetworkInteger (IntegerType* value) + { + // Must be an integral type! + // not available in all versions of std:: unfortunately + //static_bassert (std::is_integral ::value); + IntegerType networkValue; + if (! read (&networkValue)) + return; + *value = fromNetworkByteOrder (networkValue); + return true; + } + +private: + boost::array m_storage; + MutableBuffer m_buffer; + std::size_t m_size; + uint8 const* m_data; +}; + +#endif diff --git a/Subtrees/beast/modules/beast_asio/beast_asio.cpp b/Subtrees/beast/modules/beast_asio/beast_asio.cpp index 71a155aafb..cb9dd8d638 100644 --- a/Subtrees/beast/modules/beast_asio/beast_asio.cpp +++ b/Subtrees/beast/modules/beast_asio/beast_asio.cpp @@ -30,8 +30,7 @@ namespace beast #include "sockets/beast_Socket.cpp" #include "sockets/beast_SslContext.cpp" -#include "protocol/beast_ProxyHandshake.cpp" -#include "protocol/beast_StreamHandshakeDetectorType.cpp" +#include "handshake/beast_ProxyHandshake.cpp" #include "tests/beast_TestPeerBasics.cpp" #include "tests/beast_TestPeerLogic.cpp" diff --git a/Subtrees/beast/modules/beast_asio/beast_asio.h b/Subtrees/beast/modules/beast_asio/beast_asio.h index 4006b81105..acba94323b 100644 --- a/Subtrees/beast/modules/beast_asio/beast_asio.h +++ b/Subtrees/beast/modules/beast_asio/beast_asio.h @@ -48,24 +48,25 @@ namespace beast // Order matters -#include "basics/beast_PeerRole.h" #include "basics/beast_BufferType.h" #include "basics/beast_CompletionCall.h" #include "basics/beast_ErrorCall.h" +#include "basics/beast_FixedInputBuffer.h" +#include "basics/beast_PeerRole.h" #include "basics/beast_TransferCall.h" #include "sockets/beast_SocketBase.h" #include "sockets/beast_Socket.h" -#include "sockets/beast_SocketInterface.h" #include "sockets/beast_SocketWrapper.h" -#include "sockets/beast_SharedSocket.h" #include "sockets/beast_SslContext.h" -#include "protocol/beast_ProxyHandshake.h" -#include "protocol/beast_HandshakeDetectorType.h" -#include "protocol/beast_StreamHandshakeDetectorType.h" +#include "handshake/beast_ProxyHandshake.h" + #include "handshake/beast_HandshakeDetectLogic.h" +#include "handshake/beast_HandshakeDetectLogicSSL2.h" +#include "handshake/beast_HandshakeDetectLogicSSL3.h" +#include "handshake/beast_HandshakeDetectStream.h" -#include "streams/beast_prefilled_read_stream.h" +#include "streams/beast_PrefilledReadStream.h" #include "tests/beast_TestPeerBasics.h" #include "tests/beast_TestPeer.h" diff --git a/Subtrees/beast/modules/beast_asio/handshake/beast_HandshakeDetectLogic.h b/Subtrees/beast/modules/beast_asio/handshake/beast_HandshakeDetectLogic.h new file mode 100644 index 0000000000..62eae110db --- /dev/null +++ b/Subtrees/beast/modules/beast_asio/handshake/beast_HandshakeDetectLogic.h @@ -0,0 +1,129 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_HANDSHAKEDETECTLOGIC_H_INCLUDED +#define BEAST_HANDSHAKEDETECTLOGIC_H_INCLUDED + +class HandshakeDetectLogic +{ +public: + HandshakeDetectLogic () + : m_finished (false) + , m_success (false) + { + } + + /** How many bytes maximum we might need. + + This is the largest number of bytes that the detector + might need in order to come to a conclusion about + whether or not the handshake is a match. Depending + on the data, it could come to that conclusion sooner + though. + + Use read_some instead of read so that the detect logic + can reject the handshake sooner if possible. + */ + virtual std::size_t max_needed () = 0; + + /** Return true if we have enough data to form a conclusion. + */ + bool finished () const noexcept + { + return m_finished; + } + + /** Return true if we came to a conclusion and the data matched. + */ + bool success () const noexcept + { + return m_finished && m_success; + } + +protected: + void conclude (bool success = true) + { + m_finished = true; + m_success = success; + } + + void fail () + { + conclude (false); + } + +private: + bool m_finished; + bool m_success; +}; + +//------------------------------------------------------------------------------ + +/** Wraps the logic and exports it as an abstract interface. +*/ +template +class HandshakeDetectLogicType +{ +public: + typedef Logic LogicType; + typedef typename Logic::arg_type arg_type; + + explicit HandshakeDetectLogicType (arg_type const& arg = arg_type ()) + : m_logic (arg) + { + } + + LogicType& get () + { + return m_logic; + } + + std::size_t max_needed () noexcept + { + return m_logic.max_needed (); + } + + bool finished () noexcept + { + return m_logic.finished (); + } + + /** If finished is true, this tells us if the handshake was detected. + */ + bool success () noexcept + { + return m_logic.success (); + } + + /** Analyze the buffer to match the Handshake. + Returns `true` if the analysis is complete. + */ + template + bool analyze (ConstBufferSequence const& buffer) + { + bassert (! m_logic.finished ()); + m_logic.analyze (buffer); + return m_logic.finished (); + } + +private: + Logic m_logic; +}; + +#endif diff --git a/Subtrees/beast/modules/beast_asio/handshake/beast_HandshakeDetectLogicSSL2.h b/Subtrees/beast/modules/beast_asio/handshake/beast_HandshakeDetectLogicSSL2.h new file mode 100644 index 0000000000..49f63eeb91 --- /dev/null +++ b/Subtrees/beast/modules/beast_asio/handshake/beast_HandshakeDetectLogicSSL2.h @@ -0,0 +1,103 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_HANDSHAKEDETECTLOGICSSL2_H_INCLUDED +#define BEAST_HANDSHAKEDETECTLOGICSSL2_H_INCLUDED + +// Handshake for SSL 2 +// +// http://tools.ietf.org/html/rfc5246#appendix-E.2 +// +// uint8 V2CipherSpec[3]; +// struct { +// uint16 msg_length; +// uint8 msg_type; +// Version version; Should be 'ProtocolVersion'? +// uint16 cipher_spec_length; +// uint16 session_id_length; +// uint16 challenge_length; +// ... +// +class HandshakeDetectLogicSSL2 : public HandshakeDetectLogic +{ +public: + typedef int arg_type; + + explicit HandshakeDetectLogicSSL2 (arg_type const&) + { + } + + enum + { + bytesNeeded = 3 + }; + + std::size_t max_needed () + { + return bytesNeeded; + } + + template + void analyze (ConstBufferSequence const& buffer) + { + FixedInputBuffer in (buffer); + + { + uint8 byte; + if (! in.peek (&byte)) + return; + + // First byte must have the high bit set + // + if((byte & 0x80) != 0x80) + return fail (); + } + + // The remaining bits contain the + // length of the following data in bytes. + // + uint16 msg_length; + if (! in.readNetworkInteger(&msg_length)) + return; + + // sizeof (msg_type + + // Version (ProtcolVersion?) + + // cipher_spec_length + + // session_id_length + + // challenge_length) + // + // Should be 9 or greater. + // + if (msg_length < 9) + return fail (); + + uint8 msg_type; + if (! in.read (&msg_type)) + return; + + // The msg_type must be 0x01 for a version 2 ClientHello + // + if (msg_type != 0x01) + return fail (); + + conclude (); + } +}; + +#endif diff --git a/Subtrees/beast/modules/beast_asio/handshake/beast_HandshakeDetectLogicSSL3.h b/Subtrees/beast/modules/beast_asio/handshake/beast_HandshakeDetectLogicSSL3.h new file mode 100644 index 0000000000..c2314f04a1 --- /dev/null +++ b/Subtrees/beast/modules/beast_asio/handshake/beast_HandshakeDetectLogicSSL3.h @@ -0,0 +1,77 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_HANDSHAKEDETECTLOGICSSL3_H_INCLUDED +#define BEAST_HANDSHAKEDETECTLOGICSSL3_H_INCLUDED + +// Handshake for SSL 3 (Also TLS 1.0 and 1.1) +// +// http://www.ietf.org/rfc/rfc2246.txt +// +// Section 7.4. Handshake protocol +// +class HandshakeDetectLogicSSL3 : public HandshakeDetectLogic +{ +public: + typedef int arg_type; // dummy + + explicit HandshakeDetectLogicSSL3 (arg_type const&) + { + } + + enum + { + bytesNeeded = 6 + }; + + std::size_t max_needed () + { + return bytesNeeded; + } + + template + void analyze (ConstBufferSequence const& buffer) + { + uint16 version; + FixedInputBuffer in (buffer); + + uint8 msg_type; + if (! in.read (&msg_type)) + return; + + // msg_type must be 0x16 = "SSL Handshake" + // + if (msg_type != 0x16) + return fail (); + + if (! in.read (&version)) + return; + version = fromNetworkByteOrder (version); + + uint16 length; + if (! in.read (&length)) + return; + + length = fromNetworkByteOrder (length); + + conclude (); + } +}; + +#endif diff --git a/Subtrees/beast/modules/beast_asio/handshake/beast_HandshakeDetectStream.h b/Subtrees/beast/modules/beast_asio/handshake/beast_HandshakeDetectStream.h new file mode 100644 index 0000000000..82c59c45a0 --- /dev/null +++ b/Subtrees/beast/modules/beast_asio/handshake/beast_HandshakeDetectStream.h @@ -0,0 +1,307 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_HANDSHAKEDETECTSTREAM_H_INCLUDED +#define BEAST_HANDSHAKEDETECTSTREAM_H_INCLUDED + +/** A stream that can detect a handshake. +*/ +/** @{ */ +template +class HandshakeDetectStream +{ +protected: + typedef boost::system::error_code error_code; + +public: + typedef Logic LogicType; + + /** Called when the state is known. + + This could be called from any thread, most likely an io_service + thread but don't rely on that. + + The Callback must be allocated via operator new. + */ + struct Callback + { + virtual ~Callback () { } + + /** Called for synchronous ssl detection. + + Note that the storage for the buffers passed to the + callback is owned by the detector class and becomes + invalid when the detector class is destroyed, which is + a common thing to do from inside your callback. + + @param ec A modifiable error code that becomes the return + value of handshake. + @param buffers The bytes that were read in. + @param is_ssl True if the sequence is an ssl handshake. + */ + virtual void on_detect (Logic& logic, + error_code& ec, ConstBuffers const& buffers) = 0; + + virtual void on_async_detect (Logic& logic, + error_code const& ec, ConstBuffers const& buffers, + ErrorCall const& origHandler) = 0; + + #if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE + virtual void on_async_detect (Logic& logic, + error_code const& ec, ConstBuffers const& buffers, + TransferCall const& origHandler) = 0; + #endif + }; +}; + +//------------------------------------------------------------------------------ + +template +class HandshakeDetectStreamType + : public HandshakeDetectStream + , public boost::asio::ssl::stream_base + , public boost::asio::socket_base +{ +private: + typedef HandshakeDetectStreamType this_type; + typedef boost::asio::streambuf buffer_type; + typedef typename boost::remove_reference ::type stream_type; + +public: + typedef typename HandshakeDetectStream CallbackType; + + /** This takes ownership of the callback. + The callback must be allocated with operator new. + */ + template + HandshakeDetectStreamType (Callback* callback, Arg& arg) + : m_callback (callback) + , m_next_layer (arg) + , m_stream (m_next_layer) + { + } + + // basic_io_object + + boost::asio::io_service& get_io_service () + { + return m_next_layer.get_io_service (); + } + + // basic_socket + + typedef typename stream_type::protocol_type protocol_type; + typedef typename stream_type::lowest_layer_type lowest_layer_type; + + lowest_layer_type& lowest_layer () + { + return m_next_layer.lowest_layer (); + } + + lowest_layer_type const& lowest_layer () const + { + return m_next_layer.lowest_layer (); + } + + // ssl::stream + + error_code handshake (handshake_type type, error_code& ec) + { + return do_handshake (type, ec, ConstBuffers ()); + } + + template + BOOST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler, void (error_code)) + async_handshake (handshake_type type, BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler) + { +#if BEAST_ASIO_HAS_FUTURE_RETURNS + boost::asio::detail::async_result_init< + ErrorCall, void (error_code)> init( + BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler)); + // init.handler is copied + m_origHandler = ErrorCall (HandshakeHandler(init.handler)); + bassert (m_origBufferedHandler.isNull ()); + async_do_handshake (type, ConstBuffers ()); + return init.result.get(); +#else + m_origHandler = ErrorCall (handler); + bassert (m_origBufferedHandler.isNull ()); + async_do_handshake (type, ConstBuffers ()); +#endif + } + +#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE + template + error_code handshake (handshake_type type, + const ConstBufferSequence& buffers, error_code& ec) + { + return do_handshake (type, ec, ConstBuffers (buffers));; + } + + template + BOOST_ASIO_INITFN_RESULT_TYPE(BufferedHandshakeHandler, void (error_code, std::size_t)) + async_handshake(handshake_type type, const ConstBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler) + { +#if BEAST_ASIO_HAS_FUTURE_RETURNS + boost::asio::detail::async_result_init< + BufferedHandshakeHandler, void (error_code, std::size_t)> init( + BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler)); + // init.handler is copied + m_origBufferedHandler = TransferCall (BufferedHandshakeHandler(init.handler)); + bassert (m_origHandler.isNull ()); + async_do_handshake (type, ConstBuffers (buffers)); + return init.result.get(); +#else + m_origBufferedHandler = TransferCall (handler); + bassert (m_origHandler.isNull ()); + async_do_handshake (type, ConstBuffers (buffers)); +#endif + } +#endif + + //-------------------------------------------------------------------------- + + error_code do_handshake (handshake_type, error_code& ec, ConstBuffers const& buffers) + { + ec = error_code (); + + // Transfer caller data to our buffer. + m_buffer.commit (boost::asio::buffer_copy (m_buffer.prepare ( + boost::asio::buffer_size (buffers)), buffers)); + + do + { + std::size_t const available = m_buffer.size (); + std::size_t const needed = m_logic.max_needed (); + if (available < needed) + { + buffer_type::mutable_buffers_type buffers ( + m_buffer.prepare (needed - available)); + m_buffer.commit (m_next_layer.read_some (buffers, ec)); + } + + if (! ec) + { + m_logic.analyze (m_buffer.data ()); + + if (m_logic.finished ()) + { + m_callback->on_detect (m_logic.get (), ec, + ConstBuffers (m_buffer.data ())); + break; + } + + // If this fails it means we will never finish + check_postcondition (available < needed); + } + } + while (! ec); + + return ec; + } + + //-------------------------------------------------------------------------- + + void async_do_handshake (handshake_type type, ConstBuffers const& buffers) + { + // Transfer caller data to our buffer. + std::size_t const bytes_transferred (boost::asio::buffer_copy ( + m_buffer.prepare (boost::asio::buffer_size (buffers)), buffers)); + + // bootstrap the asynchronous loop + on_async_read_some (error_code (), bytes_transferred); + } + + // asynchronous version of the synchronous loop found in handshake () + // + void on_async_read_some (error_code const& ec, std::size_t bytes_transferred) + { + if (! ec) + { + m_buffer.commit (bytes_transferred); + + std::size_t const available = m_buffer.size (); + std::size_t const needed = m_logic.max_needed (); + + m_logic.analyze (m_buffer.data ()); + + if (m_logic.finished ()) + { + #if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE + if (! m_origBufferedHandler.isNull ()) + { + bassert (m_origHandler.isNull ()); + // continuation? + m_callback->on_async_detect (m_logic.get (), ec, + ConstBuffers (m_buffer.data ()), m_origBufferedHandler); + return; + } + #endif + + bassert (! m_origHandler.isNull ()) + // continuation? + m_callback->on_async_detect (m_logic.get (), ec, + ConstBuffers (m_buffer.data ()), m_origHandler); + return; + } + + // If this fails it means we will never finish + check_postcondition (available < needed); + + buffer_type::mutable_buffers_type buffers (m_buffer.prepare ( + needed - available)); + + // need a continuation hook here? + m_next_layer.async_read_some (buffers, boost::bind ( + &this_type::on_async_read_some, this, boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + + return; + } + + #if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE + if (! m_origBufferedHandler.isNull ()) + { + bassert (m_origHandler.isNull ()); + // continuation? + m_callback->on_async_detect (m_logic.get (), ec, + ConstBuffers (m_buffer.data ()), m_origBufferedHandler); + return; + } + #endif + + bassert (! m_origHandler.isNull ()) + // continuation? + m_callback->on_async_detect (m_logic.get (), ec, + ConstBuffers (m_buffer.data ()), m_origHandler); + } + +private: + ScopedPointer ::Callback> m_callback; + Stream m_next_layer; + buffer_type m_buffer; + boost::asio::buffered_read_stream m_stream; + HandshakeDetectLogicType m_logic; + ErrorCall m_origHandler; + TransferCall m_origBufferedHandler; +}; +/** @} */ + +#endif diff --git a/Subtrees/beast/modules/beast_asio/protocol/beast_ProxyHandshake.cpp b/Subtrees/beast/modules/beast_asio/handshake/beast_ProxyHandshake.cpp similarity index 100% rename from Subtrees/beast/modules/beast_asio/protocol/beast_ProxyHandshake.cpp rename to Subtrees/beast/modules/beast_asio/handshake/beast_ProxyHandshake.cpp diff --git a/Subtrees/beast/modules/beast_asio/protocol/beast_ProxyHandshake.h b/Subtrees/beast/modules/beast_asio/handshake/beast_ProxyHandshake.h similarity index 100% rename from Subtrees/beast/modules/beast_asio/protocol/beast_ProxyHandshake.h rename to Subtrees/beast/modules/beast_asio/handshake/beast_ProxyHandshake.h diff --git a/Subtrees/beast/modules/beast_asio/protocol/beast_HandshakeDetectorType.h b/Subtrees/beast/modules/beast_asio/protocol/beast_HandshakeDetectorType.h deleted file mode 100644 index b896815cd5..0000000000 --- a/Subtrees/beast/modules/beast_asio/protocol/beast_HandshakeDetectorType.h +++ /dev/null @@ -1,350 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of Beast: https://github.com/vinniefalco/Beast - Copyright 2013, Vinnie Falco - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#ifndef BEAST_HANDSHAKEDETECTORTYPE_H_INCLUDED -#define BEAST_HANDSHAKEDETECTORTYPE_H_INCLUDED - -class DetectPolicy -{ -public: - DetectPolicy () - : m_finished (false) - , m_success (false) - { - } - - /** How many bytes maximum we might need. - - This is the largest number of bytes that the detector - might need in order to come to a conclusion about - whether or not the handshake is a match. Depending - on the data, it could come to that conclusion sooner - though. - */ - virtual std::size_t max_needed () = 0; - - /** Returns true if the return value of success() is valid. - */ - bool finished () const noexcept - { - return m_finished; - } - - /** Returns true if the buffers matched the Handshake - */ - bool success () const noexcept - { - bassert (m_finished); - return m_success; - } - -protected: - void conclude (bool success = true) - { - m_finished = true; - m_success = success; - } - - void fail () - { - conclude (false); - } - - //-------------------------------------------------------------------------- - - /** Represents a small, fixed size buffer. - This provides a convenient interface for doing a bytewise - verification/reject test on a handshake protocol. - */ - template - struct Input - { - template - explicit Input (ConstBufferSequence const& buffer) - : m_buffer (boost::asio::buffer (m_storage)) - , m_size (boost::asio::buffer_copy (m_buffer, buffer)) - , m_data (boost::asio::buffer_cast (m_buffer)) - { - } -#if 0 - uint8 const* data () const noexcept - { - return m_data; - } -#endif - - uint8 operator[] (std::size_t index) const noexcept - { - bassert (index >= 0 && index < m_size); - return m_data [index]; - } - - bool peek (std::size_t bytes) const noexcept - { - if (m_size >= bytes) - return true; - return false; - } - - template - bool peek (T* t) noexcept - { - std::size_t const bytes = sizeof (T); - if (m_size >= bytes) - { - std::copy (m_data, m_data + bytes, t); - return true; - } - return false; - } - - bool consume (std::size_t bytes) noexcept - { - if (m_size >= bytes) - { - m_data += bytes; - m_size -= bytes; - return true; - } - return false; - } - - template - bool read (T* t) noexcept - { - std::size_t const bytes = sizeof (T); - if (m_size >= bytes) - { - //this causes a stack corruption. - //std::copy (m_data, m_data + bytes, t); - - memcpy (t, m_data, bytes); - m_data += bytes; - m_size -= bytes; - return true; - } - return false; - } - - // Reads an integraltype in network byte order - template - bool readNetworkInteger (IntegerType* value) - { - // Must be an integral type! - // not available in all versions of std:: unfortunately - //static_bassert (std::is_integral ::value); - IntegerType networkValue; - if (! read (&networkValue)) - return false; - *value = fromNetworkByteOrder (networkValue); - return true; - } - - private: - boost::array m_storage; - MutableBuffer m_buffer; - std::size_t m_size; - uint8 const* m_data; - }; - -private: - bool m_finished; - bool m_success; -}; - -// Handshake for SSL 2 -// -// http://tools.ietf.org/html/rfc5246#appendix-E.2 -// -// uint8 V2CipherSpec[3]; -// struct { -// uint16 msg_length; -// uint8 msg_type; -// Version version; Should be 'ProtocolVersion'? -// uint16 cipher_spec_length; -// uint16 session_id_length; -// uint16 challenge_length; -// ... -// -class SSL2 : public DetectPolicy -{ -public: - typedef int arg_type; - - explicit SSL2 (arg_type const&) - { - } - - enum - { - bytesNeeded = 3 - }; - - std::size_t max_needed () - { - return bytesNeeded; - } - - template - void analyze (ConstBufferSequence const& buffer) - { - Input in (buffer); - - { - uint8 byte; - if (! in.peek (&byte)) - return; - - // First byte must have the high bit set - // - if((byte & 0x80) != 0x80) - return fail (); - } - - // The remaining bits contain the - // length of the following data in bytes. - // - uint16 msg_length; - if (! in.readNetworkInteger(&msg_length)) - return; - - // sizeof (msg_type + - // Version (ProtcolVersion?) + - // cipher_spec_length + - // session_id_length + - // challenge_length) - // - // Should be 9 or greater. - // - if (msg_length < 9) - return fail (); - - uint8 msg_type; - if (! in.read (&msg_type)) - return; - - // The msg_type must be 0x01 for a version 2 ClientHello - // - if (msg_type != 0x01) - return fail (); - - conclude (); - } -}; - -// Handshake for SSL 3 (Also TLS 1.0 and 1.1) -// -// http://www.ietf.org/rfc/rfc2246.txt -// -// Section 7.4. Handshake protocol -// -class SSL3 : public DetectPolicy -{ -public: - typedef int arg_type; // dummy - - explicit SSL3 (arg_type const&) - { - } - - enum - { - bytesNeeded = 6 - }; - - std::size_t max_needed () - { - return bytesNeeded; - } - - template - void analyze (ConstBufferSequence const& buffer) - { - uint16 version; - Input in (buffer); - - uint8 msg_type; - if (! in.read (&msg_type)) - return; - - // msg_type must be 0x16 = "SSL Handshake" - // - if (msg_type != 0x16) - return fail (); - - if (! in.read (&version)) - return; - version = fromNetworkByteOrder (version); - - uint16 length; - if (! in.read (&length)) - return; - - length = fromNetworkByteOrder (length); - - conclude (); - } -}; - -//-------------------------------------------------------------------------- - -template -class HandshakeDetectorType -{ -public: - typedef typename Logic::arg_type arg_type; - - explicit HandshakeDetectorType (arg_type const& arg = arg_type ()) - : m_logic (arg) - { - } - - std::size_t max_needed () noexcept - { - return m_logic.max_needed (); - } - - bool finished () noexcept - { - return m_logic.finished (); - } - - /** If finished is true, this tells us if the handshake was detected. - */ - bool success () noexcept - { - return m_logic.success (); - } - - /** Analyze the buffer to match the Handshake. - Returns `true` if the analysis is complete. - */ - template - bool analyze (ConstBufferSequence const& buffer) - { - bassert (! m_logic.finished ()); - m_logic.analyze (buffer); - return m_logic.finished (); - } - -private: - Logic m_logic; -}; - -#endif diff --git a/Subtrees/beast/modules/beast_asio/protocol/beast_StreamHandshakeDetectorType.cpp b/Subtrees/beast/modules/beast_asio/protocol/beast_StreamHandshakeDetectorType.cpp deleted file mode 100644 index 31d57f5deb..0000000000 --- a/Subtrees/beast/modules/beast_asio/protocol/beast_StreamHandshakeDetectorType.cpp +++ /dev/null @@ -1,19 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of Beast: https://github.com/vinniefalco/Beast - Copyright 2013, Vinnie Falco - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - diff --git a/Subtrees/beast/modules/beast_asio/protocol/beast_StreamHandshakeDetectorType.h b/Subtrees/beast/modules/beast_asio/protocol/beast_StreamHandshakeDetectorType.h deleted file mode 100644 index 7550e77655..0000000000 --- a/Subtrees/beast/modules/beast_asio/protocol/beast_StreamHandshakeDetectorType.h +++ /dev/null @@ -1,78 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of Beast: https://github.com/vinniefalco/Beast - Copyright 2013, Vinnie Falco - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#ifndef BEAST_STREAMHANDSHAKEDETECTORTYPE_H_INCLUDED -#define BEAST_STREAMHANDSHAKEDETECTORTYPE_H_INCLUDED - -/** Wraps a HandshakeDetector and does the work on the Socket for you. -*/ -template -class StreamHandshakeDetectorType -{ -protected: - typedef boost::system::error_code error_code; - typedef StreamHandshakeDetectorType This; - -public: - typedef typename Detector::arg_type arg_type; - - explicit StreamHandshakeDetectorType (arg_type const& arg = arg_type ()) - { - } - - template - void async_handshake (Socket& socket, BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler) - { -#if 0 - std::size_t const bytes = m_detector.needed (); -#if 1 - boost::asio::async_read (socket, m_buffer.prepare (bytes), boost::bind ( - &This::on_read , this, &socket, - handler, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); -#else - boost::asio::async_read (socket, m_buffer.prepare (bytes), boost::bind ( - &This::on_read2, this, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); -#endif -#endif - } - -protected: - template - void on_read (Socket* socket, BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler, - error_code const& ec, std::size_t bytes_transferred) - { - m_buffer.commit (bytes_transferred); - - if (m_detector.analyze (m_buffer.data ())) - { - if (m_detector.success ()) - { - //socket->async_handshake (Socket::server, m_buffer.data (), handler); - } - } - } - -private: - Detector m_detector; - boost::asio::streambuf m_buffer; -}; - -#endif diff --git a/Subtrees/beast/modules/beast_asio/sockets/beast_SharedSocket.h b/Subtrees/beast/modules/beast_asio/sockets/beast_SharedSocket.h deleted file mode 100644 index ed8554f135..0000000000 --- a/Subtrees/beast/modules/beast_asio/sockets/beast_SharedSocket.h +++ /dev/null @@ -1,83 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of Beast: https://github.com/vinniefalco/Beast - Copyright 2013, Vinnie Falco - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#ifndef BEAST_SHAREDSOCKET_H_INCLUDED -#define BEAST_SHAREDSOCKET_H_INCLUDED - -/** A Socket interface with reference counting. - - You can keep a pointer to the base class so that you don't have - to see the template or underlying object implementation. - - @see SharedSocketTYpe, SharedObjectPtr -*/ -/** @{ */ -class SharedSocket - : public SharedObject - , public virtual Socket -{ -public: - /** Store your SharedSocket in one of these! */ - typedef SharedObjectPtr Ptr; -}; - -//------------------------------------------------------------------------------ - -/** A RAII container for wrapping an object as a Socket. - - To use this, construct the class with an instance of your object - created with operator new. The constructor will take ownership, - and delete it when the last reference is removed. For example: - - @code - - boost::asio::io_service ios; - boost::asio::ssl:context ctx; - - SharedSocket::Ptr mySocket ( - new (boost::asio::ssl::stream (ios, ctx))); - - mySocket->handshake (); - - @endcode - - @see SharedSocket -*/ -template -class SharedSocketType - : public SharedSocket - , public SocketWrapper -{ -public: - /** Create the shared socket. - This takes posession of the object, which will be deleted - when the last reference goes away. - */ - SharedSocketType (Object* object) - : SocketWrapper (object) - , m_object (object) - { - } - -private: - ScopedPointer m_object; -}; -/** @} */ - -#endif diff --git a/Subtrees/beast/modules/beast_asio/sockets/beast_SocketInterface.h b/Subtrees/beast/modules/beast_asio/sockets/beast_SocketInterface.h deleted file mode 100644 index f1d47d5753..0000000000 --- a/Subtrees/beast/modules/beast_asio/sockets/beast_SocketInterface.h +++ /dev/null @@ -1,62 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of Beast: https://github.com/vinniefalco/Beast - Copyright 2013, Vinnie Falco - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#ifndef BEAST_SOCKETINTERFACE_H_INCLUDED -#define BEAST_SOCKETINTERFACE_H_INCLUDED - -/** These define the interfaces that SocketWrapper can adapt with SFINAE. */ -struct SocketInterface -{ - // has close() - struct Close { }; - - /** Tag for some compatibility with boost::asio::basic_socket_acceptor - http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/basic_socket_acceptor.html - */ - struct Acceptor : Close { }; - - // Has lowest_layer() and lowest_layer_type - struct LowestLayer { }; - - /** Tag for parts of boost::asio::basic_socket - http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/basic_socket.html - */ - struct Socket : Close, LowestLayer { }; - - /** Tag for parts of boost::asio::basic_stream_socket - http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/basic_stream_socket.html - */ - struct SyncStream { }; - struct AsyncStream { }; - struct Stream : SyncStream, AsyncStream { }; - - /** Tags for parts of boost::asio::ssl::stream - http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream.html - */ - struct AnyHandshake { }; - struct SyncHandshake : AnyHandshake { }; - struct AsyncHandshake : AnyHandshake { }; - struct BufferedSyncHandshake : AnyHandshake { }; - struct BufferedAsyncHandshake : AnyHandshake { }; - struct Handshake : SyncHandshake, AsyncHandshake, - BufferedSyncHandshake, BufferedAsyncHandshake, - LowestLayer { }; -}; - -#endif diff --git a/Subtrees/beast/modules/beast_asio/streams/beast_prefilled_read_stream.h b/Subtrees/beast/modules/beast_asio/streams/beast_PrefilledReadStream.h similarity index 100% rename from Subtrees/beast/modules/beast_asio/streams/beast_prefilled_read_stream.h rename to Subtrees/beast/modules/beast_asio/streams/beast_PrefilledReadStream.h diff --git a/modules/ripple_asio/sockets/ripple_MultiSocketType.h b/modules/ripple_asio/sockets/ripple_MultiSocketType.h index 2f446f75a3..e74acb36bd 100644 --- a/modules/ripple_asio/sockets/ripple_MultiSocketType.h +++ b/modules/ripple_asio/sockets/ripple_MultiSocketType.h @@ -7,296 +7,6 @@ #ifndef RIPPLE_MULTISOCKETTYPE_H_INCLUDED #define RIPPLE_MULTISOCKETTYPE_H_INCLUDED -//------------------------------------------------------------------------------ - -// should really start using this -namespace detail -{ -} - -//------------------------------------------------------------------------------ - -class ssl_detector_base -{ -protected: - typedef boost::system::error_code error_code; - -public: - /** Called when the state is known. - - This could be called from any thread, most likely an io_service - thread but don't rely on that. - - The Callback must be allocated via operator new. - */ - struct Callback - { - virtual ~Callback () { } - - /** Called for synchronous ssl detection. - - Note that the storage for the buffers passed to the - callback is owned by the detector class and becomes - invalid when the detector class is destroyed, which is - a common thing to do from inside your callback. - - @param ec A modifiable error code that becomes the return - value of handshake. - @param buffers The bytes that were read in. - @param is_ssl True if the sequence is an ssl handshake. - */ - virtual void on_detect (error_code& ec, - ConstBuffers const& buffers, bool is_ssl) = 0; - - virtual void on_async_detect (error_code const& ec, - ConstBuffers const& buffers, ErrorCall const& origHandler, - bool is_ssl) = 0; - - #if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE - virtual void on_async_detect (error_code const& ec, - ConstBuffers const& buffers, TransferCall const& origHandler, - bool is_ssl) = 0; - #endif - - }; -}; - -/** A stream that can detect an SSL handshake. -*/ -template -class ssl_detector - : public ssl_detector_base - , public boost::asio::ssl::stream_base - , public boost::asio::socket_base -{ -private: - typedef ssl_detector this_type; - typedef boost::asio::streambuf buffer_type; - typedef typename boost::remove_reference ::type stream_type; - -public: - /** This takes ownership of the callback. - The callback must be allocated with operator new. - */ - template - ssl_detector (Callback* callback, Arg& arg) - : m_callback (callback) - , m_next_layer (arg) - , m_stream (m_next_layer) - { - } - - // basic_io_object - - boost::asio::io_service& get_io_service () - { - return m_next_layer.get_io_service (); - } - - // basic_socket - - typedef typename stream_type::protocol_type protocol_type; - typedef typename stream_type::lowest_layer_type lowest_layer_type; - - lowest_layer_type& lowest_layer () - { - return m_next_layer.lowest_layer (); - } - - lowest_layer_type const& lowest_layer () const - { - return m_next_layer.lowest_layer (); - } - - // ssl::stream - - error_code handshake (handshake_type type, error_code& ec) - { - return do_handshake (type, ec, ConstBuffers ()); - } - - template - BOOST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler, void (error_code)) - async_handshake (handshake_type type, BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler) - { -#if BEAST_ASIO_HAS_FUTURE_RETURNS - boost::asio::detail::async_result_init< - ErrorCall, void (error_code)> init( - BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler)); - // init.handler is copied - m_origHandler = ErrorCall (HandshakeHandler(init.handler)); - bassert (m_origBufferedHandler.isNull ()); - async_do_handshake (type, ConstBuffers ()); - return init.result.get(); -#else - m_origHandler = ErrorCall (handler); - bassert (m_origBufferedHandler.isNull ()); - async_do_handshake (type, ConstBuffers ()); -#endif - } - -#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE - template - error_code handshake (handshake_type type, - const ConstBufferSequence& buffers, error_code& ec) - { - return do_handshake (type, ec, ConstBuffers (buffers));; - } - - template - BOOST_ASIO_INITFN_RESULT_TYPE(BufferedHandshakeHandler, void (error_code, std::size_t)) - async_handshake(handshake_type type, const ConstBufferSequence& buffers, - BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler) - { -#if BEAST_ASIO_HAS_FUTURE_RETURNS - boost::asio::detail::async_result_init< - BufferedHandshakeHandler, void (error_code, std::size_t)> init( - BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler)); - // init.handler is copied - m_origBufferedHandler = TransferCall (BufferedHandshakeHandler(init.handler)); - bassert (m_origHandler.isNull ()); - async_do_handshake (type, ConstBuffers (buffers)); - return init.result.get(); -#else - m_origBufferedHandler = TransferCall (handler); - bassert (m_origHandler.isNull ()); - async_do_handshake (type, ConstBuffers (buffers)); -#endif - } -#endif - - //-------------------------------------------------------------------------- - - error_code do_handshake (handshake_type, error_code& ec, ConstBuffers const& buffers) - { - ec = error_code (); - - // Transfer caller data to our buffer. - m_buffer.commit (boost::asio::buffer_copy (m_buffer.prepare ( - boost::asio::buffer_size (buffers)), buffers)); - - do - { - std::size_t const available = m_buffer.size (); - std::size_t const needed = m_detector.max_needed (); - if (available < needed) - { - buffer_type::mutable_buffers_type buffers ( - m_buffer.prepare (needed - available)); - m_buffer.commit (m_next_layer.read_some (buffers, ec)); - } - - if (! ec) - { - m_detector.analyze (m_buffer.data ()); - - if (m_detector.finished ()) - { - m_callback->on_detect (ec, - ConstBuffers (m_buffer.data ()), - m_detector.success ()); - break; - } - - // If this fails it means we will never finish - check_postcondition (available < needed); - } - } - while (! ec); - - return ec; - } - - //-------------------------------------------------------------------------- - - void async_do_handshake (handshake_type type, ConstBuffers const& buffers) - { - // Transfer caller data to our buffer. - std::size_t const bytes_transferred (boost::asio::buffer_copy ( - m_buffer.prepare (boost::asio::buffer_size (buffers)), buffers)); - - // bootstrap the asynchronous loop - on_async_read_some (error_code (), bytes_transferred); - } - - // asynchronous version of the synchronous loop found in handshake () - // - void on_async_read_some (error_code const& ec, std::size_t bytes_transferred) - { - if (! ec) - { - m_buffer.commit (bytes_transferred); - - std::size_t const available = m_buffer.size (); - std::size_t const needed = m_detector.max_needed (); - - m_detector.analyze (m_buffer.data ()); - - if (m_detector.finished ()) - { - #if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE - if (! m_origBufferedHandler.isNull ()) - { - bassert (m_origHandler.isNull ()); - // continuation? - m_callback->on_async_detect (ec, ConstBuffers (m_buffer.data ()), - m_origBufferedHandler, m_detector.success ()); - return; - } - #endif - - bassert (! m_origHandler.isNull ()) - // continuation? - m_callback->on_async_detect (ec, - ConstBuffers (m_buffer.data ()), m_origHandler, - m_detector.success ()); - return; - } - - // If this fails it means we will never finish - check_postcondition (available < needed); - - buffer_type::mutable_buffers_type buffers (m_buffer.prepare ( - needed - available)); - - // need a continuation hook here? - m_next_layer.async_read_some (buffers, boost::bind ( - &this_type::on_async_read_some, this, boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - - return; - } - - #if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE - if (! m_origBufferedHandler.isNull ()) - { - bassert (m_origHandler.isNull ()); - // continuation? - m_callback->on_async_detect (ec, ConstBuffers (m_buffer.data ()), - m_origBufferedHandler, false); - return; - } - #endif - - bassert (! m_origHandler.isNull ()) - // continuation? - m_callback->on_async_detect (ec, - ConstBuffers (m_buffer.data ()), m_origHandler, - false); - } - -private: - ScopedPointer m_callback; - Stream m_next_layer; - buffer_type m_buffer; - boost::asio::buffered_read_stream m_stream; - HandshakeDetectorType m_detector; - ErrorCall m_origHandler; - TransferCall m_origBufferedHandler; -}; - -//------------------------------------------------------------------------------ - /** Template for producing instances of MultiSocket */ template @@ -325,7 +35,7 @@ public: // These types are used internaly // - // The type of stream that the ssl_detector uses + // The type of stream that the HandshakeDetectStream uses typedef next_layer_type& ssl_detector_stream_type; template @@ -603,8 +313,8 @@ protected: Socket* new_detect_ssl_stream () { - ssl_detector_callback* callback = new ssl_detector_callback (this); - typedef ssl_detector this_type; + SSL3DetectCallback* callback = new SSL3DetectCallback (this); + typedef HandshakeDetectStreamType this_type; return new SocketWrapper (callback, m_next_layer); } @@ -848,35 +558,36 @@ protected: //-------------------------------------------------------------------------- // - // ssl_detector calback + // HandshakeDetectStream calback // - class ssl_detector_callback : public ssl_detector_base::Callback + class SSL3DetectCallback + : public HandshakeDetectStream ::Callback { public: - explicit ssl_detector_callback (MultiSocketType * owner) + typedef HandshakeDetectLogicSSL3 LogicType; + + explicit SSL3DetectCallback (MultiSocketType * owner) : m_owner (owner) { } - void on_detect (error_code& ec, - ConstBuffers const& buffers, bool is_ssl) + void on_detect (LogicType& logic, error_code& ec, + ConstBuffers const& buffers) { - m_owner->on_detect_ssl (ec, buffers, is_ssl); + m_owner->on_detect_ssl (ec, buffers, logic.success ()); } - void on_async_detect (error_code const& ec, - ConstBuffers const& buffers, ErrorCall const& origHandler, - bool is_ssl) + void on_async_detect (LogicType& logic, error_code const& ec, + ConstBuffers const& buffers, ErrorCall const& origHandler) { - m_owner->on_async_detect_ssl (ec, buffers, origHandler, is_ssl); + m_owner->on_async_detect_ssl (ec, buffers, origHandler, logic.success ()); } #if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE - void on_async_detect (error_code const& ec, - ConstBuffers const& buffers, TransferCall const& origHandler, - bool is_ssl) + void on_async_detect (LogicType& logic, error_code const& ec, + ConstBuffers const& buffers, TransferCall const& origHandler) { - m_owner->on_async_detect_ssl (ec, buffers, origHandler, is_ssl); + m_owner->on_async_detect_ssl (ec, buffers, origHandler, logic.success ()); } #endif