Remove unused and obsolete classes and tidy up:

Many classes required to support type-erasure of handlers and boost::asio
types are now obsolete, so these classes and files are removed:
HTTPClientType, FixedInputBuffer, PeerRole, socket_wrapper,
client_session, basic_url, abstract_socket, buffer_sequence, memory_buffer,
enable_wait_for_async, shared_handler, wrap_handler, streambuf,
ContentBodyBuffer, SSLContext, completion-handler based handshake detectors.
These structural changes are made:
* Some missing includes added to headers
* asio module directory flattened
This commit is contained in:
Vinnie Falco
2014-10-25 17:59:04 -07:00
parent 3cd391daa6
commit fefdb32d08
83 changed files with 48 additions and 10042 deletions

View File

@@ -20,6 +20,9 @@
#ifndef BEAST_ASIO_ASYNCOBJECT_H_INCLUDED
#define BEAST_ASIO_ASYNCOBJECT_H_INCLUDED
#include <beast/Atomic.h>
#include <cassert>
namespace beast {
namespace asio {
@@ -34,7 +37,7 @@ public:
~AsyncObject ()
{
// Destroying the object with I/O pending? Not a clean exit!
bassert (m_pending.get() == 0);
assert (m_pending.get() == 0);
}
/** RAII container that maintains the count of pending I/O.

View File

@@ -17,6 +17,8 @@
*/
//==============================================================================
#include <beast/module/asio/HTTPField.h>
namespace beast {
HTTPField::HTTPField ()

View File

@@ -17,6 +17,7 @@
*/
//==============================================================================
#include <beast/module/asio/HTTPHeaders.h>
#include <algorithm>
namespace beast {

View File

@@ -20,7 +20,7 @@
#ifndef BEAST_ASIO_HTTPHEADERS_H_INCLUDED
#define BEAST_ASIO_HTTPHEADERS_H_INCLUDED
#include <beast/module/asio/http/HTTPField.h>
#include <beast/module/asio/HTTPField.h>
#include <beast/module/core/text/StringPairArray.h>
#include <map>

View File

@@ -17,6 +17,8 @@
*/
//==============================================================================
#include <beast/module/asio/HTTPMessage.h>
namespace beast {
HTTPMessage::HTTPMessage (HTTPVersion const& version_,

View File

@@ -20,8 +20,8 @@
#ifndef BEAST_ASIO_HTTPMESSAGE_H_INCLUDED
#define BEAST_ASIO_HTTPMESSAGE_H_INCLUDED
#include <beast/module/asio/http/HTTPHeaders.h>
#include <beast/module/asio/http/HTTPVersion.h>
#include <beast/module/asio/HTTPHeaders.h>
#include <beast/module/asio/HTTPVersion.h>
#include <beast/smart_ptr/SharedObject.h>
#include <beast/net/DynamicBuffer.h>

View File

@@ -17,6 +17,9 @@
*/
//==============================================================================
#include <beast/module/asio/HTTPParser.h>
#include <beast/module/asio/HTTPParserImpl.h>
namespace beast {
HTTPParser::HTTPParser (Type type)

View File

@@ -20,8 +20,8 @@
#ifndef BEAST_ASIO_HTTPPARSER_H_INCLUDED
#define BEAST_ASIO_HTTPPARSER_H_INCLUDED
#include <beast/module/asio/http/HTTPRequest.h>
#include <beast/module/asio/http/HTTPResponse.h>
#include <beast/module/asio/HTTPRequest.h>
#include <beast/module/asio/HTTPResponse.h>
namespace beast {

View File

@@ -20,6 +20,9 @@
#ifndef BEAST_HTTPPARSERIMPL_H_INCLUDED
#define BEAST_HTTPPARSERIMPL_H_INCLUDED
#include <beast/http/impl/joyent_parser.h>
#include <boost/asio/buffer.hpp>
namespace beast {
class HTTPParserImpl

View File

@@ -17,6 +17,8 @@
*/
//==============================================================================
#include <beast/module/asio/HTTPRequest.h>
namespace beast {
HTTPRequest::HTTPRequest (

View File

@@ -20,7 +20,7 @@
#ifndef BEAST_ASIO_HTTPREQUEST_H_INCLUDED
#define BEAST_ASIO_HTTPREQUEST_H_INCLUDED
#include <beast/module/asio/http/HTTPMessage.h>
#include <beast/module/asio/HTTPMessage.h>
namespace beast {

View File

@@ -17,7 +17,7 @@
*/
//==============================================================================
//#include "HTTPRequestParser.h"
#include <beast/module/asio/HTTPRequestParser.h>
namespace beast {

View File

@@ -20,7 +20,7 @@
#ifndef BEAST_HTTP_REQUESTPARSER_H_INCLUDED
#define BEAST_HTTP_REQUESTPARSER_H_INCLUDED
#include <beast/module/asio/http/HTTPParser.h>
#include <beast/module/asio/HTTPParser.h>
namespace beast {

View File

@@ -17,6 +17,8 @@
*/
//==============================================================================
#include <beast/module/asio/HTTPResponse.h>
namespace beast {
HTTPResponse::HTTPResponse (

View File

@@ -20,6 +20,8 @@
#ifndef BEAST_ASIO_HTTPRESPONSE_H_INCLUDED
#define BEAST_ASIO_HTTPRESPONSE_H_INCLUDED
#include <beast/module/asio/HTTPMessage.h>
namespace beast {
class HTTPResponse : public HTTPMessage

View File

@@ -17,7 +17,7 @@
*/
//==============================================================================
//#include "HTTPResponseParser.h"
#include <beast/module/asio/HTTPResponseParser.h>
namespace beast {

View File

@@ -20,7 +20,7 @@
#ifndef BEAST_HTTP_RESPONSEPARSER_H_INCLUDED
#define BEAST_HTTP_RESPONSEPARSER_H_INCLUDED
#include <beast/module/asio/http/HTTPParser.h>
#include <beast/module/asio/HTTPParser.h>
namespace beast {

View File

@@ -1,75 +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_ASIO_MODULE_H_INCLUDED
#define BEAST_ASIO_MODULE_H_INCLUDED
// Must come before boost includes to fix the bost placeholders.
#include <beast/module/core/core.h>
// This module requires boost and possibly OpenSSL
#include <beast/module/asio/system/BoostIncludes.h>
#include <beast/http/URL.h>
#include <beast/asio/IPAddressConversion.h>
// Order matters
#include <beast/module/asio/async/AsyncObject.h>
#include <beast/module/asio/basics/FixedInputBuffer.h>
#include <beast/module/asio/basics/PeerRole.h>
#include <beast/module/asio/basics/SSLContext.h>
#include <beast/module/asio/http/HTTPVersion.h>
#include <beast/module/asio/http/HTTPField.h>
#include <beast/module/asio/http/HTTPHeaders.h>
#include <beast/module/asio/http/HTTPMessage.h>
#include <beast/module/asio/http/HTTPRequest.h>
#include <beast/module/asio/http/HTTPResponse.h>
#include <beast/module/asio/http/HTTPParser.h>
#include <beast/module/asio/http/HTTPRequestParser.h>
#include <beast/module/asio/http/HTTPResponseParser.h>
#include <beast/module/asio/http/HTTPClientType.h>
#include <beast/module/asio/protocol/InputParser.h>
#include <beast/module/asio/protocol/HandshakeDetectLogic.h>
#include <beast/module/asio/protocol/HandshakeDetectLogicPROXY.h>
#include <beast/module/asio/protocol/HandshakeDetectLogicSSL2.h>
#include <beast/module/asio/protocol/HandshakeDetectLogicSSL3.h>
#include <beast/module/asio/protocol/HandshakeDetector.h>
#include <beast/module/asio/protocol/PrefilledReadStream.h>
#include <beast/module/asio/tests/TestPeerBasics.h>
#include <beast/module/asio/tests/TestPeer.h>
#include <beast/module/asio/tests/TestPeerDetails.h>
#include <beast/module/asio/tests/TestPeerLogic.h>
#include <beast/module/asio/tests/TestPeerLogicSyncServer.h>
#include <beast/module/asio/tests/TestPeerLogicSyncClient.h>
#include <beast/module/asio/tests/TestPeerLogicProxyClient.h>
#include <beast/module/asio/tests/TestPeerLogicAsyncServer.h>
#include <beast/module/asio/tests/TestPeerLogicAsyncClient.h>
#include <beast/module/asio/tests/TestPeerType.h>
#include <beast/module/asio/tests/TestPeerDetailsTcp.h>
#include <beast/module/asio/tests/PeerTest.h>
#endif

View File

@@ -21,36 +21,12 @@
#include <BeastConfig.h>
#endif
#include <beast/module/asio/system/OpenSSLIncludes.h>
#include <beast/module/asio/asio.h>
#include <beast/http/impl/joyent_parser.h>
#include <beast/module/asio/basics/PeerRole.cpp>
#include <beast/module/asio/basics/SSLContext.cpp>
#include <beast/module/asio/protocol/HandshakeDetectLogicPROXY.cpp>
#include <beast/module/asio/http/HTTPParserImpl.h>
#include <beast/module/asio/http/HTTPClientType.cpp>
#include <beast/module/asio/http/HTTPField.cpp>
#include <beast/module/asio/http/HTTPHeaders.cpp>
#include <beast/module/asio/http/HTTPMessage.cpp>
#include <beast/module/asio/http/HTTPRequest.cpp>
#include <beast/module/asio/http/HTTPResponse.cpp>
#include <beast/module/asio/http/HTTPVersion.cpp>
#include <beast/module/asio/tests/PeerTest.cpp>
#include <beast/module/asio/tests/TestPeerBasics.cpp>
#include <beast/module/asio/tests/TestPeerLogic.cpp>
#include <beast/module/asio/tests/TestPeerLogicProxyClient.cpp>
#include <beast/module/asio/tests/TestPeerLogicSyncServer.cpp>
#include <beast/module/asio/tests/TestPeerLogicSyncClient.cpp>
#include <beast/module/asio/tests/TestPeerLogicAsyncServer.cpp>
#include <beast/module/asio/tests/TestPeerLogicAsyncClient.cpp>
#include <beast/module/asio/tests/TestPeerUnitTests.cpp>
#include <beast/module/asio/http/HTTPParser.cpp>
#include <beast/module/asio/http/HTTPRequestParser.cpp>
#include <beast/module/asio/http/HTTPResponseParser.cpp>
#include <beast/module/asio/HTTPField.cpp>
#include <beast/module/asio/HTTPHeaders.cpp>
#include <beast/module/asio/HTTPMessage.cpp>
#include <beast/module/asio/HTTPRequest.cpp>
#include <beast/module/asio/HTTPResponse.cpp>
#include <beast/module/asio/HTTPVersion.cpp>
#include <beast/module/asio/HTTPParser.cpp>
#include <beast/module/asio/HTTPRequestParser.cpp>
#include <beast/module/asio/HTTPResponseParser.cpp>

View File

@@ -1,101 +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.
*/
//==============================================================================
ContentBodyBuffer::ContentBodyBuffer (size_type blocksize)
: m_blocksize (blocksize)
, m_size (0)
{
}
ContentBodyBuffer::~ContentBodyBuffer ()
{
for (Handles::iterator iter (m_handles.begin());
iter != m_handles.end(); ++iter)
{
void* const buffer (*iter);
std::free (buffer);
}
}
void ContentBodyBuffer::swapWith (ContentBodyBuffer& other)
{
std::swap (m_blocksize, other.m_blocksize);
std::swap (m_size, other.m_size);
m_handles.swap (other.m_handles);
}
void ContentBodyBuffer::commit (size_type n)
{
m_size += n;
bassert (m_size <= m_handles.size () * m_blocksize);
}
ConstBuffers ContentBodyBuffer::data () const
{
size_type n (m_size);
std::vector <ConstBuffer> v;
v.reserve ((m_size + m_blocksize - 1) / m_blocksize);
for (Handles::const_iterator iter (m_handles.begin());
iter != m_handles.end() && n > 0; ++iter)
{
size_type const amount (std::min (n, m_blocksize));
v.push_back (MutableBuffer (*iter, amount));
n -= amount;
}
return ConstBuffers (v);
}
ContentBodyBuffer::size_type ContentBodyBuffer::size () const
{
return m_size;
}
MutableBuffers ContentBodyBuffer::prepare (size_type n)
{
reserve (n);
std::vector <MutableBuffer> v;
size_type offset (m_size % m_blocksize);
for (Handles::iterator iter = m_handles.begin () + (m_size / m_blocksize);
iter != m_handles.end () && n > 0; ++iter)
{
size_type const amount (std::min (n, m_blocksize - offset));
v.push_back (MutableBuffer (*iter, amount));
n -= amount;
offset = 0;
}
return MutableBuffers (v);
}
void ContentBodyBuffer::reserve (size_type n)
{
size_type count ((m_size + n + m_blocksize - 1) / m_blocksize);
if (count > m_handles.size ())
for (count -= m_handles.size (); count-- > 0;)
m_handles.push_back (std::malloc (m_blocksize));
}
void ContentBodyBuffer::shrink_to_fit ()
{
size_type const count ((m_size + m_blocksize - 1) / m_blocksize);
while (m_handles.size () > count)
{
std::free (m_handles.back ());
m_handles.erase (m_handles.end () - 1);
}
}

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_ASIO_BASICS_CONTENTBODYBUFFER_H_INCLUDED
#define BEAST_ASIO_BASICS_CONTENTBODYBUFFER_H_INCLUDED
/** Dynamic storage optimized for a large Content-Body of unknown size.
This comes at the expense of discontiguous storage of the segments.
We derive from SharedObject to make transfer of ownership inexpensive.
*/
class ContentBodyBuffer
{
public:
enum
{
defaultBlocksize = 32 * 1024
};
typedef std::size_t size_type;
typedef ConstBuffers const_buffers_tyoe;
typedef MutableBuffers mutable_buffers_type;
explicit ContentBodyBuffer (size_type blocksize = defaultBlocksize);
~ContentBodyBuffer ();
/** Swap the contents of this buffer with another.
This is the preferred way to transfer ownership.
*/
void swapWith (ContentBodyBuffer& other);
/** Move bytes from the output to the input sequence.
This will invalidate references to buffers.
*/
void commit (size_type n);
/** Returns a buffer to the input sequence. */
ConstBuffers data () const;
/** Returns the size of the input sequence. */
size_type size () const;
/** Reserve space in the output sequence.
This also returns a buffer suitable for writing.
*/
MutableBuffers prepare (size_type n);
/** Reserve space in the output sequence. */
void reserve (size_type n);
/** Release memory while preserving the input sequence. */
void shrink_to_fit ();
private:
typedef std::vector <void*> Handles;
size_type m_blocksize;
size_type m_size;
Handles m_handles;
};
#endif

View File

@@ -1,202 +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_ASIO_BASICS_FIXEDINPUTBUFFER_H_INCLUDED
#define BEAST_ASIO_BASICS_FIXEDINPUTBUFFER_H_INCLUDED
#include <beast/asio/buffer_sequence.h>
#include <array>
namespace beast {
namespace asio {
/** Represents a small, fixed size buffer.
This provides a convenient interface for doing a bytewise
verification/reject test on a handshake protocol.
*/
/** @{ */
class FixedInputBuffer
{
protected:
struct CtorParams
{
CtorParams (std::uint8_t const* begin_, std::size_t bytes_)
: begin (begin_)
, bytes (bytes_)
{
}
std::uint8_t const* begin;
std::size_t bytes;
};
FixedInputBuffer (CtorParams const& params)
: m_begin (params.begin)
, m_iter (m_begin)
, m_end (m_begin + params.bytes)
{
}
public:
FixedInputBuffer (FixedInputBuffer const& other)
: m_begin (other.m_begin)
, m_iter (other.m_iter)
, m_end (other.m_end)
{
}
FixedInputBuffer& operator= (FixedInputBuffer const& other)
{
m_begin = other.m_begin;
m_iter = other.m_iter;
m_end = other.m_end;
return *this;
}
// Returns the number of bytes consumed
std::size_t used () const noexcept
{
return m_iter - m_begin;
}
// Returns the size of what's remaining
std::size_t size () const noexcept
{
return m_end - m_iter;
}
void const* peek (std::size_t bytes)
{
return peek_impl (bytes, nullptr);
}
template <typename T>
bool peek (T* t) const noexcept
{
return peek_impl (sizeof (T), t) != nullptr;
}
bool consume (std::size_t bytes) noexcept
{
return read_impl (bytes, nullptr) != nullptr;
}
bool read (std::size_t bytes) noexcept
{
return read_impl (bytes, nullptr) != nullptr;
}
template <typename T>
bool read (T* t) noexcept
{
return read_impl (sizeof (T), t) != nullptr;
}
std::uint8_t operator[] (std::size_t index) const noexcept
{
bassert (index >= 0 && index < size ());
return m_iter [index];
}
// 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;
}
protected:
void const* peek_impl (std::size_t bytes, void* buffer) const noexcept
{
if (size () >= bytes)
{
if (buffer != nullptr)
memcpy (buffer, m_iter, bytes);
return m_iter;
}
return nullptr;
}
void const* read_impl (std::size_t bytes, void* buffer) noexcept
{
if (size () >= bytes)
{
if (buffer != nullptr)
memcpy (buffer, m_iter, bytes);
void const* data = m_iter;
m_iter += bytes;
return data;
}
return nullptr;
}
private:
std::uint8_t const* m_begin;
std::uint8_t const* m_iter;
std::uint8_t const* m_end;
};
//------------------------------------------------------------------------------
template <int Bytes>
class FixedInputBufferSize : public FixedInputBuffer
{
protected:
struct SizedCtorParams
{
template <typename ConstBufferSequence, typename Storage>
SizedCtorParams (ConstBufferSequence const& buffers, Storage& storage)
{
boost::asio::mutable_buffer buffer (boost::asio::buffer (storage));
data = boost::asio::buffer_cast <std::uint8_t const*> (buffer);
bytes = boost::asio::buffer_copy (buffer, buffers);
}
operator CtorParams () const noexcept
{
return CtorParams (data, bytes);
}
std::uint8_t const* data;
std::size_t bytes;
};
public:
template <typename ConstBufferSequence>
explicit FixedInputBufferSize (ConstBufferSequence const& buffers)
: FixedInputBuffer (SizedCtorParams (buffers, m_storage))
{
}
private:
std::array <std::uint8_t, Bytes> m_storage;
boost::asio::mutable_buffer m_buffer;
};
}
}
#endif

View File

@@ -1,50 +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.
*/
//==============================================================================
namespace beast {
namespace asio {
PeerRole::PeerRole (role_t role)
: m_role (role)
{
}
String PeerRole::name () const noexcept
{
if (m_role == server)
return "server";
return "client";
}
bool PeerRole::operator== (role_t role) const noexcept
{
return m_role == role;
}
#if 0
PeerRole::operator abstract_socket::handshake_type () const noexcept
{
if (m_role == server)
return abstract_socket::server;
return abstract_socket::client;
}
#endif
}
}

View File

@@ -1,46 +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_ASIO_BASICS_PEERROLE_H_INCLUDED
#define BEAST_ASIO_BASICS_PEERROLE_H_INCLUDED
namespace beast {
namespace asio {
/** Identifies if the peer is a client or a server. */
struct PeerRole
{
enum role_t
{
client,
server
};
PeerRole (role_t role);
String name () const noexcept;
bool operator== (role_t role) const noexcept;
private:
role_t m_role;
};
}
}
#endif

View File

@@ -1,33 +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.
*/
//==============================================================================
namespace beast {
namespace asio {
SSLContext::SSLContext (ContextType& context)
: m_context (context)
{
}
SSLContext::~SSLContext ()
{
}
}
}

View File

@@ -1,72 +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_ASIO_BASICS_SSLCONTEXT_H_INCLUDED
#define BEAST_ASIO_BASICS_SSLCONTEXT_H_INCLUDED
#include <boost/asio/ssl/context.hpp>
namespace beast {
namespace asio {
/** Simple base class for passing a context around.
This lets derived classes hide their implementation from the headers.
*/
class SSLContext
{
public:
virtual ~SSLContext ();
// Saves typing
typedef boost::asio::ssl::context ContextType;
inline ContextType& get () noexcept
{
return m_context;
}
inline ContextType const& get () const noexcept
{
return m_context;
}
// implicit conversion
inline operator ContextType& () noexcept
{
return get ();
}
inline operator ContextType const& () const noexcept
{
return get ();
}
protected:
explicit SSLContext (ContextType& context);
SSLContext(SSLContext const&) = delete;
SSLContext& operator= (SSLContext const&) = delete;
ContextType& m_context;
};
}
}
#endif

View File

@@ -1,693 +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.
*/
//==============================================================================
#include <beast/asio/wrap_handler.h>
#include <beast/asio/placeholders.h>
#include <beast/unit_test/suite.h>
#include <boost/asio/ssl/stream.hpp>
#include <beast/cxx14/memory.h> // <memory>
namespace beast {
namespace asio {
class HTTPClientType : public HTTPClientBase
{
public:
class Session;
struct State
{
List <Session> list;
};
typedef SharedData <State> SharedState;
SharedState m_state;
Journal m_journal;
double m_timeoutSeconds;
std::size_t m_messageLimitBytes;
std::size_t m_bufferSize;
boost::asio::io_service m_io_service;
WaitableEvent m_stopped;
//--------------------------------------------------------------------------
HTTPClientType (
Journal journal,
double timeoutSeconds,
std::size_t messageLimitBytes,
std::size_t bufferSize)
: m_journal (journal)
, m_timeoutSeconds (timeoutSeconds)
, m_messageLimitBytes (messageLimitBytes)
, m_bufferSize (bufferSize)
, m_stopped (true, true) // manual reset, initially signaled
{
}
HTTPClientType(HTTPClientType const&) = delete;
HTTPClientType& operator= (HTTPClientType const&) = delete;
~HTTPClientType ()
{
cancel();
wait();
}
result_type get (URL const& url)
{
result_type result;
boost::asio::io_service io_service;
async_get (io_service, url, std::bind (
&HTTPClientType::handle_get, std::placeholders::_1, &result));
io_service.run ();
return result;
}
void async_get (boost::asio::io_service& io_service, URL const& url,
asio::shared_handler <void (result_type)> handler)
{
new Session (*this, io_service, url,
handler, m_timeoutSeconds, m_messageLimitBytes, m_bufferSize);
}
void cancel ()
{
SharedState::Access state (m_state);
for (List <Session>::iterator iter (state->list.begin());
iter != state->list.end(); ++iter)
iter->cancel();
}
void wait()
{
m_stopped.wait();
}
//--------------------------------------------------------------------------
void add (Session& session)
{
SharedState::Access state (m_state);
if (state->list.empty())
m_stopped.reset();
state->list.push_back (session);
}
void remove (Session& session)
{
SharedState::Access state (m_state);
state->list.erase (state->list.iterator_to (session));
if (state->list.empty())
m_stopped.signal();
}
static void handle_get (result_type const& result, result_type* dest)
{
*dest = result;
}
Journal journal() const
{
return m_journal;
}
boost::asio::io_service& get_io_service()
{
return m_io_service;
}
//--------------------------------------------------------------------------
/** Helper function to get a const_buffer from a String. */
static boost::asio::const_buffers_1 stringBuffer (String const& s)
{
return boost::asio::const_buffers_1 (s.getCharPointer (), s.length ());
}
/** Helper function to fill out a Query from a URL. */
template <typename Query>
static Query queryFromURL (URL const& url)
{
if (url.port () != 0)
{
return Query (
url.host(),
url.port_string(),
Query::numeric_service);
}
return Query (
url.host(),
url.scheme());
}
//--------------------------------------------------------------------------
class Session
: public SharedObject
, public List <Session>::Node
{
public:
typedef SharedPtr <Session> Ptr;
typedef boost::asio::ip::tcp Protocol;
typedef boost::system::error_code error_code;
typedef HTTPClientBase::error_type error_type;
typedef HTTPClientBase::value_type value_type;
typedef HTTPClientBase::result_type result_type;
typedef Protocol::resolver resolver;
typedef Protocol::socket socket;
typedef resolver::query query;
typedef resolver::iterator iterator;
typedef iterator::value_type resolver_entry;
HTTPClientType& m_owner;
boost::asio::io_service& m_io_service;
boost::asio::io_service::strand m_strand;
boost::asio::deadline_timer m_timer;
resolver m_resolver;
socket m_socket;
asio::shared_handler <void (result_type)> m_handler;
URL m_url;
boost::asio::ssl::context m_context;
MemoryBlock m_buffer;
HTTPResponseParser m_parser;
std::size_t m_messageLimitBytes;
std::size_t m_bytesReceived;
String m_get_string;
WaitableEvent m_done;
std::unique_ptr <abstract_socket> m_stream;
struct State
{
State () : complete (false)
{
}
bool complete;
error_code error;
SharedPtr <HTTPResponse> response;
};
typedef SharedData <State> SharedState;
SharedState m_state;
//----------------------------------------------------------------------
Session (HTTPClientType& owner,
boost::asio::io_service& io_service,
URL const& url,
asio::shared_handler <void (result_type)> const& handler,
double timeoutSeconds,
std::size_t messageLimitBytes,
std::size_t bufferSize)
: m_owner (owner)
, m_io_service (io_service)
, m_strand (io_service)
, m_timer (io_service)
, m_resolver (io_service)
, m_socket (io_service)
, m_handler (handler)
, m_url (url)
, m_context (boost::asio::ssl::context::sslv23)
, m_buffer (bufferSize)
, m_messageLimitBytes (messageLimitBytes)
, m_bytesReceived (0)
{
m_owner.add (*this);
// Configure the SSL context for certificate verification
m_context.set_default_verify_paths ();
m_context.set_options (
boost::asio::ssl::context::no_sslv2 |
boost::asio::ssl::context::no_sslv3 |
boost::asio::ssl::context::single_dh_use |
boost::asio::ssl::context::default_workarounds);
//m_context.set_verify_mode (boost::asio::ssl::verify_peer);
// Set the timer if a timeout is requested
if (timeoutSeconds > 0)
{
m_timer.expires_from_now (
boost::posix_time::milliseconds (
long (timeoutSeconds * 1000)));
m_timer.async_wait (m_strand.wrap (asio::wrap_handler (
std::bind (&Session::handle_timer, Ptr(this),
asio::placeholders::error), m_handler)));
}
// Start the operation on an io_service thread
io_service.dispatch (m_strand.wrap (asio::wrap_handler (
std::bind (&Session::handle_start, Ptr(this)), m_handler)));
}
~Session ()
{
State result;
{
SharedState::ConstAccess state (m_state);
result = *state;
}
m_io_service.post (bind_handler (m_handler,
std::make_pair (result.error, result.response)));
m_owner.remove (*this);
}
//----------------------------------------------------------------------
// Called by the owner to cancel pending i/o.
void cancel ()
{
{
SharedState::Access state (m_state);
if (! state->complete)
{
state->complete = true;
state->error = boost::asio::error::operation_aborted;
}
}
cancel_all();
}
// Cancel all pending I/O
void cancel_all ()
{
error_code ec;
m_timer.cancel (ec);
m_resolver.cancel ();
m_socket.cancel (ec);
m_socket.shutdown (socket::shutdown_both, ec);
}
// Called by a completion handler when error is not eof or aborted.
void failed (error_code ec)
{
{
SharedState::Access state (m_state);
if (! state->complete)
{
state->complete = true;
state->error = ec;
state->response = nullptr;
}
}
cancel_all();
}
void async_read_some ()
{
boost::asio::mutable_buffers_1 buf (
m_buffer.getData (), m_buffer.getSize ());
m_stream->async_read_some (buf, m_strand.wrap (
asio::wrap_handler (std::bind (&Session::handle_read,
Ptr(this), asio::placeholders::error,
asio::placeholders::bytes_transferred), m_handler)));
}
//----------------------------------------------------------------------
//
// Completion handlers
//
// Called when the operation starts
void handle_start ()
{
query q (queryFromURL <query> (m_url));
m_resolver.async_resolve (q, m_strand.wrap (
asio::wrap_handler (std::bind (&Session::handle_resolve,
Ptr(this), asio::placeholders::error,
asio::placeholders::iterator), m_handler)));
}
// Called when the timer completes
void handle_timer (error_code ec)
{
if (ec == boost::asio::error::operation_aborted)
return;
if (ec != 0)
{
failed (ec);
return;
}
failed (boost::system::errc::make_error_code (
boost::system::errc::timed_out));
}
// Called when the resolver completes
void handle_resolve (error_code ec, iterator iter)
{
if (ec == boost::asio::error::operation_aborted)
return;
if (ec != 0)
{
failed (ec);
return;
}
resolver_entry const entry (*iter);
m_socket.async_connect (entry.endpoint (), m_strand.wrap (
asio::wrap_handler (std::bind (&Session::handle_connect,
Ptr(this), asio::placeholders::error), m_handler)));
}
// Called when the connection attempt completes
void handle_connect (error_code ec)
{
if (ec == boost::asio::error::operation_aborted)
return;
if (ec != 0)
{
failed (ec);
return;
}
if (m_url.scheme () == "https")
{
typedef boost::asio::ssl::stream <socket&> ssl_stream;
m_stream = std::make_unique <
socket_wrapper <ssl_stream>> (m_socket, m_context);
/*
m_stream->set_verify_mode (
boost::asio::ssl::verify_peer |
boost::asio::ssl::verify_fail_if_no_peer_cert);
*/
m_stream->async_handshake (abstract_socket::client, m_strand.wrap (
asio::wrap_handler (std::bind (&Session::handle_handshake,
Ptr(this), asio::placeholders::error), m_handler)));
return;
}
m_stream = std::make_unique <socket_wrapper <socket&>> (m_socket);
handle_handshake (ec);
}
// Called when the SSL handshake completes
void handle_handshake (error_code ec)
{
if (ec == boost::asio::error::operation_aborted)
return;
if (ec != 0)
{
failed (ec);
return;
}
m_get_string =
"GET " + m_url.path() + " HTTP/1.1\r\n" +
"Host: " + m_url.host() + "\r\n" +
"Accept: */*\r\n" +
"Connection: close\r\n\r\n";
boost::asio::async_write (*m_stream, stringBuffer (
m_get_string), m_strand.wrap (asio::wrap_handler (
std::bind (&Session::handle_write, Ptr(this),
asio::placeholders::error,
asio::placeholders::bytes_transferred), m_handler)));
async_read_some ();
}
// Called when the write operation completes
void handle_write (error_code ec, std::size_t)
{
if (ec == boost::asio::error::operation_aborted)
return;
if (ec != 0)
{
failed (ec);
return;
}
if (! m_stream->needs_handshake ())
m_socket.shutdown (socket::shutdown_send, ec);
}
void handle_read (error_code ec,
std::size_t bytes_transferred)
{
if (ec == boost::asio::error::operation_aborted)
return;
if (ec != 0)
{
failed (ec);
return;
}
m_bytesReceived += bytes_transferred;
if (m_bytesReceived > m_messageLimitBytes)
{
failed (error_code (
boost::system::errc::invalid_argument,
boost::system::system_category ()));
return;
}
std::size_t const bytes_parsed (m_parser.process (
m_buffer.getData (), bytes_transferred));
if (m_parser.error ())
{
failed (error_code (
boost::system::errc::invalid_argument,
boost::system::system_category ()));
return;
}
if (bytes_parsed != bytes_transferred)
{
failed (error_code (
boost::system::errc::invalid_argument,
boost::system::system_category ()));
return;
}
if (ec == boost::asio::error::eof)
m_parser.process_eof ();
if (m_parser.finished ())
{
if (m_stream->needs_handshake ())
{
m_stream->async_shutdown (m_strand.wrap (asio::wrap_handler (
std::bind (&Session::handle_shutdown,
Ptr(this), asio::placeholders::error), m_handler)));
}
else
{
handle_shutdown (error_code ());
}
return;
}
async_read_some ();
}
void handle_shutdown (error_code ec)
{
if (ec == boost::asio::error::operation_aborted)
return;
if (ec == boost::asio::error::eof)
ec = error_code();
if (ec != 0)
{
failed (ec);
return;
}
{
SharedState::Access state (m_state);
if (! state->complete)
{
state->complete = true;
state->response = m_parser.response();
}
}
cancel_all();
}
};
};
//------------------------------------------------------------------------------
HTTPClientBase* HTTPClientBase::New (Journal journal,
double timeoutSeconds, std::size_t messageLimitBytes, std::size_t bufferSize)
{
return new HTTPClientType (
journal, timeoutSeconds, messageLimitBytes, bufferSize);
}
//------------------------------------------------------------------------------
class HTTPClient_test : public unit_test::suite
{
public:
typedef boost::system::error_code error_code;
//--------------------------------------------------------------------------
class IoServiceThread : protected Thread
{
public:
explicit IoServiceThread (String name = "io_service")
: Thread (name)
{
}
~IoServiceThread ()
{
join ();
}
boost::asio::io_service& get_io_service ()
{
return m_service;
}
void start ()
{
startThread ();
}
void join ()
{
this->waitForThreadToExit ();
}
private:
void run ()
{
m_service.run ();
}
private:
boost::asio::io_service m_service;
};
//--------------------------------------------------------------------------
void print (HTTPMessage const& m)
{
for (int i = 0; i < m.headers().size(); ++i)
{
HTTPField const f (m.headers()[i]);
std::stringstream ss;
log <<
"[ '" << f.name() <<
"' , '" << f.value() + "' ]";
}
}
void print (HTTPClientBase::error_type error,
HTTPClientBase::value_type const& response)
{
if (error != 0)
{
log <<
"HTTPClient error: '" + error.message() << "'";
}
else if (! response.empty ())
{
log <<
"Status: " <<
String::fromNumber (response->status()).toStdString();
print (*response);
}
else
{
log <<
"HTTPClient: no response";
}
}
//--------------------------------------------------------------------------
void handle_get (HTTPClientBase::result_type result)
{
print (result.first, result.second);
}
void testSync (String const& s, double timeoutSeconds)
{
std::unique_ptr <HTTPClientBase> client (
HTTPClientBase::New (Journal(), timeoutSeconds));
HTTPClientBase::result_type const& result (
client->get (parse_URL (s.toStdString ()).second));
print (result.first, result.second);
}
void testAsync (String const& s, double timeoutSeconds)
{
IoServiceThread t;
std::unique_ptr <HTTPClientBase> client (
HTTPClientBase::New (Journal(), timeoutSeconds));
client->async_get (t.get_io_service (), parse_URL (s.toStdString ()).second,
std::bind (&HTTPClient_test::handle_get, this,
std::placeholders::_1));
t.start ();
t.join ();
}
//--------------------------------------------------------------------------
void run ()
{
testSync (
"http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference.html",
5);
testAsync (
"http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference.html",
5);
testAsync (
"https://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference.html",
5);
pass ();
}
};
BEAST_DEFINE_TESTSUITE_MANUAL(HTTPClient,beast_asio,beast);
}
}

View File

@@ -1,68 +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_ASIO_HTTPCLIENTTYPE_H_INCLUDED
#define BEAST_ASIO_HTTPCLIENTTYPE_H_INCLUDED
#include <beast/asio/shared_handler.h>
#include <utility>
namespace beast {
namespace asio {
class HTTPClientBase
{
public:
typedef boost::system::error_code error_type;
typedef SharedPtr <HTTPResponse> value_type;
typedef std::pair <error_type, value_type> result_type;
static HTTPClientBase* New (
Journal journal = Journal(),
double timeoutSeconds = 30,
std::size_t messageLimitBytes = 256 * 1024,
std::size_t bufferSize = 16 * 1024);
/** Destroy the client.
This will cancel any pending i/o and block until all completion
handlers have been called.
*/
virtual ~HTTPClientBase () { }
virtual result_type get (URL const& url) = 0;
/** Perform an asynchronous get on the specified URL.
Handler will be called with this signature:
void (result_type)
*/
virtual void async_get (boost::asio::io_service& io_service,
URL const& url, asio::shared_handler <void (result_type)> handler) = 0;
/** Cancel all pending asynchronous operations. */
virtual void cancel() = 0;
/** Block until all asynchronous i/o completes. */
virtual void wait() = 0;
};
}
}
#endif

View File

@@ -1,147 +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_ASIO_HANDSHAKE_HANDSHAKEDETECTLOGIC_H_INCLUDED
#define BEAST_ASIO_HANDSHAKE_HANDSHAKEDETECTLOGIC_H_INCLUDED
namespace beast {
namespace asio {
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;
/** How many bytes the handshake consumes.
If the detector processes the entire handshake this will
be non zero. The SSL detector would return 0, since we
want all the existing bytes to be passed on.
*/
virtual std::size_t bytes_consumed () = 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 ()
{
return m_logic.max_needed ();
}
std::size_t bytes_consumed ()
{
return m_logic.bytes_consumed ();
}
bool finished ()
{
return m_logic.finished ();
}
/** If finished is true, this tells us if the handshake was detected.
*/
bool success ()
{
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,24 +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.
*/
//==============================================================================
namespace beast {
namespace asio {
}
}

View File

@@ -1,168 +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_ASIO_HANDSHAKE_HANDSHAKEDETECTLOGICPROXY_H_INCLUDED
#define BEAST_ASIO_HANDSHAKE_HANDSHAKEDETECTLOGICPROXY_H_INCLUDED
#include <beast/module/asio/protocol/HandshakeDetectLogic.h>
#include <beast/module/asio/protocol/InputParser.h>
namespace beast {
namespace asio {
/** Handshake detector for the PROXY protcol
http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt
*/
class HandshakeDetectLogicPROXY : public HandshakeDetectLogic
{
public:
typedef int arg_type;
enum
{
// This is for version 1. The largest number of bytes
// that we could possibly need to parse a valid handshake.
// We will reject it much sooner if there's an illegal value.
//
maxBytesNeeded = 107 // including CRLF, no null term
};
struct ProxyInfo
{
typedef InputParser::IPv4Address IPv4Address;
String protocol; // "TCP4", "TCP6", "UNKNOWN"
IPv4Address sourceAddress;
IPv4Address destAddress;
std::uint16_t sourcePort;
std::uint16_t destPort;
};
explicit HandshakeDetectLogicPROXY (arg_type const&)
: m_consumed (0)
{
}
ProxyInfo const& getInfo () const noexcept
{
return m_info;
}
std::size_t max_needed ()
{
return maxBytesNeeded;
}
std::size_t bytes_consumed ()
{
return m_consumed;
}
template <typename ConstBufferSequence>
void analyze (ConstBufferSequence const& buffer)
{
FixedInputBufferSize <maxBytesNeeded> in (buffer);
InputParser::State state;
analyze_input (in, state);
if (state.passed ())
{
m_consumed = in.used ();
conclude (true);
}
else if (state.failed ())
{
conclude (false);
}
}
void analyze_input (FixedInputBuffer& in, InputParser::State& state)
{
using namespace InputParser;
if (! match (in, "PROXY ", state))
return;
if (match (in, "TCP4 "))
{
m_info.protocol = "TCP4";
if (! read (in, m_info.sourceAddress, state))
return;
if (! match (in, " ", state))
return;
if (! read (in, m_info.destAddress, state))
return;
if (! match (in, " ", state))
return;
UInt16Str sourcePort;
if (! read (in, sourcePort, state))
return;
m_info.sourcePort = sourcePort.value;
if (! match (in, " ", state))
return;
UInt16Str destPort;
if (! read (in, destPort, state))
return;
m_info.destPort = destPort.value;
if (! match (in, "\r\n", state))
return;
state = State::pass;
return;
}
else if (match (in, "TCP6 "))
{
m_info.protocol = "TCP6";
state = State::fail;
return;
}
else if (match (in, "UNKNOWN "))
{
m_info.protocol = "UNKNOWN";
state = State::fail;
return;
}
state = State::fail;
}
private:
std::size_t m_consumed;
ProxyInfo m_info;
};
}
}
#endif

View File

@@ -1,114 +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_ASIO_HANDSHAKE_HANDSHAKEDETECTLOGICSSL2_H_INCLUDED
#define BEAST_ASIO_HANDSHAKE_HANDSHAKEDETECTLOGICSSL2_H_INCLUDED
namespace beast {
namespace asio {
// Handshake for SSL 2
//
// http://tools.ietf.org/html/rfc5246#appendix-E.2
//
// std::uint8_t V2CipherSpec[3];
// struct {
// std::uint16_t msg_length;
// std::uint8_t msg_type;
// Version version; Should be 'ProtocolVersion'?
// std::uint16_t cipher_spec_length;
// std::uint16_t session_id_length;
// std::uint16_t 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;
}
std::size_t bytes_consumed ()
{
return 0;
}
template <typename ConstBufferSequence>
void analyze (ConstBufferSequence const& buffer)
{
FixedInputBufferSize <bytesNeeded> in (buffer);
{
std::uint8_t 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.
//
std::uint16_t 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 ();
std::uint8_t 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

@@ -1,90 +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_ASIO_HANDSHAKE_HANDSHAKEDETECTLOGICSSL3_H_INCLUDED
#define BEAST_ASIO_HANDSHAKE_HANDSHAKEDETECTLOGICSSL3_H_INCLUDED
#include <beast/ByteOrder.h>
namespace beast {
namespace asio {
// 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;
}
std::size_t bytes_consumed ()
{
return 0;
}
template <typename ConstBufferSequence>
void analyze (ConstBufferSequence const& buffer)
{
std::uint16_t version;
FixedInputBufferSize <bytesNeeded> in (buffer);
std::uint8_t 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);
std::uint16_t length;
if (! in.read (&length))
return;
length = fromNetworkByteOrder (length);
conclude ();
}
};
}
}
#endif

View File

@@ -1,220 +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_ASIO_HANDSHAKE_HANDSHAKEDETECTOR_H_INCLUDED
#define BEAST_ASIO_HANDSHAKE_HANDSHAKEDETECTOR_H_INCLUDED
#include <beast/boost/get_pointer.h>
#include <beast/asio/bind_handler.h>
#include <beast/asio/wrap_handler.h>
#include <beast/asio/placeholders.h>
#include <beast/asio/shared_handler.h>
#include <boost/asio/detail/handler_cont_helpers.hpp>
#include <boost/asio/streambuf.hpp>
namespace beast {
namespace asio {
/** A wrapper to decode the handshake data on a Stream.
Stream must meet these requirements
For detect:
SyncReadStream
For async_detect:
AsyncReadStream
Logic must meet this requirement:
HandshakeDetectLogic
*/
template <typename Stream, typename Logic>
class HandshakeDetectorType
{
protected:
typedef boost::system::error_code error_code;
public:
Logic& getLogic ()
{
return m_logic.get ();
}
//--------------------------------------------------------------------------
/** Synchronous handshake detect.
The bytes from the input sequence in the specified buffer
are used first.
*/
template <typename Allocator>
error_code detect (Stream& stream,
boost::asio::basic_streambuf <Allocator>& buffer)
{
typedef boost::asio::basic_streambuf <Allocator> BuffersType;
error_code ec;
do
{
m_logic.analyze (buffer.data ());
if (m_logic.finished ())
{
// consume what we used (for SSL its 0)
std::size_t const consumed = m_logic.bytes_consumed ();
bassert (consumed <= buffer.size ());
buffer.consume (consumed);
break;
}
std::size_t const available = buffer.size ();
std::size_t const needed = m_logic.max_needed ();
// If postcondition fails, loop will never end
if (meets_postcondition (available < needed))
{
typename BuffersType::mutable_buffers_type buffers (
buffer.prepare (needed - available));
buffer.commit (stream.read_some (buffers, ec));
}
}
while (! ec);
return ec;
}
//--------------------------------------------------------------------------
/** Asynchronous handshake detect.
The bytes from the input sequence in the specified buffer
are used first.
DetectHandler must have this signature:
void(error_code)
*/
template <typename Allocator>
void async_detect (Stream& stream,
boost::asio::basic_streambuf <Allocator>& buffer,
asio::shared_handler <void(error_code)> handler)
{
typedef AsyncOp <Allocator> Op;
auto const op (std::make_shared <Op> (std::ref (m_logic),
std::ref (stream), std::ref (buffer), std::cref (handler)));
//op->start();
stream.get_io_service().post (asio::wrap_handler (std::bind (
&Op::start, op), handler));
}
private:
template <typename Allocator>
class AsyncOp
: public std::enable_shared_from_this <AsyncOp <Allocator>>
{
public:
typedef boost::asio::basic_streambuf <Allocator> BuffersType;
AsyncOp (HandshakeDetectLogicType <Logic>& logic, Stream& stream,
BuffersType& buffer, asio::shared_handler <
void(error_code)> const& handler)
: m_logic (logic)
, m_stream (stream)
, m_buffer (buffer)
, m_handler (handler)
, m_continuation (false)
{
}
// Set breakpoint to prove it gets destroyed
~AsyncOp ()
{
}
void start()
{
async_read_some (error_code(), 0);
}
void on_read (error_code ec, size_t bytes_transferred)
{
m_continuation = true;
async_read_some (ec, bytes_transferred);
}
void async_read_some (error_code ec, size_t bytes_transferred)
{
if (! ec)
{
m_buffer.commit (bytes_transferred);
m_logic.analyze (m_buffer.data ());
if (!m_logic.finished ())
{
std::size_t const available = m_buffer.size ();
std::size_t const needed = m_logic.max_needed ();
// If postcondition fails, loop will never end
if (meets_postcondition (available < needed))
{
typename BuffersType::mutable_buffers_type buffers (
m_buffer.prepare (needed - available));
m_stream.async_read_some (buffers, asio::wrap_handler (
std::bind (&AsyncOp <Allocator>::on_read,
this->shared_from_this(), asio::placeholders::error,
asio::placeholders::bytes_transferred),
m_handler, m_continuation));
}
return;
}
std::size_t const consumed = m_logic.bytes_consumed ();
m_buffer.consume (consumed);
}
// Finalize with a call to the original handler.
if (m_continuation)
{
m_handler (ec);
return;
}
// Post, otherwise we would call the
// handler from the initiating function.
m_stream.get_io_service ().post (asio::bind_handler (
m_handler, ec));
}
private:
HandshakeDetectLogicType <Logic>& m_logic;
Stream& m_stream;
BuffersType& m_buffer;
asio::shared_handler <void(error_code)> m_handler;
bool m_continuation;
};
private:
HandshakeDetectLogicType <Logic> m_logic;
};
}
}
#endif

View File

@@ -1,395 +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_ASIO_HANDSHAKE_INPUTPARSER_H_INCLUDED
#define BEAST_ASIO_HANDSHAKE_INPUTPARSER_H_INCLUDED
#include <beast/module/asio/basics/FixedInputBuffer.h>
#include <beast/strings/String.h>
#include <cctype>
namespace beast {
namespace asio {
namespace InputParser {
/** Tri-valued parsing state.
This is convertible to bool which means continue.
Or you can use stop() to decide if you should return.
After a stop you can use failed () to determine if parsing failed.
*/
struct State
{
enum State_t
{
pass, // passed the parse
fail, // failed the parse
more // didn't fail but need more bytes
};
State () : m_state (more) { }
State (State_t state) : m_state (state) { }
/** Implicit construction from bool.
If condition is true then the parse passes, else need more.
*/
State (bool condition) : m_state (condition ? pass : more) { }
State& operator= (State_t state) { m_state = state; return *this; }
bool eof () const noexcept { return m_state == more; }
bool stop () const noexcept { return m_state != pass; }
bool passed () const noexcept { return m_state == pass; }
bool failed () const noexcept { return m_state == fail; }
explicit operator bool() const noexcept { return m_state == pass; }
private:
State_t m_state;
};
//------------------------------------------------------------------------------
// Shortcut to save typing.
typedef FixedInputBuffer& Input;
/** Specializations implement the get() function. */
template <class T>
struct Get;
/** Specializations implement the match() function.
Default implementation of match tries to read it into a local.
*/
template <class T>
struct Match
{
static State func (Input in, T other)
{
T t;
State state = Get <T>::func (in, t);
if (state.passed ())
{
if (t == other)
return State::pass;
return State::fail;
}
return state;
}
};
/** Specializations implement the peek() function.
Default implementation of peek reads and rewinds.
*/
template <class T>
struct Peek
{
static State func (Input in, T& t)
{
Input dup (in);
return Get <T>::func (dup, t);
}
};
//------------------------------------------------------------------------------
//
// Free Functions
//
//------------------------------------------------------------------------------
// match a block of data in memory
//
static State match_buffer (Input in, void const* buffer, std::size_t bytes)
{
bassert (bytes > 0);
if (in.size () <= 0)
return State::more;
std::size_t const have = std::min (in.size (), bytes);
void const* data = in.peek (have);
bassert (data != nullptr);
int const compare = memcmp (data, buffer, have);
if (compare != 0)
return State::fail;
in.consume (have);
return have == bytes;
}
//------------------------------------------------------------------------------
//
// match
//
// Returns the state
template <class T>
State match (Input in, T t)
{
return Match <T>::func (in, t);
}
// Stores the state in the argument and returns true if its a pass
template <class T>
bool match (Input in, T t, State& state)
{
return (state = match (in, t)).passed ();
}
//------------------------------------------------------------------------------
//
// peek
//
// Returns the state
template <class T>
State peek (Input in, T& t)
{
return Peek <T>::func (in, t);
}
// Stores the state in the argument and returns true if its a pass
template <class T>
bool peek (Input in, T& t, State& state)
{
return (state = peek (in, t)).passed ();
}
//------------------------------------------------------------------------------
//
// read
//
// Returns the state
template <class T>
State read (Input in, T& t)
{
return Get <T>::func (in, t);
}
// Stores the state in the argument and returns true if its a pass
template <class T>
bool read (Input in, T& t, State& state)
{
return (state = read (in, t)).passed ();
}
//------------------------------------------------------------------------------
//
// Specializations for basic types
//
template <>
struct Match <char const*>
{
static State func (Input in, char const* text)
{
return InputParser::match_buffer (in, text, strlen (text));
}
};
//------------------------------------------------------------------------------
//
// Special types and their specializations
//
struct Digit
{
int value;
};
template <>
struct Get <Digit>
{
static State func (Input in, Digit& t)
{
char c;
if (! in.peek (&c))
return State::more;
if (! std::isdigit (c))
return State::fail;
in.consume (1);
t.value = c - '0';
return State::pass;
}
};
//------------------------------------------------------------------------------
// An unsigned 32 bit number expressed as a string
struct UInt32Str
{
std::uint32_t value;
};
template <>
struct Get <UInt32Str>
{
static State func (Input in, UInt32Str& t)
{
State state;
std::uint32_t value (0);
Digit digit;
// have to have at least one digit
if (! read (in, digit, state))
return state;
value = digit.value;
for (;;)
{
state = peek (in, digit);
if (state.failed ())
{
t.value = value;
return State::pass;
}
else if (state.eof ())
{
t.value = value;
return state;
}
// can't have a digit following a zero
if (value == 0)
return State::fail;
std::uint32_t newValue = (value * 10) + digit.value;
// overflow
if (newValue < value)
return State::fail;
value = newValue;
}
return State::fail;
}
};
//------------------------------------------------------------------------------
// An unsigned 16 bit number expressed as a string
struct UInt16Str
{
std::uint16_t value;
};
template <>
struct Get <UInt16Str>
{
static State func (Input in, UInt16Str& t)
{
UInt32Str v;
State state = read (in, v);
if (state.passed ())
{
if (v.value <= 65535)
{
t.value = std::uint16_t(v.value);
return State::pass;
}
return State::fail;
}
return state;
}
};
//------------------------------------------------------------------------------
// An unsigned 8 bit number expressed as a string
struct UInt8Str
{
std::uint8_t value;
};
template <>
struct Get <UInt8Str>
{
static State func (Input in, UInt8Str& t)
{
UInt32Str v;
State state = read (in, v);
if (state.passed ())
{
if (v.value <= 255)
{
t.value = std::uint8_t(v.value);
return State::pass;
}
return State::fail;
}
return state;
}
};
//------------------------------------------------------------------------------
// An dotted IPv4 address
struct IPv4Address
{
std::uint8_t value [4];
String toString () const
{
return String::fromNumber <int> (value [0]) + "." +
String::fromNumber <int> (value [1]) + "." +
String::fromNumber <int> (value [2]) + "." +
String::fromNumber <int> (value [3]);
}
};
template <>
struct Get <IPv4Address>
{
static State func (Input in, IPv4Address& t)
{
State state;
UInt8Str digit [4];
if (! read (in, digit [0], state))
return state;
if (! match (in, ".", state))
return state;
if (! read (in, digit [1], state))
return state;
if (! match (in, ".", state))
return state;
if (! read (in, digit [2], state))
return state;
if (! match (in, ".", state))
return state;
if (! read (in, digit [3], state))
return state;
t.value [0] = digit [0].value;
t.value [1] = digit [1].value;
t.value [2] = digit [2].value;
t.value [3] = digit [3].value;
return State::pass;
}
};
}
}
}
#endif

View File

@@ -1,207 +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_ASIO_HANDSHAKE_PREFILLEDREADSTREAM_H_INCLUDED
#define BEAST_ASIO_HANDSHAKE_PREFILLEDREADSTREAM_H_INCLUDED
#include <beast/cxx14/type_traits.h> // <type_traits>
#include <utility>
namespace beast {
namespace asio {
/** Front-ends a stream with a provided block of data.
When read operations are performed on this object, bytes will first be
returned from the buffer provided on construction. When those bytes
are exhausted, read operations will then pass through to the underlying
stream.
Write operations are all simply passed through.
*/
template <class Stream>
class PrefilledReadStream
{
protected:
typedef boost::system::error_code error_code;
static void throw_if (error_code const& ec)
{
throw boost::system::system_error (ec);
}
public:
PrefilledReadStream (PrefilledReadStream const&) = delete;
PrefilledReadStream& operator= (PrefilledReadStream const&) = delete;
typedef std::remove_reference_t <Stream> next_layer_type;
typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
/** Single argument constructor for when we are wrapped in something.
arg is passed through to the next layer's constructor.
*/
template <class Arg>
explicit PrefilledReadStream (Arg& arg)
: m_next_layer (arg)
{
}
/** Construct with the buffer, and argument passed through.
This creates a copy of the data. The argument is passed through
to the constructor of Stream.
*/
template <class Arg, class ConstBufferSequence>
PrefilledReadStream (Arg& arg, ConstBufferSequence const& buffers)
: m_next_layer (arg)
{
fill (buffers);
}
/** Place some input into the prefilled buffer.
Note that this is in no way thread safe. The only reason this function
is here is for the case when you can't pass the buffer through the
constructor because there is another object wrapping this stream.
*/
template <class ConstBufferSequence>
void fill (ConstBufferSequence const& buffers)
{
// We don't assume the caller's buffers will
// remain valid for the lifetime of this object.
//
m_buffer.commit (boost::asio::buffer_copy (
m_buffer.prepare (boost::asio::buffer_size (buffers)),
buffers));
}
next_layer_type& next_layer()
{
return m_next_layer;
}
next_layer_type const& next_layer() const
{
return m_next_layer;
}
lowest_layer_type& lowest_layer()
{
return m_next_layer.lowest_layer();
}
const lowest_layer_type& lowest_layer() const
{
return m_next_layer.lowest_layer();
}
boost::asio::io_service& get_io_service()
{
return m_next_layer.get_io_service();
}
void close()
{
error_code ec;
close (ec);
throw_if (ec);
}
error_code close (error_code& ec)
{
// VFALCO NOTE This is questionable. We can't
// call m_next_layer.close() because Stream might not
// support that function. For example, ssl::stream has no close()
//
return lowest_layer ().close(ec);
}
template <class MutableBufferSequence>
std::size_t read_some (MutableBufferSequence const& buffers)
{
error_code ec;
std::size_t const amount = read_some (buffers, ec);
throw_if (ec);
return amount;
}
template <class MutableBufferSequence>
std::size_t read_some (MutableBufferSequence const& buffers,
error_code& ec)
{
if (m_buffer.size () > 0)
{
ec = error_code ();
std::size_t const bytes_transferred = boost::asio::buffer_copy (
buffers, m_buffer.data ());
m_buffer.consume (bytes_transferred);
return bytes_transferred;
}
return m_next_layer.read_some (buffers, ec);
}
template <class ConstBufferSequence>
std::size_t write_some (ConstBufferSequence const& buffers)
{
error_code ec;
auto const amount (write_some (buffers, ec));
throw_if (ec);
return amount;
}
template <class ConstBufferSequence>
std::size_t write_some (ConstBufferSequence const& buffers,
error_code& ec)
{
return m_next_layer.write_some (buffers, ec);
}
template <class MutableBufferSequence, class ReadHandler>
void async_read_some (MutableBufferSequence const& buffers,
ReadHandler&& handler)
{
if (m_buffer.size () > 0)
{
auto const bytes_transferred (boost::asio::buffer_copy (
buffers, m_buffer.data ()));
m_buffer.consume (bytes_transferred);
get_io_service ().post (bind_handler (
std::forward <ReadHandler> (handler),
error_code (), bytes_transferred));
return;
}
m_next_layer.async_read_some (buffers,
std::forward <ReadHandler> (handler));
}
template <class ConstBufferSequence, class WriteHandler>
void async_write_some (ConstBufferSequence const& buffers,
WriteHandler&& handler)
{
m_next_layer.async_write_some (buffers,
std::forward <WriteHandler> (handler));
}
private:
Stream m_next_layer;
boost::asio::streambuf m_buffer;
};
}
}
#endif

View File

@@ -1,110 +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.
*/
//==============================================================================
namespace beast {
namespace asio {
PeerTest::Result::Result ()
: m_ec (TestPeerBasics::make_error (TestPeerBasics::errc::skipped))
, m_message (m_ec.message ())
{
}
PeerTest::Result::Result (boost::system::error_code const& ec, String const& prefix)
: m_ec (ec)
, m_message ((prefix == String::empty) ? ec.message ()
: prefix + ": " + ec.message ())
{
}
PeerTest::Result::Result (std::exception const& e, String const& prefix)
: m_ec (TestPeerBasics::make_error (TestPeerBasics::errc::exceptioned))
, m_message ((prefix == String::empty) ? e.what ()
: prefix + ": " + e.what ())
{
}
bool PeerTest::Result::operator== (Result const& other) const noexcept
{
return m_ec == other.m_ec;
}
bool PeerTest::Result::operator!= (Result const& other) const noexcept
{
return m_ec != other.m_ec;
}
bool PeerTest::Result::failed () const noexcept
{
return TestPeerBasics::failure (m_ec);
}
bool PeerTest::Result::timedout () const noexcept
{
return m_ec == TestPeerBasics::make_error (TestPeerBasics::errc::timeout);
}
String PeerTest::Result::message () const noexcept
{
return m_message;
}
bool PeerTest::Result::report (unit_test::suite& suite,
bool reportPassingTests) const
{
bool const success = suite.expect (! failed (),
message ().toStdString());
if (reportPassingTests && success)
suite.log <<
"pass " + message().toStdString();
return success;
}
//------------------------------------------------------------------------------
PeerTest::Results::Results ()
: name ("unknown")
{
}
bool PeerTest::Results::operator== (Results const& other) const noexcept
{
return (client == other.client) && (server == other.server);
}
bool PeerTest::Results::operator!= (Results const& other) const noexcept
{
return (client != other.client) || (server != other.server);
}
bool PeerTest::Results::report (unit_test::suite& suite,
bool beginTestCase) const
{
if (beginTestCase)
suite.testcase << name.toStdString();
bool success = true;
if (! client.report (suite))
success = false;
if (! server.report (suite))
success = false;
return success;
}
}
}

View File

@@ -1,247 +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_ASIO_TESTS_PEERTEST_H_INCLUDED
#define BEAST_ASIO_TESTS_PEERTEST_H_INCLUDED
#include <beast/unit_test/suite.h>
namespace beast {
namespace asio {
/** Performs a test of two peers defined by template parameters. */
class PeerTest
{
public:
enum
{
/** How long to wait before aborting a peer and reporting a timeout.
@note Aborting synchronous logics may cause undefined behavior.
*/
defaultTimeoutSeconds = 30
};
//--------------------------------------------------------------------------
/** Holds the test results for one peer.
*/
class Result
{
public:
/** Default constructor indicates the test was skipped.
*/
Result ();
/** Construct from an error code.
The prefix is prepended to the error message.
*/
explicit Result (boost::system::error_code const& ec, String const& prefix = "");
explicit Result (std::exception const& e, String const& prefix = "");
/** Returns true if the error codes match (message is ignored).
*/
bool operator== (Result const& other) const noexcept;
bool operator!= (Result const& other) const noexcept;
/** Returns true if the peer failed.
*/
bool failed () const noexcept;
/** Convenience for determining if the peer timed out.
*/
bool timedout () const noexcept;
/** Provides a descriptive message.
This is suitable to pass to suite::fail.
*/
String message () const noexcept;
/** Report the result to a testsuite.
A return value of true indicates success.
*/
bool report (unit_test::suite& suite,
bool reportPassingTests = false) const;
private:
boost::system::error_code m_ec;
String m_message;
};
//--------------------------------------------------------------------------
/** Holds the results for both peers in a test.
*/
struct Results
{
String name; // A descriptive name for this test case.
Result client;
Result server;
Results ();
/** Determines if client and server results match. */
bool operator== (Results const& other) const noexcept;
bool operator!= (Results const& other) const noexcept;
/** Report the results to a suite object.
A return value of true indicates success.
@param beginTestCase `true` to call test.beginTestCase for you
*/
bool report (unit_test::suite& suite, bool beginTestCase = true) const;
};
//--------------------------------------------------------------------------
/** Test two peers and return the results.
*/
template <class Details, class ClientLogic, class ServerLogic,
class ClientArg, class ServerArg>
static Results run (ClientArg const& clientArg, ServerArg const& serverArg,
int timeoutSeconds = defaultTimeoutSeconds)
{
Results results;
if (Process::isRunningUnderDebugger ())
timeoutSeconds = -1;
try
{
TestPeerType <ServerLogic, Details> server (serverArg);
results.name = server.name () + Details::getArgName (serverArg);
try
{
TestPeerType <ClientLogic, Details> client (clientArg);
results.name << " / " + client.name () + Details::getArgName (clientArg);
try
{
server.start (timeoutSeconds);
try
{
client.start (timeoutSeconds);
boost::system::error_code const ec = client.join ();
results.client = Result (ec, client.name ());
try
{
boost::system::error_code const ec = server.join ();
results.server = Result (ec, server.name ());
}
catch (std::exception& e)
{
results.server = Result (e, server.name ());
}
catch (...)
{
results.server = Result (TestPeerBasics::make_error (
TestPeerBasics::errc::exceptioned), server.name ());
}
}
catch (std::exception& e)
{
results.server = Result (e, client.name ());
}
catch (...)
{
results.client = Result (TestPeerBasics::make_error (
TestPeerBasics::errc::exceptioned), client.name ());
}
}
catch (std::exception& e)
{
results.server = Result (e, server.name ());
}
catch (...)
{
results.server = Result (TestPeerBasics::make_error (
TestPeerBasics::errc::exceptioned), server.name ());
}
}
catch (std::exception& e)
{
results.server = Result (e, "client");
}
catch (...)
{
results.client = Result (TestPeerBasics::make_error (
TestPeerBasics::errc::exceptioned), "client");
}
}
catch (std::exception& e)
{
results.server = Result (e, "server");
}
catch (...)
{
results.server = Result (TestPeerBasics::make_error (
TestPeerBasics::errc::exceptioned), "server");
}
return results;
}
template <class Details, class ClientLogic, class ServerLogic, class Arg>
static Results run (Arg const& arg, int timeoutSeconds = defaultTimeoutSeconds)
{
return run <Details, ClientLogic, ServerLogic, Arg, Arg> (
arg, arg, timeoutSeconds);
}
//--------------------------------------------------------------------------
template <class Details, class Arg>
static void report_async (unit_test::suite& suite, Arg const& arg,
int timeoutSeconds = defaultTimeoutSeconds,
bool beginTestCase = true)
{
run <Details, TestPeerLogicAsyncClient, TestPeerLogicAsyncServer>
(arg, timeoutSeconds).report (suite, beginTestCase);
}
template <class Details, class Arg>
static
void
report (unit_test::suite& suite, Arg const& arg,
int timeoutSeconds = defaultTimeoutSeconds, bool beginTestCase = true)
{
run <Details, TestPeerLogicSyncClient, TestPeerLogicSyncServer>
(arg, timeoutSeconds).report (suite, beginTestCase);
run <Details, TestPeerLogicAsyncClient, TestPeerLogicSyncServer>
(arg, timeoutSeconds).report (suite, beginTestCase);
run <Details, TestPeerLogicSyncClient, TestPeerLogicAsyncServer>
(arg, timeoutSeconds).report (suite, beginTestCase);
report_async <Details> (suite, arg, timeoutSeconds, beginTestCase);
}
};
}
}
#endif

View File

@@ -1,58 +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_ASIO_TESTS_TESTPEER_H_INCLUDED
#define BEAST_ASIO_TESTS_TESTPEER_H_INCLUDED
namespace beast {
namespace asio {
/** An abstract peer for unit tests. */
class TestPeer : public TestPeerBasics
{
public:
enum
{
// This should be long enough to go about your business.
defaultTimeout = 10
};
virtual ~TestPeer () { }
/** Get the name of this peer. */
virtual String name () const = 0;
/** Start the peer.
If timeoutSeconds is 0 or less, the wait is infinite.
@param timeoutSeconds How long until the peer should be
considered timed out.
*/
virtual void start (int timeoutSeconds = defaultTimeout) = 0;
/** Wait for the peer to finish.
@return Any error code generated during the server operation.
*/
virtual boost::system::error_code join () = 0;
};
}
}
#endif

View File

@@ -1,161 +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.
*/
//==============================================================================
namespace beast {
namespace asio {
TestPeerBasics::Model::Model (model_t model)
: m_model (model)
{
}
String TestPeerBasics::Model::name () const noexcept
{
if (m_model == async)
return "async";
return "sync";
}
bool TestPeerBasics::Model::operator== (model_t model) const noexcept
{
return m_model == model;
}
boost::asio::ssl::stream_base::handshake_type
TestPeerBasics::to_handshake_type (PeerRole const& role)
{
if (role == PeerRole::client)
return boost::asio::ssl::stream_base::client;
return boost::asio::ssl::stream_base::server;
}
//------------------------------------------------------------------------------
boost::system::error_category const& TestPeerBasics::test_category () noexcept
{
struct test_category_type : boost::system::error_category
{
char const* name () const noexcept
{
return "TestPeer";
}
std::string message (int ev) const
{
switch (ev)
{
case errc::none: return "No error";
case errc::timeout: return "The timeout expired before the test could complete";
case errc::unexpected: return "An unexpected test result was encountered";
case errc::exceptioned: return "An unexpected exception was thrown";
case errc::skipped: return "The test was skipped because of previous errors";
default:
break;
};
return "An unknown error";
}
boost::system::error_condition default_error_condition (int ev) const noexcept
{
return boost::system::error_condition (ev, *this);
}
bool equivalent (int ev, boost::system::error_condition const& condition) const noexcept
{
return default_error_condition (ev) == condition;
}
bool equivalent (boost::system::error_code const& code, int ev) const noexcept
{
return *this == code.category() && code.value() == ev;
}
};
static test_category_type category;
return category;
}
boost::system::error_code TestPeerBasics::make_error (errc::errc_t ev) noexcept
{
return boost::system::error_code (ev, test_category ());
}
boost::system::error_code TestPeerBasics::make_error (errc::errc_t ev, boost::system::error_code& ec) noexcept
{
return ec = make_error (ev);
}
bool TestPeerBasics::success (boost::system::error_code const& ec, bool eofIsOkay) noexcept
{
if (eofIsOkay && ec == boost::asio::error::eof)
return true;
if (! ec)
return true;
breakpoint (ec);
return false;
}
bool TestPeerBasics::failure (boost::system::error_code const& ec, bool eofIsOkay) noexcept
{
return ! success (ec, eofIsOkay);
}
bool TestPeerBasics::expected (bool condition, boost::system::error_code& ec) noexcept
{
if (condition)
{
ec = boost::system::error_code ();
}
else
{
make_error (errc::unexpected, ec);
breakpoint (ec);
}
return condition;
}
bool TestPeerBasics::unexpected (bool condition, boost::system::error_code& ec) noexcept
{
return ! expected (condition, ec);
}
bool TestPeerBasics::aborted (boost::system::error_code const& ec) noexcept
{
return ec == boost::asio::error::operation_aborted;
}
//------------------------------------------------------------------------------
void TestPeerBasics::breakpoint (boost::system::error_code const& ec)
{
// Set a breakpoint here to catch a failure
std::string const& message = ec.message ();
char const* const c_str = message.c_str ();
breakpoint (c_str);
}
void TestPeerBasics::breakpoint (char const* const)
{
}
}
}

View File

@@ -1,114 +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_ASIO_TESTS_TESTPEERBASICS_H_INCLUDED
#define BEAST_ASIO_TESTS_TESTPEERBASICS_H_INCLUDED
#include <boost/asio/ssl/stream_base.hpp>
namespace beast {
namespace asio {
/** Common declarations for TestPeer.
@see TestPeer
*/
class TestPeerBasics
{
public:
/** Selects between synchronous or asynchronous networking i/o usage. */
struct Model
{
enum model_t
{
sync,
async
};
Model (model_t model);
String name () const noexcept;
bool operator== (model_t model) const noexcept;
private:
model_t m_model;
};
//--------------------------------------------------------------------------
/** Convert a PeerRole to boost::asio::ssl::stream_base_handshake_type */
static boost::asio::ssl::stream_base::handshake_type to_handshake_type (PeerRole const& role);
//--------------------------------------------------------------------------
// Custom error codes for distinguishing test conditions
struct errc
{
enum errc_t
{
none = 0,
timeout, // The peer join timeout expired
unexpected, // An expected condition was false
exceptioned, // An exception occurred
skipped // Test skipped due to previous errors
};
};
/** Returns the category that represents TestPeer errors.
*/
static boost::system::error_category const& test_category () noexcept;
/** Creates a test error_code from the give code value.
*/
static boost::system::error_code make_error (errc::errc_t ev) noexcept;
/** Sets the passed error_code to a test error and returns it.
*/
static boost::system::error_code make_error (errc::errc_t ev,
boost::system::error_code& ec) noexcept;
/** Returns true if the error code indicates success.
*/
static bool success (boost::system::error_code const& ec, bool eofIsOkay = false) noexcept;
/** Returns false if the error code indicates failure.
*/
static bool failure (boost::system::error_code const& ec, bool eofIsOkay = false) noexcept;
/** Set the error based on a failed condition and return the success.
*/
static bool expected (bool condition, boost::system::error_code& ec) noexcept;
/** Set the error based on a passed condition and return the success.
*/
static bool unexpected (bool condition, boost::system::error_code& ec) noexcept;
/** Returns true if the error condition indicates an aborted I/O. */
static bool aborted (boost::system::error_code const& ec) noexcept;
/** Provides a place to set a breakpoint to catch a failed condition. */
static void breakpoint (boost::system::error_code const& ec);
/** Forces the variable to exist in the debugger. */
static void breakpoint (char const* const message);
};
}
}
#endif

View File

@@ -1,52 +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_ASIO_TESTS_TESTPEERDETAILS_H_INCLUDED
#define BEAST_ASIO_TESTS_TESTPEERDETAILS_H_INCLUDED
#include <beast/asio/abstract_socket.h>
namespace beast {
namespace asio {
/** Base class of all detail objects. */
class TestPeerDetails
{
public:
virtual ~TestPeerDetails () { }
virtual String name () const = 0;
virtual abstract_socket& get_socket () = 0;
virtual abstract_socket& get_acceptor () = 0;
boost::asio::io_service& get_io_service ()
{
return m_io_service;
}
private:
boost::asio::io_service m_io_service;
};
}
}
#endif

View File

@@ -1,115 +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_ASIO_TESTS_TESTPEERDETAILSTCP_H_INCLUDED
#define BEAST_ASIO_TESTS_TESTPEERDETAILSTCP_H_INCLUDED
#include <beast/asio/socket_wrapper.h>
namespace beast {
namespace asio {
/** Some predefined Detail classes for TestPeer */
struct TcpDetails : public TestPeerDetails
{
protected:
typedef boost::asio::ip::tcp protocol_type;
typedef protocol_type::socket socket_type;
typedef protocol_type::acceptor acceptor_type;
typedef protocol_type::endpoint endpoint_type;
typedef protocol_type::resolver resolver_type;
public:
typedef protocol_type arg_type;
typedef socket_type native_socket_type;
typedef acceptor_type native_acceptor_type;
explicit TcpDetails (arg_type protocol)
: m_protocol (protocol)
, m_socket (get_io_service ())
, m_acceptor (get_io_service ())
, m_socket_wrapper (m_socket)
, m_acceptor_wrapper (m_acceptor)
{
}
static String getArgName (arg_type arg)
{
if (arg == protocol_type::v4 ())
return ".tcpv4";
else if (arg == protocol_type::v6 ())
return ".tcpv6";
return ".tcp?";
}
String name () const
{
return getArgName (m_protocol);
}
abstract_socket& get_socket ()
{
return m_socket_wrapper;
}
abstract_socket& get_acceptor ()
{
return m_acceptor_wrapper;
}
socket_type& get_native_socket ()
{
return m_socket;
}
acceptor_type& get_native_acceptor ()
{
return m_acceptor;
}
endpoint_type get_endpoint (PeerRole role)
{
if (m_protocol == protocol_type::v4 ())
{
if (role == PeerRole::server)
return endpoint_type (m_protocol, 1053);
else
return endpoint_type (boost::asio::ip::address_v4::loopback (), 1053);
}
else
{
if (role == PeerRole::server)
return endpoint_type (m_protocol, 1052);
else
return endpoint_type (boost::asio::ip::address_v6 ().from_string ("::1"), 1052);
}
}
protected:
protocol_type m_protocol;
socket_type m_socket;
acceptor_type m_acceptor;
socket_wrapper <socket_type&> m_socket_wrapper;
socket_wrapper <acceptor_type&> m_acceptor_wrapper;
};
}
}
#endif

View File

@@ -1,69 +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.
*/
//==============================================================================
namespace beast {
namespace asio {
TestPeerLogic::TestPeerLogic (abstract_socket& socket)
: m_socket (&socket)
{
}
TestPeerLogic::error_code& TestPeerLogic::error () noexcept
{
return m_ec;
}
TestPeerLogic::error_code const& TestPeerLogic::error () const noexcept
{
return m_ec;
}
TestPeerLogic::error_code const& TestPeerLogic::error (error_code const& ec) noexcept
{
return m_ec = ec;
}
abstract_socket& TestPeerLogic::socket () noexcept
{
return *m_socket;
}
void TestPeerLogic::on_connect ()
{
pure_virtual ();
}
void TestPeerLogic::on_connect_async (error_code const&)
{
pure_virtual ();
}
void TestPeerLogic::finished ()
{
pure_virtual ();
}
void TestPeerLogic::pure_virtual ()
{
fatal_error ("A TestPeerLogic function was called incorrectly");
}
}
}

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_ASIO_TESTS_TESTPEERLOGIC_H_INCLUDED
#define BEAST_ASIO_TESTS_TESTPEERLOGIC_H_INCLUDED
namespace beast {
namespace asio {
/** Interface for implementing the logic part of a peer test. */
class TestPeerLogic : public TestPeerBasics
{
public:
typedef boost::system::error_code error_code;
explicit TestPeerLogic (abstract_socket& socket);
error_code& error () noexcept;
error_code const& error () const noexcept;
error_code const& error (error_code const& ec) noexcept; // assigns to m_ec
abstract_socket& socket () noexcept;
virtual PeerRole get_role () const noexcept = 0;
virtual Model get_model () const noexcept = 0;
virtual void on_connect ();
virtual void on_connect_async (error_code const&);
// asynchronous logic classes
// must call this when they are done
virtual void finished ();
static void pure_virtual ();
private:
error_code m_ec;
abstract_socket* m_socket;
};
}
}
#endif

View File

@@ -1,164 +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.
*/
//==============================================================================
#include <beast/asio/placeholders.h>
namespace beast {
namespace asio {
TestPeerLogicAsyncClient::TestPeerLogicAsyncClient (abstract_socket& socket)
: TestPeerLogic (socket)
{
}
PeerRole TestPeerLogicAsyncClient::get_role () const noexcept
{
return PeerRole::client;
}
TestPeerBasics::Model TestPeerLogicAsyncClient::get_model () const noexcept
{
return Model::async;
}
void TestPeerLogicAsyncClient::on_connect_async (error_code const& ec)
{
if (aborted (ec) || failure (error (ec)))
return finished ();
if (socket ().needs_handshake ())
{
socket ().async_handshake (abstract_socket::client,
std::bind (&TestPeerLogicAsyncClient::on_handshake, this,
beast::asio::placeholders::error));
}
else
{
on_handshake (ec);
}
}
void TestPeerLogicAsyncClient::on_handshake (error_code const& ec)
{
if (aborted (ec) || failure (error (ec)))
return finished ();
boost::asio::async_write (socket (), boost::asio::buffer ("hello", 5),
std::bind (&TestPeerLogicAsyncClient::on_write, this,
beast::asio::placeholders::error,
beast::asio::placeholders::bytes_transferred));
}
void TestPeerLogicAsyncClient::on_write (error_code const& ec, std::size_t bytes_transferred)
{
if (aborted (ec) || failure (error (ec)))
return finished ();
if (unexpected (bytes_transferred == 5, error ()))
return finished ();
boost::asio::async_read_until (socket (), m_buf, std::string ("goodbye"),
std::bind (&TestPeerLogicAsyncClient::on_read, this,
beast::asio::placeholders::error, beast::asio::placeholders::bytes_transferred));
}
void TestPeerLogicAsyncClient::on_read (error_code const& ec, std::size_t bytes_transferred)
{
if (aborted (ec) || failure (error (ec)))
return finished ();
if (unexpected (bytes_transferred == 7, error ()))
return finished ();
// should check the data here?
m_buf.consume (bytes_transferred);
// Fire up a 1 byte read, to wait for the server to
// shut down its end of the connection.
boost::asio::async_read (socket (), m_buf.prepare (1),
std::bind (&TestPeerLogicAsyncClient::on_read_final, this,
beast::asio::placeholders::error, beast::asio::placeholders::bytes_transferred));
}
void TestPeerLogicAsyncClient::on_read_final (error_code const& ec, std::size_t)
{
if (aborted (ec))
return finished ();
// An eof is the normal case. The server should have closed shop.
//
if (ec == boost::asio::error::eof)
{
if (socket ().needs_handshake ())
{
socket ().async_shutdown (std::bind (&TestPeerLogicAsyncClient::on_shutdown, this,
beast::asio::placeholders::error));
}
else
{
// on_shutdown will call finished ()
error_code ec;
on_shutdown (socket ().shutdown (abstract_socket::shutdown_send, ec));
}
}
else
{
// If we don't get eof, then there should be some other
// error in there. We don't expect the server to send more bytes!
//
// This statement will do the following:
//
// error (ec) save ec into our error state
// success () return true if ec represents success
// unexpected () changes error() to 'unexpected' result if
// success() returned true
//
unexpected (success (error (ec)), error ());
return finished ();
}
}
void TestPeerLogicAsyncClient::on_shutdown (error_code const& ec)
{
if (! aborted (ec))
{
if (success (error (ec), true))
{
if (socket ().needs_handshake ())
{
socket ().shutdown (abstract_socket::shutdown_send, error ());
}
if (! error ())
{
if (success (socket ().close (error ())))
{
// doing nothing here is intended,
// as the calls to success() may set error()
}
}
}
}
finished ();
}
}
}

View File

@@ -1,45 +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_ASIO_TESTS_TESTPEERLOGICASYNCCLIENT_H_INCLUDED
#define BEAST_ASIO_TESTS_TESTPEERLOGICASYNCCLIENT_H_INCLUDED
namespace beast {
namespace asio {
class TestPeerLogicAsyncClient : public TestPeerLogic
{
public:
explicit TestPeerLogicAsyncClient (abstract_socket& socket);
PeerRole get_role () const noexcept;
Model get_model () const noexcept;
void on_connect_async (error_code const& ec);
void on_handshake (error_code const& ec);
void on_write (error_code const& ec, std::size_t bytes_transferred);
void on_read (error_code const& ec, std::size_t bytes_transferred);
void on_read_final (error_code const& ec, std::size_t);
void on_shutdown (error_code const& ec);
private:
boost::asio::streambuf m_buf;
};
}
}
#endif

View File

@@ -1,126 +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.
*/
//==============================================================================
#include <beast/asio/placeholders.h>
namespace beast {
namespace asio {
TestPeerLogicAsyncServer::TestPeerLogicAsyncServer (abstract_socket& socket)
: TestPeerLogic (socket)
{
}
PeerRole TestPeerLogicAsyncServer::get_role () const noexcept
{
return PeerRole::server;
}
TestPeerBasics::Model TestPeerLogicAsyncServer::get_model () const noexcept
{
return Model::async;
}
void TestPeerLogicAsyncServer::on_connect_async (error_code const& ec)
{
if (aborted (ec) || failure (error (ec)))
return finished ();
if (socket ().needs_handshake ())
{
socket ().async_handshake (abstract_socket::server,
std::bind (&TestPeerLogicAsyncServer::on_handshake, this,
beast::asio::placeholders::error));
}
else
{
on_handshake (ec);
}
}
void TestPeerLogicAsyncServer::on_handshake (error_code const& ec)
{
if (aborted (ec) || failure (error (ec)))
return finished ();
boost::asio::async_read_until (socket (), m_buf, std::string ("hello"),
std::bind (&TestPeerLogicAsyncServer::on_read, this,
beast::asio::placeholders::error, beast::asio::placeholders::bytes_transferred));
}
void TestPeerLogicAsyncServer::on_read (error_code const& ec, std::size_t bytes_transferred)
{
if (aborted (ec) || failure (error (ec)))
return finished ();
if (unexpected (bytes_transferred == 5, error ()))
return finished ();
boost::asio::async_write (socket (), boost::asio::buffer ("goodbye", 7),
std::bind (&TestPeerLogicAsyncServer::on_write, this,
beast::asio::placeholders::error, beast::asio::placeholders::bytes_transferred));
}
void TestPeerLogicAsyncServer::on_write (error_code const& ec, std::size_t bytes_transferred)
{
if (aborted (ec) || failure (error (ec)))
return finished ();
if (unexpected (bytes_transferred == 7, error ()))
return finished ();
if (socket ().needs_handshake ())
{
socket ().async_shutdown (std::bind (&TestPeerLogicAsyncServer::on_shutdown, this,
beast::asio::placeholders::error));
}
else
{
// on_shutdown will call finished ()
// we need another instance of ec so we can call on_shutdown()
error_code ec;
on_shutdown (socket ().shutdown (abstract_socket::shutdown_receive, ec));
}
}
void TestPeerLogicAsyncServer::on_shutdown (error_code const& ec)
{
if (! aborted (ec))
{
if (success (error (ec), true))
{
if (socket ().needs_handshake ())
{
socket ().shutdown (abstract_socket::shutdown_receive, error ());
}
if (success (socket ().close (error ())))
{
// doing nothing here is intended,
// as the calls to success() may set error()
}
}
}
finished ();
}
}
}

View File

@@ -1,44 +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_ASIO_TESTS_TESTPEERLOGICASYNCSERVER_H_INCLUDED
#define BEAST_ASIO_TESTS_TESTPEERLOGICASYNCSERVER_H_INCLUDED
namespace beast {
namespace asio {
class TestPeerLogicAsyncServer : public TestPeerLogic
{
public:
explicit TestPeerLogicAsyncServer (abstract_socket& socket);
PeerRole get_role () const noexcept;
Model get_model () const noexcept;
void on_connect_async (error_code const& ec);
void on_handshake (error_code const& ec);
void on_read (error_code const& ec, std::size_t bytes_transferred);
void on_write (error_code const& ec, std::size_t bytes_transferred);
void on_shutdown (error_code const& ec);
private:
boost::asio::streambuf m_buf;
};
}
}
#endif

View File

@@ -1,42 +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.
*/
//==============================================================================
namespace beast {
namespace asio {
TestPeerLogicProxyClient::TestPeerLogicProxyClient (abstract_socket& socket)
: TestPeerLogicSyncClient (socket)
{
}
void TestPeerLogicProxyClient::on_pre_handshake ()
{
//ProxyHandshakeParser h;
static std::string line (
"PROXY TCP4 255.255.255.255 255.255.255.255 65535 65535\r\n"
// 56 chars
);
boost::asio::write (socket (), boost::asio::buffer (line), error ());
}
}
}

View File

@@ -1,37 +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_ASIO_TESTS_TESTPEERLOGICPROXYCLIENT_H_INCLUDED
#define BEAST_ASIO_TESTS_TESTPEERLOGICPROXYCLIENT_H_INCLUDED
namespace beast {
namespace asio {
/** A synchronous client logic that sends a PROXY protocol pre-handshake. */
class TestPeerLogicProxyClient : public TestPeerLogicSyncClient
{
public:
explicit TestPeerLogicProxyClient (abstract_socket& socket);
void on_pre_handshake ();
};
}
}
#endif

View File

@@ -1,115 +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.
*/
//==============================================================================
namespace beast {
namespace asio {
TestPeerLogicSyncClient::TestPeerLogicSyncClient (abstract_socket& socket)
: TestPeerLogic (socket)
{
}
PeerRole TestPeerLogicSyncClient::get_role () const noexcept
{
return PeerRole::client;
}
TestPeerBasics::Model TestPeerLogicSyncClient::get_model () const noexcept
{
return Model::sync;
}
void TestPeerLogicSyncClient::on_connect ()
{
{
// pre-handshake hook is optional
on_pre_handshake ();
if (failure (error ()))
return ;
}
if (socket ().needs_handshake ())
{
if (failure (socket ().handshake (to_handshake_type (get_role ()), error ())))
return;
}
{
std::size_t const amount = boost::asio::write (
socket (), boost::asio::buffer ("hello", 5), error ());
if (failure (error ()))
return;
if (unexpected (amount == 5, error ()))
return;
}
{
char data [7];
size_t const amount = boost::asio::read (
socket (), boost::asio::buffer (data, 7), error ());
if (failure (error ()))
return;
if (unexpected (amount == 7, error ()))
return;
if (unexpected (memcmp (&data, "goodbye", 7) == 0, error ()))
return;
}
// Wait for 1 byte which should never come. Instead,
// the server should close its end and we will get eof
{
char data [1];
boost::asio::read (socket (), boost::asio::buffer (data, 1), error ());
if (error () == boost::asio::error::eof)
{
error () = error_code ();
}
else if (unexpected (failure (error ()), error ()))
{
return;
}
}
if (socket ().needs_handshake ())
{
if (failure (socket ().shutdown (error ()), true))
return;
error () = error_code ();
}
if (failure (socket ().shutdown (abstract_socket::shutdown_send, error ())))
return;
if (failure (socket ().close (error ())))
return;
}
void TestPeerLogicSyncClient::on_pre_handshake ()
{
}
}
}

View File

@@ -1,39 +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_ASIO_TESTS_TESTPEERLOGICSYNCCLIENT_H_INCLUDED
#define BEAST_ASIO_TESTS_TESTPEERLOGICSYNCCLIENT_H_INCLUDED
namespace beast {
namespace asio {
class TestPeerLogicSyncClient : public TestPeerLogic
{
public:
explicit TestPeerLogicSyncClient (abstract_socket& socket);
PeerRole get_role () const noexcept;
Model get_model () const noexcept;
void on_connect ();
virtual void on_pre_handshake ();
};
}
}
#endif

View File

@@ -1,86 +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.
*/
//==============================================================================
namespace beast {
namespace asio {
TestPeerLogicSyncServer::TestPeerLogicSyncServer (abstract_socket& socket)
: TestPeerLogic (socket)
{
}
PeerRole TestPeerLogicSyncServer::get_role () const noexcept
{
return PeerRole::server;
}
TestPeerBasics::Model TestPeerLogicSyncServer::get_model () const noexcept
{
return Model::sync;
}
void TestPeerLogicSyncServer::on_connect ()
{
if (socket ().needs_handshake ())
{
if (failure (socket ().handshake (to_handshake_type (get_role ()), error ())))
return;
}
{
boost::asio::streambuf buf (5);
std::size_t const amount = boost::asio::read_until (
socket (), buf, "hello", error ());
if (failure (error ()))
return;
if (unexpected (amount == 5, error ()))
return;
if (unexpected (buf.size () == 5, error ()))
return;
}
{
std::size_t const amount = boost::asio::write (
socket (), boost::asio::buffer ("goodbye", 7), error ());
if (failure (error ()))
return;
if (unexpected (amount == 7, error ()))
return;
}
if (socket ().needs_handshake ())
{
if (failure (socket ().shutdown (error ()), true))
return;
}
if (failure (socket ().shutdown (abstract_socket::shutdown_send, error ())))
return;
if (failure (socket ().close (error ())))
return;
}
}
}

View File

@@ -1,38 +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_ASIO_TESTS_TESTPEERLOGICSYNCSERVER_H_INCLUDED
#define BEAST_ASIO_TESTS_TESTPEERLOGICSYNCSERVER_H_INCLUDED
namespace beast {
namespace asio {
class TestPeerLogicSyncServer : public TestPeerLogic
{
public:
explicit TestPeerLogicSyncServer (abstract_socket& socket);
PeerRole get_role () const noexcept;
Model get_model () const noexcept;
void on_connect ();
};
}
}
#endif

View File

@@ -1,404 +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_ASIO_TESTS_TESTPEERTYPE_H_INCLUDED
#define BEAST_ASIO_TESTS_TESTPEERTYPE_H_INCLUDED
#include <beast/asio/placeholders.h>
namespace beast {
namespace asio {
template <typename Logic, typename Details>
class TestPeerType
: public Details
, public Logic
, public TestPeer
, public Thread
{
protected:
// TestPeerDetails
using Details::get_socket;
using Details::get_acceptor;
using Details::get_io_service;
// Details
typedef typename Details::protocol_type protocol_type;
typedef typename Details::socket_type socket_type;
typedef typename Details::acceptor_type acceptor_type;
typedef typename Details::endpoint_type endpoint_type;
typedef typename Details::resolver_type resolver_type;
using Details::get_native_socket;
using Details::get_native_acceptor;
using Details::get_endpoint;
// TestPeerLogic
typedef typename Logic::error_code error_code;
using Logic::error;
using Logic::socket;
using Logic::get_role;
using Logic::get_model;
using Logic::on_connect;
using Logic::on_connect_async;
using Logic::pure_virtual;
typedef TestPeerType <Logic, Details> This;
public:
// Details
typedef typename Details::arg_type arg_type;
typedef typename Details::native_socket_type native_socket_type;
typedef typename Details::native_acceptor_type native_acceptor_type;
TestPeerType (arg_type const& arg)
: Details (arg)
, Logic (get_socket ())
, Thread (name ())
, m_timer (get_io_service ())
, m_timer_set (false)
, m_timed_out (false)
{
}
~TestPeerType ()
{
}
String name () const
{
return get_model ().name () + "_" + get_role ().name ();
}
bool is_async () const noexcept
{
return get_model () == Model::async;
}
void start (int timeoutSeconds)
{
if (is_async ())
{
if (timeoutSeconds > 0)
{
m_timer.expires_from_now (
boost::posix_time::seconds (timeoutSeconds));
m_timer.async_wait (std::bind (&This::on_deadline,
this, beast::asio::placeholders::error));
m_timer_set = true;
}
else
{
// Don't set the timer, so infinite wait.
}
}
else
{
// Save the value for when join() is called later.
//
m_timeoutSeconds = timeoutSeconds;
}
startThread ();
// For server roles block until the thread is litening.
//
if (get_role () == PeerRole::server)
m_listening.wait ();
}
error_code join ()
{
if (is_async ())
{
// If the timer expired, then all our i/o should be
// aborted and the thread will exit. So we will wait
// for the thread for an infinite amount of time to
// prevent undefined behavior. If an asynchronous logic
// fails to end when the deadline timer expires, it
// means there's a bug in the logic code.
//
m_join.wait ();
// The wait was satisfied but now the thread is still on
// it's way out of the thread function, so block until
// we know its done.
//
stopThread ();
// If we timed out then always report the custom error
if (m_timed_out)
return error (make_error (errc::timeout));
}
else
{
if (m_timeoutSeconds > 0)
{
// Wait for the thread to finish
//
if (! m_join.wait (m_timeoutSeconds * 1000))
{
// Uh oh, we timed out! This is bad.
// The synchronous model requires that the thread
// be forcibly killed, which can result in undefined
// behavior. It's best not to perform tests with
// synchronous Logic objects that are supposed to time out.
// Force the thread to be killed, without waiting.
stopThread (0);
error () = make_error (errc::timeout);
}
else
{
stopThread ();
}
}
else
{
// They requested an infinite wait.
//
m_join.wait ();
stopThread ();
}
}
return error ();
}
//--------------------------------------------------------------------------
void run ()
{
if (is_async ())
{
if (get_role () == PeerRole::server)
{
run_async_server ();
}
else if (get_role () == PeerRole::client)
{
run_async_client ();
}
else
{
error () = make_error (errc::unexpected);
}
}
else if (get_model () == Model::sync)
{
if (get_role () == PeerRole::server)
{
run_sync_server ();
}
else if (get_role () == PeerRole::client)
{
run_sync_client ();
}
else
{
error () = make_error (errc::unexpected);
}
}
else
{
error () = make_error (errc::unexpected);
}
get_io_service ().run ();
}
//--------------------------------------------------------------------------
void run_sync_server ()
{
do_listen ();
if (failure (error ()))
return finished ();
if (failure (get_acceptor ().accept (get_socket (), error ())))
return finished ();
if (failure (get_acceptor ().close (error ())))
return finished ();
this->on_connect ();
finished ();
}
//--------------------------------------------------------------------------
void on_accept (error_code const& ec)
{
if (failure (ec))
return finished ();
// Close the acceptor down so we don't block the io_service forever
//
// VFALCO NOTE what difference between cancel and close?
#if 0
if (failure (get_acceptor ().close (error ())))
return finished ();
#endif
this->on_connect_async (ec);
}
void run_async_server ()
{
do_listen ();
if (failure (error ()))
return finished ();
get_acceptor ().async_accept (get_socket (), std::bind (
&This::on_accept, this, beast::asio::placeholders::error));
}
//--------------------------------------------------------------------------
void run_sync_client ()
{
if (failure (get_native_socket ().connect (get_endpoint (get_role ()), error ())))
return finished ();
this->on_connect ();
finished ();
}
void run_async_client ()
{
get_native_socket ().async_connect (get_endpoint (get_role ()),
std::bind (&Logic::on_connect_async, this,
beast::asio::placeholders::error));
}
//--------------------------------------------------------------------------
void do_listen ()
{
if (failure (get_native_acceptor ().open (
get_endpoint (get_role ()).protocol (), error ())))
return;
// VFALCO TODO Figure out how to not hard code boost::asio::socket_base
if (failure (get_native_acceptor ().set_option (
boost::asio::socket_base::reuse_address (true), error ())))
return;
if (failure (get_native_acceptor ().bind (get_endpoint (get_role ()), error ())))
return;
// VFALCO TODO Figure out how to not hard code boost::asio::socket_base
if (failure (get_native_acceptor ().listen (
boost::asio::socket_base::max_connections, error ())))
return;
m_listening.signal ();
}
void on_deadline (error_code const& ec)
{
m_timer_set = false;
if (ec != boost::asio::error::operation_aborted)
{
// We expect that ec represents no error, since the
// timer expired and the operation wasn't aborted.
//
// If by some chance there is an error in ec we will
// report that as an unexpected test condition instead
// of a timeout.
//
if (expected (! ec, error ()))
m_timed_out = true;
}
else
{
// The timer was canceled because the Logic
// called finished(), so we do nothing here.
}
finished ();
}
void finished ()
{
// If the server errors out it will come through
// here so signal the listening event and unblock
// the main thread.
//
if (get_role () == PeerRole::server)
m_listening.signal ();
if (m_timer_set)
{
error_code ec;
std::size_t const amount = m_timer.cancel (ec);
// The Logic should not have any I/O pending when
// it calls finished, so amount should be zero.
//
unexpected (amount == 0, ec);
}
// The logic should close the socket at the end of
// its operations, unless it encounters an error.
// Therefore, we will clean everything up and squelch
// any errors, so that io_service::run() will return.
//
{
error_code ec;
this->get_socket ().close (ec);
}
// The acceptor will not have closed if the client
// never established the connection, so do it here.
{
error_code ec;
this->get_acceptor ().close (ec);
}
// Wake up the thread blocked on join()
m_join.signal ();
}
private:
WaitableEvent m_listening;
WaitableEvent m_join;
// for async peers
boost::asio::deadline_timer m_timer;
bool m_timer_set;
bool m_timed_out;
// for sync peers
int m_timeoutSeconds;
};
}
}
#endif

View File

@@ -1,54 +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.
*/
//==============================================================================
#include <beast/unit_test/suite.h>
namespace beast {
namespace asio {
/** Test suite for the TestPeer family of objects. */
class TestPeer_test : public unit_test::suite
{
public:
template <typename Details, typename Arg >
void testDetails (Arg const& arg = Arg ())
{
PeerTest::report <Details> (*this, arg, timeoutSeconds);
}
void run ()
{
typedef boost::asio::ip::tcp protocol;
testDetails <TcpDetails, TcpDetails::arg_type> (protocol::v4 ());
testDetails <TcpDetails, TcpDetails::arg_type> (protocol::v6 ());
}
//--------------------------------------------------------------------------
enum
{
timeoutSeconds = 10
};
};
BEAST_DEFINE_TESTSUITE(TestPeer,beast_asio,beast);
}
}