mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-17 17:45:52 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a0e806f78 | ||
|
|
20c9632996 | ||
|
|
65a628ca88 | ||
|
|
d82dbba096 | ||
|
|
704d7451a0 |
@@ -1898,18 +1898,18 @@
|
||||
<ClCompile Include="..\..\src\ripple\common\tests\cross_offer.test.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\http\api\Handler.h">
|
||||
<ClInclude Include="..\..\src\ripple\http\Server.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\http\api\Port.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 Include="..\..\src\ripple\http\Session.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\http\impl\Door.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\http\impl\Door.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\http\impl\Peer.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\http\impl\Peer.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\http\impl\Port.cpp">
|
||||
@@ -3448,8 +3448,6 @@
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\unity\http.cpp">
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\unity\http.h">
|
||||
</ClInclude>
|
||||
<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)'=='release|x64'">..\..\src\hyperleveldb;..\..\src\snappy\config;..\..\src\snappy\snappy;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
|
||||
@@ -334,9 +334,6 @@
|
||||
<Filter Include="ripple\http">
|
||||
<UniqueIdentifier>{8601C61D-413C-725E-C9E6-BD4F97E40032}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="ripple\http\api">
|
||||
<UniqueIdentifier>{F98B3E94-4FB9-98FF-C625-533A969D1210}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="ripple\http\impl">
|
||||
<UniqueIdentifier>{43D68742-4714-D103-EE00-EB10BD045FB6}</UniqueIdentifier>
|
||||
</Filter>
|
||||
@@ -2856,24 +2853,21 @@
|
||||
<ClCompile Include="..\..\src\ripple\common\tests\cross_offer.test.cpp">
|
||||
<Filter>ripple\common\tests</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\http\api\Handler.h">
|
||||
<Filter>ripple\http\api</Filter>
|
||||
<ClInclude Include="..\..\src\ripple\http\Server.h">
|
||||
<Filter>ripple\http</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\http\api\Port.h">
|
||||
<Filter>ripple\http\api</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 Include="..\..\src\ripple\http\Session.h">
|
||||
<Filter>ripple\http</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\http\impl\Door.cpp">
|
||||
<Filter>ripple\http\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\http\impl\Door.h">
|
||||
<Filter>ripple\http\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\http\impl\Peer.cpp">
|
||||
<Filter>ripple\http\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\http\impl\Peer.h">
|
||||
<Filter>ripple\http\impl</Filter>
|
||||
</ClInclude>
|
||||
@@ -4740,9 +4734,6 @@
|
||||
<ClCompile Include="..\..\src\ripple\unity\http.cpp">
|
||||
<Filter>ripple\unity</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\unity\http.h">
|
||||
<Filter>ripple\unity</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\unity\hyperleveldb.cpp">
|
||||
<Filter>ripple\unity</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Name: rippled
|
||||
Version: 0.26.0
|
||||
Version: 0.26.1
|
||||
Release: 1%{?dist}
|
||||
Summary: Ripple peer-to-peer network daemon
|
||||
|
||||
|
||||
@@ -227,4 +227,10 @@
|
||||
#define RIPPLE_STRUCTURED_OVERLAY 0
|
||||
#endif
|
||||
|
||||
/** Config: RIPPLE_ASYNC_RPC_HANDLER
|
||||
*/
|
||||
#ifndef RIPPLE_ASYNC_RPC_HANDLER
|
||||
#define RIPPLE_ASYNC_RPC_HANDLER 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -56,6 +56,7 @@ private:
|
||||
public:
|
||||
typedef void result_type;
|
||||
|
||||
explicit
|
||||
bound_handler (DeducedHandler&& handler, Args&&... args)
|
||||
: m_handler (std::forward <DeducedHandler> (handler))
|
||||
, m_args (std::forward <Args> (args)...)
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#ifndef BEAST_ASIO_BASICS_SSLCONTEXT_H_INCLUDED
|
||||
#define BEAST_ASIO_BASICS_SSLCONTEXT_H_INCLUDED
|
||||
|
||||
#include <beast/Uncopyable.h>
|
||||
#include <boost/asio/ssl/context.hpp>
|
||||
|
||||
namespace beast {
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#ifndef BEAST_ASIO_SHAREDARG_H_INCLUDED
|
||||
#define BEAST_ASIO_SHAREDARG_H_INCLUDED
|
||||
|
||||
#include <beast/smart_ptr/SharedPtr.h>
|
||||
|
||||
namespace beast {
|
||||
namespace asio {
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace beast {
|
||||
|
||||
HTTPHeaders::HTTPHeaders ()
|
||||
@@ -86,4 +88,20 @@ String HTTPHeaders::toString () const
|
||||
return s;
|
||||
}
|
||||
|
||||
std::map <std::string, std::string>
|
||||
HTTPHeaders::build_map() const
|
||||
{
|
||||
std::map <std::string, std::string> c;
|
||||
auto const& k (m_fields.getAllKeys());
|
||||
auto const& v (m_fields.getAllValues());
|
||||
for (std::size_t i = 0; i < m_fields.size(); ++i)
|
||||
{
|
||||
auto key (k[i].toStdString());
|
||||
auto const value (v[i].toStdString());
|
||||
std::transform (key.begin(), key.end(), key.begin(), ::tolower);
|
||||
c[key] = value;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
#define BEAST_ASIO_HTTPHEADERS_H_INCLUDED
|
||||
|
||||
#include <beast/module/asio/http/HTTPField.h>
|
||||
|
||||
#include <beast/module/core/text/StringPairArray.h>
|
||||
#include <map>
|
||||
|
||||
namespace beast {
|
||||
|
||||
@@ -70,6 +70,10 @@ public:
|
||||
/** Outputs all the headers into one string. */
|
||||
String toString () const;
|
||||
|
||||
// VFALCO HACK to present the headers in a useful format
|
||||
std::map <std::string, std::string>
|
||||
build_map() const;
|
||||
|
||||
private:
|
||||
StringPairArray m_fields;
|
||||
};
|
||||
|
||||
@@ -96,15 +96,6 @@ public:
|
||||
private:
|
||||
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;
|
||||
|
||||
|
||||
@@ -20,13 +20,80 @@
|
||||
#ifndef 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 <ostream>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
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;
|
||||
|
||||
/** Multi-threaded, asynchronous HTTP server. */
|
||||
@@ -39,17 +106,19 @@ public:
|
||||
/** Destroy the server.
|
||||
This blocks until the server stops.
|
||||
*/
|
||||
virtual ~Server ();
|
||||
|
||||
virtual
|
||||
~Server ();
|
||||
/** Returns the Journal associated with the server. */
|
||||
beast::Journal const& journal () const;
|
||||
beast::Journal
|
||||
journal () const;
|
||||
|
||||
/** Returns the listening ports settings.
|
||||
Thread safety:
|
||||
Safe to call from any thread.
|
||||
Cannot be called concurrently with setPorts.
|
||||
*/
|
||||
Ports const& getPorts () const;
|
||||
Ports const&
|
||||
getPorts () const;
|
||||
|
||||
/** Set the listening ports settings.
|
||||
These take effect immediately. Any current ports that are not in the
|
||||
@@ -57,13 +126,15 @@ public:
|
||||
Thread safety:
|
||||
Cannot be called concurrently.
|
||||
*/
|
||||
void setPorts (Ports const& ports);
|
||||
void
|
||||
setPorts (Ports const& ports);
|
||||
|
||||
/** Notify the server to stop, without blocking.
|
||||
Thread safety:
|
||||
Safe to call concurrently from any thread.
|
||||
*/
|
||||
void stopAsync ();
|
||||
void
|
||||
stopAsync ();
|
||||
|
||||
/** Notify the server to stop, and block until the stop is complete.
|
||||
The handler's onStopped method will be called when the stop completes.
|
||||
@@ -71,13 +142,14 @@ public:
|
||||
Cannot be called concurrently.
|
||||
Cannot be called from the thread of execution of any Handler functions.
|
||||
*/
|
||||
void stop ();
|
||||
void
|
||||
stop ();
|
||||
|
||||
private:
|
||||
std::unique_ptr <ServerImpl> m_impl;
|
||||
};
|
||||
|
||||
} // namespace HTTP
|
||||
} // namespace ripple
|
||||
} // HTTP
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
@@ -24,13 +24,52 @@
|
||||
#include <beast/net/IPEndpoint.h>
|
||||
#include <beast/utility/Journal.h>
|
||||
#include <beast/module/asio/http/HTTPRequest.h>
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
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.
|
||||
These values are preserved between calls for efficiency.
|
||||
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
|
||||
#define RIPPLE_HTTP_DOOR_H_INCLUDED
|
||||
|
||||
#include <ripple/http/impl/ServerImpl.h>
|
||||
#include <ripple/http/impl/Types.h>
|
||||
#include <beast/asio/placeholders.h>
|
||||
|
||||
namespace ripple {
|
||||
@@ -28,95 +30,37 @@ namespace HTTP {
|
||||
/** A listening socket. */
|
||||
class Door
|
||||
: public beast::SharedObject
|
||||
, public beast::asio::AsyncObject <Door>
|
||||
, public beast::List <Door>::Node
|
||||
, public beast::LeakChecked <Door>
|
||||
{
|
||||
public:
|
||||
private:
|
||||
// VFALCO TODO Use shared_ptr
|
||||
typedef beast::SharedPtr <Door> Ptr;
|
||||
|
||||
ServerImpl& m_impl;
|
||||
acceptor m_acceptor;
|
||||
Port m_port;
|
||||
ServerImpl& impl_;
|
||||
acceptor acceptor_;
|
||||
Port port_;
|
||||
|
||||
Door (ServerImpl& impl, Port const& port)
|
||||
: m_impl (impl)
|
||||
, m_acceptor (m_impl.get_io_service(), to_asio (port))
|
||||
, m_port (port)
|
||||
{
|
||||
m_impl.add (*this);
|
||||
public:
|
||||
Door (ServerImpl& impl, Port const& port);
|
||||
|
||||
error_code ec;
|
||||
~Door ();
|
||||
|
||||
m_acceptor.set_option (acceptor::reuse_address (true), ec);
|
||||
if (ec)
|
||||
{
|
||||
m_impl.journal().error <<
|
||||
"Error setting acceptor socket option: " << ec.message();
|
||||
}
|
||||
Port const&
|
||||
port () const;
|
||||
|
||||
if (! ec)
|
||||
{
|
||||
m_impl.journal().info << "Bound to endpoint " <<
|
||||
to_string (m_acceptor.local_endpoint());
|
||||
void
|
||||
cancel ();
|
||||
|
||||
async_accept();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_impl.journal().error << "Error binding to endpoint " <<
|
||||
to_string (m_acceptor.local_endpoint()) <<
|
||||
", '" << ec.message() << "'";
|
||||
}
|
||||
}
|
||||
void
|
||||
failed (error_code ec);
|
||||
|
||||
~Door ()
|
||||
{
|
||||
m_impl.remove (*this);
|
||||
}
|
||||
void
|
||||
async_accept ();
|
||||
|
||||
Port const& port () const
|
||||
{
|
||||
return m_port;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
void
|
||||
handle_accept (error_code ec,
|
||||
std::shared_ptr <Peer> const& peer);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
#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 <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/http/HTTPRequestParser.h>
|
||||
#include <boost/bind.hpp>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace ripple {
|
||||
namespace HTTP {
|
||||
|
||||
// Holds the copy of buffers being sent
|
||||
// VFALCO TODO Replace with std::shared_ptr<std::string>
|
||||
//
|
||||
typedef beast::asio::SharedArg <std::string> SharedBuffer;
|
||||
|
||||
/** Represents an active connection. */
|
||||
class Peer
|
||||
: public beast::SharedObject
|
||||
, public beast::asio::AsyncObject <Peer>
|
||||
: public std::enable_shared_from_this <Peer>
|
||||
, public Session
|
||||
, public beast::List <Peer>::Node
|
||||
, public beast::LeakChecked <Peer>
|
||||
{
|
||||
public:
|
||||
private:
|
||||
enum
|
||||
{
|
||||
// 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;
|
||||
boost::asio::io_service::strand m_strand;
|
||||
boost::asio::deadline_timer m_data_timer;
|
||||
boost::asio::deadline_timer m_request_timer;
|
||||
std::unique_ptr <MultiSocket> m_socket;
|
||||
beast::MemoryBlock m_buffer;
|
||||
beast::HTTPRequestParser m_parser;
|
||||
int m_writesPending;
|
||||
bool m_closed;
|
||||
bool m_callClose;
|
||||
beast::SharedPtr <Peer> m_detach_ref;
|
||||
boost::optional <boost::asio::io_service::work> m_work;
|
||||
int m_errorCode;
|
||||
std::atomic <int> m_detached;
|
||||
// VFALCO TODO Use c++11
|
||||
beast::MemoryBlock buffer_;
|
||||
|
||||
beast::HTTPRequestParser parser_;
|
||||
int writesPending_;
|
||||
bool closed_;
|
||||
bool callClose_;
|
||||
std::shared_ptr <Peer> detach_ref_;
|
||||
boost::optional <boost::asio::io_service::work> work_;
|
||||
int errorCode_;
|
||||
std::atomic <int> detached_;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
Peer (ServerImpl& impl, Port const& port)
|
||||
: m_impl (impl)
|
||||
, m_strand (m_impl.get_io_service())
|
||||
, 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);
|
||||
}
|
||||
public:
|
||||
Peer (ServerImpl& impl, Port const& port);
|
||||
~Peer ();
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// 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());
|
||||
}
|
||||
|
||||
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.
|
||||
// VFALCO NOTE This is inefficient...
|
||||
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;
|
||||
}
|
||||
std::string
|
||||
content();
|
||||
|
||||
// Send a copy of the data.
|
||||
void 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))));
|
||||
}
|
||||
void
|
||||
write (void const* buffer, std::size_t bytes);
|
||||
|
||||
// Make the Session asynchronous
|
||||
void detach ()
|
||||
{
|
||||
if (m_detached.exchange (1) == 0)
|
||||
{
|
||||
bassert (! m_work);
|
||||
bassert (m_detach_ref.empty());
|
||||
void
|
||||
detach ();
|
||||
|
||||
// Maintain an additional reference while detached
|
||||
m_detach_ref = 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.
|
||||
//
|
||||
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))));
|
||||
}
|
||||
void
|
||||
close ();
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Completion Handlers
|
||||
//
|
||||
|
||||
// Called when the last pending completion handler returns.
|
||||
void asyncHandlersComplete ()
|
||||
{
|
||||
}
|
||||
void
|
||||
handle_handshake (error_code ec);
|
||||
|
||||
// Called when the acceptor accepts our socket.
|
||||
void handle_accept ()
|
||||
{
|
||||
m_callClose = true;
|
||||
void
|
||||
handle_data_timer (error_code ec);
|
||||
|
||||
m_impl.handler().onAccept (session());
|
||||
void
|
||||
handle_request_timer (error_code ec);
|
||||
|
||||
if (m_closed)
|
||||
{
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
void
|
||||
handle_write (error_code ec, std::size_t bytes_transferred,
|
||||
SharedBuffer const& buf);
|
||||
|
||||
m_request_timer.expires_from_now (
|
||||
boost::posix_time::seconds (
|
||||
requestTimeoutSeconds));
|
||||
void
|
||||
handle_read (error_code ec, std::size_t bytes_transferred);
|
||||
|
||||
m_request_timer.async_wait (m_strand.wrap (boost::bind (
|
||||
&Peer::handle_request_timer, Ptr(this),
|
||||
boost::asio::placeholders::error,
|
||||
CompletionCounter (this))));
|
||||
void
|
||||
handle_headers ();
|
||||
|
||||
if (m_socket->needs_handshake ())
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
void
|
||||
handle_request ();
|
||||
|
||||
// Called from an io_service thread to write the shared buffer.
|
||||
void handle_write (SharedBuffer const& buf, CompletionCounter)
|
||||
{
|
||||
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;
|
||||
}
|
||||
void
|
||||
handle_close ();
|
||||
|
||||
public:
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Peer
|
||||
//
|
||||
|
||||
// Returns the asio socket for the peer.
|
||||
socket& 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;
|
||||
}
|
||||
|
||||
// Cancel all pending i/o and timers and send tcp shutdown.
|
||||
void cancel ()
|
||||
{
|
||||
error_code ec;
|
||||
m_data_timer.cancel (ec);
|
||||
m_request_timer.cancel (ec);
|
||||
m_socket->cancel (ec);
|
||||
m_socket->shutdown (socket::shutdown_both);
|
||||
}
|
||||
void
|
||||
accept ();
|
||||
|
||||
// Called by a completion handler when error is not eof or aborted.
|
||||
void failed (error_code const& ec)
|
||||
{
|
||||
m_errorCode = ec.value();
|
||||
bassert (m_errorCode != 0);
|
||||
cancel ();
|
||||
}
|
||||
void
|
||||
cancel ();
|
||||
|
||||
// Call the async_read_some initiating function.
|
||||
void async_read_some ()
|
||||
{
|
||||
// re-arm the data timer
|
||||
// (this cancels the previous wait, if any)
|
||||
//
|
||||
m_data_timer.expires_from_now (
|
||||
boost::posix_time::seconds (
|
||||
dataTimeoutSeconds));
|
||||
void
|
||||
failed (error_code const& ec);
|
||||
|
||||
m_data_timer.async_wait (m_strand.wrap (boost::bind (
|
||||
&Peer::handle_data_timer, Ptr(this),
|
||||
boost::asio::placeholders::error,
|
||||
CompletionCounter (this))));
|
||||
void
|
||||
async_read_some ();
|
||||
|
||||
// issue the read
|
||||
//
|
||||
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)));
|
||||
}
|
||||
}
|
||||
void async_write (SharedBuffer const& buf);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -21,16 +21,16 @@ namespace ripple {
|
||||
namespace HTTP {
|
||||
|
||||
Port::Port ()
|
||||
: port (0)
|
||||
, security (no_ssl)
|
||||
: security (no_ssl)
|
||||
, port (0)
|
||||
, context (nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
Port::Port (Port const& other)
|
||||
: port (other.port)
|
||||
: security (other.security)
|
||||
, port (other.port)
|
||||
, addr (other.addr)
|
||||
, security (other.security)
|
||||
, context (other.context)
|
||||
{
|
||||
}
|
||||
@@ -44,14 +44,11 @@ Port& Port::operator= (Port const& other)
|
||||
return *this;
|
||||
}
|
||||
|
||||
Port::Port (
|
||||
std::uint16_t port_,
|
||||
beast::IP::Endpoint const& addr_,
|
||||
Security security_,
|
||||
beast::asio::SSLContext* context_)
|
||||
: port (port_)
|
||||
Port::Port (std::uint16_t port_, beast::IP::Endpoint const& addr_,
|
||||
Security security_, beast::asio::SSLContext* context_)
|
||||
: security (security_)
|
||||
, port (port_)
|
||||
, addr (addr_)
|
||||
, security (security_)
|
||||
, context (context_)
|
||||
{
|
||||
}
|
||||
@@ -88,18 +85,5 @@ bool operator< (Port const& lhs, Port const& rhs)
|
||||
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 HTTP {
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
beast::Journal const& Server::journal () const
|
||||
beast::Journal
|
||||
Server::journal () const
|
||||
{
|
||||
return m_impl->journal();
|
||||
}
|
||||
|
||||
Ports const& Server::getPorts () const
|
||||
Ports const&
|
||||
Server::getPorts () const
|
||||
{
|
||||
return m_impl->getPorts();
|
||||
}
|
||||
|
||||
void Server::setPorts (Ports const& ports)
|
||||
void
|
||||
Server::setPorts (Ports const& ports)
|
||||
{
|
||||
m_impl->setPorts (ports);
|
||||
}
|
||||
|
||||
void Server::stopAsync ()
|
||||
void
|
||||
Server::stopAsync ()
|
||||
{
|
||||
m_impl->stop(false);
|
||||
}
|
||||
|
||||
void Server::stop ()
|
||||
void
|
||||
Server::stop ()
|
||||
{
|
||||
m_impl->stop(true);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/http/impl/ServerImpl.h>
|
||||
|
||||
namespace ripple {
|
||||
namespace HTTP {
|
||||
|
||||
@@ -24,7 +26,7 @@ ServerImpl::ServerImpl (Server& server, Handler& handler, beast::Journal journal
|
||||
: Thread ("HTTP::Server")
|
||||
, m_server (server)
|
||||
, m_handler (handler)
|
||||
, m_journal (journal)
|
||||
, journal_ (journal)
|
||||
, m_strand (m_io_service)
|
||||
, m_work (boost::in_place (std::ref (m_io_service)))
|
||||
, m_stopped (true)
|
||||
@@ -37,11 +39,6 @@ ServerImpl::~ServerImpl ()
|
||||
stopThread ();
|
||||
}
|
||||
|
||||
beast::Journal const& ServerImpl::journal() const
|
||||
{
|
||||
return m_journal;
|
||||
}
|
||||
|
||||
Ports const& ServerImpl::getPorts () const
|
||||
{
|
||||
SharedState::ConstUnlockedAccess state (m_state);
|
||||
@@ -129,7 +126,7 @@ int ServerImpl::compare (Port const& lhs, Port const& rhs)
|
||||
{
|
||||
if (lhs < rhs)
|
||||
return -1;
|
||||
else if (lhs > rhs)
|
||||
else if (rhs < lhs)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -20,8 +20,14 @@
|
||||
#ifndef 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/module/asio/basics/SharedArg.h>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <thread>
|
||||
|
||||
namespace ripple {
|
||||
namespace HTTP {
|
||||
@@ -31,7 +37,7 @@ class Peer;
|
||||
|
||||
class ServerImpl : public beast::Thread
|
||||
{
|
||||
public:
|
||||
private:
|
||||
struct State
|
||||
{
|
||||
// Attributes for our listening ports
|
||||
@@ -49,7 +55,7 @@ public:
|
||||
|
||||
Server& m_server;
|
||||
Handler& m_handler;
|
||||
beast::Journal m_journal;
|
||||
beast::Journal journal_;
|
||||
boost::asio::io_service m_io_service;
|
||||
boost::asio::io_service::strand m_strand;
|
||||
boost::optional <boost::asio::io_service::work> m_work;
|
||||
@@ -57,24 +63,54 @@ public:
|
||||
SharedState m_state;
|
||||
Doors m_doors;
|
||||
|
||||
public:
|
||||
ServerImpl (Server& server, Handler& handler, beast::Journal journal);
|
||||
~ServerImpl ();
|
||||
beast::Journal const& journal() const;
|
||||
Ports const& getPorts () const;
|
||||
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);
|
||||
beast::Journal
|
||||
journal() const
|
||||
{
|
||||
return journal_;
|
||||
}
|
||||
|
||||
void handle_update ();
|
||||
void update ();
|
||||
void run ();
|
||||
Ports const&
|
||||
getPorts () const;
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
@@ -801,6 +801,10 @@ public:
|
||||
//
|
||||
// Allow RPC connections.
|
||||
//
|
||||
#if RIPPLE_ASYNC_RPC_HANDLER
|
||||
m_rpcHTTPServer->setup (m_journal);
|
||||
|
||||
#else
|
||||
if (! getConfig ().getRpcIP().empty () && getConfig ().getRpcPort() != 0)
|
||||
{
|
||||
try
|
||||
@@ -820,6 +824,7 @@ public:
|
||||
{
|
||||
m_journal.info << "RPC interface: disabled";
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Begin connecting to network.
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/common/RippleSSLContext.h>
|
||||
#include <ripple/http/Session.h>
|
||||
#include <ripple/module/app/main/RPCHTTPServer.h>
|
||||
#include <ripple/module/rpc/RPCHandler.h>
|
||||
#include <ripple/module/rpc/RPCServerHandler.h>
|
||||
@@ -75,9 +76,12 @@ public:
|
||||
getConfig ().getRpcPort() != 0)
|
||||
{
|
||||
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;
|
||||
port.security = HTTP::Port::allow_ssl;
|
||||
port.addr = ep.at_port(0);
|
||||
if (getConfig ().getRpcPort() != 0)
|
||||
port.port = getConfig ().getRpcPort();
|
||||
@@ -131,16 +135,24 @@ public:
|
||||
|
||||
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
|
||||
// Synchronous version that doesn't use job queue
|
||||
Job job;
|
||||
processSession (job, session);
|
||||
|
||||
#else
|
||||
session.detach();
|
||||
|
||||
// The "boost::"'s are a workaround for broken versions of tr1::functional that
|
||||
// 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 (
|
||||
m_jobQueue.addJob (jtCLIENT, "RPC-Client", std::bind (
|
||||
&RPCHTTPServerImp::processSession, this, std::placeholders::_1,
|
||||
std::ref (session)));
|
||||
#endif
|
||||
@@ -159,8 +171,14 @@ public:
|
||||
|
||||
void processSession (Job& job, HTTP::Session& session)
|
||||
{
|
||||
#if 0
|
||||
// Goes through the old code
|
||||
session.write (m_deprecatedHandler.processRequest (
|
||||
session.content(), session.remoteAddress().at_port(0)));
|
||||
#else
|
||||
session.write (processRequest (session.content(),
|
||||
session.remoteAddress().at_port(0)));
|
||||
#endif
|
||||
|
||||
session.close();
|
||||
}
|
||||
@@ -172,14 +190,10 @@ public:
|
||||
return HTTPReply (statusCode, description);
|
||||
}
|
||||
|
||||
bool isAuthorized (
|
||||
std::map <std::string, std::string> const& headers)
|
||||
{
|
||||
return HTTPAuthorized (headers);
|
||||
}
|
||||
|
||||
// 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;
|
||||
{
|
||||
@@ -247,14 +261,6 @@ public:
|
||||
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;
|
||||
|
||||
m_journal.debug << "Query: " << strMethod << params;
|
||||
|
||||
@@ -77,10 +77,10 @@ CreateOffer::checkAcceptAsset(IssueRef issue) const
|
||||
// ordering. Determine which entry we need to access.
|
||||
bool const canonical_gt (mTxnAccountID > issue.account);
|
||||
|
||||
bool const need_auth (trustLine->getFieldU32 (sfFlags) &
|
||||
bool const is_authorized (trustLine->getFieldU32 (sfFlags) &
|
||||
(canonical_gt ? lsfLowAuth : lsfHighAuth));
|
||||
|
||||
if (need_auth)
|
||||
if (!is_authorized)
|
||||
{
|
||||
if (m_journal.debug) m_journal.debug <<
|
||||
"delay: can't receive IOUs from issuer without auth.";
|
||||
|
||||
@@ -31,7 +31,7 @@ char const* BuildInfo::getRawVersionString ()
|
||||
//
|
||||
// The build version number (edit this for each release)
|
||||
//
|
||||
"0.26.0"
|
||||
"0.26.1"
|
||||
//
|
||||
// Must follow the format described here:
|
||||
//
|
||||
|
||||
@@ -262,10 +262,14 @@ std::string DecodeBase64 (std::string s)
|
||||
|
||||
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 "))
|
||||
return getConfig ().RPC_USER.empty () && getConfig ().RPC_PASSWORD.empty ();
|
||||
return false;
|
||||
|
||||
std::string strUserPass64 = it->second.substr (6);
|
||||
boost::trim (strUserPass64);
|
||||
|
||||
@@ -23,11 +23,12 @@
|
||||
#include <ripple/unity/net.h>
|
||||
#include <ripple/unity/rpcx.h>
|
||||
#include <ripple/unity/websocket.h>
|
||||
#include <ripple/unity/http.h>
|
||||
#include <ripple/unity/resource.h>
|
||||
#include <ripple/unity/sitefiles.h>
|
||||
#include <ripple/unity/validators.h>
|
||||
|
||||
#include <ripple/http/Server.h>
|
||||
|
||||
#include <ripple/module/app/main/CollectorManager.cpp>
|
||||
#include <ripple/module/app/main/NodeStoreScheduler.cpp>
|
||||
#include <ripple/module/app/main/IoServicePool.cpp>
|
||||
|
||||
@@ -19,19 +19,9 @@
|
||||
|
||||
#include <BeastConfig.h>
|
||||
|
||||
#include <ripple/unity/http.h>
|
||||
|
||||
#include <ripple/unity/net.h>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <ripple/http/impl/Door.cpp>
|
||||
#include <ripple/http/impl/Peer.cpp>
|
||||
#include <ripple/http/impl/Port.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/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