mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Enable asynchronous handling of HTTP-RPC (RIPD-390)
* Activate async code path * Tidy up HTTP server code * Use shared_ptr in HTTP server * Remove check for unspecified IP * Remove hairtrigger * Fix missing HTTP authorization check * Fix multisocket flags in RPC-HTTP server * Fix authorization failure when no credentials required * Addresses RIPD-159, RIPD-161, RIPD-390
This commit is contained in:
@@ -1898,18 +1898,18 @@
|
|||||||
<ClCompile Include="..\..\src\ripple\common\tests\cross_offer.test.cpp">
|
<ClCompile Include="..\..\src\ripple\common\tests\cross_offer.test.cpp">
|
||||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClInclude Include="..\..\src\ripple\http\api\Handler.h">
|
<ClInclude Include="..\..\src\ripple\http\Server.h">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ripple\http\api\Port.h">
|
<ClInclude Include="..\..\src\ripple\http\Session.h">
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\src\ripple\http\api\ScopedStream.h">
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\src\ripple\http\api\Server.h">
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\src\ripple\http\api\Session.h">
|
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ripple\http\impl\Door.cpp">
|
||||||
|
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
<ClInclude Include="..\..\src\ripple\http\impl\Door.h">
|
<ClInclude Include="..\..\src\ripple\http\impl\Door.h">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ripple\http\impl\Peer.cpp">
|
||||||
|
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
<ClInclude Include="..\..\src\ripple\http\impl\Peer.h">
|
<ClInclude Include="..\..\src\ripple\http\impl\Peer.h">
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ripple\http\impl\Port.cpp">
|
<ClCompile Include="..\..\src\ripple\http\impl\Port.cpp">
|
||||||
@@ -3448,8 +3448,6 @@
|
|||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClCompile Include="..\..\src\ripple\unity\http.cpp">
|
<ClCompile Include="..\..\src\ripple\unity\http.cpp">
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClInclude Include="..\..\src\ripple\unity\http.h">
|
|
||||||
</ClInclude>
|
|
||||||
<ClCompile Include="..\..\src\ripple\unity\hyperleveldb.cpp">
|
<ClCompile Include="..\..\src\ripple\unity\hyperleveldb.cpp">
|
||||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='debug|x64'">..\..\src\hyperleveldb;..\..\src\snappy\config;..\..\src\snappy\snappy;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='debug|x64'">..\..\src\hyperleveldb;..\..\src\snappy\config;..\..\src\snappy\snappy;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='release|x64'">..\..\src\hyperleveldb;..\..\src\snappy\config;..\..\src\snappy\snappy;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='release|x64'">..\..\src\hyperleveldb;..\..\src\snappy\config;..\..\src\snappy\snappy;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
|||||||
@@ -334,9 +334,6 @@
|
|||||||
<Filter Include="ripple\http">
|
<Filter Include="ripple\http">
|
||||||
<UniqueIdentifier>{8601C61D-413C-725E-C9E6-BD4F97E40032}</UniqueIdentifier>
|
<UniqueIdentifier>{8601C61D-413C-725E-C9E6-BD4F97E40032}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter Include="ripple\http\api">
|
|
||||||
<UniqueIdentifier>{F98B3E94-4FB9-98FF-C625-533A969D1210}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="ripple\http\impl">
|
<Filter Include="ripple\http\impl">
|
||||||
<UniqueIdentifier>{43D68742-4714-D103-EE00-EB10BD045FB6}</UniqueIdentifier>
|
<UniqueIdentifier>{43D68742-4714-D103-EE00-EB10BD045FB6}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
@@ -2856,24 +2853,21 @@
|
|||||||
<ClCompile Include="..\..\src\ripple\common\tests\cross_offer.test.cpp">
|
<ClCompile Include="..\..\src\ripple\common\tests\cross_offer.test.cpp">
|
||||||
<Filter>ripple\common\tests</Filter>
|
<Filter>ripple\common\tests</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClInclude Include="..\..\src\ripple\http\api\Handler.h">
|
<ClInclude Include="..\..\src\ripple\http\Server.h">
|
||||||
<Filter>ripple\http\api</Filter>
|
<Filter>ripple\http</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\src\ripple\http\api\Port.h">
|
<ClInclude Include="..\..\src\ripple\http\Session.h">
|
||||||
<Filter>ripple\http\api</Filter>
|
<Filter>ripple\http</Filter>
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\src\ripple\http\api\ScopedStream.h">
|
|
||||||
<Filter>ripple\http\api</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\src\ripple\http\api\Server.h">
|
|
||||||
<Filter>ripple\http\api</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\src\ripple\http\api\Session.h">
|
|
||||||
<Filter>ripple\http\api</Filter>
|
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ripple\http\impl\Door.cpp">
|
||||||
|
<Filter>ripple\http\impl</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClInclude Include="..\..\src\ripple\http\impl\Door.h">
|
<ClInclude Include="..\..\src\ripple\http\impl\Door.h">
|
||||||
<Filter>ripple\http\impl</Filter>
|
<Filter>ripple\http\impl</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\..\src\ripple\http\impl\Peer.cpp">
|
||||||
|
<Filter>ripple\http\impl</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClInclude Include="..\..\src\ripple\http\impl\Peer.h">
|
<ClInclude Include="..\..\src\ripple\http\impl\Peer.h">
|
||||||
<Filter>ripple\http\impl</Filter>
|
<Filter>ripple\http\impl</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -4740,9 +4734,6 @@
|
|||||||
<ClCompile Include="..\..\src\ripple\unity\http.cpp">
|
<ClCompile Include="..\..\src\ripple\unity\http.cpp">
|
||||||
<Filter>ripple\unity</Filter>
|
<Filter>ripple\unity</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClInclude Include="..\..\src\ripple\unity\http.h">
|
|
||||||
<Filter>ripple\unity</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClCompile Include="..\..\src\ripple\unity\hyperleveldb.cpp">
|
<ClCompile Include="..\..\src\ripple\unity\hyperleveldb.cpp">
|
||||||
<Filter>ripple\unity</Filter>
|
<Filter>ripple\unity</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|||||||
@@ -227,4 +227,10 @@
|
|||||||
#define RIPPLE_STRUCTURED_OVERLAY 0
|
#define RIPPLE_STRUCTURED_OVERLAY 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/** Config: RIPPLE_ASYNC_RPC_HANDLER
|
||||||
|
*/
|
||||||
|
#ifndef RIPPLE_ASYNC_RPC_HANDLER
|
||||||
|
#define RIPPLE_ASYNC_RPC_HANDLER 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -96,15 +96,6 @@ public:
|
|||||||
private:
|
private:
|
||||||
int m_flags;
|
int m_flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Flags
|
|
||||||
{
|
|
||||||
none = 0,
|
|
||||||
client_ssl = 1,
|
|
||||||
server_ssl = 2,
|
|
||||||
server_ssl_required = 4,
|
|
||||||
server_proxy = 8
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef beast::asio::HandshakeDetectLogicPROXY::ProxyInfo ProxyInfo;
|
typedef beast::asio::HandshakeDetectLogicPROXY::ProxyInfo ProxyInfo;
|
||||||
|
|
||||||
|
|||||||
@@ -20,13 +20,80 @@
|
|||||||
#ifndef RIPPLE_HTTP_SERVER_H_INCLUDED
|
#ifndef RIPPLE_HTTP_SERVER_H_INCLUDED
|
||||||
#define RIPPLE_HTTP_SERVER_H_INCLUDED
|
#define RIPPLE_HTTP_SERVER_H_INCLUDED
|
||||||
|
|
||||||
|
#include <beast/net/IPEndpoint.h>
|
||||||
|
#include <beast/module/asio/basics/SSLContext.h>
|
||||||
|
#include <beast/utility/Journal.h>
|
||||||
|
#include <cstdint>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
namespace HTTP {
|
namespace HTTP {
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** Configuration information for a server listening port. */
|
||||||
|
struct Port
|
||||||
|
{
|
||||||
|
enum Security
|
||||||
|
{
|
||||||
|
no_ssl,
|
||||||
|
allow_ssl,
|
||||||
|
require_ssl
|
||||||
|
};
|
||||||
|
|
||||||
|
Security security;
|
||||||
|
std::uint16_t port;
|
||||||
|
beast::IP::Endpoint addr;
|
||||||
|
beast::asio::SSLContext* context;
|
||||||
|
|
||||||
|
Port ();
|
||||||
|
Port (Port const& other);
|
||||||
|
Port& operator= (Port const& other);
|
||||||
|
Port (std::uint16_t port_, beast::IP::Endpoint const& addr_,
|
||||||
|
Security security_, beast::asio::SSLContext* context_);
|
||||||
|
};
|
||||||
|
|
||||||
|
bool operator== (Port const& lhs, Port const& rhs);
|
||||||
|
bool operator< (Port const& lhs, Port const& rhs);
|
||||||
|
|
||||||
|
/** A set of listening ports settings. */
|
||||||
|
typedef std::vector <Port> Ports;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class Server;
|
||||||
|
class Session;
|
||||||
|
|
||||||
|
/** Processes all sessions.
|
||||||
|
Thread safety:
|
||||||
|
Must be safe to call concurrently from any number of foreign threads.
|
||||||
|
*/
|
||||||
|
struct Handler
|
||||||
|
{
|
||||||
|
/** Called when the connection is accepted and we know remoteAddress. */
|
||||||
|
virtual void onAccept (Session& session) = 0;
|
||||||
|
|
||||||
|
/** Called repeatedly as new HTTP headers are received.
|
||||||
|
Guaranteed to be called at least once.
|
||||||
|
*/
|
||||||
|
virtual void onHeaders (Session& session) = 0;
|
||||||
|
|
||||||
|
/** Called when we have the full Content-Body. */
|
||||||
|
virtual void onRequest (Session& session) = 0;
|
||||||
|
|
||||||
|
/** Called when the session ends.
|
||||||
|
Guaranteed to be called once.
|
||||||
|
@param errorCode Non zero for a failed connection.
|
||||||
|
*/
|
||||||
|
virtual void onClose (Session& session, int errorCode) = 0;
|
||||||
|
|
||||||
|
/** Called when the server has finished its stop. */
|
||||||
|
virtual void onStopped (Server& server) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
class ServerImpl;
|
class ServerImpl;
|
||||||
|
|
||||||
/** Multi-threaded, asynchronous HTTP server. */
|
/** Multi-threaded, asynchronous HTTP server. */
|
||||||
@@ -39,17 +106,19 @@ public:
|
|||||||
/** Destroy the server.
|
/** Destroy the server.
|
||||||
This blocks until the server stops.
|
This blocks until the server stops.
|
||||||
*/
|
*/
|
||||||
virtual ~Server ();
|
virtual
|
||||||
|
~Server ();
|
||||||
/** Returns the Journal associated with the server. */
|
/** Returns the Journal associated with the server. */
|
||||||
beast::Journal const& journal () const;
|
beast::Journal
|
||||||
|
journal () const;
|
||||||
|
|
||||||
/** Returns the listening ports settings.
|
/** Returns the listening ports settings.
|
||||||
Thread safety:
|
Thread safety:
|
||||||
Safe to call from any thread.
|
Safe to call from any thread.
|
||||||
Cannot be called concurrently with setPorts.
|
Cannot be called concurrently with setPorts.
|
||||||
*/
|
*/
|
||||||
Ports const& getPorts () const;
|
Ports const&
|
||||||
|
getPorts () const;
|
||||||
|
|
||||||
/** Set the listening ports settings.
|
/** Set the listening ports settings.
|
||||||
These take effect immediately. Any current ports that are not in the
|
These take effect immediately. Any current ports that are not in the
|
||||||
@@ -57,13 +126,15 @@ public:
|
|||||||
Thread safety:
|
Thread safety:
|
||||||
Cannot be called concurrently.
|
Cannot be called concurrently.
|
||||||
*/
|
*/
|
||||||
void setPorts (Ports const& ports);
|
void
|
||||||
|
setPorts (Ports const& ports);
|
||||||
|
|
||||||
/** Notify the server to stop, without blocking.
|
/** Notify the server to stop, without blocking.
|
||||||
Thread safety:
|
Thread safety:
|
||||||
Safe to call concurrently from any thread.
|
Safe to call concurrently from any thread.
|
||||||
*/
|
*/
|
||||||
void stopAsync ();
|
void
|
||||||
|
stopAsync ();
|
||||||
|
|
||||||
/** Notify the server to stop, and block until the stop is complete.
|
/** Notify the server to stop, and block until the stop is complete.
|
||||||
The handler's onStopped method will be called when the stop completes.
|
The handler's onStopped method will be called when the stop completes.
|
||||||
@@ -71,13 +142,14 @@ public:
|
|||||||
Cannot be called concurrently.
|
Cannot be called concurrently.
|
||||||
Cannot be called from the thread of execution of any Handler functions.
|
Cannot be called from the thread of execution of any Handler functions.
|
||||||
*/
|
*/
|
||||||
void stop ();
|
void
|
||||||
|
stop ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr <ServerImpl> m_impl;
|
std::unique_ptr <ServerImpl> m_impl;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace HTTP
|
} // HTTP
|
||||||
} // namespace ripple
|
} // ripple
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -24,13 +24,52 @@
|
|||||||
#include <beast/net/IPEndpoint.h>
|
#include <beast/net/IPEndpoint.h>
|
||||||
#include <beast/utility/Journal.h>
|
#include <beast/utility/Journal.h>
|
||||||
#include <beast/module/asio/http/HTTPRequest.h>
|
#include <beast/module/asio/http/HTTPRequest.h>
|
||||||
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
namespace HTTP {
|
namespace HTTP {
|
||||||
|
|
||||||
|
class Session;
|
||||||
|
|
||||||
|
/** Scoped ostream-based RAII container for building the HTTP response. */
|
||||||
|
// VFALCO TODO Use abstract_ostream
|
||||||
|
class ScopedStream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ScopedStream (Session& session);
|
||||||
|
ScopedStream (ScopedStream const& other);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
ScopedStream (Session& session, T const& t)
|
||||||
|
: m_session (session)
|
||||||
|
{
|
||||||
|
m_ostream << t;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopedStream (Session& session, std::ostream& manip (std::ostream&));
|
||||||
|
|
||||||
|
~ScopedStream ();
|
||||||
|
|
||||||
|
std::ostringstream& ostream () const;
|
||||||
|
|
||||||
|
std::ostream& operator<< (std::ostream& manip (std::ostream&)) const;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::ostream& operator<< (T const& t) const
|
||||||
|
{
|
||||||
|
return m_ostream << t;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ScopedStream& operator= (ScopedStream const&); // disallowed
|
||||||
|
|
||||||
|
Session& m_session;
|
||||||
|
std::ostringstream mutable m_ostream;
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
/** Persistent state information for a connection session.
|
/** Persistent state information for a connection session.
|
||||||
These values are preserved between calls for efficiency.
|
These values are preserved between calls for efficiency.
|
||||||
Some fields are input parameters, some are output parameters,
|
Some fields are input parameters, some are output parameters,
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of rippled: https://github.com/ripple/rippled
|
|
||||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
|
||||||
|
|
||||||
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 RIPPLE_HTTP_HANDLER_H_INCLUDED
|
|
||||||
#define RIPPLE_HTTP_HANDLER_H_INCLUDED
|
|
||||||
|
|
||||||
namespace ripple {
|
|
||||||
|
|
||||||
namespace HTTP {
|
|
||||||
|
|
||||||
class Server;
|
|
||||||
class Session;
|
|
||||||
|
|
||||||
/** Processes all sessions.
|
|
||||||
Thread safety:
|
|
||||||
Must be safe to call concurrently from any number of foreign threads.
|
|
||||||
*/
|
|
||||||
struct Handler
|
|
||||||
{
|
|
||||||
/** Called when the connection is accepted and we know remoteAddress. */
|
|
||||||
virtual void onAccept (Session& session) = 0;
|
|
||||||
|
|
||||||
/** Called repeatedly as new HTTP headers are received.
|
|
||||||
Guaranteed to be called at least once.
|
|
||||||
*/
|
|
||||||
virtual void onHeaders (Session& session) = 0;
|
|
||||||
|
|
||||||
/** Called when we have the full Content-Body. */
|
|
||||||
virtual void onRequest (Session& session) = 0;
|
|
||||||
|
|
||||||
/** Called when the session ends.
|
|
||||||
Guaranteed to be called once.
|
|
||||||
@param errorCode Non zero for a failed connection.
|
|
||||||
*/
|
|
||||||
virtual void onClose (Session& session, int errorCode) = 0;
|
|
||||||
|
|
||||||
/** Called when the server has finished its stop. */
|
|
||||||
virtual void onStopped (Server& server) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace HTTP
|
|
||||||
} // namespace ripple
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of rippled: https://github.com/ripple/rippled
|
|
||||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
|
||||||
|
|
||||||
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 RIPPLE_HTTP_PORT_H_INCLUDED
|
|
||||||
#define RIPPLE_HTTP_PORT_H_INCLUDED
|
|
||||||
|
|
||||||
#include <beast/net/IPEndpoint.h>
|
|
||||||
#include <beast/module/asio/basics/SSLContext.h>
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace ripple {
|
|
||||||
|
|
||||||
namespace HTTP {
|
|
||||||
|
|
||||||
/** Configuration information for a server listening port. */
|
|
||||||
struct Port
|
|
||||||
{
|
|
||||||
enum Security
|
|
||||||
{
|
|
||||||
no_ssl,
|
|
||||||
allow_ssl,
|
|
||||||
require_ssl
|
|
||||||
};
|
|
||||||
|
|
||||||
Port ();
|
|
||||||
Port (Port const& other);
|
|
||||||
Port& operator= (Port const& other);
|
|
||||||
Port (std::uint16_t port_, beast::IP::Endpoint const& addr_,
|
|
||||||
Security security_, beast::asio::SSLContext* context_);
|
|
||||||
|
|
||||||
std::uint16_t port;
|
|
||||||
beast::IP::Endpoint addr;
|
|
||||||
Security security;
|
|
||||||
beast::asio::SSLContext* context;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool operator== (Port const& lhs, Port const& rhs);
|
|
||||||
bool operator!= (Port const& lhs, Port const& rhs);
|
|
||||||
bool operator< (Port const& lhs, Port const& rhs);
|
|
||||||
bool operator<= (Port const& lhs, Port const& rhs);
|
|
||||||
bool operator> (Port const& lhs, Port const& rhs);
|
|
||||||
bool operator>= (Port const& lhs, Port const& rhs);
|
|
||||||
|
|
||||||
/** A set of listening ports settings. */
|
|
||||||
typedef std::vector <Port> Ports;
|
|
||||||
|
|
||||||
} // namespace HTTP
|
|
||||||
} // namespace ripple
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of rippled: https://github.com/ripple/rippled
|
|
||||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
|
||||||
|
|
||||||
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 RIPPLE_HTTP_SCOPEDSTREAM_H_INCLUDED
|
|
||||||
#define RIPPLE_HTTP_SCOPEDSTREAM_H_INCLUDED
|
|
||||||
|
|
||||||
#include <ostream>
|
|
||||||
|
|
||||||
namespace ripple {
|
|
||||||
|
|
||||||
namespace HTTP {
|
|
||||||
|
|
||||||
class Session;
|
|
||||||
|
|
||||||
/** Scoped ostream-based RAII container for building the HTTP response. */
|
|
||||||
class ScopedStream
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit ScopedStream (Session& session);
|
|
||||||
ScopedStream (ScopedStream const& other);
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
ScopedStream (Session& session, T const& t)
|
|
||||||
: m_session (session)
|
|
||||||
{
|
|
||||||
m_ostream << t;
|
|
||||||
}
|
|
||||||
|
|
||||||
ScopedStream (Session& session, std::ostream& manip (std::ostream&));
|
|
||||||
|
|
||||||
~ScopedStream ();
|
|
||||||
|
|
||||||
std::ostringstream& ostream () const;
|
|
||||||
|
|
||||||
std::ostream& operator<< (std::ostream& manip (std::ostream&)) const;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
std::ostream& operator<< (T const& t) const
|
|
||||||
{
|
|
||||||
return m_ostream << t;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
ScopedStream& operator= (ScopedStream const&); // disallowed
|
|
||||||
|
|
||||||
Session& m_session;
|
|
||||||
std::ostringstream mutable m_ostream;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace HTTP
|
|
||||||
} // namespace ripple
|
|
||||||
|
|
||||||
#endif
|
|
||||||
108
src/ripple/http/impl/Door.cpp
Normal file
108
src/ripple/http/impl/Door.cpp
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of rippled: https://github.com/ripple/rippled
|
||||||
|
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||||
|
|
||||||
|
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 <ripple/http/impl/Door.h>
|
||||||
|
#include <ripple/http/impl/Peer.h>
|
||||||
|
#include <beast/asio/placeholders.h>
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
namespace HTTP {
|
||||||
|
|
||||||
|
Door::Door (ServerImpl& impl, Port const& port)
|
||||||
|
: impl_ (impl)
|
||||||
|
, acceptor_ (impl_.get_io_service(), to_asio (port))
|
||||||
|
, port_ (port)
|
||||||
|
{
|
||||||
|
impl_.add (*this);
|
||||||
|
|
||||||
|
error_code ec;
|
||||||
|
|
||||||
|
acceptor_.set_option (acceptor::reuse_address (true), ec);
|
||||||
|
if (ec)
|
||||||
|
{
|
||||||
|
impl_.journal().error <<
|
||||||
|
"Error setting acceptor socket option: " << ec.message();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! ec)
|
||||||
|
{
|
||||||
|
impl_.journal().info << "Bound to endpoint " <<
|
||||||
|
to_string (acceptor_.local_endpoint());
|
||||||
|
|
||||||
|
async_accept();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
impl_.journal().error << "Error binding to endpoint " <<
|
||||||
|
to_string (acceptor_.local_endpoint()) <<
|
||||||
|
", '" << ec.message() << "'";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Door::~Door ()
|
||||||
|
{
|
||||||
|
impl_.remove (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Port const&
|
||||||
|
Door::port () const
|
||||||
|
{
|
||||||
|
return port_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Door::cancel ()
|
||||||
|
{
|
||||||
|
acceptor_.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Door::failed (error_code ec)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Door::async_accept ()
|
||||||
|
{
|
||||||
|
auto const peer (std::make_shared <Peer> (impl_, port_));
|
||||||
|
acceptor_.async_accept (peer->get_socket(), std::bind (
|
||||||
|
&Door::handle_accept, Ptr(this),
|
||||||
|
beast::asio::placeholders::error, peer));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Door::handle_accept (error_code ec,
|
||||||
|
std::shared_ptr <Peer> const& peer)
|
||||||
|
{
|
||||||
|
if (ec == boost::asio::error::operation_aborted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ec)
|
||||||
|
{
|
||||||
|
impl_.journal().error << "Accept failed: " << ec.message();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
async_accept();
|
||||||
|
|
||||||
|
peer->accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,6 +20,8 @@
|
|||||||
#ifndef RIPPLE_HTTP_DOOR_H_INCLUDED
|
#ifndef RIPPLE_HTTP_DOOR_H_INCLUDED
|
||||||
#define RIPPLE_HTTP_DOOR_H_INCLUDED
|
#define RIPPLE_HTTP_DOOR_H_INCLUDED
|
||||||
|
|
||||||
|
#include <ripple/http/impl/ServerImpl.h>
|
||||||
|
#include <ripple/http/impl/Types.h>
|
||||||
#include <beast/asio/placeholders.h>
|
#include <beast/asio/placeholders.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
@@ -28,95 +30,37 @@ namespace HTTP {
|
|||||||
/** A listening socket. */
|
/** A listening socket. */
|
||||||
class Door
|
class Door
|
||||||
: public beast::SharedObject
|
: public beast::SharedObject
|
||||||
, public beast::asio::AsyncObject <Door>
|
|
||||||
, public beast::List <Door>::Node
|
, public beast::List <Door>::Node
|
||||||
, public beast::LeakChecked <Door>
|
, public beast::LeakChecked <Door>
|
||||||
{
|
{
|
||||||
public:
|
private:
|
||||||
|
// VFALCO TODO Use shared_ptr
|
||||||
typedef beast::SharedPtr <Door> Ptr;
|
typedef beast::SharedPtr <Door> Ptr;
|
||||||
|
|
||||||
ServerImpl& m_impl;
|
ServerImpl& impl_;
|
||||||
acceptor m_acceptor;
|
acceptor acceptor_;
|
||||||
Port m_port;
|
Port port_;
|
||||||
|
|
||||||
Door (ServerImpl& impl, Port const& port)
|
public:
|
||||||
: m_impl (impl)
|
Door (ServerImpl& impl, Port const& port);
|
||||||
, m_acceptor (m_impl.get_io_service(), to_asio (port))
|
|
||||||
, m_port (port)
|
|
||||||
{
|
|
||||||
m_impl.add (*this);
|
|
||||||
|
|
||||||
error_code ec;
|
~Door ();
|
||||||
|
|
||||||
m_acceptor.set_option (acceptor::reuse_address (true), ec);
|
Port const&
|
||||||
if (ec)
|
port () const;
|
||||||
{
|
|
||||||
m_impl.journal().error <<
|
|
||||||
"Error setting acceptor socket option: " << ec.message();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! ec)
|
void
|
||||||
{
|
cancel ();
|
||||||
m_impl.journal().info << "Bound to endpoint " <<
|
|
||||||
to_string (m_acceptor.local_endpoint());
|
|
||||||
|
|
||||||
async_accept();
|
void
|
||||||
}
|
failed (error_code ec);
|
||||||
else
|
|
||||||
{
|
|
||||||
m_impl.journal().error << "Error binding to endpoint " <<
|
|
||||||
to_string (m_acceptor.local_endpoint()) <<
|
|
||||||
", '" << ec.message() << "'";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~Door ()
|
void
|
||||||
{
|
async_accept ();
|
||||||
m_impl.remove (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
Port const& port () const
|
void
|
||||||
{
|
handle_accept (error_code ec,
|
||||||
return m_port;
|
std::shared_ptr <Peer> const& peer);
|
||||||
}
|
|
||||||
|
|
||||||
void cancel ()
|
|
||||||
{
|
|
||||||
m_acceptor.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
void failed (error_code ec)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void asyncHandlersComplete ()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void async_accept ()
|
|
||||||
{
|
|
||||||
Peer* peer (new Peer (m_impl, m_port));
|
|
||||||
m_acceptor.async_accept (peer->get_socket(), std::bind (
|
|
||||||
&Door::handle_accept, Ptr(this),
|
|
||||||
beast::asio::placeholders::error,
|
|
||||||
Peer::Ptr (peer), CompletionCounter (this)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void handle_accept (error_code ec, Peer::Ptr peer, CompletionCounter)
|
|
||||||
{
|
|
||||||
if (ec == boost::asio::error::operation_aborted)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (ec)
|
|
||||||
{
|
|
||||||
m_impl.journal().error << "Accept failed: " << ec.message();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
async_accept();
|
|
||||||
|
|
||||||
peer->handle_accept();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
409
src/ripple/http/impl/Peer.cpp
Normal file
409
src/ripple/http/impl/Peer.cpp
Normal file
@@ -0,0 +1,409 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
This file is part of rippled: https://github.com/ripple/rippled
|
||||||
|
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||||
|
|
||||||
|
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 <ripple/http/impl/Peer.h>
|
||||||
|
|
||||||
|
namespace ripple {
|
||||||
|
namespace HTTP {
|
||||||
|
|
||||||
|
Peer::Peer (ServerImpl& impl, Port const& port)
|
||||||
|
: impl_ (impl)
|
||||||
|
, strand_ (impl_.get_io_service())
|
||||||
|
, data_timer_ (impl_.get_io_service())
|
||||||
|
, request_timer_ (impl_.get_io_service())
|
||||||
|
, buffer_ (bufferSize)
|
||||||
|
, writesPending_ (0)
|
||||||
|
, closed_ (false)
|
||||||
|
, callClose_ (false)
|
||||||
|
, errorCode_ (0)
|
||||||
|
, detached_ (0)
|
||||||
|
{
|
||||||
|
tag = nullptr;
|
||||||
|
|
||||||
|
int flags = MultiSocket::Flag::server_role;
|
||||||
|
switch (port.security)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
bassertfalse;
|
||||||
|
|
||||||
|
case Port::no_ssl:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Port::allow_ssl:
|
||||||
|
flags |= MultiSocket::Flag::ssl;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Port::require_ssl:
|
||||||
|
flags |= MultiSocket::Flag::ssl_required;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
socket_.reset (MultiSocket::New (
|
||||||
|
impl_.get_io_service(), port.context->get(), flags));
|
||||||
|
|
||||||
|
impl_.add (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Peer::~Peer ()
|
||||||
|
{
|
||||||
|
if (callClose_)
|
||||||
|
impl_.handler().onClose (session(), errorCode_);
|
||||||
|
|
||||||
|
impl_.remove (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Returns the Content-Body as a single buffer.
|
||||||
|
// VFALCO NOTE This is inefficient...
|
||||||
|
std::string
|
||||||
|
Peer::content()
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
beast::DynamicBuffer const& body (
|
||||||
|
parser_.request()->body ());
|
||||||
|
s.resize (body.size ());
|
||||||
|
boost::asio::buffer_copy (
|
||||||
|
boost::asio::buffer (&s[0],
|
||||||
|
s.size()), body.data <boost::asio::const_buffer>());
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send a copy of the data.
|
||||||
|
void
|
||||||
|
Peer::write (void const* buffer, std::size_t bytes)
|
||||||
|
{
|
||||||
|
// Make sure this happens on an io_service thread.
|
||||||
|
impl_.get_io_service().dispatch (strand_.wrap (
|
||||||
|
std::bind (&Peer::async_write, shared_from_this(),
|
||||||
|
SharedBuffer (static_cast <char const*> (buffer), bytes))));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make the Session asynchronous
|
||||||
|
void
|
||||||
|
Peer::detach ()
|
||||||
|
{
|
||||||
|
if (detached_.exchange (1) == 0)
|
||||||
|
{
|
||||||
|
bassert (! work_);
|
||||||
|
bassert (detach_ref_ == nullptr);
|
||||||
|
|
||||||
|
// Maintain an additional reference while detached
|
||||||
|
detach_ref_ = shared_from_this();
|
||||||
|
|
||||||
|
// Prevent the io_service from running out of work.
|
||||||
|
// The work object will be destroyed with the Peer
|
||||||
|
// after the Session is closed and handlers complete.
|
||||||
|
//
|
||||||
|
work_ = boost::in_place (std::ref (
|
||||||
|
impl_.get_io_service()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by the Handler to close the session.
|
||||||
|
void
|
||||||
|
Peer::close ()
|
||||||
|
{
|
||||||
|
// Make sure this happens on an io_service thread.
|
||||||
|
impl_.get_io_service().dispatch (strand_.wrap (
|
||||||
|
std::bind (&Peer::handle_close, shared_from_this())));
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Called when the handshake completes
|
||||||
|
//
|
||||||
|
void
|
||||||
|
Peer::handle_handshake (error_code ec)
|
||||||
|
{
|
||||||
|
if (ec == boost::asio::error::operation_aborted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ec != 0)
|
||||||
|
{
|
||||||
|
failed (ec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
async_read_some();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when the data timer expires
|
||||||
|
//
|
||||||
|
void
|
||||||
|
Peer::handle_data_timer (error_code ec)
|
||||||
|
{
|
||||||
|
if (ec == boost::asio::error::operation_aborted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (closed_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ec != 0)
|
||||||
|
{
|
||||||
|
failed (ec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
failed (boost::system::errc::make_error_code (
|
||||||
|
boost::system::errc::timed_out));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when the request timer expires
|
||||||
|
//
|
||||||
|
void
|
||||||
|
Peer::handle_request_timer (error_code ec)
|
||||||
|
{
|
||||||
|
if (ec == boost::asio::error::operation_aborted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (closed_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ec != 0)
|
||||||
|
{
|
||||||
|
failed (ec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
failed (boost::system::errc::make_error_code (
|
||||||
|
boost::system::errc::timed_out));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when async_write completes.
|
||||||
|
void
|
||||||
|
Peer::handle_write (error_code ec, std::size_t bytes_transferred,
|
||||||
|
SharedBuffer const& buf)
|
||||||
|
{
|
||||||
|
if (ec == boost::asio::error::operation_aborted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ec != 0)
|
||||||
|
{
|
||||||
|
failed (ec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bassert (writesPending_ > 0);
|
||||||
|
if (--writesPending_ == 0 && closed_)
|
||||||
|
socket_->shutdown (socket::shutdown_send);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when async_read_some completes.
|
||||||
|
void
|
||||||
|
Peer::handle_read (error_code ec, std::size_t bytes_transferred)
|
||||||
|
{
|
||||||
|
if (ec == boost::asio::error::operation_aborted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ec != 0 && ec != boost::asio::error::eof)
|
||||||
|
{
|
||||||
|
failed (ec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t const bytes_parsed (parser_.process (
|
||||||
|
buffer_.getData(), bytes_transferred));
|
||||||
|
|
||||||
|
if (parser_.error() ||
|
||||||
|
bytes_parsed != bytes_transferred)
|
||||||
|
{
|
||||||
|
failed (boost::system::errc::make_error_code (
|
||||||
|
boost::system::errc::bad_message));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ec == boost::asio::error::eof)
|
||||||
|
{
|
||||||
|
parser_.process_eof();
|
||||||
|
ec = error_code();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parser_.error())
|
||||||
|
{
|
||||||
|
failed (boost::system::errc::make_error_code (
|
||||||
|
boost::system::errc::bad_message));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! parser_.finished())
|
||||||
|
{
|
||||||
|
// Feed some headers to the callback
|
||||||
|
if (parser_.fields().size() > 0)
|
||||||
|
{
|
||||||
|
handle_headers();
|
||||||
|
if (closed_)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parser_.finished ())
|
||||||
|
{
|
||||||
|
data_timer_.cancel();
|
||||||
|
// VFALCO NOTE: Should we cancel this one?
|
||||||
|
request_timer_.cancel();
|
||||||
|
|
||||||
|
if (! socket_->needs_handshake())
|
||||||
|
socket_->shutdown (socket::shutdown_receive);
|
||||||
|
|
||||||
|
handle_request ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
async_read_some();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when we have some new headers.
|
||||||
|
void
|
||||||
|
Peer::handle_headers ()
|
||||||
|
{
|
||||||
|
impl_.handler().onHeaders (session());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when we have a complete http request.
|
||||||
|
void
|
||||||
|
Peer::handle_request ()
|
||||||
|
{
|
||||||
|
// This is to guarantee onHeaders is called at least once.
|
||||||
|
handle_headers();
|
||||||
|
|
||||||
|
if (closed_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Process the HTTPRequest
|
||||||
|
impl_.handler().onRequest (session());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called to close the session.
|
||||||
|
void
|
||||||
|
Peer::handle_close ()
|
||||||
|
{
|
||||||
|
closed_ = true;
|
||||||
|
|
||||||
|
// Release our additional reference
|
||||||
|
detach_ref_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Peer
|
||||||
|
//
|
||||||
|
|
||||||
|
// Called when the acceptor accepts our socket.
|
||||||
|
void
|
||||||
|
Peer::accept ()
|
||||||
|
{
|
||||||
|
callClose_ = true;
|
||||||
|
|
||||||
|
impl_.handler().onAccept (session());
|
||||||
|
|
||||||
|
if (closed_)
|
||||||
|
{
|
||||||
|
cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
request_timer_.expires_from_now (
|
||||||
|
boost::posix_time::seconds (
|
||||||
|
requestTimeoutSeconds));
|
||||||
|
|
||||||
|
request_timer_.async_wait (strand_.wrap (std::bind (
|
||||||
|
&Peer::handle_request_timer, shared_from_this(),
|
||||||
|
beast::asio::placeholders::error)));
|
||||||
|
|
||||||
|
if (socket_->needs_handshake ())
|
||||||
|
{
|
||||||
|
socket_->async_handshake (beast::asio::abstract_socket::server,
|
||||||
|
strand_.wrap (std::bind (&Peer::handle_handshake, shared_from_this(),
|
||||||
|
beast::asio::placeholders::error)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
async_read_some();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cancel all pending i/o and timers and send tcp shutdown.
|
||||||
|
void
|
||||||
|
Peer::cancel ()
|
||||||
|
{
|
||||||
|
error_code ec;
|
||||||
|
data_timer_.cancel (ec);
|
||||||
|
request_timer_.cancel (ec);
|
||||||
|
socket_->cancel (ec);
|
||||||
|
socket_->shutdown (socket::shutdown_both);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by a completion handler when error is not eof or aborted.
|
||||||
|
void
|
||||||
|
Peer::failed (error_code const& ec)
|
||||||
|
{
|
||||||
|
errorCode_ = ec.value();
|
||||||
|
bassert (errorCode_ != 0);
|
||||||
|
cancel ();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the async_read_some initiating function.
|
||||||
|
void
|
||||||
|
Peer::async_read_some ()
|
||||||
|
{
|
||||||
|
// re-arm the data timer
|
||||||
|
// (this cancels the previous wait, if any)
|
||||||
|
//
|
||||||
|
data_timer_.expires_from_now (
|
||||||
|
boost::posix_time::seconds (
|
||||||
|
dataTimeoutSeconds));
|
||||||
|
|
||||||
|
data_timer_.async_wait (strand_.wrap (std::bind (
|
||||||
|
&Peer::handle_data_timer, shared_from_this(),
|
||||||
|
beast::asio::placeholders::error)));
|
||||||
|
|
||||||
|
// issue the read
|
||||||
|
//
|
||||||
|
boost::asio::mutable_buffers_1 buf (
|
||||||
|
buffer_.getData (), buffer_.getSize ());
|
||||||
|
|
||||||
|
socket_->async_read_some (buf, strand_.wrap (
|
||||||
|
std::bind (&Peer::handle_read, shared_from_this(),
|
||||||
|
beast::asio::placeholders::error,
|
||||||
|
beast::asio::placeholders::bytes_transferred)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send a shared buffer
|
||||||
|
void
|
||||||
|
Peer::async_write (SharedBuffer const& buf)
|
||||||
|
{
|
||||||
|
bassert (buf.get().size() > 0);
|
||||||
|
|
||||||
|
++writesPending_;
|
||||||
|
|
||||||
|
// Send the copy. We pass the SharedBuffer in the last parameter
|
||||||
|
// so that a reference is maintained as the handler gets copied.
|
||||||
|
// When the final completion function returns, the reference
|
||||||
|
// count will drop to zero and the buffer will be freed.
|
||||||
|
//
|
||||||
|
boost::asio::async_write (*socket_,
|
||||||
|
boost::asio::const_buffers_1 (&(*buf)[0], buf->size()),
|
||||||
|
strand_.wrap (std::bind (&Peer::handle_write,
|
||||||
|
shared_from_this(), beast::asio::placeholders::error,
|
||||||
|
beast::asio::placeholders::bytes_transferred, buf)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,29 +20,34 @@
|
|||||||
#ifndef RIPPLE_HTTP_PEER_H_INCLUDED
|
#ifndef RIPPLE_HTTP_PEER_H_INCLUDED
|
||||||
#define RIPPLE_HTTP_PEER_H_INCLUDED
|
#define RIPPLE_HTTP_PEER_H_INCLUDED
|
||||||
|
|
||||||
#include <ripple/http/api/Session.h>
|
#include <ripple/http/Server.h>
|
||||||
|
#include <ripple/http/Session.h>
|
||||||
|
#include <ripple/http/impl/Types.h>
|
||||||
|
#include <ripple/http/impl/ServerImpl.h>
|
||||||
#include <ripple/common/MultiSocket.h>
|
#include <ripple/common/MultiSocket.h>
|
||||||
#include <beast/module/asio/async/AsyncObject.h>
|
#include <beast/asio/placeholders.h>
|
||||||
|
#include <beast/module/core/core.h>
|
||||||
#include <beast/module/asio/basics/SharedArg.h>
|
#include <beast/module/asio/basics/SharedArg.h>
|
||||||
#include <beast/module/asio/http/HTTPRequestParser.h>
|
#include <beast/module/asio/http/HTTPRequestParser.h>
|
||||||
#include <boost/bind.hpp>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace HTTP {
|
namespace HTTP {
|
||||||
|
|
||||||
// Holds the copy of buffers being sent
|
// Holds the copy of buffers being sent
|
||||||
|
// VFALCO TODO Replace with std::shared_ptr<std::string>
|
||||||
|
//
|
||||||
typedef beast::asio::SharedArg <std::string> SharedBuffer;
|
typedef beast::asio::SharedArg <std::string> SharedBuffer;
|
||||||
|
|
||||||
/** Represents an active connection. */
|
/** Represents an active connection. */
|
||||||
class Peer
|
class Peer
|
||||||
: public beast::SharedObject
|
: public std::enable_shared_from_this <Peer>
|
||||||
, public beast::asio::AsyncObject <Peer>
|
|
||||||
, public Session
|
, public Session
|
||||||
, public beast::List <Peer>::Node
|
, public beast::List <Peer>::Node
|
||||||
, public beast::LeakChecked <Peer>
|
, public beast::LeakChecked <Peer>
|
||||||
{
|
{
|
||||||
public:
|
private:
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
// Size of our receive buffer
|
// Size of our receive buffer
|
||||||
@@ -59,462 +64,138 @@ public:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef beast::SharedPtr <Peer> Ptr;
|
ServerImpl& impl_;
|
||||||
|
boost::asio::io_service::strand strand_;
|
||||||
|
boost::asio::deadline_timer data_timer_;
|
||||||
|
boost::asio::deadline_timer request_timer_;
|
||||||
|
std::unique_ptr <MultiSocket> socket_;
|
||||||
|
|
||||||
ServerImpl& m_impl;
|
// VFALCO TODO Use c++11
|
||||||
boost::asio::io_service::strand m_strand;
|
beast::MemoryBlock buffer_;
|
||||||
boost::asio::deadline_timer m_data_timer;
|
|
||||||
boost::asio::deadline_timer m_request_timer;
|
beast::HTTPRequestParser parser_;
|
||||||
std::unique_ptr <MultiSocket> m_socket;
|
int writesPending_;
|
||||||
beast::MemoryBlock m_buffer;
|
bool closed_;
|
||||||
beast::HTTPRequestParser m_parser;
|
bool callClose_;
|
||||||
int m_writesPending;
|
std::shared_ptr <Peer> detach_ref_;
|
||||||
bool m_closed;
|
boost::optional <boost::asio::io_service::work> work_;
|
||||||
bool m_callClose;
|
int errorCode_;
|
||||||
beast::SharedPtr <Peer> m_detach_ref;
|
std::atomic <int> detached_;
|
||||||
boost::optional <boost::asio::io_service::work> m_work;
|
|
||||||
int m_errorCode;
|
|
||||||
std::atomic <int> m_detached;
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
Peer (ServerImpl& impl, Port const& port)
|
public:
|
||||||
: m_impl (impl)
|
Peer (ServerImpl& impl, Port const& port);
|
||||||
, m_strand (m_impl.get_io_service())
|
~Peer ();
|
||||||
, m_data_timer (m_impl.get_io_service())
|
|
||||||
, m_request_timer (m_impl.get_io_service())
|
|
||||||
, m_buffer (bufferSize)
|
|
||||||
, m_writesPending (0)
|
|
||||||
, m_closed (false)
|
|
||||||
, m_callClose (false)
|
|
||||||
, m_errorCode (0)
|
|
||||||
, m_detached (0)
|
|
||||||
{
|
|
||||||
tag = nullptr;
|
|
||||||
|
|
||||||
int flags;
|
|
||||||
switch (port.security)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
bassertfalse;
|
|
||||||
case Port::no_ssl: flags = MultiSocket::none; break;
|
|
||||||
case Port::allow_ssl: flags = MultiSocket::server_ssl; break;
|
|
||||||
case Port::require_ssl: flags = MultiSocket::server_ssl_required; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_socket.reset (MultiSocket::New (
|
|
||||||
m_impl.get_io_service(), port.context->get(), flags));
|
|
||||||
|
|
||||||
m_impl.add (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
~Peer ()
|
|
||||||
{
|
|
||||||
if (m_callClose)
|
|
||||||
m_impl.handler().onClose (session(), m_errorCode);
|
|
||||||
|
|
||||||
m_impl.remove (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private:
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Session
|
// Session
|
||||||
//
|
//
|
||||||
|
|
||||||
beast::Journal journal()
|
beast::Journal
|
||||||
|
journal()
|
||||||
{
|
{
|
||||||
return m_impl.journal();
|
return impl_.journal();
|
||||||
}
|
}
|
||||||
|
|
||||||
beast::IP::Endpoint remoteAddress()
|
beast::IP::Endpoint
|
||||||
|
remoteAddress()
|
||||||
{
|
{
|
||||||
return from_asio (get_socket().remote_endpoint());
|
return from_asio (get_socket().remote_endpoint());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool headersComplete()
|
bool
|
||||||
|
headersComplete()
|
||||||
{
|
{
|
||||||
return m_parser.headersComplete();
|
return parser_.headersComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
beast::HTTPHeaders headers()
|
beast::HTTPHeaders
|
||||||
|
headers()
|
||||||
{
|
{
|
||||||
return beast::HTTPHeaders (m_parser.fields());
|
return beast::HTTPHeaders (parser_.fields());
|
||||||
}
|
}
|
||||||
|
|
||||||
beast::SharedPtr <beast::HTTPRequest> const& request()
|
beast::SharedPtr <beast::HTTPRequest> const&
|
||||||
|
request()
|
||||||
{
|
{
|
||||||
return m_parser.request();
|
return parser_.request();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the Content-Body as a single buffer.
|
std::string
|
||||||
// VFALCO NOTE This is inefficient...
|
content();
|
||||||
std::string content()
|
|
||||||
{
|
|
||||||
std::string s;
|
|
||||||
beast::DynamicBuffer const& body (
|
|
||||||
m_parser.request()->body ());
|
|
||||||
s.resize (body.size ());
|
|
||||||
boost::asio::buffer_copy (
|
|
||||||
boost::asio::buffer (&s[0],
|
|
||||||
s.size()), body.data <boost::asio::const_buffer>());
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send a copy of the data.
|
void
|
||||||
void write (void const* buffer, std::size_t bytes)
|
write (void const* buffer, std::size_t bytes);
|
||||||
{
|
|
||||||
// Make sure this happens on an io_service thread.
|
|
||||||
m_impl.get_io_service().dispatch (m_strand.wrap (
|
|
||||||
boost::bind (&Peer::handle_write, Ptr (this),
|
|
||||||
SharedBuffer (static_cast <char const*> (buffer), bytes),
|
|
||||||
CompletionCounter (this))));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make the Session asynchronous
|
void
|
||||||
void detach ()
|
detach ();
|
||||||
{
|
|
||||||
if (m_detached.exchange (1) == 0)
|
|
||||||
{
|
|
||||||
bassert (! m_work);
|
|
||||||
bassert (m_detach_ref.empty());
|
|
||||||
|
|
||||||
// Maintain an additional reference while detached
|
void
|
||||||
m_detach_ref = this;
|
close ();
|
||||||
|
|
||||||
// Prevent the io_service from running out of work.
|
|
||||||
// The work object will be destroyed with the Peer
|
|
||||||
// after the Session is closed and handlers complete.
|
|
||||||
//
|
|
||||||
m_work = boost::in_place (std::ref (
|
|
||||||
m_impl.get_io_service()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called by the Handler to close the session.
|
|
||||||
void close ()
|
|
||||||
{
|
|
||||||
// Make sure this happens on an io_service thread.
|
|
||||||
m_impl.get_io_service().dispatch (m_strand.wrap (
|
|
||||||
boost::bind (&Peer::handle_close, Ptr (this),
|
|
||||||
CompletionCounter (this))));
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Completion Handlers
|
// Completion Handlers
|
||||||
//
|
//
|
||||||
|
|
||||||
// Called when the last pending completion handler returns.
|
void
|
||||||
void asyncHandlersComplete ()
|
handle_handshake (error_code ec);
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when the acceptor accepts our socket.
|
void
|
||||||
void handle_accept ()
|
handle_data_timer (error_code ec);
|
||||||
{
|
|
||||||
m_callClose = true;
|
|
||||||
|
|
||||||
m_impl.handler().onAccept (session());
|
void
|
||||||
|
handle_request_timer (error_code ec);
|
||||||
|
|
||||||
if (m_closed)
|
void
|
||||||
{
|
handle_write (error_code ec, std::size_t bytes_transferred,
|
||||||
cancel();
|
SharedBuffer const& buf);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_request_timer.expires_from_now (
|
void
|
||||||
boost::posix_time::seconds (
|
handle_read (error_code ec, std::size_t bytes_transferred);
|
||||||
requestTimeoutSeconds));
|
|
||||||
|
|
||||||
m_request_timer.async_wait (m_strand.wrap (boost::bind (
|
void
|
||||||
&Peer::handle_request_timer, Ptr(this),
|
handle_headers ();
|
||||||
boost::asio::placeholders::error,
|
|
||||||
CompletionCounter (this))));
|
|
||||||
|
|
||||||
if (m_socket->needs_handshake ())
|
void
|
||||||
{
|
handle_request ();
|
||||||
m_socket->async_handshake (beast::asio::abstract_socket::server,
|
|
||||||
m_strand.wrap (boost::bind (&Peer::handle_handshake, Ptr(this),
|
|
||||||
boost::asio::placeholders::error,
|
|
||||||
CompletionCounter (this))));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
async_read_some();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called from an io_service thread to write the shared buffer.
|
void
|
||||||
void handle_write (SharedBuffer const& buf, CompletionCounter)
|
handle_close ();
|
||||||
{
|
|
||||||
async_write (buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when the handshake completes
|
|
||||||
//
|
|
||||||
void handle_handshake (error_code ec, CompletionCounter)
|
|
||||||
{
|
|
||||||
if (ec == boost::asio::error::operation_aborted)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (ec != 0)
|
|
||||||
{
|
|
||||||
failed (ec);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
async_read_some();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when the data timer expires
|
|
||||||
//
|
|
||||||
void handle_data_timer (error_code ec, CompletionCounter)
|
|
||||||
{
|
|
||||||
if (ec == boost::asio::error::operation_aborted)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (m_closed)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (ec != 0)
|
|
||||||
{
|
|
||||||
failed (ec);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
failed (boost::system::errc::make_error_code (
|
|
||||||
boost::system::errc::timed_out));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when the request timer expires
|
|
||||||
//
|
|
||||||
void handle_request_timer (error_code ec, CompletionCounter)
|
|
||||||
{
|
|
||||||
if (ec == boost::asio::error::operation_aborted)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (m_closed)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (ec != 0)
|
|
||||||
{
|
|
||||||
failed (ec);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
failed (boost::system::errc::make_error_code (
|
|
||||||
boost::system::errc::timed_out));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when async_write completes.
|
|
||||||
void handle_write (error_code ec, std::size_t bytes_transferred,
|
|
||||||
SharedBuffer buf, CompletionCounter)
|
|
||||||
{
|
|
||||||
if (ec == boost::asio::error::operation_aborted)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (ec != 0)
|
|
||||||
{
|
|
||||||
failed (ec);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bassert (m_writesPending > 0);
|
|
||||||
if (--m_writesPending == 0 && m_closed)
|
|
||||||
m_socket->shutdown (socket::shutdown_send);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when async_read_some completes.
|
|
||||||
void handle_read (error_code ec, std::size_t bytes_transferred, CompletionCounter)
|
|
||||||
{
|
|
||||||
if (ec == boost::asio::error::operation_aborted)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (ec != 0 && ec != boost::asio::error::eof)
|
|
||||||
{
|
|
||||||
failed (ec);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t const bytes_parsed (m_parser.process (
|
|
||||||
m_buffer.getData(), bytes_transferred));
|
|
||||||
|
|
||||||
if (m_parser.error() ||
|
|
||||||
bytes_parsed != bytes_transferred)
|
|
||||||
{
|
|
||||||
failed (boost::system::errc::make_error_code (
|
|
||||||
boost::system::errc::bad_message));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ec == boost::asio::error::eof)
|
|
||||||
{
|
|
||||||
m_parser.process_eof();
|
|
||||||
ec = error_code();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_parser.error())
|
|
||||||
{
|
|
||||||
failed (boost::system::errc::make_error_code (
|
|
||||||
boost::system::errc::bad_message));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! m_parser.finished())
|
|
||||||
{
|
|
||||||
// Feed some headers to the callback
|
|
||||||
if (m_parser.fields().size() > 0)
|
|
||||||
{
|
|
||||||
handle_headers();
|
|
||||||
if (m_closed)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_parser.finished ())
|
|
||||||
{
|
|
||||||
m_data_timer.cancel();
|
|
||||||
// VFALCO NOTE: Should we cancel this one?
|
|
||||||
m_request_timer.cancel();
|
|
||||||
|
|
||||||
if (! m_socket->needs_handshake())
|
|
||||||
m_socket->shutdown (socket::shutdown_receive);
|
|
||||||
|
|
||||||
handle_request ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
async_read_some();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when we have some new headers.
|
|
||||||
void handle_headers ()
|
|
||||||
{
|
|
||||||
m_impl.handler().onHeaders (session());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when we have a complete http request.
|
|
||||||
void handle_request ()
|
|
||||||
{
|
|
||||||
// This is to guarantee onHeaders is called at least once.
|
|
||||||
handle_headers();
|
|
||||||
|
|
||||||
if (m_closed)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Process the HTTPRequest
|
|
||||||
m_impl.handler().onRequest (session());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called to close the session.
|
|
||||||
void handle_close (CompletionCounter)
|
|
||||||
{
|
|
||||||
m_closed = true;
|
|
||||||
|
|
||||||
// Release our additional reference
|
|
||||||
m_detach_ref = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public:
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Peer
|
// Peer
|
||||||
//
|
//
|
||||||
|
socket&
|
||||||
// Returns the asio socket for the peer.
|
get_socket()
|
||||||
socket& get_socket()
|
|
||||||
{
|
{
|
||||||
return m_socket->this_layer<socket>();
|
return socket_->this_layer<socket>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the Session associated with this peer's session.
|
Session&
|
||||||
Session& session ()
|
session ()
|
||||||
{
|
{
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cancel all pending i/o and timers and send tcp shutdown.
|
void
|
||||||
void cancel ()
|
accept ();
|
||||||
{
|
|
||||||
error_code ec;
|
|
||||||
m_data_timer.cancel (ec);
|
|
||||||
m_request_timer.cancel (ec);
|
|
||||||
m_socket->cancel (ec);
|
|
||||||
m_socket->shutdown (socket::shutdown_both);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called by a completion handler when error is not eof or aborted.
|
void
|
||||||
void failed (error_code const& ec)
|
cancel ();
|
||||||
{
|
|
||||||
m_errorCode = ec.value();
|
|
||||||
bassert (m_errorCode != 0);
|
|
||||||
cancel ();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call the async_read_some initiating function.
|
void
|
||||||
void async_read_some ()
|
failed (error_code const& ec);
|
||||||
{
|
|
||||||
// re-arm the data timer
|
|
||||||
// (this cancels the previous wait, if any)
|
|
||||||
//
|
|
||||||
m_data_timer.expires_from_now (
|
|
||||||
boost::posix_time::seconds (
|
|
||||||
dataTimeoutSeconds));
|
|
||||||
|
|
||||||
m_data_timer.async_wait (m_strand.wrap (boost::bind (
|
void
|
||||||
&Peer::handle_data_timer, Ptr(this),
|
async_read_some ();
|
||||||
boost::asio::placeholders::error,
|
|
||||||
CompletionCounter (this))));
|
|
||||||
|
|
||||||
// issue the read
|
void async_write (SharedBuffer const& buf);
|
||||||
//
|
|
||||||
boost::asio::mutable_buffers_1 buf (
|
|
||||||
m_buffer.getData (), m_buffer.getSize ());
|
|
||||||
|
|
||||||
m_socket->async_read_some (buf, m_strand.wrap (
|
|
||||||
boost::bind (&Peer::handle_read, Ptr (this),
|
|
||||||
boost::asio::placeholders::error,
|
|
||||||
boost::asio::placeholders::bytes_transferred,
|
|
||||||
CompletionCounter (this))));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send a shared buffer
|
|
||||||
void async_write (SharedBuffer const& buf)
|
|
||||||
{
|
|
||||||
bassert (buf.get().size() > 0);
|
|
||||||
|
|
||||||
++m_writesPending;
|
|
||||||
|
|
||||||
// Send the copy. We pass the SharedBuffer in the last parameter
|
|
||||||
// so that a reference is maintained as the handler gets copied.
|
|
||||||
// When the final completion function returns, the reference
|
|
||||||
// count will drop to zero and the buffer will be freed.
|
|
||||||
//
|
|
||||||
boost::asio::async_write (*m_socket,
|
|
||||||
boost::asio::const_buffers_1 (&(*buf)[0], buf->size()),
|
|
||||||
m_strand.wrap (boost::bind (&Peer::handle_write,
|
|
||||||
Ptr (this), boost::asio::placeholders::error,
|
|
||||||
boost::asio::placeholders::bytes_transferred,
|
|
||||||
buf, CompletionCounter (this))));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send a copy of a BufferSequence
|
|
||||||
template <typename BufferSequence>
|
|
||||||
void async_write (BufferSequence const& buffers)
|
|
||||||
{
|
|
||||||
// Iterate over each linear vector in the BufferSequence.
|
|
||||||
for (typename BufferSequence::const_iterator iter (buffers.begin());
|
|
||||||
iter != buffers.end(); ++iter)
|
|
||||||
{
|
|
||||||
typename BufferSequence::value_type const& buffer (*iter);
|
|
||||||
|
|
||||||
// Put a copy of this section of the buffer sequence into
|
|
||||||
// a reference counted, shared container.
|
|
||||||
//
|
|
||||||
async_write (SharedBuffer (
|
|
||||||
boost::asio::buffer_cast <char const*> (buffer),
|
|
||||||
boost::asio::buffer_size (buffer)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,16 +21,16 @@ namespace ripple {
|
|||||||
namespace HTTP {
|
namespace HTTP {
|
||||||
|
|
||||||
Port::Port ()
|
Port::Port ()
|
||||||
: port (0)
|
: security (no_ssl)
|
||||||
, security (no_ssl)
|
, port (0)
|
||||||
, context (nullptr)
|
, context (nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Port::Port (Port const& other)
|
Port::Port (Port const& other)
|
||||||
: port (other.port)
|
: security (other.security)
|
||||||
|
, port (other.port)
|
||||||
, addr (other.addr)
|
, addr (other.addr)
|
||||||
, security (other.security)
|
|
||||||
, context (other.context)
|
, context (other.context)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -44,14 +44,11 @@ Port& Port::operator= (Port const& other)
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Port::Port (
|
Port::Port (std::uint16_t port_, beast::IP::Endpoint const& addr_,
|
||||||
std::uint16_t port_,
|
Security security_, beast::asio::SSLContext* context_)
|
||||||
beast::IP::Endpoint const& addr_,
|
: security (security_)
|
||||||
Security security_,
|
, port (port_)
|
||||||
beast::asio::SSLContext* context_)
|
|
||||||
: port (port_)
|
|
||||||
, addr (addr_)
|
, addr (addr_)
|
||||||
, security (security_)
|
|
||||||
, context (context_)
|
, context (context_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -88,18 +85,5 @@ bool operator< (Port const& lhs, Port const& rhs)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!= (Port const& lhs, Port const& rhs)
|
|
||||||
{ return ! (lhs == rhs); }
|
|
||||||
|
|
||||||
bool operator> (Port const& lhs, Port const& rhs)
|
|
||||||
{ return rhs < lhs; }
|
|
||||||
|
|
||||||
bool operator<= (Port const& lhs, Port const& rhs)
|
|
||||||
{ return ! (rhs < lhs); }
|
|
||||||
|
|
||||||
bool operator>= (Port const& lhs, Port const& rhs)
|
|
||||||
{ return ! (lhs < rhs); }
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,11 +17,15 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
|
#include <ripple/http/Server.h>
|
||||||
|
#include <ripple/http/impl/ServerImpl.h>
|
||||||
|
#include <beast/cxx14/memory.h> // <memory>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace HTTP {
|
namespace HTTP {
|
||||||
|
|
||||||
Server::Server (Handler& handler, beast::Journal journal)
|
Server::Server (Handler& handler, beast::Journal journal)
|
||||||
: m_impl (new ServerImpl (*this, handler, journal))
|
: m_impl (std::make_unique <ServerImpl> (*this, handler, journal))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,27 +34,32 @@ Server::~Server ()
|
|||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
beast::Journal const& Server::journal () const
|
beast::Journal
|
||||||
|
Server::journal () const
|
||||||
{
|
{
|
||||||
return m_impl->journal();
|
return m_impl->journal();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ports const& Server::getPorts () const
|
Ports const&
|
||||||
|
Server::getPorts () const
|
||||||
{
|
{
|
||||||
return m_impl->getPorts();
|
return m_impl->getPorts();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::setPorts (Ports const& ports)
|
void
|
||||||
|
Server::setPorts (Ports const& ports)
|
||||||
{
|
{
|
||||||
m_impl->setPorts (ports);
|
m_impl->setPorts (ports);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::stopAsync ()
|
void
|
||||||
|
Server::stopAsync ()
|
||||||
{
|
{
|
||||||
m_impl->stop(false);
|
m_impl->stop(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::stop ()
|
void
|
||||||
|
Server::stop ()
|
||||||
{
|
{
|
||||||
m_impl->stop(true);
|
m_impl->stop(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
*/
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
|
#include <ripple/http/impl/ServerImpl.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace HTTP {
|
namespace HTTP {
|
||||||
|
|
||||||
@@ -24,7 +26,7 @@ ServerImpl::ServerImpl (Server& server, Handler& handler, beast::Journal journal
|
|||||||
: Thread ("HTTP::Server")
|
: Thread ("HTTP::Server")
|
||||||
, m_server (server)
|
, m_server (server)
|
||||||
, m_handler (handler)
|
, m_handler (handler)
|
||||||
, m_journal (journal)
|
, journal_ (journal)
|
||||||
, m_strand (m_io_service)
|
, m_strand (m_io_service)
|
||||||
, m_work (boost::in_place (std::ref (m_io_service)))
|
, m_work (boost::in_place (std::ref (m_io_service)))
|
||||||
, m_stopped (true)
|
, m_stopped (true)
|
||||||
@@ -37,11 +39,6 @@ ServerImpl::~ServerImpl ()
|
|||||||
stopThread ();
|
stopThread ();
|
||||||
}
|
}
|
||||||
|
|
||||||
beast::Journal const& ServerImpl::journal() const
|
|
||||||
{
|
|
||||||
return m_journal;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ports const& ServerImpl::getPorts () const
|
Ports const& ServerImpl::getPorts () const
|
||||||
{
|
{
|
||||||
SharedState::ConstUnlockedAccess state (m_state);
|
SharedState::ConstUnlockedAccess state (m_state);
|
||||||
@@ -129,7 +126,7 @@ int ServerImpl::compare (Port const& lhs, Port const& rhs)
|
|||||||
{
|
{
|
||||||
if (lhs < rhs)
|
if (lhs < rhs)
|
||||||
return -1;
|
return -1;
|
||||||
else if (lhs > rhs)
|
else if (rhs < lhs)
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,8 +20,14 @@
|
|||||||
#ifndef RIPPLE_HTTP_SERVERIMPL_H_INCLUDED
|
#ifndef RIPPLE_HTTP_SERVERIMPL_H_INCLUDED
|
||||||
#define RIPPLE_HTTP_SERVERIMPL_H_INCLUDED
|
#define RIPPLE_HTTP_SERVERIMPL_H_INCLUDED
|
||||||
|
|
||||||
|
#include <ripple/http/Server.h>
|
||||||
|
#include <beast/intrusive/List.h>
|
||||||
|
#include <beast/threads/SharedData.h>
|
||||||
#include <beast/threads/Thread.h>
|
#include <beast/threads/Thread.h>
|
||||||
#include <beast/module/asio/basics/SharedArg.h>
|
#include <beast/module/asio/basics/SharedArg.h>
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace HTTP {
|
namespace HTTP {
|
||||||
@@ -31,7 +37,7 @@ class Peer;
|
|||||||
|
|
||||||
class ServerImpl : public beast::Thread
|
class ServerImpl : public beast::Thread
|
||||||
{
|
{
|
||||||
public:
|
private:
|
||||||
struct State
|
struct State
|
||||||
{
|
{
|
||||||
// Attributes for our listening ports
|
// Attributes for our listening ports
|
||||||
@@ -49,7 +55,7 @@ public:
|
|||||||
|
|
||||||
Server& m_server;
|
Server& m_server;
|
||||||
Handler& m_handler;
|
Handler& m_handler;
|
||||||
beast::Journal m_journal;
|
beast::Journal journal_;
|
||||||
boost::asio::io_service m_io_service;
|
boost::asio::io_service m_io_service;
|
||||||
boost::asio::io_service::strand m_strand;
|
boost::asio::io_service::strand m_strand;
|
||||||
boost::optional <boost::asio::io_service::work> m_work;
|
boost::optional <boost::asio::io_service::work> m_work;
|
||||||
@@ -57,24 +63,54 @@ public:
|
|||||||
SharedState m_state;
|
SharedState m_state;
|
||||||
Doors m_doors;
|
Doors m_doors;
|
||||||
|
|
||||||
|
public:
|
||||||
ServerImpl (Server& server, Handler& handler, beast::Journal journal);
|
ServerImpl (Server& server, Handler& handler, beast::Journal journal);
|
||||||
~ServerImpl ();
|
~ServerImpl ();
|
||||||
beast::Journal const& journal() const;
|
|
||||||
Ports const& getPorts () const;
|
|
||||||
void setPorts (Ports const& ports);
|
|
||||||
bool stopping () const;
|
|
||||||
void stop (bool wait);
|
|
||||||
|
|
||||||
Handler& handler();
|
beast::Journal
|
||||||
boost::asio::io_service& get_io_service();
|
journal() const
|
||||||
void add (Peer& peer);
|
{
|
||||||
void add (Door& door);
|
return journal_;
|
||||||
void remove (Peer& peer);
|
}
|
||||||
void remove (Door& door);
|
|
||||||
|
|
||||||
void handle_update ();
|
Ports const&
|
||||||
void update ();
|
getPorts () const;
|
||||||
void run ();
|
|
||||||
|
void
|
||||||
|
setPorts (Ports const& ports);
|
||||||
|
|
||||||
|
bool
|
||||||
|
stopping () const;
|
||||||
|
|
||||||
|
void
|
||||||
|
stop (bool wait);
|
||||||
|
|
||||||
|
Handler&
|
||||||
|
handler();
|
||||||
|
|
||||||
|
boost::asio::io_service&
|
||||||
|
get_io_service();
|
||||||
|
|
||||||
|
void
|
||||||
|
add (Peer& peer);
|
||||||
|
|
||||||
|
void
|
||||||
|
add (Door& door);
|
||||||
|
|
||||||
|
void
|
||||||
|
remove (Peer& peer);
|
||||||
|
|
||||||
|
void
|
||||||
|
remove (Door& door);
|
||||||
|
|
||||||
|
void
|
||||||
|
handle_update ();
|
||||||
|
|
||||||
|
void
|
||||||
|
update ();
|
||||||
|
|
||||||
|
void
|
||||||
|
run ();
|
||||||
|
|
||||||
static int compare (Port const& lhs, Port const& rhs);
|
static int compare (Port const& lhs, Port const& rhs);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -801,6 +801,10 @@ public:
|
|||||||
//
|
//
|
||||||
// Allow RPC connections.
|
// Allow RPC connections.
|
||||||
//
|
//
|
||||||
|
#if RIPPLE_ASYNC_RPC_HANDLER
|
||||||
|
m_rpcHTTPServer->setup (m_journal);
|
||||||
|
|
||||||
|
#else
|
||||||
if (! getConfig ().getRpcIP().empty () && getConfig ().getRpcPort() != 0)
|
if (! getConfig ().getRpcIP().empty () && getConfig ().getRpcPort() != 0)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -820,6 +824,7 @@ public:
|
|||||||
{
|
{
|
||||||
m_journal.info << "RPC interface: disabled";
|
m_journal.info << "RPC interface: disabled";
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
// Begin connecting to network.
|
// Begin connecting to network.
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
#include <ripple/common/RippleSSLContext.h>
|
#include <ripple/common/RippleSSLContext.h>
|
||||||
|
#include <ripple/http/Session.h>
|
||||||
#include <ripple/module/app/main/RPCHTTPServer.h>
|
#include <ripple/module/app/main/RPCHTTPServer.h>
|
||||||
#include <ripple/module/rpc/RPCHandler.h>
|
#include <ripple/module/rpc/RPCHandler.h>
|
||||||
#include <ripple/module/rpc/RPCServerHandler.h>
|
#include <ripple/module/rpc/RPCServerHandler.h>
|
||||||
@@ -75,9 +76,12 @@ public:
|
|||||||
getConfig ().getRpcPort() != 0)
|
getConfig ().getRpcPort() != 0)
|
||||||
{
|
{
|
||||||
beast::IP::Endpoint ep (beast::IP::Endpoint::from_string (getConfig().getRpcIP()));
|
beast::IP::Endpoint ep (beast::IP::Endpoint::from_string (getConfig().getRpcIP()));
|
||||||
if (! is_unspecified (ep))
|
|
||||||
|
// VFALCO TODO IP address should not have an "unspecified" state
|
||||||
|
//if (! is_unspecified (ep))
|
||||||
{
|
{
|
||||||
HTTP::Port port;
|
HTTP::Port port;
|
||||||
|
port.security = HTTP::Port::allow_ssl;
|
||||||
port.addr = ep.at_port(0);
|
port.addr = ep.at_port(0);
|
||||||
if (getConfig ().getRpcPort() != 0)
|
if (getConfig ().getRpcPort() != 0)
|
||||||
port.port = getConfig ().getRpcPort();
|
port.port = getConfig ().getRpcPort();
|
||||||
@@ -131,16 +135,24 @@ public:
|
|||||||
|
|
||||||
void onRequest (HTTP::Session& session)
|
void onRequest (HTTP::Session& session)
|
||||||
{
|
{
|
||||||
|
// Check user/password authorization
|
||||||
|
auto const headers (session.request()->headers().build_map());
|
||||||
|
if (! HTTPAuthorized (headers))
|
||||||
|
{
|
||||||
|
session.write (HTTPReply (403, "Forbidden"));
|
||||||
|
session.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
// Synchronous version that doesn't use job queue
|
||||||
Job job;
|
Job job;
|
||||||
processSession (job, session);
|
processSession (job, session);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
session.detach();
|
session.detach();
|
||||||
|
|
||||||
// The "boost::"'s are a workaround for broken versions of tr1::functional that
|
m_jobQueue.addJob (jtCLIENT, "RPC-Client", std::bind (
|
||||||
// require the reference wrapper to be callable. HTTP::Session has abstract functions
|
|
||||||
// and so references to it are not callable.
|
|
||||||
m_jobQueue.addJob (jtRPC, "RPC", std::bind (
|
|
||||||
&RPCHTTPServerImp::processSession, this, std::placeholders::_1,
|
&RPCHTTPServerImp::processSession, this, std::placeholders::_1,
|
||||||
std::ref (session)));
|
std::ref (session)));
|
||||||
#endif
|
#endif
|
||||||
@@ -159,8 +171,14 @@ public:
|
|||||||
|
|
||||||
void processSession (Job& job, HTTP::Session& session)
|
void processSession (Job& job, HTTP::Session& session)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
|
// Goes through the old code
|
||||||
session.write (m_deprecatedHandler.processRequest (
|
session.write (m_deprecatedHandler.processRequest (
|
||||||
session.content(), session.remoteAddress().at_port(0)));
|
session.content(), session.remoteAddress().at_port(0)));
|
||||||
|
#else
|
||||||
|
session.write (processRequest (session.content(),
|
||||||
|
session.remoteAddress().at_port(0)));
|
||||||
|
#endif
|
||||||
|
|
||||||
session.close();
|
session.close();
|
||||||
}
|
}
|
||||||
@@ -172,14 +190,10 @@ public:
|
|||||||
return HTTPReply (statusCode, description);
|
return HTTPReply (statusCode, description);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isAuthorized (
|
|
||||||
std::map <std::string, std::string> const& headers)
|
|
||||||
{
|
|
||||||
return HTTPAuthorized (headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stolen directly from RPCServerHandler
|
// Stolen directly from RPCServerHandler
|
||||||
std::string processRequest (std::string const& request, beast::IP::Endpoint const& remoteIPAddress)
|
std::string
|
||||||
|
processRequest (std::string const& request,
|
||||||
|
beast::IP::Endpoint const& remoteIPAddress)
|
||||||
{
|
{
|
||||||
Json::Value jvRequest;
|
Json::Value jvRequest;
|
||||||
{
|
{
|
||||||
@@ -247,14 +261,6 @@ public:
|
|||||||
return HTTPReply (403, "Forbidden");
|
return HTTPReply (403, "Forbidden");
|
||||||
}
|
}
|
||||||
|
|
||||||
// This code does all the work on the io_service thread and
|
|
||||||
// has no rate-limiting based on source IP or anything.
|
|
||||||
// This is a temporary safety
|
|
||||||
if ((role != Config::ADMIN) && (getApp().getFeeTrack().isLoadedLocal()))
|
|
||||||
{
|
|
||||||
return HTTPReply (503, "Unable to service at this time");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string response;
|
std::string response;
|
||||||
|
|
||||||
m_journal.debug << "Query: " << strMethod << params;
|
m_journal.debug << "Query: " << strMethod << params;
|
||||||
|
|||||||
@@ -262,10 +262,14 @@ std::string DecodeBase64 (std::string s)
|
|||||||
|
|
||||||
bool HTTPAuthorized (const std::map<std::string, std::string>& mapHeaders)
|
bool HTTPAuthorized (const std::map<std::string, std::string>& mapHeaders)
|
||||||
{
|
{
|
||||||
std::map<std::string, std::string>::const_iterator it = mapHeaders.find ("authorization");
|
bool const credentialsRequired (! getConfig().RPC_USER.empty() &&
|
||||||
|
! getConfig().RPC_PASSWORD.empty());
|
||||||
|
if (! credentialsRequired)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
auto const it = mapHeaders.find ("authorization");
|
||||||
if ((it == mapHeaders.end ()) || (it->second.substr (0, 6) != "Basic "))
|
if ((it == mapHeaders.end ()) || (it->second.substr (0, 6) != "Basic "))
|
||||||
return getConfig ().RPC_USER.empty () && getConfig ().RPC_PASSWORD.empty ();
|
return false;
|
||||||
|
|
||||||
std::string strUserPass64 = it->second.substr (6);
|
std::string strUserPass64 = it->second.substr (6);
|
||||||
boost::trim (strUserPass64);
|
boost::trim (strUserPass64);
|
||||||
|
|||||||
@@ -23,11 +23,12 @@
|
|||||||
#include <ripple/unity/net.h>
|
#include <ripple/unity/net.h>
|
||||||
#include <ripple/unity/rpcx.h>
|
#include <ripple/unity/rpcx.h>
|
||||||
#include <ripple/unity/websocket.h>
|
#include <ripple/unity/websocket.h>
|
||||||
#include <ripple/unity/http.h>
|
|
||||||
#include <ripple/unity/resource.h>
|
#include <ripple/unity/resource.h>
|
||||||
#include <ripple/unity/sitefiles.h>
|
#include <ripple/unity/sitefiles.h>
|
||||||
#include <ripple/unity/validators.h>
|
#include <ripple/unity/validators.h>
|
||||||
|
|
||||||
|
#include <ripple/http/Server.h>
|
||||||
|
|
||||||
#include <ripple/module/app/main/CollectorManager.cpp>
|
#include <ripple/module/app/main/CollectorManager.cpp>
|
||||||
#include <ripple/module/app/main/NodeStoreScheduler.cpp>
|
#include <ripple/module/app/main/NodeStoreScheduler.cpp>
|
||||||
#include <ripple/module/app/main/IoServicePool.cpp>
|
#include <ripple/module/app/main/IoServicePool.cpp>
|
||||||
|
|||||||
@@ -19,19 +19,9 @@
|
|||||||
|
|
||||||
#include <BeastConfig.h>
|
#include <BeastConfig.h>
|
||||||
|
|
||||||
#include <ripple/unity/http.h>
|
#include <ripple/http/impl/Door.cpp>
|
||||||
|
#include <ripple/http/impl/Peer.cpp>
|
||||||
#include <ripple/unity/net.h>
|
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
|
||||||
#include <boost/optional.hpp>
|
|
||||||
|
|
||||||
#include <ripple/http/impl/Port.cpp>
|
#include <ripple/http/impl/Port.cpp>
|
||||||
#include <ripple/http/impl/ScopedStream.cpp>
|
#include <ripple/http/impl/ScopedStream.cpp>
|
||||||
|
|
||||||
#include <ripple/http/impl/Types.h>
|
|
||||||
#include <ripple/http/impl/ServerImpl.h>
|
|
||||||
#include <ripple/http/impl/Peer.h>
|
|
||||||
#include <ripple/http/impl/Door.h>
|
|
||||||
#include <ripple/http/impl/ServerImpl.cpp>
|
#include <ripple/http/impl/ServerImpl.cpp>
|
||||||
#include <ripple/http/impl/Server.cpp>
|
#include <ripple/http/impl/Server.cpp>
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
This file is part of rippled: https://github.com/ripple/rippled
|
|
||||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
|
||||||
|
|
||||||
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 RIPPLE_HTTP_H_INCLUDED
|
|
||||||
#define RIPPLE_HTTP_H_INCLUDED
|
|
||||||
|
|
||||||
// VFALCO This entire file is deprecated now, I'm working on a replacement
|
|
||||||
|
|
||||||
// VFALCO NOTE this sucks that we have to include asio in the header
|
|
||||||
// just for HTTPMessage!!
|
|
||||||
#include <beast/module/asio/asio.h>
|
|
||||||
|
|
||||||
#include <ripple/http/api/Port.h>
|
|
||||||
#include <ripple/http/api/ScopedStream.h>
|
|
||||||
#include <ripple/http/api/Session.h>
|
|
||||||
#include <ripple/http/api/Handler.h>
|
|
||||||
#include <ripple/http/api/Server.h>
|
|
||||||
|
|
||||||
#endif
|
|
||||||
Reference in New Issue
Block a user