mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
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:
@@ -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.
|
||||
@@ -17,6 +17,8 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <beast/module/asio/HTTPField.h>
|
||||
|
||||
namespace beast {
|
||||
|
||||
HTTPField::HTTPField ()
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <beast/module/asio/HTTPHeaders.h>
|
||||
#include <algorithm>
|
||||
|
||||
namespace beast {
|
||||
@@ -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>
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <beast/module/asio/HTTPMessage.h>
|
||||
|
||||
namespace beast {
|
||||
|
||||
HTTPMessage::HTTPMessage (HTTPVersion const& version_,
|
||||
@@ -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>
|
||||
@@ -17,6 +17,9 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <beast/module/asio/HTTPParser.h>
|
||||
#include <beast/module/asio/HTTPParserImpl.h>
|
||||
|
||||
namespace beast {
|
||||
|
||||
HTTPParser::HTTPParser (Type type)
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
@@ -17,6 +17,8 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <beast/module/asio/HTTPRequest.h>
|
||||
|
||||
namespace beast {
|
||||
|
||||
HTTPRequest::HTTPRequest (
|
||||
@@ -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 {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
//#include "HTTPRequestParser.h"
|
||||
#include <beast/module/asio/HTTPRequestParser.h>
|
||||
|
||||
namespace beast {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <beast/module/asio/HTTPResponse.h>
|
||||
|
||||
namespace beast {
|
||||
|
||||
HTTPResponse::HTTPResponse (
|
||||
@@ -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
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
//#include "HTTPResponseParser.h"
|
||||
#include <beast/module/asio/HTTPResponseParser.h>
|
||||
|
||||
namespace beast {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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 ()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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 ();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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 ();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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 ());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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 ()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user