Generic HandshakeDetectStream and HandshakeDetectLogic

This commit is contained in:
Vinnie Falco
2013-08-16 08:01:59 -07:00
parent 0feccfd7b0
commit bb941354ce
18 changed files with 787 additions and 945 deletions

View File

@@ -72,19 +72,20 @@
<ClInclude Include="..\..\modules\beast_asio\basics\beast_BufferType.h" /> <ClInclude Include="..\..\modules\beast_asio\basics\beast_BufferType.h" />
<ClInclude Include="..\..\modules\beast_asio\basics\beast_CompletionCall.h" /> <ClInclude Include="..\..\modules\beast_asio\basics\beast_CompletionCall.h" />
<ClInclude Include="..\..\modules\beast_asio\basics\beast_ErrorCall.h" /> <ClInclude Include="..\..\modules\beast_asio\basics\beast_ErrorCall.h" />
<ClInclude Include="..\..\modules\beast_asio\basics\beast_FixedInputBuffer.h" />
<ClInclude Include="..\..\modules\beast_asio\basics\beast_PeerRole.h" /> <ClInclude Include="..\..\modules\beast_asio\basics\beast_PeerRole.h" />
<ClInclude Include="..\..\modules\beast_asio\basics\beast_TransferCall.h" /> <ClInclude Include="..\..\modules\beast_asio\basics\beast_TransferCall.h" />
<ClInclude Include="..\..\modules\beast_asio\beast_asio.h" /> <ClInclude Include="..\..\modules\beast_asio\beast_asio.h" />
<ClInclude Include="..\..\modules\beast_asio\protocol\beast_HandshakeDetectorType.h" /> <ClInclude Include="..\..\modules\beast_asio\handshake\beast_HandshakeDetectLogic.h" />
<ClInclude Include="..\..\modules\beast_asio\protocol\beast_StreamHandshakeDetectorType.h" /> <ClInclude Include="..\..\modules\beast_asio\handshake\beast_HandshakeDetectLogicSSL2.h" />
<ClInclude Include="..\..\modules\beast_asio\protocol\beast_ProxyHandshake.h" /> <ClInclude Include="..\..\modules\beast_asio\handshake\beast_HandshakeDetectLogicSSL3.h" />
<ClInclude Include="..\..\modules\beast_asio\handshake\beast_HandshakeDetectStream.h" />
<ClInclude Include="..\..\modules\beast_asio\handshake\beast_ProxyHandshake.h" />
<ClInclude Include="..\..\modules\beast_asio\sockets\beast_Socket.h" /> <ClInclude Include="..\..\modules\beast_asio\sockets\beast_Socket.h" />
<ClInclude Include="..\..\modules\beast_asio\sockets\beast_SharedSocket.h" />
<ClInclude Include="..\..\modules\beast_asio\sockets\beast_SocketBase.h" /> <ClInclude Include="..\..\modules\beast_asio\sockets\beast_SocketBase.h" />
<ClInclude Include="..\..\modules\beast_asio\sockets\beast_SocketInterface.h" />
<ClInclude Include="..\..\modules\beast_asio\sockets\beast_SocketWrapper.h" /> <ClInclude Include="..\..\modules\beast_asio\sockets\beast_SocketWrapper.h" />
<ClInclude Include="..\..\modules\beast_asio\sockets\beast_SslContext.h" /> <ClInclude Include="..\..\modules\beast_asio\sockets\beast_SslContext.h" />
<ClInclude Include="..\..\modules\beast_asio\streams\beast_prefilled_read_stream.h" /> <ClInclude Include="..\..\modules\beast_asio\streams\beast_PrefilledReadStream.h" />
<ClInclude Include="..\..\modules\beast_asio\system\beast_BoostIncludes.h" /> <ClInclude Include="..\..\modules\beast_asio\system\beast_BoostIncludes.h" />
<ClInclude Include="..\..\modules\beast_asio\tests\beast_TestPeer.h" /> <ClInclude Include="..\..\modules\beast_asio\tests\beast_TestPeer.h" />
<ClInclude Include="..\..\modules\beast_asio\tests\beast_TestPeerBasics.h" /> <ClInclude Include="..\..\modules\beast_asio\tests\beast_TestPeerBasics.h" />
@@ -308,13 +309,7 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\modules\beast_asio\beast_asio.cpp" /> <ClCompile Include="..\..\modules\beast_asio\beast_asio.cpp" />
<ClCompile Include="..\..\modules\beast_asio\protocol\beast_StreamHandshakeDetectorType.cpp"> <ClCompile Include="..\..\modules\beast_asio\handshake\beast_ProxyHandshake.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_asio\protocol\beast_ProxyHandshake.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>

View File

@@ -152,15 +152,15 @@
<Filter Include="beast_asio\tests"> <Filter Include="beast_asio\tests">
<UniqueIdentifier>{422da6a1-e57e-4a96-9fce-e5958c16026e}</UniqueIdentifier> <UniqueIdentifier>{422da6a1-e57e-4a96-9fce-e5958c16026e}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="beast_asio\protocol">
<UniqueIdentifier>{c4a7b6bb-88ec-4ff1-bc56-7c432a467500}</UniqueIdentifier>
</Filter>
<Filter Include="beast_asio\basics"> <Filter Include="beast_asio\basics">
<UniqueIdentifier>{ccdc0c8e-f77a-486e-ba2f-29c10ec97f18}</UniqueIdentifier> <UniqueIdentifier>{ccdc0c8e-f77a-486e-ba2f-29c10ec97f18}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="beast_asio\streams"> <Filter Include="beast_asio\streams">
<UniqueIdentifier>{dfa79046-33ef-4653-a6f9-83954b76a10f}</UniqueIdentifier> <UniqueIdentifier>{dfa79046-33ef-4653-a6f9-83954b76a10f}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="beast_asio\handshake">
<UniqueIdentifier>{4856837a-fa72-4252-8e8f-a112c1dbb3d2}</UniqueIdentifier>
</Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\modules\beast_core\beast_core.h"> <ClInclude Include="..\..\modules\beast_core\beast_core.h">
@@ -767,15 +767,9 @@
<ClInclude Include="..\..\modules\beast_asio\sockets\beast_SocketWrapper.h"> <ClInclude Include="..\..\modules\beast_asio\sockets\beast_SocketWrapper.h">
<Filter>beast_asio\sockets</Filter> <Filter>beast_asio\sockets</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\modules\beast_asio\sockets\beast_SharedSocket.h">
<Filter>beast_asio\sockets</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_asio\sockets\beast_Socket.h"> <ClInclude Include="..\..\modules\beast_asio\sockets\beast_Socket.h">
<Filter>beast_asio\sockets</Filter> <Filter>beast_asio\sockets</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\modules\beast_asio\sockets\beast_SocketInterface.h">
<Filter>beast_asio\sockets</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_asio\system\beast_BoostIncludes.h"> <ClInclude Include="..\..\modules\beast_asio\system\beast_BoostIncludes.h">
<Filter>beast_asio\system</Filter> <Filter>beast_asio\system</Filter>
</ClInclude> </ClInclude>
@@ -815,9 +809,6 @@
<ClInclude Include="..\..\modules\beast_asio\tests\beast_PeerTest.h"> <ClInclude Include="..\..\modules\beast_asio\tests\beast_PeerTest.h">
<Filter>beast_asio\tests</Filter> <Filter>beast_asio\tests</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\modules\beast_asio\protocol\beast_ProxyHandshake.h">
<Filter>beast_asio\protocol</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_asio\tests\beast_TestPeerLogicProxyClient.h"> <ClInclude Include="..\..\modules\beast_asio\tests\beast_TestPeerLogicProxyClient.h">
<Filter>beast_asio\tests</Filter> <Filter>beast_asio\tests</Filter>
</ClInclude> </ClInclude>
@@ -842,15 +833,27 @@
<ClInclude Include="..\..\modules\beast_core\memory\beast_ByteSwap.h"> <ClInclude Include="..\..\modules\beast_core\memory\beast_ByteSwap.h">
<Filter>beast_core\memory</Filter> <Filter>beast_core\memory</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\modules\beast_asio\protocol\beast_HandshakeDetectorType.h"> <ClInclude Include="..\..\modules\beast_asio\streams\beast_PrefilledReadStream.h">
<Filter>beast_asio\protocol</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_asio\protocol\beast_StreamHandshakeDetectorType.h">
<Filter>beast_asio\protocol</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_asio\streams\beast_prefilled_read_stream.h">
<Filter>beast_asio\streams</Filter> <Filter>beast_asio\streams</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\modules\beast_asio\handshake\beast_ProxyHandshake.h">
<Filter>beast_asio\handshake</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_asio\handshake\beast_HandshakeDetectLogic.h">
<Filter>beast_asio\handshake</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_asio\basics\beast_FixedInputBuffer.h">
<Filter>beast_asio\basics</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_asio\handshake\beast_HandshakeDetectLogicSSL2.h">
<Filter>beast_asio\handshake</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_asio\handshake\beast_HandshakeDetectLogicSSL3.h">
<Filter>beast_asio\handshake</Filter>
</ClInclude>
<ClInclude Include="..\..\modules\beast_asio\handshake\beast_HandshakeDetectStream.h">
<Filter>beast_asio\handshake</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\..\modules\beast_core\beast_core.cpp"> <ClCompile Include="..\..\modules\beast_core\beast_core.cpp">
@@ -1303,17 +1306,14 @@
<ClCompile Include="..\..\modules\beast_asio\tests\beast_TestPeerUnitTests.cpp"> <ClCompile Include="..\..\modules\beast_asio\tests\beast_TestPeerUnitTests.cpp">
<Filter>beast_asio\tests</Filter> <Filter>beast_asio\tests</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\modules\beast_asio\protocol\beast_ProxyHandshake.cpp">
<Filter>beast_asio\protocol</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_asio\tests\beast_TestPeerLogicProxyClient.cpp"> <ClCompile Include="..\..\modules\beast_asio\tests\beast_TestPeerLogicProxyClient.cpp">
<Filter>beast_asio\tests</Filter> <Filter>beast_asio\tests</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\modules\beast_asio\basics\beast_PeerRole.cpp"> <ClCompile Include="..\..\modules\beast_asio\basics\beast_PeerRole.cpp">
<Filter>beast_asio\basics</Filter> <Filter>beast_asio\basics</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\modules\beast_asio\protocol\beast_StreamHandshakeDetectorType.cpp"> <ClCompile Include="..\..\modules\beast_asio\handshake\beast_ProxyHandshake.cpp">
<Filter>beast_asio\protocol</Filter> <Filter>beast_asio\handshake</Filter>
</ClCompile> </ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -0,0 +1,112 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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 <int Bytes>
struct FixedInputBuffer
{
template <typename ConstBufferSequence>
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 <uint8 const*> (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 <typename T>
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 <typename T>
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 <typename IntegerType>
bool readNetworkInteger (IntegerType* value)
{
// Must be an integral type!
// not available in all versions of std:: unfortunately
//static_bassert (std::is_integral <IntegerType>::value);
IntegerType networkValue;
if (! read (&networkValue))
return;
*value = fromNetworkByteOrder (networkValue);
return true;
}
private:
boost::array <uint8, Bytes> m_storage;
MutableBuffer m_buffer;
std::size_t m_size;
uint8 const* m_data;
};
#endif

View File

@@ -30,8 +30,7 @@ namespace beast
#include "sockets/beast_Socket.cpp" #include "sockets/beast_Socket.cpp"
#include "sockets/beast_SslContext.cpp" #include "sockets/beast_SslContext.cpp"
#include "protocol/beast_ProxyHandshake.cpp" #include "handshake/beast_ProxyHandshake.cpp"
#include "protocol/beast_StreamHandshakeDetectorType.cpp"
#include "tests/beast_TestPeerBasics.cpp" #include "tests/beast_TestPeerBasics.cpp"
#include "tests/beast_TestPeerLogic.cpp" #include "tests/beast_TestPeerLogic.cpp"

View File

@@ -48,24 +48,25 @@ namespace beast
// Order matters // Order matters
#include "basics/beast_PeerRole.h"
#include "basics/beast_BufferType.h" #include "basics/beast_BufferType.h"
#include "basics/beast_CompletionCall.h" #include "basics/beast_CompletionCall.h"
#include "basics/beast_ErrorCall.h" #include "basics/beast_ErrorCall.h"
#include "basics/beast_FixedInputBuffer.h"
#include "basics/beast_PeerRole.h"
#include "basics/beast_TransferCall.h" #include "basics/beast_TransferCall.h"
#include "sockets/beast_SocketBase.h" #include "sockets/beast_SocketBase.h"
#include "sockets/beast_Socket.h" #include "sockets/beast_Socket.h"
#include "sockets/beast_SocketInterface.h"
#include "sockets/beast_SocketWrapper.h" #include "sockets/beast_SocketWrapper.h"
#include "sockets/beast_SharedSocket.h"
#include "sockets/beast_SslContext.h" #include "sockets/beast_SslContext.h"
#include "protocol/beast_ProxyHandshake.h" #include "handshake/beast_ProxyHandshake.h"
#include "protocol/beast_HandshakeDetectorType.h" #include "handshake/beast_HandshakeDetectLogic.h"
#include "protocol/beast_StreamHandshakeDetectorType.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_TestPeerBasics.h"
#include "tests/beast_TestPeer.h" #include "tests/beast_TestPeer.h"

View File

@@ -0,0 +1,129 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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 <typename Logic>
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 <typename ConstBufferSequence>
bool analyze (ConstBufferSequence const& buffer)
{
bassert (! m_logic.finished ());
m_logic.analyze (buffer);
return m_logic.finished ();
}
private:
Logic m_logic;
};
#endif

View File

@@ -0,0 +1,103 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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 <typename ConstBufferSequence>
void analyze (ConstBufferSequence const& buffer)
{
FixedInputBuffer <bytesNeeded> 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

View File

@@ -0,0 +1,77 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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 <typename ConstBufferSequence>
void analyze (ConstBufferSequence const& buffer)
{
uint16 version;
FixedInputBuffer <bytesNeeded> 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

View File

@@ -0,0 +1,307 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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 Logic>
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 <typename Stream, typename Logic>
class HandshakeDetectStreamType
: public HandshakeDetectStream <Logic>
, public boost::asio::ssl::stream_base
, public boost::asio::socket_base
{
private:
typedef HandshakeDetectStreamType <Stream, Logic> this_type;
typedef boost::asio::streambuf buffer_type;
typedef typename boost::remove_reference <Stream>::type stream_type;
public:
typedef typename HandshakeDetectStream <Logic> CallbackType;
/** This takes ownership of the callback.
The callback must be allocated with operator new.
*/
template <typename Arg>
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 <typename HandshakeHandler>
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 <typename ConstBufferSequence>
error_code handshake (handshake_type type,
const ConstBufferSequence& buffers, error_code& ec)
{
return do_handshake (type, ec, ConstBuffers (buffers));;
}
template <typename ConstBufferSequence, typename BufferedHandshakeHandler>
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 <typename HandshakeDetectStream <Logic>::Callback> m_callback;
Stream m_next_layer;
buffer_type m_buffer;
boost::asio::buffered_read_stream <stream_type&> m_stream;
HandshakeDetectLogicType <Logic> m_logic;
ErrorCall m_origHandler;
TransferCall m_origBufferedHandler;
};
/** @} */
#endif

View File

@@ -1,350 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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 <int Bytes>
struct Input
{
template <typename ConstBufferSequence>
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 <uint8 const*> (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 <typename T>
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 <typename T>
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 <typename IntegerType>
bool readNetworkInteger (IntegerType* value)
{
// Must be an integral type!
// not available in all versions of std:: unfortunately
//static_bassert (std::is_integral <IntegerType>::value);
IntegerType networkValue;
if (! read (&networkValue))
return false;
*value = fromNetworkByteOrder (networkValue);
return true;
}
private:
boost::array <uint8, Bytes> 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 <typename ConstBufferSequence>
void analyze (ConstBufferSequence const& buffer)
{
Input <bytesNeeded> 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 <typename ConstBufferSequence>
void analyze (ConstBufferSequence const& buffer)
{
uint16 version;
Input <bytesNeeded> 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 <typename Logic>
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 <typename ConstBufferSequence>
bool analyze (ConstBufferSequence const& buffer)
{
bassert (! m_logic.finished ());
m_logic.analyze (buffer);
return m_logic.finished ();
}
private:
Logic m_logic;
};
#endif

View File

@@ -1,19 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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.
*/
//==============================================================================

View File

@@ -1,78 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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 Detector>
class StreamHandshakeDetectorType
{
protected:
typedef boost::system::error_code error_code;
typedef StreamHandshakeDetectorType <Detector> This;
public:
typedef typename Detector::arg_type arg_type;
explicit StreamHandshakeDetectorType (arg_type const& arg = arg_type ())
{
}
template <typename HandshakeHandler>
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 <typename HandshakeHandler>, 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 <typename HandshakeHandler>
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

View File

@@ -1,83 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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 <SharedSocket> 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 Object>
class SharedSocketType
: public SharedSocket
, public SocketWrapper <Object>
{
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> (object)
, m_object (object)
{
}
private:
ScopedPointer <Object> m_object;
};
/** @} */
#endif

View File

@@ -1,62 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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

View File

@@ -7,296 +7,6 @@
#ifndef RIPPLE_MULTISOCKETTYPE_H_INCLUDED #ifndef RIPPLE_MULTISOCKETTYPE_H_INCLUDED
#define 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 <typename Stream>
class ssl_detector
: public ssl_detector_base
, public boost::asio::ssl::stream_base
, public boost::asio::socket_base
{
private:
typedef ssl_detector <Stream> this_type;
typedef boost::asio::streambuf buffer_type;
typedef typename boost::remove_reference <Stream>::type stream_type;
public:
/** This takes ownership of the callback.
The callback must be allocated with operator new.
*/
template <typename Arg>
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 <typename HandshakeHandler>
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 <typename ConstBufferSequence>
error_code handshake (handshake_type type,
const ConstBufferSequence& buffers, error_code& ec)
{
return do_handshake (type, ec, ConstBuffers (buffers));;
}
template <typename ConstBufferSequence, typename BufferedHandshakeHandler>
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 <Callback> m_callback;
Stream m_next_layer;
buffer_type m_buffer;
boost::asio::buffered_read_stream <stream_type&> m_stream;
HandshakeDetectorType <SSL3> m_detector;
ErrorCall m_origHandler;
TransferCall m_origBufferedHandler;
};
//------------------------------------------------------------------------------
/** Template for producing instances of MultiSocket /** Template for producing instances of MultiSocket
*/ */
template <class StreamSocket> template <class StreamSocket>
@@ -325,7 +35,7 @@ public:
// These types are used internaly // 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; typedef next_layer_type& ssl_detector_stream_type;
template <class Arg> template <class Arg>
@@ -603,8 +313,8 @@ protected:
Socket* new_detect_ssl_stream () Socket* new_detect_ssl_stream ()
{ {
ssl_detector_callback* callback = new ssl_detector_callback (this); SSL3DetectCallback* callback = new SSL3DetectCallback (this);
typedef ssl_detector <ssl_detector_stream_type> this_type; typedef HandshakeDetectStreamType <ssl_detector_stream_type, HandshakeDetectLogicSSL3> this_type;
return new SocketWrapper <this_type> (callback, m_next_layer); return new SocketWrapper <this_type> (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 <HandshakeDetectLogicSSL3>::Callback
{ {
public: public:
explicit ssl_detector_callback (MultiSocketType <StreamSocket>* owner) typedef HandshakeDetectLogicSSL3 LogicType;
explicit SSL3DetectCallback (MultiSocketType <StreamSocket>* owner)
: m_owner (owner) : m_owner (owner)
{ {
} }
void on_detect (error_code& ec, void on_detect (LogicType& logic, error_code& ec,
ConstBuffers const& buffers, bool is_ssl) 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, void on_async_detect (LogicType& logic, error_code const& ec,
ConstBuffers const& buffers, ErrorCall const& origHandler, ConstBuffers const& buffers, ErrorCall const& origHandler)
bool is_ssl)
{ {
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 #if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE
void on_async_detect (error_code const& ec, void on_async_detect (LogicType& logic, error_code const& ec,
ConstBuffers const& buffers, TransferCall const& origHandler, ConstBuffers const& buffers, TransferCall const& origHandler)
bool is_ssl)
{ {
m_owner->on_async_detect_ssl (ec, buffers, origHandler, is_ssl); m_owner->on_async_detect_ssl (ec, buffers, origHandler, logic.success ());
} }
#endif #endif