Refactor Server (RIPD-1120):

* Make Handler a template argument
This commit is contained in:
Vinnie Falco
2016-05-20 08:44:13 -04:00
parent 80a9a2bf5d
commit 289c8c9f09
53 changed files with 997 additions and 1176 deletions

View File

@@ -3302,6 +3302,10 @@
</ClCompile>
<ClInclude Include="..\..\src\ripple\rpc\impl\LegacyPathFind.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\rpc\impl\Role.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\rpc\impl\RPCHandler.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
@@ -3312,6 +3316,12 @@
</ClCompile>
<ClInclude Include="..\..\src\ripple\rpc\impl\RPCHelpers.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\rpc\impl\ServerHandlerImp.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClInclude Include="..\..\src\ripple\rpc\impl\ServerHandlerImp.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\rpc\impl\Status.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
@@ -3324,12 +3334,20 @@
</ClInclude>
<ClInclude Include="..\..\src\ripple\rpc\impl\Tuning.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\rpc\impl\WSInfoSub.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\rpc\InternalHandler.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\rpc\json_body.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\rpc\RipplePathFind.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\rpc\Role.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\rpc\RPCHandler.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\rpc\ServerHandler.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\rpc\Status.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\rpc\tests\AccountInfo_test.cpp">
@@ -3370,8 +3388,6 @@
</ClCompile>
<ClInclude Include="..\..\src\ripple\rpc\tests\TestOutputSuite.test.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\server\Handler.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\server\Handoff.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\server\impl\BaseHTTPPeer.h">
@@ -3380,10 +3396,6 @@
</ClInclude>
<ClInclude Include="..\..\src\ripple\server\impl\BaseWSPeer.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\server\impl\Door.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClInclude Include="..\..\src\ripple\server\impl\Door.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\server\impl\io_list.h">
@@ -3402,42 +3414,16 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\server\impl\Role.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\server\impl\ServerHandlerImp.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClInclude Include="..\..\src\ripple\server\impl\ServerHandlerImp.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\server\impl\ServerImpl.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClInclude Include="..\..\src\ripple\server\impl\ServerImpl.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\server\impl\SSLHTTPPeer.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\server\impl\SSLWSPeer.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\server\json_body.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\server\make_Server.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\server\make_ServerHandler.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\server\Port.h">
</ClInclude>
<None Include="..\..\src\ripple\server\README.md">
</None>
<ClInclude Include="..\..\src\ripple\server\Role.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\server\Server.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\server\ServerHandler.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\server\Session.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\server\SimpleWriter.h">

View File

@@ -3762,6 +3762,9 @@
<ClInclude Include="..\..\src\ripple\rpc\impl\LegacyPathFind.h">
<Filter>ripple\rpc\impl</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\rpc\impl\Role.cpp">
<Filter>ripple\rpc\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\rpc\impl\RPCHandler.cpp">
<Filter>ripple\rpc\impl</Filter>
</ClCompile>
@@ -3771,6 +3774,12 @@
<ClInclude Include="..\..\src\ripple\rpc\impl\RPCHelpers.h">
<Filter>ripple\rpc\impl</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\rpc\impl\ServerHandlerImp.cpp">
<Filter>ripple\rpc\impl</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ripple\rpc\impl\ServerHandlerImp.h">
<Filter>ripple\rpc\impl</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\rpc\impl\Status.cpp">
<Filter>ripple\rpc\impl</Filter>
</ClCompile>
@@ -3783,15 +3792,27 @@
<ClInclude Include="..\..\src\ripple\rpc\impl\Tuning.h">
<Filter>ripple\rpc\impl</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\rpc\impl\WSInfoSub.h">
<Filter>ripple\rpc\impl</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\rpc\InternalHandler.h">
<Filter>ripple\rpc</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\rpc\json_body.h">
<Filter>ripple\rpc</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\rpc\RipplePathFind.h">
<Filter>ripple\rpc</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\rpc\Role.h">
<Filter>ripple\rpc</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\rpc\RPCHandler.h">
<Filter>ripple\rpc</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\rpc\ServerHandler.h">
<Filter>ripple\rpc</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\rpc\Status.h">
<Filter>ripple\rpc</Filter>
</ClInclude>
@@ -3825,9 +3846,6 @@
<ClInclude Include="..\..\src\ripple\rpc\tests\TestOutputSuite.test.h">
<Filter>ripple\rpc\tests</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\server\Handler.h">
<Filter>ripple\server</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\server\Handoff.h">
<Filter>ripple\server</Filter>
</ClInclude>
@@ -3840,9 +3858,6 @@
<ClInclude Include="..\..\src\ripple\server\impl\BaseWSPeer.h">
<Filter>ripple\server\impl</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\server\impl\Door.cpp">
<Filter>ripple\server\impl</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ripple\server\impl\Door.h">
<Filter>ripple\server\impl</Filter>
</ClInclude>
@@ -3864,18 +3879,6 @@
<ClCompile Include="..\..\src\ripple\server\impl\Port.cpp">
<Filter>ripple\server\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\server\impl\Role.cpp">
<Filter>ripple\server\impl</Filter>
</ClCompile>
<ClCompile Include="..\..\src\ripple\server\impl\ServerHandlerImp.cpp">
<Filter>ripple\server\impl</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ripple\server\impl\ServerHandlerImp.h">
<Filter>ripple\server\impl</Filter>
</ClInclude>
<ClCompile Include="..\..\src\ripple\server\impl\ServerImpl.cpp">
<Filter>ripple\server\impl</Filter>
</ClCompile>
<ClInclude Include="..\..\src\ripple\server\impl\ServerImpl.h">
<Filter>ripple\server\impl</Filter>
</ClInclude>
@@ -3885,30 +3888,12 @@
<ClInclude Include="..\..\src\ripple\server\impl\SSLWSPeer.h">
<Filter>ripple\server\impl</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\server\json_body.h">
<Filter>ripple\server</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\server\make_Server.h">
<Filter>ripple\server</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\server\make_ServerHandler.h">
<Filter>ripple\server</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\server\Port.h">
<Filter>ripple\server</Filter>
</ClInclude>
<None Include="..\..\src\ripple\server\README.md">
<Filter>ripple\server</Filter>
</None>
<ClInclude Include="..\..\src\ripple\server\Role.h">
<Filter>ripple\server</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\server\Server.h">
<Filter>ripple\server</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\server\ServerHandler.h">
<Filter>ripple\server</Filter>
</ClInclude>
<ClInclude Include="..\..\src\ripple\server\Session.h">
<Filter>ripple\server</Filter>
</ClInclude>

View File

@@ -67,7 +67,6 @@
#include <ripple/protocol/SecretKey.h>
#include <ripple/protocol/STParsedJSON.h>
#include <ripple/protocol/types.h>
#include <ripple/server/make_ServerHandler.h>
#include <ripple/shamap/Family.h>
#include <ripple/unity/git_id.h>
#include <ripple/websocket/MakeServer.h>

View File

@@ -34,7 +34,6 @@
#include <ripple/net/RPCCall.h>
#include <ripple/resource/Fees.h>
#include <ripple/rpc/RPCHandler.h>
#include <ripple/server/Role.h>
#include <ripple/protocol/BuildInfo.h>
#include <ripple/beast/clock/basic_seconds_clock.h>
#include <ripple/beast/core/Time.h>

View File

@@ -33,11 +33,12 @@
#include <ripple/protocol/Feature.h>
#include <ripple/protocol/SystemParameters.h>
#include <ripple/protocol/types.h>
#include <ripple/server/ServerHandler.h>
#include <ripple/rpc/ServerHandler.h>
#include <ripple/beast/core/LexicalCast.h>
#include <beast/core/detail/ci_char_traits.hpp>
#include <boost/asio/streambuf.hpp>
#include <boost/regex.hpp>
#include <openssl/bio.h>
#include <iostream>
#include <type_traits>

View File

@@ -27,7 +27,7 @@
#include <ripple/basics/make_SSLContext.h>
#include <ripple/beast/rfc2616.h>
#include <ripple/protocol/JsonFields.h>
#include <ripple/server/json_body.h>
#include <ripple/rpc/json_body.h>
#include <ripple/server/SimpleWriter.h>
#include <ripple/overlay/Cluster.h>
#include <ripple/overlay/impl/ConnectAttempt.h>

View File

@@ -26,7 +26,7 @@
#include <ripple/overlay/impl/Manifest.h>
#include <ripple/overlay/impl/TrafficCount.h>
#include <ripple/server/Handoff.h>
#include <ripple/server/ServerHandler.h>
#include <ripple/rpc/ServerHandler.h>
#include <ripple/basics/Resolver.h>
#include <ripple/basics/chrono.h>
#include <ripple/basics/UnorderedContainers.h>

View File

@@ -39,7 +39,7 @@
#include <ripple/core/TimeKeeper.h>
#include <ripple/json/json_reader.h>
#include <ripple/resource/Fees.h>
#include <ripple/server/ServerHandler.h>
#include <ripple/rpc/ServerHandler.h>
#include <ripple/overlay/Cluster.h>
#include <ripple/overlay/ClusterNode.h>
#include <ripple/protocol/BuildInfo.h>

View File

@@ -20,7 +20,7 @@
#ifndef RIPPLE_OVERLAY_MAKE_OVERLAY_H_INCLUDED
#define RIPPLE_OVERLAY_MAKE_OVERLAY_H_INCLUDED
#include <ripple/server/ServerHandler.h>
#include <ripple/rpc/ServerHandler.h>
#include <ripple/overlay/Overlay.h>
#include <ripple/resource/ResourceManager.h>
#include <ripple/basics/Resolver.h>

View File

@@ -23,7 +23,7 @@
#include <ripple/core/Config.h>
#include <ripple/core/JobCoro.h>
#include <ripple/net/InfoSub.h>
#include <ripple/server/Role.h>
#include <ripple/rpc/Role.h>
#include <ripple/beast/utility/Journal.h>

View File

@@ -17,19 +17,30 @@
*/
//==============================================================================
#ifndef RIPPLE_SERVER_MAKE_SERVERHANDLER_H_INCLUDED
#define RIPPLE_SERVER_MAKE_SERVERHANDLER_H_INCLUDED
#ifndef RIPPLE_RPC_SERVERHANDLER_H_INCLUDED
#define RIPPLE_RPC_SERVERHANDLER_H_INCLUDED
#include <ripple/basics/BasicConfig.h>
#include <ripple/core/Config.h>
#include <ripple/core/JobQueue.h>
#include <ripple/resource/ResourceManager.h>
#include <ripple/server/ServerHandler.h>
#include <ripple/core/Stoppable.h>
#include <ripple/server/Port.h>
#include <ripple/resource/ResourceManager.h>
#include <ripple/rpc/impl/ServerHandlerImp.h>
#include <ripple/beast/utility/Journal.h>
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/address.hpp>
#include <memory>
#include <vector>
namespace ripple {
class NetworkOPs;
using ServerHandler = ServerHandlerImp;
ServerHandler::Setup
setup_ServerHandler (
Config const& c,
std::ostream& log);
std::unique_ptr <ServerHandler>
make_ServerHandler (Application& app, Stoppable& parent, boost::asio::io_service&,

View File

@@ -1,6 +0,0 @@
# RPC TODO
- Redo the interface to actually work correctly for the existing
use-cases that the old code supports. Specifically that RPC commands
can be issued for a particular context like a websocket connection
or other subscriber.

View File

@@ -31,7 +31,7 @@
#include <ripple/resource/Fees.h>
#include <ripple/rpc/Context.h>
#include <ripple/rpc/impl/RPCHelpers.h>
#include <ripple/server/Role.h>
#include <ripple/rpc/Role.h>
namespace ripple {

View File

@@ -29,7 +29,7 @@
#include <ripple/resource/Fees.h>
#include <ripple/rpc/Context.h>
#include <ripple/rpc/impl/RPCHelpers.h>
#include <ripple/server/Role.h>
#include <ripple/rpc/Role.h>
namespace ripple {

View File

@@ -25,7 +25,7 @@
#include <ripple/rpc/impl/RPCHelpers.h>
#include <ripple/rpc/impl/Tuning.h>
#include <ripple/rpc/Context.h>
#include <ripple/server/Role.h>
#include <ripple/rpc/Role.h>
namespace ripple {

View File

@@ -27,7 +27,7 @@
#include <ripple/protocol/JsonFields.h>
#include <ripple/resource/Fees.h>
#include <ripple/rpc/impl/RPCHelpers.h>
#include <ripple/server/Role.h>
#include <ripple/rpc/Role.h>
namespace ripple {
namespace RPC {

View File

@@ -30,7 +30,7 @@
#include <ripple/rpc/Context.h>
#include <ripple/rpc/Status.h>
#include <ripple/rpc/impl/Handler.h>
#include <ripple/server/Role.h>
#include <ripple/rpc/Role.h>
namespace Json {
class Object;

View File

@@ -20,7 +20,7 @@
#include <BeastConfig.h>
#include <ripple/json/json_value.h>
#include <ripple/protocol/JsonFields.h>
#include <ripple/server/Role.h>
#include <ripple/rpc/Role.h>
#include <ripple/rpc/Context.h>
namespace ripple {

View File

@@ -43,7 +43,7 @@
#include <ripple/rpc/impl/LegacyPathFind.h>
#include <ripple/rpc/impl/RPCHelpers.h>
#include <ripple/rpc/impl/Tuning.h>
#include <ripple/server/Role.h>
#include <ripple/rpc/Role.h>
namespace ripple {

View File

@@ -24,7 +24,7 @@
#include <ripple/protocol/JsonFields.h>
#include <ripple/rpc/Context.h>
#include <ripple/rpc/impl/TransactionSign.h>
#include <ripple/server/Role.h>
#include <ripple/rpc/Role.h>
namespace ripple {

View File

@@ -24,7 +24,7 @@
#include <ripple/protocol/JsonFields.h>
#include <ripple/rpc/Context.h>
#include <ripple/rpc/impl/TransactionSign.h>
#include <ripple/server/Role.h>
#include <ripple/rpc/Role.h>
namespace ripple {

View File

@@ -30,7 +30,7 @@
#include <ripple/resource/Fees.h>
#include <ripple/rpc/impl/RPCHelpers.h>
#include <ripple/rpc/Context.h>
#include <ripple/server/Role.h>
#include <ripple/rpc/Role.h>
namespace ripple {

View File

@@ -27,7 +27,7 @@
#include <ripple/protocol/ErrorCodes.h>
#include <ripple/resource/Fees.h>
#include <ripple/rpc/Context.h>
#include <ripple/server/Role.h>
#include <ripple/rpc/Role.h>
#include <boost/format.hpp>
namespace ripple {

View File

@@ -25,7 +25,7 @@
#include <ripple/protocol/JsonFields.h>
#include <ripple/rpc/Context.h>
#include <ripple/rpc/impl/RPCHelpers.h>
#include <ripple/server/Role.h>
#include <ripple/rpc/Role.h>
namespace ripple {

View File

@@ -35,7 +35,7 @@
#include <ripple/net/RPCErr.h>
#include <ripple/protocol/JsonFields.h>
#include <ripple/resource/Fees.h>
#include <ripple/server/Role.h>
#include <ripple/rpc/Role.h>
#include <ripple/resource/Fees.h>
namespace ripple {

View File

@@ -18,7 +18,7 @@
//==============================================================================
#include <BeastConfig.h>
#include <ripple/server/Role.h>
#include <ripple/rpc/Role.h>
namespace ripple {

View File

@@ -23,17 +23,17 @@
#include <ripple/beast/rfc2616.h>
#include <ripple/beast/net/IPAddressConversion.h>
#include <ripple/json/json_reader.h>
#include <ripple/server/json_body.h>
#include <ripple/server/make_ServerHandler.h>
#include <ripple/rpc/json_body.h>
#include <ripple/rpc/ServerHandler.h>
#include <ripple/server/Server.h>
#include <ripple/server/impl/JSONRPCUtil.h>
#include <ripple/server/impl/ServerHandlerImp.h>
#include <ripple/rpc/impl/ServerHandlerImp.h>
#include <ripple/basics/contract.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/make_SSLContext.h>
#include <ripple/core/JobQueue.h>
#include <ripple/json/to_string.h>
#include <ripple/net/RPCErr.h>
#include <ripple/server/make_Server.h>
#include <ripple/overlay/Overlay.h>
#include <ripple/resource/ResourceManager.h>
#include <ripple/resource/Fees.h>
@@ -50,18 +50,11 @@
namespace ripple {
ServerHandler::ServerHandler (Stoppable& parent)
: Stoppable ("ServerHandler", parent)
{
}
//------------------------------------------------------------------------------
ServerHandlerImp::ServerHandlerImp (Application& app, Stoppable& parent,
boost::asio::io_service& io_service, JobQueue& jobQueue,
NetworkOPs& networkOPs, Resource::Manager& resourceManager,
CollectorManager& cm)
: ServerHandler (parent)
: Stoppable("ServerHandler", parent)
, app_ (app)
, m_resourceManager (resourceManager)
, m_journal (app_.journal("Server"))

View File

@@ -17,22 +17,20 @@
*/
//==============================================================================
#ifndef RIPPLE_SERVER_SERVERHANDLERIMP_H_INCLUDED
#define RIPPLE_SERVER_SERVERHANDLERIMP_H_INCLUDED
#ifndef RIPPLE_RPC_SERVERHANDLERIMP_H_INCLUDED
#define RIPPLE_RPC_SERVERHANDLERIMP_H_INCLUDED
#include <ripple/core/Job.h>
#include <ripple/core/JobCoro.h>
#include <ripple/json/Output.h>
#include <ripple/json/to_string.h>
#include <ripple/net/InfoSub.h>
#include <ripple/server/Handler.h>
#include <ripple/server/ServerHandler.h>
#include <ripple/rpc/impl/WSInfoSub.h>
#include <ripple/server/Server.h>
#include <ripple/server/Session.h>
#include <ripple/server/WSSession.h>
#include <ripple/rpc/RPCHandler.h>
#include <ripple/app/main/CollectorManager.h>
#include <map>
#include <mutex>
#include <vector>
namespace ripple {
@@ -42,69 +40,42 @@ bool operator< (Port const& lhs, Port const& rhs)
return lhs.name < rhs.name;
}
class WSInfoSub : public InfoSub
class ServerHandlerImp
: public Stoppable
{
std::weak_ptr<WSSession> ws_;
std::string user_;
std::string fwdfor_;
public:
WSInfoSub(Source& source,
std::shared_ptr<WSSession> const& ws)
: InfoSub(source)
, ws_(ws)
struct Setup
{
auto const& h = ws->request().headers;
auto it = h.find("X-User");
if (it != h.end() &&
isIdentified(
ws->port(), beast::IPAddressConversion::from_asio(
ws->remote_endpoint()).address(), it->second))
{
user_ = it->second;
it = h.find("X-Forwarded-For");
if (it != h.end())
fwdfor_ = it->second;
}
}
std::vector<Port> ports;
std::string
user() const
// Memberspace
struct client_t
{
return user_;
}
bool secure = false;
std::string ip;
std::uint16_t port = 0;
std::string user;
std::string password;
std::string admin_user;
std::string admin_password;
};
std::string
forwarded_for() const
// Configuration when acting in client role
client_t client;
// Configuration for the Overlay
struct overlay_t
{
return fwdfor_;
}
boost::asio::ip::address ip;
std::uint16_t port = 0;
};
overlay_t overlay;
void
send(Json::Value const& jv, bool)
{
auto sp = ws_.lock();
if(! sp)
return;
beast::streambuf sb;
stream(jv,
[&](void const* data, std::size_t n)
{
sb.commit(boost::asio::buffer_copy(
sb.prepare(n), boost::asio::buffer(data, n)));
});
auto m = std::make_shared<
StreambufWSMsg<decltype(sb)>>(
std::move(sb));
sp->send(m);
}
};
makeContexts();
};
// Private implementation
class ServerHandlerImp
: public ServerHandler
, public Handler
{
private:
Application& app_;
@@ -128,14 +99,13 @@ public:
~ServerHandlerImp();
private:
using Output = Json::Output;
void
setup (Setup const& setup, beast::Journal journal) override;
setup (Setup const& setup, beast::Journal journal);
Setup const&
setup() const override
setup() const
{
return setup_;
}
@@ -145,7 +115,7 @@ private:
//
void
onStop() override;
onStop();
//
// Handler
@@ -153,31 +123,31 @@ private:
bool
onAccept (Session& session,
boost::asio::ip::tcp::endpoint endpoint) override;
boost::asio::ip::tcp::endpoint endpoint);
Handoff
onHandoff (Session& session,
std::unique_ptr <beast::asio::ssl_bundle>&& bundle,
http_request_type&& request,
boost::asio::ip::tcp::endpoint remote_address) override;
boost::asio::ip::tcp::endpoint remote_address);
Handoff
onHandoff (Session& session, boost::asio::ip::tcp::socket&& socket,
http_request_type&& request,
boost::asio::ip::tcp::endpoint remote_address) override;
boost::asio::ip::tcp::endpoint remote_address);
void
onRequest (Session& session) override;
onRequest (Session& session);
void
onWSMessage(std::shared_ptr<WSSession> session,
std::vector<boost::asio::const_buffer> const& buffers) override;
std::vector<boost::asio::const_buffer> const& buffers);
void
onClose (Session& session,
boost::system::error_code const&) override;
boost::system::error_code const&);
void
onStopped (Server&) override;
onStopped (Server&);
//--------------------------------------------------------------------------

View File

@@ -21,7 +21,7 @@
#define RIPPLE_RPC_TRANSACTIONSIGN_H_INCLUDED
#include <ripple/app/misc/NetworkOPs.h>
#include <ripple/server/Role.h>
#include <ripple/rpc/Role.h>
#include <ripple/ledger/ApplyView.h>
namespace ripple {

View File

@@ -0,0 +1,93 @@
//------------------------------------------------------------------------------
/*
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_RPC_WSINFOSUB_H
#define RIPPLE_RPC_WSINFOSUB_H
#include <ripple/server/WSSession.h>
#include <ripple/net/InfoSub.h>
#include <ripple/beast/net/IPAddressConversion.h>
#include <ripple/json/Output.h>
#include <ripple/json/to_string.h>
#include <ripple/rpc/Role.h>
#include <memory>
#include <string>
namespace ripple {
class WSInfoSub : public InfoSub
{
std::weak_ptr<WSSession> ws_;
std::string user_;
std::string fwdfor_;
public:
WSInfoSub(Source& source, std::shared_ptr<WSSession> const& ws)
: InfoSub(source)
, ws_(ws)
{
auto const& h = ws->request().headers;
auto it = h.find("X-User");
if (it != h.end() &&
isIdentified(
ws->port(), beast::IPAddressConversion::from_asio(
ws->remote_endpoint()).address(), it->second))
{
user_ = it->second;
it = h.find("X-Forwarded-For");
if (it != h.end())
fwdfor_ = it->second;
}
}
std::string
user() const
{
return user_;
}
std::string
forwarded_for() const
{
return fwdfor_;
}
void
send(Json::Value const& jv, bool)
{
auto sp = ws_.lock();
if(! sp)
return;
beast::streambuf sb;
stream(jv,
[&](void const* data, std::size_t n)
{
sb.commit(boost::asio::buffer_copy(
sb.prepare(n), boost::asio::buffer(data, n)));
});
auto m = std::make_shared<
StreambufWSMsg<decltype(sb)>>(
std::move(sb));
sp->send(m);
}
};
} // ripple
#endif

View File

@@ -17,8 +17,8 @@
*/
//==============================================================================
#ifndef RIPPLE_SERVER_JSON_BODY_H
#define RIPPLE_SERVER_JSON_BODY_H
#ifndef RIPPLE_RPC_JSON_BODY_H
#define RIPPLE_RPC_JSON_BODY_H
#include <ripple/json/json_value.h>
#include <beast/core/streambuf.hpp>

View File

@@ -1,105 +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_SERVER_HANDLER_H_INCLUDED
#define RIPPLE_SERVER_HANDLER_H_INCLUDED
#include <ripple/server/Handoff.h>
#include <ripple/server/WSSession.h>
#include <ripple/beast/asio/ssl_bundle.h>
#include <boost/asio/buffer.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/system/error_code.hpp>
#include <memory>
namespace ripple {
class Session;
class Server;
/** Processes all sessions.
Thread safety:
Must be safe to call concurrently from any number of foreign threads.
*/
struct Handler
{
/** Called when a connection is accepted.
@return `true` If we should keep the connection.
*/
virtual
bool
onAccept (Session& session,
boost::asio::ip::tcp::endpoint remote_address) = 0;
/** Called to process a complete HTTP request.
The handler can do one of three things:
- Ignore the request (return default constructed What)
- Return a response (by setting response in the What)
- Take ownership of the socket by using rvalue move
and setting moved = `true` in the What.
If the handler ignores the request, the legacy onRequest
is called.
*/
/** @{ */
virtual
Handoff
onHandoff (Session& session,
std::unique_ptr <beast::asio::ssl_bundle>&& bundle,
http_request_type&& request,
boost::asio::ip::tcp::endpoint remote_address) = 0;
virtual
Handoff
onHandoff (Session& session, boost::asio::ip::tcp::socket&& socket,
http_request_type&& request,
boost::asio::ip::tcp::endpoint remote_address) = 0;
/** @} */
/** Called when we have a complete HTTP request. */
// VFALCO TODO Pass the message as a template arg
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,
boost::system::error_code const& ec) = 0;
/** Called when the server has finished its stop. */
virtual void onStopped (Server& server) = 0;
//
// WebSockets
//
/** Called on a WebSocket Upgrade request. */
/** Called for each complete WebSocket message. */
virtual
void
onWSMessage(std::shared_ptr<WSSession> session,
std::vector<boost::asio::const_buffer> const& buffers) = 0;
};
} // ripple
#endif

View File

@@ -1,3 +0,0 @@
# Server
This contains the HTTP Server and ServerHandler

View File

@@ -21,51 +21,22 @@
#define RIPPLE_SERVER_SERVER_H_INCLUDED
#include <ripple/server/Port.h>
#include <ripple/server/impl/ServerImpl.h>
#include <ripple/beast/utility/Journal.h>
#include <ripple/beast/utility/PropertyStream.h>
#include <boost/asio/io_service.hpp>
namespace ripple {
/** A multi-protocol server.
This server maintains multiple configured listening ports,
with each listening port allows for multiple protocols including
HTTP, HTTP/S, WebSocket, Secure WebSocket, and the Peer protocol.
*/
class Server
/** Create the HTTP server using the specified handler. */
template<class Handler>
std::unique_ptr<Server>
make_Server(Handler& handler,
boost::asio::io_service& io_service, beast::Journal journal)
{
public:
/** Destroy the server.
The server is closed if it is not already closed. This call
blocks until the server has stopped.
*/
virtual
~Server() = default;
/** Returns the Journal associated with the server. */
virtual
beast::Journal
journal() = 0;
/** Set the listening port settings.
This may only be called once.
*/
virtual
void
ports (std::vector<Port> const& v) = 0;
/** Close the server.
The close is performed asynchronously. The handler will be notified
when the server has stopped. The server is considered stopped when
there are no pending I/O completion handlers and all connections
have closed.
Thread safety:
Safe to call concurrently from any thread.
*/
virtual
void
close() = 0;
};
return std::make_unique<ServerImpl<Handler>>(
handler, io_service, journal);
}
} // ripple

View File

@@ -1,98 +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_SERVER_SERVERHANDLER_H_INCLUDED
#define RIPPLE_SERVER_SERVERHANDLER_H_INCLUDED
#include <ripple/basics/BasicConfig.h>
#include <ripple/core/Config.h>
#include <ripple/server/Port.h>
#include <ripple/overlay/Overlay.h>
#include <ripple/beast/utility/Journal.h>
#include <boost/asio/ip/address.hpp>
#include <memory>
#include <vector>
namespace ripple {
class ServerHandler : public Stoppable
{
protected:
ServerHandler (Stoppable& parent);
public:
struct Setup
{
std::vector<Port> ports;
// Memberspace
struct client_t
{
bool secure = false;
std::string ip;
std::uint16_t port = 0;
std::string user;
std::string password;
std::string admin_user;
std::string admin_password;
};
// Configuration when acting in client role
client_t client;
// Configuration for the Overlay
struct overlay_t
{
boost::asio::ip::address ip;
std::uint16_t port = 0;
};
overlay_t overlay;
void
makeContexts();
};
virtual
~ServerHandler() = default;
/** Opens listening ports based on the Config settings
This is implemented outside the constructor to support
two-stage initialization in the Application object.
*/
virtual
void
setup (Setup const& setup, beast::Journal journal) = 0;
/** Returns the setup associated with the handler. */
virtual
Setup const&
setup() const = 0;
};
//------------------------------------------------------------------------------
ServerHandler::Setup
setup_ServerHandler (
Config const& c,
std::ostream& log);
} // ripple
#endif

View File

@@ -20,6 +20,7 @@
#ifndef RIPPLE_SERVER_WSSESSION_H_INCLUDED
#define RIPPLE_SERVER_WSSESSION_H_INCLUDED
#include <ripple/server/Handoff.h>
#include <ripple/server/Port.h>
#include <ripple/server/Writer.h>
#include <beast/core/prepare_buffers.hpp>

View File

@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
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
@@ -22,9 +22,7 @@
#include <ripple/basics/Log.h>
#include <ripple/server/Session.h>
#include <ripple/server/impl/Door.h>
#include <ripple/server/impl/io_list.h>
#include <ripple/server/impl/ServerImpl.h>
#include <ripple/beast/net/IPAddressConversion.h>
#include <beast/core/placeholders.hpp>
#include <ripple/beast/asio/ssl_error.h> // for is_short_read?
@@ -48,7 +46,7 @@
namespace ripple {
/** Represents an active connection. */
template <class Impl>
template<class Handler, class Impl>
class BaseHTTPPeer
: public io_list::work
, public Session
@@ -71,12 +69,12 @@ protected:
struct buffer
{
buffer (void const* ptr, std::size_t len)
: data (new char[len])
, bytes (len)
, used (0)
buffer(void const* ptr, std::size_t len)
: data(new char[len])
, bytes(len)
, used(0)
{
memcpy (data.get(), ptr, len);
memcpy(data.get(), ptr, len);
}
std::unique_ptr <char[]> data;
@@ -111,8 +109,8 @@ protected:
//--------------------------------------------------------------------------
public:
template <class ConstBufferSequence>
BaseHTTPPeer (Port const& port, Handler& handler,
template<class ConstBufferSequence>
BaseHTTPPeer(Port const& port, Handler& handler,
boost::asio::io_service& io_service, beast::Journal journal,
endpoint_type remote_address, ConstBufferSequence const& buffers);
@@ -135,7 +133,7 @@ protected:
}
void
fail (error_code ec, char const* what);
fail(error_code ec, char const* what);
void
start_timer();
@@ -144,18 +142,18 @@ protected:
cancel_timer();
void
on_timer (error_code ec);
on_timer(error_code ec);
void
do_read (yield_context yield);
do_read(yield_context do_yield);
void
on_write(error_code const& ec,
std::size_t bytes_transferred);
void
do_writer (std::shared_ptr <Writer> const& writer,
bool keep_alive, yield_context yield);
do_writer(std::shared_ptr <Writer> const& writer,
bool keep_alive, yield_context do_yield);
virtual
void
@@ -192,10 +190,10 @@ protected:
}
void
write (void const* buffer, std::size_t bytes) override;
write(void const* buffer, std::size_t bytes) override;
void
write (std::shared_ptr <Writer> const& writer,
write(std::shared_ptr <Writer> const& writer,
bool keep_alive) override;
std::shared_ptr<Session>
@@ -205,27 +203,28 @@ protected:
complete() override;
void
close (bool graceful) override;
close(bool graceful) override;
};
//------------------------------------------------------------------------------
template <class Impl>
template <class ConstBufferSequence>
BaseHTTPPeer<Impl>::BaseHTTPPeer (Port const& port, Handler& handler,
template<class Handler, class Impl>
template<class ConstBufferSequence>
BaseHTTPPeer<Handler, Impl>::
BaseHTTPPeer(Port const& port, Handler& handler,
boost::asio::io_service& io_service, beast::Journal journal,
endpoint_type remote_address,
ConstBufferSequence const& buffers)
: port_(port)
, handler_(handler)
, work_ (io_service)
, strand_ (io_service)
, timer_ (io_service)
, remote_address_ (remote_address)
, journal_ (journal)
, work_(io_service)
, strand_(io_service)
, timer_(io_service)
, remote_address_(remote_address)
, journal_(journal)
{
read_buf_.commit(boost::asio::buffer_copy(read_buf_.prepare (
boost::asio::buffer_size (buffers)), buffers));
read_buf_.commit(boost::asio::buffer_copy(read_buf_.prepare(
boost::asio::buffer_size(buffers)), buffers));
static std::atomic <int> sid;
nid_ = ++sid;
id_ = std::string("#") + std::to_string(nid_) + " ";
@@ -233,8 +232,9 @@ BaseHTTPPeer<Impl>::BaseHTTPPeer (Port const& port, Handler& handler,
"accept: " << remote_address_.address();
}
template <class Impl>
BaseHTTPPeer<Impl>::~BaseHTTPPeer()
template<class Handler, class Impl>
BaseHTTPPeer<Handler, Impl>::
~BaseHTTPPeer()
{
handler_.onClose(session(), ec_);
JLOG(journal_.trace()) << id_ <<
@@ -242,11 +242,12 @@ BaseHTTPPeer<Impl>::~BaseHTTPPeer()
((request_count_ == 1) ? " request" : " requests");
}
template <class Impl>
template<class Handler, class Impl>
void
BaseHTTPPeer<Impl>::close()
BaseHTTPPeer<Handler, Impl>::
close()
{
if (! strand_.running_in_this_thread())
if(! strand_.running_in_this_thread())
return strand_.post(std::bind(
(void(BaseHTTPPeer::*)(void))&BaseHTTPPeer::close,
impl().shared_from_this()));
@@ -256,64 +257,69 @@ BaseHTTPPeer<Impl>::close()
//------------------------------------------------------------------------------
template <class Impl>
template<class Handler, class Impl>
void
BaseHTTPPeer<Impl>::fail (error_code ec, char const* what)
BaseHTTPPeer<Handler, Impl>::
fail(error_code ec, char const* what)
{
if (! ec_ && ec != boost::asio::error::operation_aborted)
if(! ec_ && ec != boost::asio::error::operation_aborted)
{
ec_ = ec;
JLOG(journal_.trace()) << id_ <<
std::string(what) << ": " << ec.message();
impl().stream_.lowest_layer().close (ec);
impl().stream_.lowest_layer().close(ec);
}
}
template <class Impl>
template<class Handler, class Impl>
void
BaseHTTPPeer<Impl>::start_timer()
BaseHTTPPeer<Handler, Impl>::
start_timer()
{
error_code ec;
timer_.expires_from_now (std::chrono::seconds(timeoutSeconds), ec);
if (ec)
return fail (ec, "start_timer");
timer_.async_wait (strand_.wrap (std::bind (
&BaseHTTPPeer<Impl>::on_timer, impl().shared_from_this(),
timer_.expires_from_now(std::chrono::seconds(timeoutSeconds), ec);
if(ec)
return fail(ec, "start_timer");
timer_.async_wait(strand_.wrap(std::bind(
&BaseHTTPPeer<Handler, Impl>::on_timer, impl().shared_from_this(),
beast::asio::placeholders::error)));
}
// Convenience for discarding the error code
template <class Impl>
template<class Handler, class Impl>
void
BaseHTTPPeer<Impl>::cancel_timer()
BaseHTTPPeer<Handler, Impl>::
cancel_timer()
{
error_code ec;
timer_.cancel(ec);
}
// Called when session times out
template <class Impl>
template<class Handler, class Impl>
void
BaseHTTPPeer<Impl>::on_timer (error_code ec)
BaseHTTPPeer<Handler, Impl>::
on_timer(error_code ec)
{
if (ec == boost::asio::error::operation_aborted)
if(ec == boost::asio::error::operation_aborted)
return;
if (! ec)
ec = boost::system::errc::make_error_code (
if(! ec)
ec = boost::system::errc::make_error_code(
boost::system::errc::timed_out);
fail (ec, "timer");
fail(ec, "timer");
}
//------------------------------------------------------------------------------
template <class Impl>
template<class Handler, class Impl>
void
BaseHTTPPeer<Impl>::do_read (yield_context yield)
BaseHTTPPeer<Handler, Impl>::
do_read(yield_context do_yield)
{
complete_ = false;
error_code ec;
beast::http::async_read(impl().stream_,
read_buf_, message_, yield[ec]);
read_buf_, message_, do_yield[ec]);
// VFALCO What if the connection was closed?
cancel_timer();
do_request();
@@ -321,9 +327,10 @@ BaseHTTPPeer<Impl>::do_read (yield_context yield)
// Send everything in the write queue.
// The write queue must not be empty upon entry.
template<class Impl>
template<class Handler, class Impl>
void
BaseHTTPPeer<Impl>::on_write(error_code const& ec,
BaseHTTPPeer<Handler, Impl>::
on_write(error_code const& ec,
std::size_t bytes_transferred)
{
cancel_timer();
@@ -349,19 +356,20 @@ BaseHTTPPeer<Impl>::on_write(error_code const& ec,
impl().shared_from_this(), placeholders::error,
placeholders::bytes_transferred)));
}
if (! complete_)
if(! complete_)
return;
if (graceful_)
if(graceful_)
return do_close();
boost::asio::spawn(strand_,
std::bind (&BaseHTTPPeer<Impl>::do_read,
std::bind(&BaseHTTPPeer<Handler, Impl>::do_read,
impl().shared_from_this(), std::placeholders::_1));
}
template <class Impl>
template<class Handler, class Impl>
void
BaseHTTPPeer<Impl>::do_writer (std::shared_ptr <Writer> const& writer,
bool keep_alive, yield_context yield)
BaseHTTPPeer<Handler, Impl>::
do_writer(std::shared_ptr <Writer> const& writer,
bool keep_alive, yield_context do_yield)
{
std::function <void(void)> resume;
{
@@ -369,43 +377,44 @@ BaseHTTPPeer<Impl>::do_writer (std::shared_ptr <Writer> const& writer,
resume = std::function <void(void)>(
[this, p, writer, keep_alive]()
{
boost::asio::spawn (strand_, std::bind (
&BaseHTTPPeer<Impl>::do_writer, p, writer, keep_alive,
boost::asio::spawn(strand_, std::bind(
&BaseHTTPPeer<Handler, Impl>::do_writer, p, writer, keep_alive,
std::placeholders::_1));
});
}
for(;;)
{
if (! writer->prepare (bufferSize, resume))
if(! writer->prepare(bufferSize, resume))
return;
error_code ec;
auto const bytes_transferred = boost::asio::async_write (
auto const bytes_transferred = boost::asio::async_write(
impl().stream_, writer->data(), boost::asio::transfer_at_least(1),
yield[ec]);
if (ec)
return fail (ec, "writer");
do_yield[ec]);
if(ec)
return fail(ec, "writer");
writer->consume(bytes_transferred);
if (writer->complete())
if(writer->complete())
break;
}
if (! keep_alive)
if(! keep_alive)
return do_close();
boost::asio::spawn (strand_, std::bind (&BaseHTTPPeer<Impl>::do_read,
boost::asio::spawn(strand_, std::bind(&BaseHTTPPeer<Handler, Impl>::do_read,
impl().shared_from_this(), std::placeholders::_1));
}
//------------------------------------------------------------------------------
// Send a copy of the data.
template <class Impl>
template<class Handler, class Impl>
void
BaseHTTPPeer<Impl>::write(
BaseHTTPPeer<Handler, Impl>::
write(
void const* buffer, std::size_t bytes)
{
if (bytes == 0)
if(bytes == 0)
return;
if([&]
{
@@ -414,7 +423,7 @@ BaseHTTPPeer<Impl>::write(
return wq_.size() == 1 && wq2_.size() == 0;
}())
{
if (strand_.running_in_this_thread())
if(strand_.running_in_this_thread())
return strand_.post(std::bind(
&BaseHTTPPeer::on_write,
impl().shared_from_this(),
@@ -424,33 +433,36 @@ BaseHTTPPeer<Impl>::write(
}
}
template <class Impl>
template<class Handler, class Impl>
void
BaseHTTPPeer<Impl>::write (std::shared_ptr <Writer> const& writer,
BaseHTTPPeer<Handler, Impl>::
write(std::shared_ptr <Writer> const& writer,
bool keep_alive)
{
boost::asio::spawn (strand_, std::bind (
&BaseHTTPPeer<Impl>::do_writer, impl().shared_from_this(),
boost::asio::spawn(strand_, std::bind(
&BaseHTTPPeer<Handler, Impl>::do_writer, impl().shared_from_this(),
writer, keep_alive, std::placeholders::_1));
}
// DEPRECATED
// Make the Session asynchronous
template <class Impl>
template<class Handler, class Impl>
std::shared_ptr<Session>
BaseHTTPPeer<Impl>::detach()
BaseHTTPPeer<Handler, Impl>::
detach()
{
return impl().shared_from_this();
}
// DEPRECATED
// Called to indicate the response has been written (but not sent)
template <class Impl>
// Called to indicate the response has been written(but not sent)
template<class Handler, class Impl>
void
BaseHTTPPeer<Impl>::complete()
BaseHTTPPeer<Handler, Impl>::
complete()
{
if (! strand_.running_in_this_thread())
return strand_.post(std::bind (&BaseHTTPPeer<Impl>::complete,
if(! strand_.running_in_this_thread())
return strand_.post(std::bind(&BaseHTTPPeer<Handler, Impl>::complete,
impl().shared_from_this()));
message_ = {};
@@ -458,40 +470,41 @@ BaseHTTPPeer<Impl>::complete()
{
std::lock_guard<std::mutex> lock(mutex_);
if (! wq_.empty() && ! wq2_.empty())
if(! wq_.empty() && ! wq2_.empty())
return;
}
// keep-alive
boost::asio::spawn (strand_, std::bind (&BaseHTTPPeer<Impl>::do_read,
boost::asio::spawn(strand_, std::bind(&BaseHTTPPeer<Handler, Impl>::do_read,
impl().shared_from_this(), std::placeholders::_1));
}
// DEPRECATED
// Called from the Handler to close the session.
template <class Impl>
template<class Handler, class Impl>
void
BaseHTTPPeer<Impl>::close (bool graceful)
BaseHTTPPeer<Handler, Impl>::
close(bool graceful)
{
if (! strand_.running_in_this_thread())
if(! strand_.running_in_this_thread())
return strand_.post(std::bind(
(void(BaseHTTPPeer::*)(bool))&BaseHTTPPeer<Impl>::close,
(void(BaseHTTPPeer::*)(bool))&BaseHTTPPeer<Handler, Impl>::close,
impl().shared_from_this(), graceful));
complete_ = true;
if (graceful)
if(graceful)
{
graceful_ = true;
{
std::lock_guard<std::mutex> lock(mutex_);
if (! wq_.empty() || ! wq2_.empty())
if(! wq_.empty() || ! wq2_.empty())
return;
}
return do_close();
}
error_code ec;
impl().stream_.lowest_layer().close (ec);
impl().stream_.lowest_layer().close(ec);
}
} // ripple

View File

@@ -20,7 +20,6 @@
#ifndef RIPPLE_SERVER_BASEPEER_H_INCLUDED
#define RIPPLE_SERVER_BASEPEER_H_INCLUDED
#include <ripple/server/Handler.h>
#include <ripple/server/Port.h>
#include <ripple/server/impl/io_list.h>
#include <ripple/beast/utility/WrappedSink.h>
@@ -32,7 +31,7 @@
namespace ripple {
// Common part of all peers
template<class Impl>
template<class Handler, class Impl>
class BasePeer
: public io_list::work
{
@@ -76,8 +75,9 @@ private:
//------------------------------------------------------------------------------
template<class Impl>
BasePeer<Impl>::BasePeer(Port const& port, Handler& handler,
template<class Handler, class Impl>
BasePeer<Handler, Impl>::
BasePeer(Port const& port, Handler& handler,
endpoint_type remote_address,
boost::asio::io_service& io_service,
beast::Journal journal)
@@ -96,9 +96,10 @@ BasePeer<Impl>::BasePeer(Port const& port, Handler& handler,
{
}
template<class Impl>
template<class Handler, class Impl>
void
BasePeer<Impl>::close()
BasePeer<Handler, Impl>::
close()
{
if (! strand_.running_in_this_thread())
return strand_.post(std::bind(
@@ -107,10 +108,11 @@ BasePeer<Impl>::close()
impl().ws_.lowest_layer().close(ec);
}
template<class Impl>
template<class Handler, class Impl>
template<class String>
void
BasePeer<Impl>::fail(error_code ec, String const& what)
BasePeer<Handler, Impl>::
fail(error_code ec, String const& what)
{
assert(strand_.running_in_this_thread());
if(! ec_ &&

View File

@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
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
@@ -30,9 +30,9 @@
namespace ripple {
/** Represents an active WebSocket connection. */
template <class Impl>
template<class Handler, class Impl>
class BaseWSPeer
: public BasePeer<Impl>
: public BasePeer<Handler, Impl>
, public WSSession
{
protected:
@@ -40,8 +40,8 @@ protected:
using error_code = boost::system::error_code;
using endpoint_type = boost::asio::ip::tcp::endpoint;
using waitable_timer = boost::asio::basic_waitable_timer <clock_type>;
using BasePeer<Impl>::fail;
using BasePeer<Impl>::strand_;
using BasePeer<Handler, Impl>::fail;
using BasePeer<Handler, Impl>::strand_;
enum
{
@@ -50,7 +50,7 @@ protected:
};
private:
friend class BasePeer<Impl>;
friend class BasePeer<Handler, Impl>;
http_request_type request_;
beast::websocket::opcode op_;
@@ -168,25 +168,27 @@ protected:
//------------------------------------------------------------------------------
template<class Impl>
template<class Handler, class Impl>
template<class Body, class Headers>
BaseWSPeer<Impl>::BaseWSPeer(
BaseWSPeer<Handler, Impl>::
BaseWSPeer(
Port const& port,
Handler& handler,
endpoint_type remote_address,
beast::http::request_v1<Body, Headers>&& request,
boost::asio::io_service& io_service,
beast::Journal journal)
: BasePeer<Impl>(port, handler, remote_address,
: BasePeer<Handler, Impl>(port, handler, remote_address,
io_service, journal)
, request_(std::move(request))
, timer_(io_service)
{
}
template<class Impl>
template<class Handler, class Impl>
void
BaseWSPeer<Impl>::run()
BaseWSPeer<Handler, Impl>::
run()
{
if(! strand_.running_in_this_thread())
return strand_.post(std::bind(
@@ -198,9 +200,10 @@ BaseWSPeer<Impl>::run()
placeholders::error)));
}
template<class Impl>
template<class Handler, class Impl>
void
BaseWSPeer<Impl>::send(std::shared_ptr<WSMsg> w)
BaseWSPeer<Handler, Impl>::
send(std::shared_ptr<WSMsg> w)
{
// Maximum send queue size
static std::size_t constexpr limit = 100;
@@ -208,7 +211,7 @@ BaseWSPeer<Impl>::send(std::shared_ptr<WSMsg> w)
return strand_.post(std::bind(
&BaseWSPeer::send, impl().shared_from_this(),
std::move(w)));
if (wq_.size() >= limit)
if(wq_.size() >= limit)
{
cr_.code = static_cast<beast::websocket::close_code::value>(4000);
cr_.reason = "Client is too slow.";
@@ -221,9 +224,10 @@ BaseWSPeer<Impl>::send(std::shared_ptr<WSMsg> w)
on_write({});
}
template<class Impl>
template<class Handler, class Impl>
void
BaseWSPeer<Impl>::close()
BaseWSPeer<Handler, Impl>::
close()
{
if(! strand_.running_in_this_thread())
return strand_.post(std::bind(
@@ -236,28 +240,31 @@ BaseWSPeer<Impl>::close()
beast::asio::placeholders::error)));
}
template<class Impl>
template<class Handler, class Impl>
void
BaseWSPeer<Impl>::complete()
BaseWSPeer<Handler, Impl>::
complete()
{
if (! strand_.running_in_this_thread())
if(! strand_.running_in_this_thread())
return strand_.post(std::bind(
&BaseWSPeer::complete, impl().shared_from_this()));
do_read();
}
template<class Impl>
template<class Handler, class Impl>
void
BaseWSPeer<Impl>::on_write_sb(error_code const& ec)
BaseWSPeer<Handler, Impl>::
on_write_sb(error_code const& ec)
{
if(ec)
return fail(ec, "write_resp");
do_read();
}
template<class Impl>
template<class Handler, class Impl>
void
BaseWSPeer<Impl>::do_write()
BaseWSPeer<Handler, Impl>::
do_write()
{
if(! strand_.running_in_this_thread())
return strand_.post(std::bind(
@@ -265,9 +272,10 @@ BaseWSPeer<Impl>::do_write()
on_write({});
}
template<class Impl>
template<class Handler, class Impl>
void
BaseWSPeer<Impl>::on_write(error_code const& ec)
BaseWSPeer<Handler, Impl>::
on_write(error_code const& ec)
{
cancel_timer();
if(ec)
@@ -292,9 +300,10 @@ BaseWSPeer<Impl>::on_write(error_code const& ec)
placeholders::error)));
}
template<class Impl>
template<class Handler, class Impl>
void
BaseWSPeer<Impl>::on_write_fin(error_code const& ec)
BaseWSPeer<Handler, Impl>::
on_write_fin(error_code const& ec)
{
if(ec)
return fail(ec, "write_fin");
@@ -307,9 +316,10 @@ BaseWSPeer<Impl>::on_write_fin(error_code const& ec)
on_write({});
}
template<class Impl>
template<class Handler, class Impl>
void
BaseWSPeer<Impl>::do_read()
BaseWSPeer<Handler, Impl>::
do_read()
{
if(! strand_.running_in_this_thread())
return strand_.post(std::bind(
@@ -321,9 +331,10 @@ BaseWSPeer<Impl>::do_read()
cancel_timer();
}
template<class Impl>
template<class Handler, class Impl>
void
BaseWSPeer<Impl>::on_read(error_code const& ec)
BaseWSPeer<Handler, Impl>::
on_read(error_code const& ec)
{
if(ec == beast::websocket::error::closed)
return do_close();
@@ -338,48 +349,52 @@ BaseWSPeer<Impl>::on_read(error_code const& ec)
rb_.consume(rb_.size());
}
template<class Impl>
template<class Handler, class Impl>
void
BaseWSPeer<Impl>::on_close(error_code const& ec)
BaseWSPeer<Handler, Impl>::
on_close(error_code const& ec)
{
// great
}
template <class Impl>
template<class Handler, class Impl>
void
BaseWSPeer<Impl>::start_timer()
BaseWSPeer<Handler, Impl>::
start_timer()
{
// Max seconds without completing a message
static constexpr std::chrono::seconds timeout{30};
error_code ec;
timer_.expires_from_now (timeout, ec);
if (ec)
return fail (ec, "start_timer");
timer_.async_wait (strand_.wrap (std::bind (
&BaseWSPeer<Impl>::on_timer, impl().shared_from_this(),
timer_.expires_from_now(timeout, ec);
if(ec)
return fail(ec, "start_timer");
timer_.async_wait(strand_.wrap(std::bind(
&BaseWSPeer<Handler, Impl>::on_timer, impl().shared_from_this(),
beast::asio::placeholders::error)));
}
// Convenience for discarding the error code
template <class Impl>
template<class Handler, class Impl>
void
BaseWSPeer<Impl>::cancel_timer()
BaseWSPeer<Handler, Impl>::
cancel_timer()
{
error_code ec;
timer_.cancel(ec);
}
// Called when session times out
template <class Impl>
template<class Handler, class Impl>
void
BaseWSPeer<Impl>::on_timer (error_code ec)
BaseWSPeer<Handler, Impl>::
on_timer(error_code ec)
{
if (ec == boost::asio::error::operation_aborted)
if(ec == boost::asio::error::operation_aborted)
return;
if (! ec)
ec = boost::system::errc::make_error_code (
if(! ec)
ec = boost::system::errc::make_error_code(
boost::system::errc::timed_out);
fail (ec, "timer");
fail(ec, "timer");
}
} // ripple

View File

@@ -1,296 +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.
*/
//==============================================================================
#include <BeastConfig.h>
#include <ripple/basics/contract.h>
#include <ripple/basics/Log.h>
#include <ripple/server/impl/Door.h>
#include <ripple/server/impl/PlainHTTPPeer.h>
#include <ripple/server/impl/SSLHTTPPeer.h>
#include <boost/asio/buffer.hpp>
#include <beast/core/placeholders.hpp>
#include <ripple/beast/asio/ssl_bundle.h>
#include <functional>
namespace ripple {
/** Detect SSL client handshakes.
Analyzes the bytes in the provided buffer to detect the SSL client
handshake. If the buffer contains insufficient data, more data will be
read from the stream until there is enough to determine a result.
No bytes are discarded from buf. Any additional bytes read are retained.
buf must provide an interface compatible with boost::asio::streambuf
http://boost.org/doc/libs/1_56_0/doc/html/boost_asio/reference/streambuf.html
See
http://www.ietf.org/rfc/rfc2246.txt
Section 7.4. Handshake protocol
@param socket The stream to read from
@param buf A buffer to hold the received data
@param yield A yield context
@return The error code if an error occurs, otherwise `true` if
the data read indicates the SSL client handshake.
*/
template <class Socket, class StreamBuf, class Yield>
std::pair <boost::system::error_code, bool>
detect_ssl (Socket& socket, StreamBuf& buf, Yield yield)
{
std::pair <boost::system::error_code, bool> result;
result.second = false;
for(;;)
{
std::size_t const max = 4; // the most bytes we could need
unsigned char data[max];
auto const bytes = boost::asio::buffer_copy (
boost::asio::buffer(data), buf.data());
if (bytes > 0)
{
if (data[0] != 0x16) // message type 0x16 = "SSL Handshake"
break;
}
if (bytes >= max)
{
result.second = true;
break;
}
buf.commit(boost::asio::async_read (socket,
buf.prepare(max - bytes), boost::asio::transfer_at_least(1),
yield[result.first]));
if (result.first)
break;
}
return result;
}
//------------------------------------------------------------------------------
Door::Detector::Detector(Port const& port,
Handler& handler, socket_type&& socket,
endpoint_type remote_address, beast::Journal j)
: port_(port)
, handler_(handler)
, socket_(std::move(socket))
, timer_(socket_.get_io_service())
, remote_address_(remote_address)
, strand_(socket_.get_io_service())
, j_(j)
{
}
void
Door::Detector::run()
{
// do_detect must be called before do_timer or else
// the timer can be canceled before it gets set.
boost::asio::spawn (strand_, std::bind (&Detector::do_detect,
shared_from_this(), std::placeholders::_1));
boost::asio::spawn (strand_, std::bind (&Detector::do_timer,
shared_from_this(), std::placeholders::_1));
}
void
Door::Detector::close()
{
error_code ec;
socket_.close(ec);
timer_.cancel(ec);
}
void
Door::Detector::do_timer (yield_context yield)
{
error_code ec; // ignored
while (socket_.is_open())
{
timer_.async_wait (yield[ec]);
if (timer_.expires_from_now() <= std::chrono::seconds(0))
socket_.close(ec);
}
}
void
Door::Detector::do_detect (boost::asio::yield_context yield)
{
bool ssl;
error_code ec;
beast::streambuf buf(16);
timer_.expires_from_now(std::chrono::seconds(15));
std::tie(ec, ssl) = detect_ssl(socket_, buf, yield);
error_code unused;
timer_.cancel(unused);
if (! ec)
{
if (ssl)
{
if(auto sp = ios().emplace<SSLHTTPPeer>(port_, handler_,
j_, remote_address_, buf.data(),
std::move(socket_)))
sp->run();
return;
}
if(auto sp = ios().emplace<PlainHTTPPeer>(port_, handler_,
j_, remote_address_, buf.data(),
std::move(socket_)))
sp->run();
return;
}
if (ec != boost::asio::error::operation_aborted)
{
JLOG(j_.trace()) <<
"Error detecting ssl: " << ec.message() <<
" from " << remote_address_;
}
}
//------------------------------------------------------------------------------
Door::Door (Handler& handler, boost::asio::io_service& io_service,
Port const& port, beast::Journal j)
: j_(j)
, port_(port)
, handler_(handler)
, acceptor_(io_service)
, strand_(io_service)
, ssl_(
port_.protocol.count("https") > 0 ||
//port_.protocol.count("wss") > 0 ||
port_.protocol.count("wss2") > 0 ||
port_.protocol.count("peer") > 0)
, plain_(
port_.protocol.count("http") > 0 ||
//port_.protocol.count("ws") > 0 ||
port_.protocol.count("ws2"))
{
error_code ec;
endpoint_type const local_address =
endpoint_type(port.ip, port.port);
acceptor_.open(local_address.protocol(), ec);
if (ec)
{
JLOG(j_.error()) <<
"Open port '" << port.name << "' failed:" << ec.message();
Throw<std::exception> ();
}
acceptor_.set_option(
boost::asio::ip::tcp::acceptor::reuse_address(true), ec);
if (ec)
{
JLOG(j_.error()) <<
"Option for port '" << port.name << "' failed:" << ec.message();
Throw<std::exception> ();
}
acceptor_.bind(local_address, ec);
if (ec)
{
JLOG(j_.error()) <<
"Bind port '" << port.name << "' failed:" << ec.message();
Throw<std::exception> ();
}
acceptor_.listen(boost::asio::socket_base::max_connections, ec);
if (ec)
{
JLOG(j_.error()) <<
"Listen on port '" << port.name << "' failed:" << ec.message();
Throw<std::exception> ();
}
JLOG(j_.info()) <<
"Opened " << port;
}
void
Door::run()
{
boost::asio::spawn (strand_, std::bind(&Door::do_accept,
shared_from_this(), std::placeholders::_1));
}
void
Door::close()
{
if (! strand_.running_in_this_thread())
return strand_.post(std::bind(
&Door::close, shared_from_this()));
error_code ec;
acceptor_.close(ec);
}
//------------------------------------------------------------------------------
template <class ConstBufferSequence>
void
Door::create (bool ssl, ConstBufferSequence const& buffers,
socket_type&& socket, endpoint_type remote_address)
{
if (ssl)
{
if(auto sp = ios().emplace<SSLHTTPPeer>(port_, handler_,
j_, remote_address, buffers,
std::move(socket)))
sp->run();
return;
}
if(auto sp = ios().emplace<PlainHTTPPeer>(port_, handler_,
j_, remote_address, buffers,
std::move(socket)))
sp->run();
}
void
Door::do_accept (boost::asio::yield_context yield)
{
for(;;)
{
error_code ec;
endpoint_type remote_address;
socket_type socket (acceptor_.get_io_service());
acceptor_.async_accept (socket, remote_address, yield[ec]);
if (ec && ec != boost::asio::error::operation_aborted)
{
JLOG(j_.error()) <<
"accept: " << ec.message();
}
if (ec == boost::asio::error::operation_aborted)
break;
if (ec)
continue;
if (ssl_ && plain_)
{
if(auto sp = ios().emplace<Detector>(port_,
handler_, std::move(socket), remote_address,
j_))
sp->run();
}
else if (ssl_ || plain_)
{
create(ssl_, boost::asio::null_buffers{},
std::move(socket), remote_address);
}
}
}
} // ripple

View File

@@ -21,24 +21,32 @@
#define RIPPLE_SERVER_DOOR_H_INCLUDED
#include <ripple/server/impl/io_list.h>
#include <ripple/server/impl/ServerImpl.h>
#include <ripple/basics/contract.h>
#include <ripple/basics/Log.h>
#include <ripple/server/impl/PlainHTTPPeer.h>
#include <ripple/server/impl/SSLHTTPPeer.h>
#include <ripple/beast/asio/ssl_bundle.h>
#include <beast/core/placeholders.hpp>
#include <beast/core/streambuf.hpp>
#include <boost/asio/basic_waitable_timer.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/container/flat_map.hpp>
#include <chrono>
#include <condition_variable>
#include <functional>
#include <memory>
#include <mutex>
namespace ripple {
/** A listening socket. */
template<class Handler>
class Door
: public io_list::work
, public std::enable_shared_from_this<Door>
, public std::enable_shared_from_this<Door<Handler>>
{
private:
using clock_type = std::chrono::steady_clock;
@@ -107,6 +115,287 @@ private:
void do_accept (yield_context yield);
};
/** Detect SSL client handshakes.
Analyzes the bytes in the provided buffer to detect the SSL client
handshake. If the buffer contains insufficient data, more data will be
read from the stream until there is enough to determine a result.
No bytes are discarded from buf. Any additional bytes read are retained.
buf must provide an interface compatible with boost::asio::streambuf
http://boost.org/doc/libs/1_56_0/doc/html/boost_asio/reference/streambuf.html
See
http://www.ietf.org/rfc/rfc2246.txt
Section 7.4. Handshake protocol
@param socket The stream to read from
@param buf A buffer to hold the received data
@param do_yield A do_yield context
@return The error code if an error occurs, otherwise `true` if
the data read indicates the SSL client handshake.
*/
template <class Socket, class StreamBuf, class Yield>
std::pair <boost::system::error_code, bool>
detect_ssl (Socket& socket, StreamBuf& buf, Yield do_yield)
{
std::pair <boost::system::error_code, bool> result;
result.second = false;
for(;;)
{
std::size_t const max = 4; // the most bytes we could need
unsigned char data[max];
auto const bytes = boost::asio::buffer_copy (
boost::asio::buffer(data), buf.data());
if (bytes > 0)
{
if (data[0] != 0x16) // message type 0x16 = "SSL Handshake"
break;
}
if (bytes >= max)
{
result.second = true;
break;
}
buf.commit(boost::asio::async_read (socket,
buf.prepare(max - bytes), boost::asio::transfer_at_least(1),
do_yield[result.first]));
if (result.first)
break;
}
return result;
}
template<class Handler>
Door<Handler>::Detector::
Detector(Port const& port,
Handler& handler, socket_type&& socket,
endpoint_type remote_address, beast::Journal j)
: port_(port)
, handler_(handler)
, socket_(std::move(socket))
, timer_(socket_.get_io_service())
, remote_address_(remote_address)
, strand_(socket_.get_io_service())
, j_(j)
{
}
template<class Handler>
void
Door<Handler>::Detector::
run()
{
// do_detect must be called before do_timer or else
// the timer can be canceled before it gets set.
boost::asio::spawn(strand_, std::bind (&Detector::do_detect,
this->shared_from_this(), std::placeholders::_1));
boost::asio::spawn(strand_, std::bind (&Detector::do_timer,
this->shared_from_this(), std::placeholders::_1));
}
template<class Handler>
void
Door<Handler>::Detector::
close()
{
error_code ec;
socket_.close(ec);
timer_.cancel(ec);
}
template<class Handler>
void
Door<Handler>::Detector::
do_timer(yield_context do_yield)
{
error_code ec; // ignored
while (socket_.is_open())
{
timer_.async_wait (do_yield[ec]);
if (timer_.expires_from_now() <= std::chrono::seconds(0))
socket_.close(ec);
}
}
template<class Handler>
void
Door<Handler>::Detector::
do_detect(boost::asio::yield_context do_yield)
{
bool ssl;
error_code ec;
beast::streambuf buf(16);
timer_.expires_from_now(std::chrono::seconds(15));
std::tie(ec, ssl) = detect_ssl(socket_, buf, do_yield);
error_code unused;
timer_.cancel(unused);
if (! ec)
{
if (ssl)
{
if(auto sp = ios().template emplace<SSLHTTPPeer<Handler>>(
port_, handler_, j_, remote_address_,
buf.data(), std::move(socket_)))
sp->run();
return;
}
if(auto sp = ios().template emplace<PlainHTTPPeer<Handler>>(
port_, handler_, j_, remote_address_,
buf.data(), std::move(socket_)))
sp->run();
return;
}
if (ec != boost::asio::error::operation_aborted)
{
JLOG(j_.trace()) <<
"Error detecting ssl: " << ec.message() <<
" from " << remote_address_;
}
}
//------------------------------------------------------------------------------
template<class Handler>
Door<Handler>::
Door(Handler& handler, boost::asio::io_service& io_service,
Port const& port, beast::Journal j)
: j_(j)
, port_(port)
, handler_(handler)
, acceptor_(io_service)
, strand_(io_service)
, ssl_(
port_.protocol.count("https") > 0 ||
//port_.protocol.count("wss") > 0 ||
port_.protocol.count("wss2") > 0 ||
port_.protocol.count("peer") > 0)
, plain_(
port_.protocol.count("http") > 0 ||
//port_.protocol.count("ws") > 0 ||
port_.protocol.count("ws2"))
{
error_code ec;
endpoint_type const local_address =
endpoint_type(port.ip, port.port);
acceptor_.open(local_address.protocol(), ec);
if (ec)
{
JLOG(j_.error()) <<
"Open port '" << port.name << "' failed:" << ec.message();
Throw<std::exception> ();
}
acceptor_.set_option(
boost::asio::ip::tcp::acceptor::reuse_address(true), ec);
if (ec)
{
JLOG(j_.error()) <<
"Option for port '" << port.name << "' failed:" << ec.message();
Throw<std::exception> ();
}
acceptor_.bind(local_address, ec);
if (ec)
{
JLOG(j_.error()) <<
"Bind port '" << port.name << "' failed:" << ec.message();
Throw<std::exception> ();
}
acceptor_.listen(boost::asio::socket_base::max_connections, ec);
if (ec)
{
JLOG(j_.error()) <<
"Listen on port '" << port.name << "' failed:" << ec.message();
Throw<std::exception> ();
}
JLOG(j_.info()) <<
"Opened " << port;
}
template<class Handler>
void
Door<Handler>::
run()
{
boost::asio::spawn(strand_, std::bind(&Door<Handler>::do_accept,
this->shared_from_this(), std::placeholders::_1));
}
template<class Handler>
void
Door<Handler>::
close()
{
if (! strand_.running_in_this_thread())
return strand_.post(std::bind(
&Door<Handler>::close, this->shared_from_this()));
error_code ec;
acceptor_.close(ec);
}
//------------------------------------------------------------------------------
template<class Handler>
template<class ConstBufferSequence>
void
Door<Handler>::
create(bool ssl, ConstBufferSequence const& buffers,
socket_type&& socket, endpoint_type remote_address)
{
if (ssl)
{
if(auto sp = ios().template emplace<SSLHTTPPeer<Handler>>(
port_, handler_, j_, remote_address,
buffers, std::move(socket)))
sp->run();
return;
}
if(auto sp = ios().template emplace<PlainHTTPPeer<Handler>>(
port_, handler_, j_, remote_address,
buffers, std::move(socket)))
sp->run();
}
template<class Handler>
void
Door<Handler>::
do_accept(boost::asio::yield_context do_yield)
{
for(;;)
{
error_code ec;
endpoint_type remote_address;
socket_type socket (acceptor_.get_io_service());
acceptor_.async_accept (socket, remote_address, do_yield[ec]);
if (ec && ec != boost::asio::error::operation_aborted)
{
JLOG(j_.error()) <<
"accept: " << ec.message();
}
if (ec == boost::asio::error::operation_aborted)
break;
if (ec)
continue;
if (ssl_ && plain_)
{
if(auto sp = ios().template emplace<Detector>(
port_, handler_, std::move(socket),
remote_address, j_))
sp->run();
}
else if (ssl_ || plain_)
{
create(ssl_, boost::asio::null_buffers{},
std::move(socket), remote_address);
}
}
}
} // ripple
#endif

View File

@@ -26,19 +26,21 @@
namespace ripple {
template<class Handler>
class PlainHTTPPeer
: public BaseHTTPPeer<PlainHTTPPeer>
, public std::enable_shared_from_this <PlainHTTPPeer>
: public BaseHTTPPeer<Handler, PlainHTTPPeer<Handler>>
, public std::enable_shared_from_this<PlainHTTPPeer<Handler>>
{
private:
friend class BaseHTTPPeer<PlainHTTPPeer>;
friend class BaseHTTPPeer<Handler, PlainHTTPPeer>;
using socket_type = boost::asio::ip::tcp::socket;
using endpoint_type = boost::asio::ip::tcp::endpoint;
socket_type stream_;
public:
template <class ConstBufferSequence>
PlainHTTPPeer (Port const& port, Handler& handler,
template<class ConstBufferSequence>
PlainHTTPPeer(Port const& port, Handler& handler,
beast::Journal journal, endpoint_type remote_address,
ConstBufferSequence const& buffers, socket_type&& socket);
@@ -58,12 +60,14 @@ private:
//------------------------------------------------------------------------------
template <class ConstBufferSequence>
PlainHTTPPeer::PlainHTTPPeer (Port const& port, Handler& handler,
template<class Handler>
template<class ConstBufferSequence>
PlainHTTPPeer<Handler>::
PlainHTTPPeer(Port const& port, Handler& handler,
beast::Journal journal, endpoint_type remote_endpoint,
ConstBufferSequence const& buffers, socket_type&& socket)
: BaseHTTPPeer(port, handler, socket.get_io_service(),
journal, remote_endpoint, buffers)
: BaseHTTPPeer<Handler, PlainHTTPPeer>(port, handler,
socket.get_io_service(), journal, remote_endpoint, buffers)
, stream_(std::move(socket))
{
// Set TCP_NODELAY on loopback interfaces,
@@ -74,67 +78,75 @@ PlainHTTPPeer::PlainHTTPPeer (Port const& port, Handler& handler,
stream_.set_option(boost::asio::ip::tcp::no_delay{true});
}
template<class Handler>
void
PlainHTTPPeer::run()
PlainHTTPPeer<Handler>::
run()
{
if (!handler_.onAccept (session(), remote_address_))
if (! this->handler_.onAccept(this->session(), this->remote_address_))
{
boost::asio::spawn (strand_,
boost::asio::spawn(this->strand_,
std::bind (&PlainHTTPPeer::do_close,
shared_from_this()));
this->shared_from_this()));
return;
}
if (! stream_.is_open())
return;
boost::asio::spawn (strand_, std::bind (&PlainHTTPPeer::do_read,
shared_from_this(), std::placeholders::_1));
boost::asio::spawn(this->strand_, std::bind(&PlainHTTPPeer::do_read,
this->shared_from_this(), std::placeholders::_1));
}
template<class Handler>
std::shared_ptr<WSSession>
PlainHTTPPeer::websocketUpgrade()
PlainHTTPPeer<Handler>::
websocketUpgrade()
{
auto ws = ios().emplace<PlainWSPeer>(
port_, handler_, remote_address_,
std::move(message_), std::move(stream_),
journal_);
auto ws = this->ios().template emplace<PlainWSPeer<Handler>>(
this->port_, this->handler_, this->remote_address_,
std::move(this->message_), std::move(stream_),
this->journal_);
return ws;
}
template<class Handler>
void
PlainHTTPPeer::do_request()
PlainHTTPPeer<Handler>::
do_request()
{
++request_count_;
auto const what = handler_.onHandoff (session(),
std::move(stream_), std::move(message_), remote_address_);
++this->request_count_;
auto const what = this->handler_.onHandoff(this->session(),
std::move(stream_), std::move(this->message_), this->remote_address_);
if (what.moved)
return;
error_code ec;
boost::system::error_code ec;
if (what.response)
{
// half-close on Connection: close
if (! what.keep_alive)
stream_.shutdown (socket_type::shutdown_receive, ec);
stream_.shutdown(socket_type::shutdown_receive, ec);
if (ec)
return fail (ec, "request");
return write(what.response, what.keep_alive);
return this->fail(ec, "request");
return this->write(what.response, what.keep_alive);
}
// Perform half-close when Connection: close and not SSL
if (! is_keep_alive(message_))
stream_.shutdown (socket_type::shutdown_receive, ec);
if (! is_keep_alive(this->message_))
stream_.shutdown(socket_type::shutdown_receive, ec);
if (ec)
return fail (ec, "request");
return this->fail(ec, "request");
// legacy
handler_.onRequest (session());
this->handler_.onRequest(this->session());
}
template<class Handler>
void
PlainHTTPPeer::do_close()
PlainHTTPPeer<Handler>::
do_close()
{
error_code ec;
stream_.shutdown (socket_type::shutdown_send, ec);
boost::system::error_code ec;
stream_.shutdown(socket_type::shutdown_send, ec);
}
} // ripple

View File

@@ -25,13 +25,14 @@
namespace ripple {
template<class Handler>
class PlainWSPeer
: public BaseWSPeer<PlainWSPeer>
, public std::enable_shared_from_this<PlainWSPeer>
: public BaseWSPeer<Handler, PlainWSPeer<Handler>>
, public std::enable_shared_from_this<PlainWSPeer<Handler>>
{
private:
friend class BasePeer<PlainWSPeer>;
friend class BaseWSPeer<PlainWSPeer>;
friend class BasePeer<Handler, PlainWSPeer>;
friend class BaseWSPeer<Handler, PlainWSPeer>;
using clock_type = std::chrono::system_clock;
using error_code = boost::system::error_code;
@@ -58,28 +59,32 @@ private:
//------------------------------------------------------------------------------
template<class Handler>
template<class Body, class Headers>
PlainWSPeer::PlainWSPeer(
PlainWSPeer<Handler>::
PlainWSPeer(
Port const& port,
Handler& handler,
endpoint_type remote_address,
beast::http::request_v1<Body, Headers>&& request,
socket_type&& socket,
beast::Journal journal)
: BaseWSPeer(port, handler, remote_address, std::move(request),
socket.get_io_service(), journal)
: BaseWSPeer<Handler, PlainWSPeer>(port, handler, remote_address,
std::move(request), socket.get_io_service(), journal)
, ws_(std::move(socket))
{
}
template<class Handler>
void
PlainWSPeer::do_close()
PlainWSPeer<Handler>::
do_close()
{
error_code ec;
auto& sock = ws_.next_layer();
sock.shutdown(socket_type::shutdown_both, ec);
if(ec)
return fail(ec, "do_close");
return this->fail(ec, "do_close");
}
} // ripple

View File

@@ -27,21 +27,25 @@
namespace ripple {
template<class Handler>
class SSLHTTPPeer
: public BaseHTTPPeer<SSLHTTPPeer>
, public std::enable_shared_from_this <SSLHTTPPeer>
: public BaseHTTPPeer<Handler, SSLHTTPPeer<Handler>>
, public std::enable_shared_from_this<SSLHTTPPeer<Handler>>
{
private:
friend class BaseHTTPPeer<SSLHTTPPeer>;
friend class BaseHTTPPeer<Handler, SSLHTTPPeer>;
using socket_type = boost::asio::ip::tcp::socket;
using stream_type = boost::asio::ssl::stream <socket_type&>;
using endpoint_type = boost::asio::ip::tcp::endpoint;
using yield_context = boost::asio::yield_context;
using error_code = boost::system::error_code;
std::unique_ptr<beast::asio::ssl_bundle> ssl_bundle_;
stream_type& stream_;
public:
template <class ConstBufferSequence>
SSLHTTPPeer (Port const& port, Handler& handler,
template<class ConstBufferSequence>
SSLHTTPPeer(Port const& port, Handler& handler,
beast::Journal journal, endpoint_type remote_address,
ConstBufferSequence const& buffers, socket_type&& socket);
@@ -53,7 +57,7 @@ public:
private:
void
do_handshake (yield_context yield);
do_handshake(yield_context do_yield);
void
do_request() override;
@@ -62,16 +66,19 @@ private:
do_close() override;
void
on_shutdown (error_code ec);
on_shutdown(error_code ec);
};
//------------------------------------------------------------------------------
template <class ConstBufferSequence>
SSLHTTPPeer::SSLHTTPPeer (Port const& port, Handler& handler,
template<class Handler>
template<class ConstBufferSequence>
SSLHTTPPeer<Handler>::
SSLHTTPPeer(Port const& port, Handler& handler,
beast::Journal journal, endpoint_type remote_address,
ConstBufferSequence const& buffers, socket_type&& socket)
: BaseHTTPPeer (port, handler, socket.get_io_service(), journal, remote_address, buffers)
: BaseHTTPPeer<Handler, SSLHTTPPeer>(port, handler,
socket.get_io_service(), journal, remote_address, buffers)
, ssl_bundle_(std::make_unique<beast::asio::ssl_bundle>(
port.context, std::move(socket)))
, stream_(ssl_bundle_->stream)
@@ -79,86 +86,99 @@ SSLHTTPPeer::SSLHTTPPeer (Port const& port, Handler& handler,
}
// Called when the acceptor accepts our socket.
template<class Handler>
void
SSLHTTPPeer::run()
SSLHTTPPeer<Handler>::
run()
{
if (!handler_.onAccept (session(), remote_address_))
if(! this->handler_.onAccept(this->session(), this->remote_address_))
{
boost::asio::spawn (strand_,
std::bind (&SSLHTTPPeer::do_close,
shared_from_this()));
boost::asio::spawn(this->strand_,
std::bind(&SSLHTTPPeer::do_close,
this->shared_from_this()));
return;
}
if (! stream_.lowest_layer().is_open())
return;
boost::asio::spawn (strand_, std::bind (&SSLHTTPPeer::do_handshake,
shared_from_this(), std::placeholders::_1));
boost::asio::spawn(this->strand_, std::bind(
&SSLHTTPPeer::do_handshake, this->shared_from_this(),
std::placeholders::_1));
}
template<class Handler>
std::shared_ptr<WSSession>
SSLHTTPPeer::websocketUpgrade()
SSLHTTPPeer<Handler>::
websocketUpgrade()
{
auto ws = ios().emplace<SSLWSPeer>(
port_, handler_, remote_address_,
std::move(message_), std::move(ssl_bundle_),
journal_);
auto ws = this->ios().template emplace<SSLWSPeer<Handler>>(
this->port_, this->handler_, this->remote_address_,
std::move(this->message_), std::move(this->ssl_bundle_),
this->journal_);
return ws;
}
template<class Handler>
void
SSLHTTPPeer::do_handshake (yield_context yield)
SSLHTTPPeer<Handler>::
do_handshake(yield_context do_yield)
{
error_code ec;
stream_.set_verify_mode (boost::asio::ssl::verify_none);
start_timer();
read_buf_.consume(stream_.async_handshake(
stream_type::server, read_buf_.data(), yield[ec]));
cancel_timer();
boost::system::error_code ec;
stream_.set_verify_mode(boost::asio::ssl::verify_none);
this->start_timer();
this->read_buf_.consume(stream_.async_handshake(
stream_type::server, this->read_buf_.data(), do_yield[ec]));
this->cancel_timer();
if (ec)
return fail(ec, "handshake");
return this->fail(ec, "handshake");
bool const http =
port().protocol.count("peer") > 0 ||
this->port().protocol.count("peer") > 0 ||
//port().protocol.count("wss") > 0 ||
port().protocol.count("wss2") > 0 ||
port().protocol.count("https") > 0;
if (http)
this->port().protocol.count("wss2") > 0 ||
this->port().protocol.count("https") > 0;
if(http)
{
boost::asio::spawn (strand_, std::bind (&SSLHTTPPeer::do_read,
shared_from_this(), std::placeholders::_1));
boost::asio::spawn(this->strand_,
std::bind(&SSLHTTPPeer::do_read,
this->shared_from_this(), std::placeholders::_1));
return;
}
// this will be destroyed
// `this` will be destroyed
}
template<class Handler>
void
SSLHTTPPeer::do_request()
SSLHTTPPeer<Handler>::
do_request()
{
++request_count_;
auto const what = handler_.onHandoff (session(),
std::move(ssl_bundle_), std::move(message_), remote_address_);
if (what.moved)
++this->request_count_;
auto const what = this->handler_.onHandoff(this->session(),
std::move(ssl_bundle_), std::move(this->message_),
this->remote_address_);
if(what.moved)
return;
if (what.response)
return write(what.response, what.keep_alive);
if(what.response)
return this->write(what.response, what.keep_alive);
// legacy
handler_.onRequest (session());
this->handler_.onRequest(this->session());
}
template<class Handler>
void
SSLHTTPPeer::do_close()
SSLHTTPPeer<Handler>::
do_close()
{
start_timer();
stream_.async_shutdown (strand_.wrap (std::bind (
&SSLHTTPPeer::on_shutdown, shared_from_this(),
this->start_timer();
stream_.async_shutdown(this->strand_.wrap(std::bind (
&SSLHTTPPeer::on_shutdown, this->shared_from_this(),
std::placeholders::_1)));
}
template<class Handler>
void
SSLHTTPPeer::on_shutdown (error_code ec)
SSLHTTPPeer<Handler>::
on_shutdown(error_code ec)
{
cancel_timer();
this->cancel_timer();
stream_.lowest_layer().close(ec);
}

View File

@@ -29,13 +29,14 @@
namespace ripple {
template<class Handler>
class SSLWSPeer
: public BaseWSPeer<SSLWSPeer>
, public std::enable_shared_from_this<SSLWSPeer>
: public BaseWSPeer<Handler, SSLWSPeer<Handler>>
, public std::enable_shared_from_this<SSLWSPeer<Handler>>
{
private:
friend class BasePeer<SSLWSPeer>;
friend class BaseWSPeer<SSLWSPeer>;
friend class BasePeer<Handler, SSLWSPeer>;
friend class BaseWSPeer<Handler, SSLWSPeer>;
using clock_type = std::chrono::system_clock;
using error_code = boost::system::error_code;
@@ -68,8 +69,10 @@ private:
//------------------------------------------------------------------------------
template<class Handler>
template<class Body, class Headers>
SSLWSPeer::SSLWSPeer(
SSLWSPeer<Handler>::
SSLWSPeer(
Port const& port,
Handler& handler,
endpoint_type remote_endpoint,
@@ -77,25 +80,30 @@ SSLWSPeer::SSLWSPeer(
std::unique_ptr<
beast::asio::ssl_bundle>&& ssl_bundle,
beast::Journal journal)
: BaseWSPeer(port, handler, remote_endpoint, std::move(request),
: BaseWSPeer<Handler, SSLWSPeer>(port, handler,
remote_endpoint, std::move(request),
ssl_bundle->socket.get_io_service(), journal)
, ssl_bundle_(std::move(ssl_bundle))
, ws_(ssl_bundle_->stream)
{
}
template<class Handler>
void
SSLWSPeer::do_close()
SSLWSPeer<Handler>::
do_close()
{
//start_timer();
using namespace beast::asio;
ws_.next_layer().async_shutdown(
strand_.wrap(std::bind(&SSLWSPeer::on_shutdown,
shared_from_this(), placeholders::error)));
this->strand_.wrap(std::bind(&SSLWSPeer::on_shutdown,
this->shared_from_this(), placeholders::error)));
}
template<class Handler>
void
SSLWSPeer::on_shutdown(error_code ec)
SSLWSPeer<Handler>::
on_shutdown(error_code ec)
{
//cancel_timer();
ws_.lowest_layer().close(ec);

View File

@@ -1,101 +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.
*/
//==============================================================================
#include <BeastConfig.h>
#include <ripple/basics/contract.h>
#include <ripple/server/impl/ServerImpl.h>
#include <ripple/server/impl/BaseHTTPPeer.h>
#include <boost/chrono/chrono_io.hpp>
#include <boost/utility/in_place_factory.hpp>
#include <cassert>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <string>
#include <stdio.h>
#include <time.h>
namespace ripple {
ServerImpl::ServerImpl (Handler& handler,
boost::asio::io_service& io_service, beast::Journal journal)
: handler_(handler)
, j_(journal)
, io_service_(io_service)
, strand_(io_service_)
, work_(io_service_)
{
}
ServerImpl::~ServerImpl()
{
// Handler::onStopped will not be called
work_ = boost::none;
ios_.close();
ios_.join();
}
void
ServerImpl::ports (std::vector<Port> const& ports)
{
if (closed())
Throw<std::logic_error> ("ports() on closed Server");
ports_.reserve(ports.size());
for(auto const& port : ports)
{
if (! port.websockets())
{
ports_.push_back(port);
if(auto sp = ios_.emplace<Door>(handler_,
io_service_, ports_.back(), j_))
{
list_.push_back(sp);
sp->run();
}
}
}
}
void
ServerImpl::close()
{
ios_.close(
[&]
{
work_ = boost::none;
handler_.onStopped(*this);
});
}
bool
ServerImpl::closed()
{
return ios_.closed();
}
//--------------------------------------------------------------------------
std::unique_ptr<Server>
make_Server (Handler& handler,
boost::asio::io_service& io_service, beast::Journal journal)
{
return std::make_unique<ServerImpl>(handler, io_service, journal);
}
} // ripple

View File

@@ -21,8 +21,8 @@
#define RIPPLE_SERVER_SERVERIMPL_H_INCLUDED
#include <ripple/basics/chrono.h>
#include <ripple/server/Handler.h>
#include <ripple/server/Server.h>
#include <ripple/server/impl/Door.h>
#include <ripple/server/impl/io_list.h>
#include <ripple/beast/core/List.h>
#include <ripple/beast/core/Thread.h>
@@ -30,17 +30,52 @@
#include <boost/optional.hpp>
#include <array>
#include <chrono>
#include <condition_variable>
#include <deque>
#include <functional>
#include <mutex>
#include <thread>
namespace ripple {
class BasicPeer;
class Door;
/** A multi-protocol server.
This server maintains multiple configured listening ports,
with each listening port allows for multiple protocols including
HTTP, HTTP/S, WebSocket, Secure WebSocket, and the Peer protocol.
*/
class Server
{
public:
/** Destroy the server.
The server is closed if it is not already closed. This call
blocks until the server has stopped.
*/
virtual
~Server() = default;
/** Returns the Journal associated with the server. */
virtual
beast::Journal
journal() = 0;
/** Set the listening port settings.
This may only be called once.
*/
virtual
void
ports (std::vector<Port> const& v) = 0;
/** Close the server.
The close is performed asynchronously. The handler will be notified
when the server has stopped. The server is considered stopped when
there are no pending I/O completion handlers and all connections
have closed.
Thread safety:
Safe to call concurrently from any thread.
*/
virtual
void
close() = 0;
};
template<class Handler>
class ServerImpl : public Server
{
private:
@@ -51,7 +86,7 @@ private:
historySize = 100
};
using Doors = std::vector <std::shared_ptr<Door>>;
using Doors = std::vector <std::shared_ptr<Door<Handler>>>;
Handler& handler_;
beast::Journal j_;
@@ -61,14 +96,14 @@ private:
std::mutex m_;
std::vector<Port> ports_;
std::vector<std::weak_ptr<Door>> list_;
std::vector<std::weak_ptr<Door<Handler>>> list_;
int high_ = 0;
std::array <std::size_t, 64> hist_;
io_list ios_;
public:
ServerImpl (Handler& handler,
ServerImpl(Handler& handler,
boost::asio::io_service& io_service, beast::Journal journal);
~ServerImpl();
@@ -91,7 +126,6 @@ public:
return ios_;
}
public:
boost::asio::io_service&
get_io_service()
{
@@ -107,7 +141,71 @@ private:
ceil_log2 (unsigned long long x);
};
template<class Handler>
ServerImpl<Handler>::
ServerImpl(Handler& handler,
boost::asio::io_service& io_service, beast::Journal journal)
: handler_(handler)
, j_(journal)
, io_service_(io_service)
, strand_(io_service_)
, work_(io_service_)
{
}
template<class Handler>
ServerImpl<Handler>::
~ServerImpl()
{
// Handler::onStopped will not be called
work_ = boost::none;
ios_.close();
ios_.join();
}
template<class Handler>
void
ServerImpl<Handler>::
ports (std::vector<Port> const& ports)
{
if (closed())
Throw<std::logic_error> ("ports() on closed Server");
ports_.reserve(ports.size());
for(auto const& port : ports)
{
if (! port.websockets())
{
ports_.push_back(port);
if(auto sp = ios_.emplace<Door<Handler>>(handler_,
io_service_, ports_.back(), j_))
{
list_.push_back(sp);
sp->run();
}
}
}
}
template<class Handler>
void
ServerImpl<Handler>::
close()
{
ios_.close(
[&]
{
work_ = boost::none;
handler_.onStopped(*this);
});
}
template<class Handler>
bool
ServerImpl<Handler>::
closed()
{
return ios_.closed();
}
} // ripple
#endif

View File

@@ -1,37 +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_SERVER_MAKE_SERVER_H_INCLUDED
#define RIPPLE_SERVER_MAKE_SERVER_H_INCLUDED
#include <ripple/server/Handler.h>
#include <ripple/server/Server.h>
#include <ripple/beast/utility/Journal.h>
#include <boost/asio/io_service.hpp>
namespace ripple {
/** Create the HTTP server using the specified handler. */
std::unique_ptr<Server>
make_Server (Handler& handler,
boost::asio::io_service& io_service, beast::Journal journal);
} // ripple
#endif

View File

@@ -19,8 +19,6 @@
#include <BeastConfig.h>
#include <ripple/basics/make_SSLContext.h>
#include <ripple/server/Handler.h>
#include <ripple/server/make_Server.h>
#include <ripple/server/Server.h>
#include <ripple/server/Session.h>
#include <ripple/beast/unit_test.h>
@@ -95,11 +93,11 @@ public:
//--------------------------------------------------------------------------
struct TestHandler : Handler
struct TestHandler
{
bool
onAccept (Session& session,
boost::asio::ip::tcp::endpoint endpoint) override
boost::asio::ip::tcp::endpoint endpoint)
{
return true;
}
@@ -108,7 +106,7 @@ public:
onHandoff (Session& session,
std::unique_ptr <beast::asio::ssl_bundle>&& bundle,
http_request_type&& request,
boost::asio::ip::tcp::endpoint remote_address) override
boost::asio::ip::tcp::endpoint remote_address)
{
return Handoff{};
}
@@ -116,13 +114,13 @@ public:
Handoff
onHandoff (Session& session, boost::asio::ip::tcp::socket&& socket,
http_request_type&& request,
boost::asio::ip::tcp::endpoint remote_address) override
boost::asio::ip::tcp::endpoint remote_address)
{
return Handoff{};
}
void
onRequest (Session& session) override
onRequest (Session& session)
{
session.write (std::string ("Hello, world!\n"));
if (is_keep_alive(session.request()))
@@ -133,18 +131,18 @@ public:
void
onWSMessage(std::shared_ptr<WSSession> session,
std::vector<boost::asio::const_buffer> const&) override
std::vector<boost::asio::const_buffer> const&)
{
}
void
onClose (Session& session,
boost::system::error_code const&) override
boost::system::error_code const&)
{
}
void
onStopped (Server& server) override
onStopped (Server& server)
{
}
};
@@ -303,11 +301,11 @@ public:
void stressTest()
{
struct NullHandler : Handler
struct NullHandler
{
bool
onAccept (Session& session,
boost::asio::ip::tcp::endpoint endpoint) override
boost::asio::ip::tcp::endpoint endpoint)
{
return true;
}
@@ -316,7 +314,7 @@ public:
onHandoff (Session& session,
std::unique_ptr <beast::asio::ssl_bundle>&& bundle,
http_request_type&& request,
boost::asio::ip::tcp::endpoint remote_address) override
boost::asio::ip::tcp::endpoint remote_address)
{
return Handoff{};
}
@@ -324,30 +322,30 @@ public:
Handoff
onHandoff (Session& session, boost::asio::ip::tcp::socket&& socket,
http_request_type&& request,
boost::asio::ip::tcp::endpoint remote_address) override
boost::asio::ip::tcp::endpoint remote_address)
{
return Handoff{};
}
void
onRequest (Session& session) override
onRequest (Session& session)
{
}
void
onWSMessage(std::shared_ptr<WSSession> session,
std::vector<boost::asio::const_buffer> const& buffers) override
std::vector<boost::asio::const_buffer> const& buffers)
{
}
void
onClose (Session& session,
boost::system::error_code const&) override
boost::system::error_code const&)
{
}
void
onStopped (Server& server) override
onStopped (Server& server)
{
}
};

View File

@@ -90,8 +90,10 @@
#include <ripple/rpc/impl/Handler.cpp>
#include <ripple/rpc/impl/LegacyPathFind.cpp>
#include <ripple/rpc/impl/TransactionSign.cpp>
#include <ripple/rpc/impl/Role.cpp>
#include <ripple/rpc/impl/RPCHelpers.cpp>
#include <ripple/rpc/impl/ServerHandlerImp.cpp>
#include <ripple/rpc/impl/TransactionSign.cpp>
#include <ripple/rpc/tests/AccountInfo_test.cpp>
#include <ripple/rpc/tests/AccountLinesRPC.test.cpp>

View File

@@ -23,11 +23,7 @@
#include <BeastConfig.h>
#include <ripple/server/impl/Door.cpp>
#include <ripple/server/impl/JSONRPCUtil.cpp>
#include <ripple/server/impl/Port.cpp>
#include <ripple/server/impl/Role.cpp>
#include <ripple/server/impl/ServerImpl.cpp>
#include <ripple/server/impl/ServerHandlerImp.cpp>
#include <ripple/server/tests/Server_test.cpp>

View File

@@ -34,10 +34,10 @@
#include <ripple/resource/ResourceManager.h>
#include <ripple/rpc/RPCHandler.h>
#include <ripple/server/Port.h>
#include <ripple/server/Role.h>
#include <ripple/rpc/Role.h>
#include <ripple/json/to_string.h>
#include <ripple/rpc/RPCHandler.h>
#include <ripple/server/Role.h>
#include <ripple/rpc/Role.h>
#include <ripple/websocket/WebSocket.h>
#include <boost/asio.hpp>