mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 02:55:50 +00:00
Universal Port (RIPD-160):
This changes the behavior and configuration specification of the listening ports that rippled uses to accept incoming connections for the supported protocols: peer (Peer Protocol), http (JSON-RPC over HTTP), https (JSON-RPC) over HTTPS, ws (Websockets Clients), and wss (Secure Websockets Clients). Each listening port is now capable of handshaking in multiple protocols specified in the configuration file (subject to some restrictions). Each port can be configured to provide its own SSL certificate, or to use a self-signed certificate. Ports can be configured to share settings, this allows multiple ports to use the same certificate or values. The list of ports is dynamic, administrators can open as few or as many ports as they like. Authentication settings such as user/password or admin user/admin password (for administrative commands on RPC or Websockets interfaces) can also be specified per-port. As the configuration file has changed significantly, administrators will need to update their ripple.cfg files and carefully review the documentation and new settings. Changes: * rippled-example.cfg updated with documentation and new example settings: All obsolete websocket, rpc, and peer configuration sections have been removed, the documentation updated, and a new documented set of example settings added. * HTTP::Writer abstraction for sending HTTP server requests and responses * HTTP::Handler handler improvements to support Universal Port * HTTP::Handler handler supports legacy Peer protocol handshakes * HTTP::Port uses shared_ptr<boost::asio::ssl::context> * HTTP::PeerImp and Overlay use ssl_bundle to support Universal Port * New JsonWriter to stream message and body through HTTP server * ServerHandler refactored to support Universal Port and legacy peers * ServerHandler Setup struct updated for Universal Port * Refactor some PeerFinder members * WSDoor and Websocket code stores and uses the HTTP::Port configuration * Websocket autotls class receives the current secure/plain SSL setting * Remove PeerDoor and obsolete Overlay peer accept code * Remove obsolete RPCDoor and synchronous RPC handling code * Remove other obsolete classes, types, and files * Command line tool uses ServerHandler Setup for port and authorization info * Fix handling of admin_user, admin_password in administrative commands * Fix adminRole to check credentials for Universal Port * Updated Overlay README.md * Overlay sends IP:port redirects on HTTP Upgrade peer connection requests: Incoming peers who handshake using the HTTP Upgrade mechanism don't get a slot, and always get HTTP Status 503 redirect containing a JSON content-body with a set of alternate IP and port addresses to try, learned from PeerFinder. A future commit related to the Hub and Spoke feature will change the response to grant the peer a slot when there are peer slots available. * HTTP responses to outgoing Peer connect requests parse redirect IP:ports: When the [overlay] configuration section (which is experimental) has http_handshake = 1, HTTP redirect responses will have the JSON content-body parsed to obtain the redirect IP:port addresses. * Use a single io_service for HTTP::Server and Overlay: This is necessary to allow HTTP::Server to pass sockets to and from Overlay and eventually Websockets. Unfortunately Websockets is not so easily changed to use an externally provided io_service. This will be addressed in a future commit, and is one step necessary ease the restriction on ports configured to offer Websocket protocols in the .cfg file.
This commit is contained in:
@@ -1811,13 +1811,6 @@
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\main\ParameterTable.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\main\ServerHandler.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\main\ServerHandlerImp.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\main\ServerHandlerImp.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\main\Tuning.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\misc\AccountState.cpp">
|
||||
@@ -2024,6 +2017,8 @@
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\shamap\SHAMapTreeNode.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\shamap\TreeNodeCache.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\transactors\AddWallet.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
@@ -2190,10 +2185,10 @@
|
||||
<ClCompile Include="..\..\src\ripple\common\impl\KeyCache.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\common\impl\ResolverAsio.cpp">
|
||||
<ClCompile Include="..\..\src\ripple\common\impl\make_SSLContext.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\common\impl\RippleSSLContext.cpp">
|
||||
<ClCompile Include="..\..\src\ripple\common\impl\ResolverAsio.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\common\impl\TaggedCache.cpp">
|
||||
@@ -2203,12 +2198,12 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\common\KeyCache.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\common\make_SSLContext.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\common\Resolver.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\common\ResolverAsio.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\common\RippleSSLContext.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\common\seconds_clock.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\common\TaggedCache.h">
|
||||
@@ -2371,37 +2366,6 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\data\utility\UptimeTimerAdapter.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\http\impl\Door.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\http\impl\Door.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\http\impl\Peer.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\http\impl\PlainPeer.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\http\impl\Port.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\http\impl\Server.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\http\impl\ServerImpl.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\http\impl\ServerImpl.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\http\impl\SSLPeer.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\http\impl\Types.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\http\Server.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\http\Session.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\http\tests\Server.test.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\json\impl\JsonPropertyStream.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
@@ -2460,9 +2424,6 @@
|
||||
<ClCompile Include="..\..\src\ripple\net\impl\RPCCall.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\net\impl\RPCDoor.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\net\impl\RPCErr.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
@@ -2471,9 +2432,6 @@
|
||||
<ClCompile Include="..\..\src\ripple\net\impl\RPCSub.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\net\impl\RPCUtil.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\net\impl\SNTPClient.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
@@ -2481,16 +2439,12 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\net\RPCCall.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\net\RPCDoor.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\net\RPCErr.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\net\RPCServer.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\net\RPCSub.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\net\RPCUtil.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\net\SNTPClient.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\nodestore\Backend.h">
|
||||
@@ -2615,11 +2569,6 @@
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\overlay\impl\OverlayImpl.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\overlay\impl\PeerDoor.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\overlay\impl\PeerDoor.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\overlay\impl\PeerImp.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
@@ -3052,6 +3001,62 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\rpc\Status.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\server\Handler.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\server\Handoff.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\server\impl\Door.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\server\impl\Door.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\server\impl\JSONRPCUtil.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\server\impl\JSONRPCUtil.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\server\impl\Peer.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\server\impl\PlainPeer.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\server\impl\Role.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\server\impl\ServerHandlerImp.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\server\impl\ServerHandlerImp.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\server\impl\ServerImpl.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\server\impl\ServerImpl.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\server\impl\SSLPeer.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\server\JsonWriter.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>
|
||||
<ClCompile Include="..\..\src\ripple\server\tests\Server.test.cpp">
|
||||
<ExcludedFromBuild>True</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\server\Writer.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\sitefiles\impl\Logic.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\sitefiles\impl\Manager.cpp">
|
||||
@@ -3185,8 +3190,6 @@
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\unity\data.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\unity\http.cpp">
|
||||
</ClCompile>
|
||||
<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>
|
||||
@@ -3233,6 +3236,8 @@
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\unity\rpcx.h">
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\unity\server.cpp">
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\unity\sitefiles.cpp">
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\unity\snappy.cpp">
|
||||
|
||||
@@ -364,15 +364,6 @@
|
||||
<Filter Include="ripple\data\utility">
|
||||
<UniqueIdentifier>{1906827A-5174-9515-DC11-9D11C511E0CB}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="ripple\http">
|
||||
<UniqueIdentifier>{8601C61D-413C-725E-C9E6-BD4F97E40032}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="ripple\http\impl">
|
||||
<UniqueIdentifier>{43D68742-4714-D103-EE00-EB10BD045FB6}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="ripple\http\tests">
|
||||
<UniqueIdentifier>{AA0D98CC-99E6-61CE-86D7-35156DC4EE55}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="ripple\json">
|
||||
<UniqueIdentifier>{BEDCC703-A2C8-FF25-7E1E-3471BD39ED98}</UniqueIdentifier>
|
||||
</Filter>
|
||||
@@ -436,6 +427,15 @@
|
||||
<Filter Include="ripple\rpc\impl">
|
||||
<UniqueIdentifier>{93AC3675-D183-4DB4-021E-8F4CA1586866}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="ripple\server">
|
||||
<UniqueIdentifier>{8A61DBF7-69CB-9043-8312-D44C40EC6AE9}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="ripple\server\impl">
|
||||
<UniqueIdentifier>{B0649154-4449-1172-FF4F-9F7A46908774}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="ripple\server\tests">
|
||||
<UniqueIdentifier>{9BA46DD5-4B0C-3C1D-6F16-93DE8A9B7313}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="ripple\sitefiles">
|
||||
<UniqueIdentifier>{CB0AC82D-AEA3-F41C-847F-D6ECA4971891}</UniqueIdentifier>
|
||||
</Filter>
|
||||
@@ -2703,15 +2703,6 @@
|
||||
<ClInclude Include="..\..\src\ripple\app\main\ParameterTable.h">
|
||||
<Filter>ripple\app\main</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\main\ServerHandler.h">
|
||||
<Filter>ripple\app\main</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\main\ServerHandlerImp.cpp">
|
||||
<Filter>ripple\app\main</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\app\main\ServerHandlerImp.h">
|
||||
<Filter>ripple\app\main</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\main\Tuning.h">
|
||||
<Filter>ripple\app\main</Filter>
|
||||
</ClInclude>
|
||||
@@ -2958,6 +2949,9 @@
|
||||
<ClInclude Include="..\..\src\ripple\app\shamap\SHAMapTreeNode.h">
|
||||
<Filter>ripple\app\shamap</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\app\shamap\TreeNodeCache.h">
|
||||
<Filter>ripple\app\shamap</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\app\transactors\AddWallet.cpp">
|
||||
<Filter>ripple\app\transactors</Filter>
|
||||
</ClCompile>
|
||||
@@ -3153,10 +3147,10 @@
|
||||
<ClCompile Include="..\..\src\ripple\common\impl\KeyCache.cpp">
|
||||
<Filter>ripple\common\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\common\impl\ResolverAsio.cpp">
|
||||
<ClCompile Include="..\..\src\ripple\common\impl\make_SSLContext.cpp">
|
||||
<Filter>ripple\common\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\common\impl\RippleSSLContext.cpp">
|
||||
<ClCompile Include="..\..\src\ripple\common\impl\ResolverAsio.cpp">
|
||||
<Filter>ripple\common\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\common\impl\TaggedCache.cpp">
|
||||
@@ -3168,15 +3162,15 @@
|
||||
<ClInclude Include="..\..\src\ripple\common\KeyCache.h">
|
||||
<Filter>ripple\common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\common\make_SSLContext.h">
|
||||
<Filter>ripple\common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\common\Resolver.h">
|
||||
<Filter>ripple\common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\common\ResolverAsio.h">
|
||||
<Filter>ripple\common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\common\RippleSSLContext.h">
|
||||
<Filter>ripple\common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\common\seconds_clock.h">
|
||||
<Filter>ripple\common</Filter>
|
||||
</ClInclude>
|
||||
@@ -3378,45 +3372,6 @@
|
||||
<ClInclude Include="..\..\src\ripple\data\utility\UptimeTimerAdapter.h">
|
||||
<Filter>ripple\data\utility</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>
|
||||
<ClInclude Include="..\..\src\ripple\http\impl\Peer.h">
|
||||
<Filter>ripple\http\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\http\impl\PlainPeer.h">
|
||||
<Filter>ripple\http\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\http\impl\Port.cpp">
|
||||
<Filter>ripple\http\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\http\impl\Server.cpp">
|
||||
<Filter>ripple\http\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\http\impl\ServerImpl.cpp">
|
||||
<Filter>ripple\http\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\http\impl\ServerImpl.h">
|
||||
<Filter>ripple\http\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\http\impl\SSLPeer.h">
|
||||
<Filter>ripple\http\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\http\impl\Types.h">
|
||||
<Filter>ripple\http\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\http\Server.h">
|
||||
<Filter>ripple\http</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\http\Session.h">
|
||||
<Filter>ripple\http</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\http\tests\Server.test.cpp">
|
||||
<Filter>ripple\http\tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\json\impl\JsonPropertyStream.cpp">
|
||||
<Filter>ripple\json\impl</Filter>
|
||||
</ClCompile>
|
||||
@@ -3489,9 +3444,6 @@
|
||||
<ClCompile Include="..\..\src\ripple\net\impl\RPCCall.cpp">
|
||||
<Filter>ripple\net\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\net\impl\RPCDoor.cpp">
|
||||
<Filter>ripple\net\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\net\impl\RPCErr.cpp">
|
||||
<Filter>ripple\net\impl</Filter>
|
||||
</ClCompile>
|
||||
@@ -3501,9 +3453,6 @@
|
||||
<ClCompile Include="..\..\src\ripple\net\impl\RPCSub.cpp">
|
||||
<Filter>ripple\net\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\net\impl\RPCUtil.cpp">
|
||||
<Filter>ripple\net\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\net\impl\SNTPClient.cpp">
|
||||
<Filter>ripple\net\impl</Filter>
|
||||
</ClCompile>
|
||||
@@ -3513,9 +3462,6 @@
|
||||
<ClInclude Include="..\..\src\ripple\net\RPCCall.h">
|
||||
<Filter>ripple\net</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\net\RPCDoor.h">
|
||||
<Filter>ripple\net</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\net\RPCErr.h">
|
||||
<Filter>ripple\net</Filter>
|
||||
</ClInclude>
|
||||
@@ -3525,9 +3471,6 @@
|
||||
<ClInclude Include="..\..\src\ripple\net\RPCSub.h">
|
||||
<Filter>ripple\net</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\net\RPCUtil.h">
|
||||
<Filter>ripple\net</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\net\SNTPClient.h">
|
||||
<Filter>ripple\net</Filter>
|
||||
</ClInclude>
|
||||
@@ -3678,12 +3621,6 @@
|
||||
<ClInclude Include="..\..\src\ripple\overlay\impl\OverlayImpl.h">
|
||||
<Filter>ripple\overlay\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\overlay\impl\PeerDoor.cpp">
|
||||
<Filter>ripple\overlay\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\overlay\impl\PeerDoor.h">
|
||||
<Filter>ripple\overlay\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\overlay\impl\PeerImp.cpp">
|
||||
<Filter>ripple\overlay\impl</Filter>
|
||||
</ClCompile>
|
||||
@@ -4179,6 +4116,81 @@
|
||||
<ClInclude Include="..\..\src\ripple\rpc\Status.h">
|
||||
<Filter>ripple\rpc</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>
|
||||
<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>
|
||||
<ClCompile Include="..\..\src\ripple\server\impl\JSONRPCUtil.cpp">
|
||||
<Filter>ripple\server\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\server\impl\JSONRPCUtil.h">
|
||||
<Filter>ripple\server\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\server\impl\Peer.h">
|
||||
<Filter>ripple\server\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\server\impl\PlainPeer.h">
|
||||
<Filter>ripple\server\impl</Filter>
|
||||
</ClInclude>
|
||||
<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>
|
||||
<ClInclude Include="..\..\src\ripple\server\impl\SSLPeer.h">
|
||||
<Filter>ripple\server\impl</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\server\JsonWriter.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>
|
||||
<ClCompile Include="..\..\src\ripple\server\tests\Server.test.cpp">
|
||||
<Filter>ripple\server\tests</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="..\..\src\ripple\server\Writer.h">
|
||||
<Filter>ripple\server</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\sitefiles\impl\Logic.h">
|
||||
<Filter>ripple\sitefiles\impl</Filter>
|
||||
</ClInclude>
|
||||
@@ -4359,9 +4371,6 @@
|
||||
<ClInclude Include="..\..\src\ripple\unity\data.h">
|
||||
<Filter>ripple\unity</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\unity\http.cpp">
|
||||
<Filter>ripple\unity</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\unity\hyperleveldb.cpp">
|
||||
<Filter>ripple\unity</Filter>
|
||||
</ClCompile>
|
||||
@@ -4419,6 +4428,9 @@
|
||||
<ClInclude Include="..\..\src\ripple\unity\rpcx.h">
|
||||
<Filter>ripple\unity</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="..\..\src\ripple\unity\server.cpp">
|
||||
<Filter>ripple\unity</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\ripple\unity\sitefiles.cpp">
|
||||
<Filter>ripple\unity</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -571,7 +571,6 @@ for toolchain in all_toolchains:
|
||||
'common.cpp',
|
||||
'core.cpp',
|
||||
'data.cpp',
|
||||
'http.cpp',
|
||||
'json.cpp',
|
||||
'net.cpp',
|
||||
'overlay.cpp',
|
||||
@@ -580,6 +579,7 @@ for toolchain in all_toolchains:
|
||||
'ripple.proto.cpp',
|
||||
'resource.cpp',
|
||||
'rpcx.cpp',
|
||||
'server.cpp',
|
||||
'sitefiles.cpp',
|
||||
'sslutil.cpp',
|
||||
'types.cpp',
|
||||
|
||||
@@ -6,23 +6,23 @@
|
||||
#
|
||||
# Contents
|
||||
#
|
||||
# 1. Peer Networking
|
||||
# 1. Server
|
||||
#
|
||||
# 2. Websocket Networking
|
||||
# 2. Peer Protocol
|
||||
#
|
||||
# 3. RPC Networking
|
||||
# 3. SMS Gateway
|
||||
#
|
||||
# 4. SMS Gateway
|
||||
# 4. Ripple Protocol
|
||||
#
|
||||
# 5. Ripple Protocol
|
||||
# 5. HTTPS Client
|
||||
#
|
||||
# 6. HTTPS Client
|
||||
# 6. Database
|
||||
#
|
||||
# 7. Database
|
||||
# 7. Diagnostics
|
||||
#
|
||||
# 8. Diagnostics
|
||||
# 8. Voting
|
||||
#
|
||||
# 9. Voting
|
||||
# 9. Example Settings
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
@@ -83,15 +83,196 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# 1. Peer Networking
|
||||
# 1. Server
|
||||
#
|
||||
#-------------------
|
||||
#----------
|
||||
#
|
||||
#
|
||||
#
|
||||
# rippled offers various server protocols to clients making inbound
|
||||
# connections. The listening ports rippled uses are "universal" ports
|
||||
# which may be configured to handshake in one or more of the available
|
||||
# supported protocols. These universal ports simplify administration:
|
||||
# A single open port can be used for multiple protocols.
|
||||
#
|
||||
# NOTE At least one server port must be defined in order
|
||||
# to accept incoming network connections.
|
||||
#
|
||||
#
|
||||
# [server]
|
||||
#
|
||||
# A list of port names and key/value pairs. A port name must start with a
|
||||
# letter and contain only letters and numbers. The name is not case-sensitive.
|
||||
# For each name in this list, rippled will look for a configuration file
|
||||
# section with the same name and use it to create a listening port. The
|
||||
# name is informational only; the choice of name does not affect the function
|
||||
# of the listening port.
|
||||
#
|
||||
# Key/value pairs specified in this section are optional, and apply to all
|
||||
# listening ports unless the port overrides the value in its section. They
|
||||
# may be considered default values.
|
||||
#
|
||||
# Suggestion:
|
||||
#
|
||||
# To avoid a conflict with port names and future configuration sections,
|
||||
# we recommend prepending "port_" to the port name. This prefix is not
|
||||
# required, but suggested.
|
||||
#
|
||||
# This example defines two ports with different port numbers and settings:
|
||||
#
|
||||
# [server]
|
||||
# port_public
|
||||
# port_private
|
||||
# port = 80
|
||||
#
|
||||
# [port_public]
|
||||
# ip=0.0.0.0
|
||||
# port = 443
|
||||
# protocol=peer,https
|
||||
#
|
||||
# [port_private]
|
||||
# ip=127.0.0.1
|
||||
# protocol=http
|
||||
#
|
||||
# When rippled is used as a command line client (for example, issuing a
|
||||
# server stop command), the first port advertising the http or https
|
||||
# protocol will be used to make the connection.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [<name>]
|
||||
#
|
||||
# A series of key/value pairs that define the settings for the port with
|
||||
# the corresponding name. These keys are possible:
|
||||
#
|
||||
# ip = <IP-address>
|
||||
#
|
||||
# Required. Determines the IP address of the network interface to bind
|
||||
# to. To bind to all available interfaces, uses 0.0.0.0
|
||||
#
|
||||
# port = <number>
|
||||
#
|
||||
# Required. Sets the port number to use for this port.
|
||||
#
|
||||
# protocol = [ http, https, peer ]
|
||||
#
|
||||
# Required. A comma-separated list of protocols to support:
|
||||
#
|
||||
# http JSON-RPC over HTTP
|
||||
# https JSON-RPC over HTTPS
|
||||
# ws Websockets
|
||||
# wss Secure Websockets
|
||||
# peer Peer Protocol
|
||||
#
|
||||
# Restrictions:
|
||||
#
|
||||
# Only one port may be configured to support the peer protocol.
|
||||
# A port cannot have websocket and non websocket protocols at the
|
||||
# same time. It is possible have both Websockets and Secure Websockets
|
||||
# together in one port.
|
||||
#
|
||||
# NOTE If no ports support the peer protocol, rippled cannot
|
||||
# receive incoming peer connections or become a superpeer.
|
||||
#
|
||||
# user = <text>
|
||||
# password = <text>
|
||||
#
|
||||
# When set, these credentials will be required on HTTP/S requests.
|
||||
# The credentials must be provided using HTTP's Basic Authentication
|
||||
# headers. If either or both fields are empty, then no credentials are
|
||||
# required. IP address restrictions, if any, will be checked in addition
|
||||
# to the credentials specified here.
|
||||
#
|
||||
# When acting in the client role, rippled will supply these credentials
|
||||
# using HTTP's Basic Authentication headers when making outbound HTTP/S
|
||||
# requests.
|
||||
#
|
||||
# admin = no | allow
|
||||
#
|
||||
# Controls whether or not administrative commands are allowed. These
|
||||
# commands may be issued over http, https, ws, or wss if configured
|
||||
# on the port. If unspecified, the default is to not allow
|
||||
# administrative commands.
|
||||
#
|
||||
# admin_user = <text>
|
||||
# admin_password = <text>
|
||||
#
|
||||
# When set, clients must provide these credentials in the submitted
|
||||
# JSON for any administrative command requests submitted to the HTTP/S,
|
||||
# WS, or WSS protocol interfaces. If administrative commands are
|
||||
# disabled for a port, these credentials have no effect.
|
||||
#
|
||||
# When acting in the client role, rippled will supply these credentials
|
||||
# in the submitted JSON for any administrative command requests when
|
||||
# invoking JSON-RPC commands on remote servers.
|
||||
#
|
||||
# ssl_key = <filename>
|
||||
# ssl_cert = <filename>
|
||||
# ssl_chain = <filename>
|
||||
#
|
||||
# Use the specified files when configuring SSL on the port.
|
||||
#
|
||||
# NOTE If no files are specified and secure protocols are selected,
|
||||
# rippled will generate an internal self-signed certificate.
|
||||
#
|
||||
# The files have these meanings:
|
||||
#
|
||||
# ssl_key
|
||||
#
|
||||
# Specifies the filename holding the SSL key in PEM format.
|
||||
#
|
||||
# ssl_cert
|
||||
#
|
||||
# Specifies the path to the SSL certificate file in PEM format.
|
||||
# This is not needed if the chain includes it.
|
||||
#
|
||||
# ssl_chain
|
||||
#
|
||||
# If you need a certificate chain, specify the path to the
|
||||
# certificate chain here. The chain may include the end certificate.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_admin_allow]
|
||||
#
|
||||
# Specify a list of IP addresses allowed to have admin access. One per line.
|
||||
# If you want to test the output of non-admin commands add this section and
|
||||
# just put an ip address not under your control.
|
||||
# Defaults to 127.0.0.1.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_startup]
|
||||
#
|
||||
# Specify a list of RPC commands to run at startup.
|
||||
#
|
||||
# Examples:
|
||||
# { "command" : "server_info" }
|
||||
# { "command" : "log_level", "partition" : "ripplecalc", "severity" : "trace" }
|
||||
#
|
||||
#
|
||||
#
|
||||
# [websocket_ping_frequency]
|
||||
#
|
||||
# <number>
|
||||
#
|
||||
# The amount of time to wait in seconds, before sending a websocket 'ping'
|
||||
# message. Ping messages are used to determine if the remote end of the
|
||||
# connection is no longer available.
|
||||
#
|
||||
#
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# 2. Peer Protocol
|
||||
#
|
||||
#-----------------
|
||||
#
|
||||
# These settings control security and access attributes of the Peer to Peer
|
||||
# server section of the rippled process. Peer Networking implements the
|
||||
# server section of the rippled process. Peer Protocol implements the
|
||||
# Ripple Payment protocol. It is over peer connections that transactions
|
||||
# and validations are passed from to machine to machine, to make up the
|
||||
# components of closed ledgers.
|
||||
# and validations are passed from to machine to machine, to determine the
|
||||
# contents of validated ledgers.
|
||||
#
|
||||
#
|
||||
#
|
||||
@@ -130,21 +311,6 @@
|
||||
#
|
||||
#
|
||||
#
|
||||
# [peer_ip]
|
||||
#
|
||||
# IP address or domain to bind to allow external connections from peers.
|
||||
# Defaults to not binding, which disallows external connections from peers.
|
||||
#
|
||||
# Examples: 0.0.0.0 - Bind on all interfaces.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [peer_port]
|
||||
#
|
||||
# If peer_ip is supplied, corresponding port to bind to for peer connections.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [peer_private]
|
||||
#
|
||||
# 0 or 1.
|
||||
@@ -238,243 +404,7 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# 2. Websocket Networking
|
||||
#
|
||||
#------------------------
|
||||
#
|
||||
# These settings control security and access attributes of the Websocket
|
||||
# server section of the rippled process, primarily used to service
|
||||
# client requests and backend applications.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [websocket_public_ip]
|
||||
#
|
||||
# IP address or domain to bind to allow untrusted connections from clients.
|
||||
# In the future, this option will go away and the peer_ip will accept
|
||||
# websocket client connections.
|
||||
#
|
||||
# Examples: 0.0.0.0 - Bind on all interfaces.
|
||||
# 127.0.0.1 - Bind on localhost interface. Only local programs may connect.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [websocket_public_port]
|
||||
#
|
||||
# Port to bind to allow untrusted connections from clients. In the future,
|
||||
# this option will go away and the peer_ip will accept websocket client
|
||||
# connections.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [websocket_public_secure]
|
||||
#
|
||||
# 0, 1 or 2.
|
||||
# 0: Provide ws service for websocket_public_ip/websocket_public_port.
|
||||
# 1: Provide both ws and wss service for websocket_public_ip/websocket_public_port. [default]
|
||||
# 2: Provide wss service only for websocket_public_ip/websocket_public_port.
|
||||
#
|
||||
# Browser pages like the Ripple client will not be able to connect to a secure
|
||||
# websocket connection if a self-signed certificate is used. As the Ripple
|
||||
# reference client currently shares secrets with its server, this should be
|
||||
# enabled.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [websocket_ping_frequency]
|
||||
#
|
||||
# <number>
|
||||
#
|
||||
# The amount of time to wait in seconds, before sending a websocket 'ping'
|
||||
# message. Ping messages are used to determine if the remote end of the
|
||||
# connection is no longer available.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [websocket_ip]
|
||||
#
|
||||
# IP address or domain to bind to allow trusted ADMIN connections from backend
|
||||
# applications.
|
||||
#
|
||||
# Examples: 0.0.0.0 - Bind on all interfaces.
|
||||
# 127.0.0.1 - Bind on localhost interface. Only local programs may connect.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [websocket_port]
|
||||
#
|
||||
# Port to bind to allow trusted ADMIN connections from backend applications.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [websocket_secure]
|
||||
#
|
||||
# 0, 1, or 2.
|
||||
# 0: Provide ws service only for websocket_ip/websocket_port. [default]
|
||||
# 1: Provide ws and wss service for websocket_ip/websocket_port
|
||||
# 2: Provide wss service for websocket_ip/websocket_port.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [websocket_ssl_cert]
|
||||
#
|
||||
# Specify the path to the SSL certificate file in PEM format.
|
||||
# This is not needed if the chain includes it.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [websocket_ssl_chain]
|
||||
#
|
||||
# If you need a certificate chain, specify the path to the certificate chain
|
||||
# here. The chain may include the end certificate.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [websocket_ssl_key]
|
||||
#
|
||||
# Specify the filename holding the SSL key in PEM format.
|
||||
#
|
||||
#
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# 3. RPC Networking
|
||||
#
|
||||
#------------------
|
||||
#
|
||||
# This group of settings configures security and access attributes of the
|
||||
# RPC server section of the rippled process, used to service both local
|
||||
# and optional remote clients.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_allow_remote]
|
||||
#
|
||||
# 0 or 1.
|
||||
#
|
||||
# 0: Allow RPC connections only from 127.0.0.1. [default]
|
||||
# 1: Allow RPC connections from any IP.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_admin_allow]
|
||||
#
|
||||
# Specify a list of IP addresses allowed to have admin access. One per line.
|
||||
# If you want to test the output of non-admin commands add this section and
|
||||
# just put an ip address not under your control.
|
||||
# Defaults to 127.0.0.1.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_admin_user]
|
||||
#
|
||||
# As a server, require this as the admin user to be specified. Also, require
|
||||
# rpc_admin_user and rpc_admin_password to be checked for RPC admin functions.
|
||||
# The request must specify these as the admin_user and admin_password in the
|
||||
# request object.
|
||||
#
|
||||
# As a client, supply this to the server in the request object.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_admin_password]
|
||||
#
|
||||
# As a server, require this as the admin password to be specified. Also,
|
||||
# require rpc_admin_user and rpc_admin_password to be checked for RPC admin
|
||||
# functions. The request must specify these as the admin_user and
|
||||
# admin_password in the request object.
|
||||
#
|
||||
# As a client, supply this to the server in the request object.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_ip]
|
||||
#
|
||||
# IP address or domain to bind to allow insecure RPC connections.
|
||||
# Defaults to not binding, which disallows RPC connections.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_port]
|
||||
#
|
||||
# If rpc_ip is supplied, corresponding port to bind to for peer connections.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_user]
|
||||
#
|
||||
# As a server, require this user to be specified and require rpc_password to
|
||||
# be checked for RPC access via the rpc_ip and rpc_port. The user and password
|
||||
# must be specified via HTTP's basic authentication method.
|
||||
# As a client, supply this to the server via HTTP's basic authentication
|
||||
# method.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_password]
|
||||
#
|
||||
# As a server, require this password to be specified and require rpc_user to
|
||||
# be checked for RPC access via the rpc_ip and rpc_port. The user and password
|
||||
# must be specified via HTTP's basic authentication method.
|
||||
# As a client, supply this to the server via HTTP's basic authentication
|
||||
# method.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_startup]
|
||||
#
|
||||
# Specify a list of RPC commands to run at startup.
|
||||
#
|
||||
# Examples:
|
||||
# { "command" : "server_info" }
|
||||
# { "command" : "log_level", "partition" : "ripplecalc", "severity" : "trace" }
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_secure]
|
||||
#
|
||||
# 0 or 1.
|
||||
#
|
||||
# 0: Server certificates are not provided for RPC clients using SSL [default]
|
||||
# 1: Client RPC connections wil be provided with SSL certificates.
|
||||
#
|
||||
# Note that if rpc_secure is enabled, it will also be necessary to configure
|
||||
# the certificate file settings located in rpc_ssl_cert, rpc_ssl_chain, and
|
||||
# rpc_ssl_key
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_ssl_cert]
|
||||
#
|
||||
# <pathname>
|
||||
#
|
||||
# A file system path leading to the SSL certificate file to use for secure
|
||||
# RPC. The file is in PEM format. The file is not needed if the chain
|
||||
# includes it.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_ssl_chain]
|
||||
#
|
||||
# <pathname>
|
||||
#
|
||||
# A file system path leading to the file with the certificate chain.
|
||||
# The chain may include the end certificate.
|
||||
#
|
||||
#
|
||||
#
|
||||
# [rpc_ssl_key]
|
||||
#
|
||||
# <pathname>
|
||||
#
|
||||
# A file system path leading to the file with the SSL key.
|
||||
# The file is in PEM format.
|
||||
#
|
||||
#
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# 4. SMS Gateway
|
||||
# 3. SMS Gateway
|
||||
#
|
||||
#---------------
|
||||
#
|
||||
@@ -510,7 +440,7 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# 5. Ripple Protocol
|
||||
# 4. Ripple Protocol
|
||||
#
|
||||
#-------------------
|
||||
#
|
||||
@@ -654,7 +584,7 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# 6. HTTPS Client
|
||||
# 5. HTTPS Client
|
||||
#
|
||||
#----------------
|
||||
#
|
||||
@@ -694,7 +624,7 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# 7. Database
|
||||
# 6. Database
|
||||
#
|
||||
#------------
|
||||
#
|
||||
@@ -767,7 +697,7 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# 8. Diagnostics
|
||||
# 7. Diagnostics
|
||||
#
|
||||
#---------------
|
||||
#
|
||||
@@ -823,7 +753,7 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# 9. Voting
|
||||
# 8. Voting
|
||||
#
|
||||
#----------
|
||||
#
|
||||
@@ -873,41 +803,84 @@
|
||||
# owner_reserve = 5000000 # 5 XRP
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
# Allow other peers to connect to this server.
|
||||
#
|
||||
[peer_ip]
|
||||
0.0.0.0
|
||||
|
||||
[peer_port]
|
||||
51235
|
||||
|
||||
# Allow untrusted clients to connect to this server.
|
||||
# 9. Example Settings
|
||||
#
|
||||
[websocket_public_ip]
|
||||
0.0.0.0
|
||||
|
||||
[websocket_public_port]
|
||||
5006
|
||||
|
||||
# Provide trusted websocket ADMIN access to the localhost.
|
||||
#--------------------
|
||||
#
|
||||
[websocket_ip]
|
||||
127.0.0.1
|
||||
|
||||
[websocket_port]
|
||||
6006
|
||||
|
||||
# Provide trusted json-rpc ADMIN access to the localhost.
|
||||
# Administrators can use these values as a starting poing for configuring
|
||||
# their instance of rippled, but each value should be checked to make sure
|
||||
# it meets the business requirements for the organization.
|
||||
#
|
||||
[rpc_ip]
|
||||
127.0.0.1
|
||||
# Server
|
||||
#
|
||||
# These example configuration settings create these ports:
|
||||
#
|
||||
# "peer"
|
||||
#
|
||||
# Peer protocol open to everyone. This is required to accept
|
||||
# incoming rippled connections. This does not affect automatic
|
||||
# or manual outgoing Peer protocol connections.
|
||||
#
|
||||
# "rpc"
|
||||
#
|
||||
# Administrative RPC commands over HTTPS, when originating from
|
||||
# the same machine (via the loopback adapter at 127.0.0.1).
|
||||
#
|
||||
# "wss_admin"
|
||||
#
|
||||
# Admin level API commands over Secure Websockets, when originating
|
||||
# from the same machine (via the loopback adapter at 127.0.0.1).
|
||||
#
|
||||
# This port is commented out but can be enabled by removing
|
||||
# the '#' from each corresponding line including the entry under [server]
|
||||
#
|
||||
# "wss_public"
|
||||
#
|
||||
# Guest level API commands over Secure Websockets, open to everyone.
|
||||
#
|
||||
# For HTTPS and Secure Websockets ports, if no certificate and key file
|
||||
# are specified then a self-signed certificate will be generated on startup.
|
||||
# If you have a certificate and key file, uncomment the corresponding lines
|
||||
# and ensure the paths to the files are correct.
|
||||
#
|
||||
# NOTE
|
||||
#
|
||||
# To accept connections on well known ports such as 80 (HTTP) or
|
||||
# 443 (HTTPS), most operating systems will require rippled to
|
||||
# run with administrator privileges, or else rippled will not start.
|
||||
|
||||
[rpc_port]
|
||||
5005
|
||||
[server]
|
||||
port_rpc
|
||||
port_peer
|
||||
port_wss_admin
|
||||
#port_ws_public
|
||||
#ssl_key = /etc/ssl/private/server.key
|
||||
#ssl_cert = /etc/ssl/certs/server.crt
|
||||
|
||||
[rpc_allow_remote]
|
||||
0
|
||||
[port_rpc]
|
||||
port = 5005
|
||||
ip = 127.0.0.1
|
||||
admin = allow
|
||||
protocol = https
|
||||
|
||||
[port_peer]
|
||||
port = 51235
|
||||
ip = 0.0.0.0
|
||||
protocol = peer
|
||||
|
||||
[port_wss_admin]
|
||||
port = 6006
|
||||
ip = 127.0.0.1
|
||||
admin = allow
|
||||
protocol = wss
|
||||
|
||||
#[port_ws_public]
|
||||
#port = 5005
|
||||
#ip = 127.0.0.1
|
||||
#protocol = wss
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
[node_size]
|
||||
medium
|
||||
@@ -962,22 +935,7 @@ n9LdgEtkmGB9E2h3K4Vp7iGUaKuq23Zr32ehxiU8FWY7xoxbWTSA RL5
|
||||
[rpc_startup]
|
||||
{ "command": "log_level", "severity": "warning" }
|
||||
|
||||
# Configure SSL for WebSockets. Not enabled by default because not everybody
|
||||
# has an SSL cert on their server, but if you uncomment the following lines and
|
||||
# set the path to the SSL certificate and private key the WebSockets protocol
|
||||
# will be protected by SSL/TLS.
|
||||
#[websocket_secure]
|
||||
#1
|
||||
|
||||
#[websocket_ssl_cert]
|
||||
#/etc/ssl/certs/server.crt
|
||||
|
||||
#[websocket_ssl_key]
|
||||
#/etc/ssl/private/server.key
|
||||
|
||||
# Defaults to 0 ("no") so that you can use self-signed SSL certificates for
|
||||
# development, or internally.
|
||||
#[ssl_verify]
|
||||
#0
|
||||
|
||||
|
||||
|
||||
@@ -24,13 +24,15 @@
|
||||
#include <ripple/basics/LoggedTimings.h>
|
||||
#include <ripple/basics/Sustain.h>
|
||||
#include <ripple/common/seconds_clock.h>
|
||||
#include <ripple/common/RippleSSLContext.h>
|
||||
#include <ripple/common/make_SSLContext.h>
|
||||
#include <ripple/core/LoadFeeTrack.h>
|
||||
#include <ripple/rpc/Manager.h>
|
||||
#include <ripple/nodestore/Database.h>
|
||||
#include <ripple/nodestore/DummyScheduler.h>
|
||||
#include <ripple/nodestore/Manager.h>
|
||||
#include <ripple/overlay/make_Overlay.h>
|
||||
#include <ripple/rpc/Manager.h>
|
||||
#include <ripple/server/make_ServerHandler.h>
|
||||
#include <ripple/sitefiles/Sitefiles.h>
|
||||
#include <ripple/validators/Manager.h>
|
||||
#include <beast/asio/io_latency_probe.h>
|
||||
#include <beast/module/core/thread/DeadlineTimer.h>
|
||||
@@ -193,12 +195,8 @@ public:
|
||||
std::unique_ptr <DatabaseCon> mTxnDB;
|
||||
std::unique_ptr <DatabaseCon> mLedgerDB;
|
||||
std::unique_ptr <DatabaseCon> mWalletDB;
|
||||
|
||||
std::unique_ptr <SSLContext> m_wsSSLContext;
|
||||
std::unique_ptr <Overlay> m_peers;
|
||||
std::unique_ptr <RPCDoor> m_rpcDoor;
|
||||
std::unique_ptr <WSDoor> m_wsPublicDoor;
|
||||
std::unique_ptr <WSDoor> m_wsPrivateDoor;
|
||||
std::unique_ptr <Overlay> m_overlay;
|
||||
std::vector <std::unique_ptr<WSDoor>> wsDoors_;
|
||||
|
||||
beast::WaitableEvent m_stop;
|
||||
|
||||
@@ -305,9 +303,9 @@ public:
|
||||
// VFALCO NOTE LocalCredentials starts the deprecated UNL service
|
||||
, m_deprecatedUNL (make_UniqueNodeList (*m_jobQueue))
|
||||
|
||||
, serverHandler_ (make_RPCHTTPServer (*m_networkOPs,
|
||||
*m_jobQueue, *m_networkOPs, *m_resourceManager,
|
||||
setup_RPC(getConfig()["rpc"])))
|
||||
, serverHandler_ (make_ServerHandler (*m_networkOPs,
|
||||
get_io_service(), *m_jobQueue, *m_networkOPs,
|
||||
*m_resourceManager))
|
||||
|
||||
, m_nodeStore (m_nodeStoreManager->make_Database ("NodeStore.main",
|
||||
m_nodeStoreScheduler, m_logs.journal("NodeObject"),
|
||||
@@ -520,7 +518,7 @@ public:
|
||||
|
||||
Overlay& overlay ()
|
||||
{
|
||||
return *m_peers;
|
||||
return *m_overlay;
|
||||
}
|
||||
|
||||
// VFALCO TODO Move these to the .cpp
|
||||
@@ -708,73 +706,42 @@ public:
|
||||
m_treeNodeCache.setTargetAge (getConfig ().getSize (siTreeCacheAge));
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// Server
|
||||
//
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
serverHandler_->setup (setup_ServerHandler(getConfig(), std::cerr),
|
||||
m_journal);
|
||||
|
||||
// VFALCO NOTE Unfortunately, in stand-alone mode some code still
|
||||
// foolishly calls overlay(). When this is fixed we can
|
||||
// move the instantiation inside a conditional:
|
||||
//
|
||||
// if (!getConfig ().RUN_STANDALONE)
|
||||
m_peers = make_Overlay (setup_Overlay(getConfig()), *m_jobQueue,
|
||||
*m_resourceManager, *m_siteFiles,
|
||||
m_overlay = make_Overlay (setup_Overlay(getConfig()), *m_jobQueue,
|
||||
*serverHandler_, *m_resourceManager,
|
||||
getConfig ().getModuleDatabasePath (), *m_resolver,
|
||||
get_io_service());
|
||||
add (*m_peers); // add to PropertyStream
|
||||
add (*m_overlay); // add to PropertyStream
|
||||
|
||||
// SSL context used for WebSocket connections.
|
||||
if (getConfig ().WEBSOCKET_SECURE)
|
||||
// Create websocket doors
|
||||
for (auto const& port : serverHandler_->setup().ports)
|
||||
{
|
||||
m_wsSSLContext.reset (RippleSSLContext::createAuthenticated (
|
||||
getConfig ().WEBSOCKET_SSL_KEY,
|
||||
getConfig ().WEBSOCKET_SSL_CERT,
|
||||
getConfig ().WEBSOCKET_SSL_CHAIN));
|
||||
if (! port.websockets())
|
||||
continue;
|
||||
auto door = make_WSDoor(port, *m_resourceManager, getOPs());
|
||||
if (door == nullptr)
|
||||
{
|
||||
m_journal.fatal << "Could not create Websocket for [" <<
|
||||
port.name << "]";
|
||||
throw std::exception();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_wsSSLContext.reset (RippleSSLContext::createWebSocket ());
|
||||
}
|
||||
|
||||
// Create private listening WebSocket socket
|
||||
//
|
||||
if (!getConfig ().WEBSOCKET_IP.empty () && getConfig ().WEBSOCKET_PORT)
|
||||
{
|
||||
m_wsPrivateDoor.reset (WSDoor::New (*m_resourceManager,
|
||||
getOPs(), getConfig ().WEBSOCKET_IP, getConfig ().WEBSOCKET_PORT,
|
||||
false, m_wsSSLContext->get ()));
|
||||
|
||||
if (m_wsPrivateDoor == nullptr)
|
||||
{
|
||||
beast::FatalError ("Could not open the WebSocket private interface.",
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_journal.info << "WebSocket private interface: disabled";
|
||||
}
|
||||
|
||||
// Create public listening WebSocket socket
|
||||
//
|
||||
if (!getConfig ().WEBSOCKET_PUBLIC_IP.empty () && getConfig ().WEBSOCKET_PUBLIC_PORT)
|
||||
{
|
||||
m_wsPublicDoor.reset (WSDoor::New (*m_resourceManager,
|
||||
getOPs(), getConfig ().WEBSOCKET_PUBLIC_IP, getConfig ().WEBSOCKET_PUBLIC_PORT,
|
||||
true, m_wsSSLContext->get ()));
|
||||
|
||||
if (m_wsPublicDoor == nullptr)
|
||||
{
|
||||
beast::FatalError ("Could not open the WebSocket public interface.",
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_journal.info << "WebSocket public interface: disabled";
|
||||
wsDoors_.emplace_back(std::move(door));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
serverHandler_->setup (m_journal);
|
||||
|
||||
// Begin connecting to network.
|
||||
if (!getConfig ().RUN_STANDALONE)
|
||||
{
|
||||
@@ -923,12 +890,6 @@ public:
|
||||
doStop ();
|
||||
|
||||
{
|
||||
// These two asssignment should no longer be necessary
|
||||
// once the WSDoor cancels its pending I/O correctly
|
||||
//m_wsPublicDoor = nullptr;
|
||||
//m_wsPrivateDoor = nullptr;
|
||||
//m_wsProxyDoor = nullptr;
|
||||
|
||||
// VFALCO TODO Try to not have to do this early, by using observers to
|
||||
// eliminate LoadManager's dependency inversions.
|
||||
//
|
||||
|
||||
@@ -21,6 +21,12 @@
|
||||
#define RIPPLE_APP_APPLICATION_H_INCLUDED
|
||||
|
||||
#include <ripple/app/main/FullBelowCache.h>
|
||||
#include <ripple/app/shamap/TreeNodeCache.h>
|
||||
#include <ripple/common/TaggedCache.h>
|
||||
#include <beast/utility/PropertyStream.h>
|
||||
#include <mutex>
|
||||
|
||||
namespace boost { namespace asio { class io_service; } }
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -31,12 +37,12 @@ namespace NodeStore { class Database; }
|
||||
namespace RPC { class Manager; }
|
||||
|
||||
// VFALCO TODO Fix forward declares required for header dependency loops
|
||||
class CollectorManager;
|
||||
class AmendmentTable;
|
||||
class CollectorManager;
|
||||
class IHashRouter;
|
||||
class Logs;
|
||||
class LoadFeeTrack;
|
||||
class Overlay;
|
||||
class LocalCredentials;
|
||||
class UniqueNodeList;
|
||||
class JobQueue;
|
||||
class InboundLedgers;
|
||||
@@ -44,12 +50,13 @@ class LedgerMaster;
|
||||
class LoadManager;
|
||||
class NetworkOPs;
|
||||
class OrderBookDB;
|
||||
class Overlay;
|
||||
class PathRequests;
|
||||
class ProofOfWorkFactory;
|
||||
class SerializedLedgerEntry;
|
||||
class TransactionMaster;
|
||||
class TxQueue;
|
||||
class LocalCredentials;
|
||||
class PathRequests;
|
||||
class Validations;
|
||||
|
||||
class DatabaseCon;
|
||||
|
||||
@@ -70,7 +77,7 @@ public:
|
||||
|
||||
other things
|
||||
*/
|
||||
typedef RippleRecursiveMutex LockType;
|
||||
typedef std::recursive_mutex LockType;
|
||||
typedef std::unique_lock <LockType> ScopedLockType;
|
||||
typedef std::unique_ptr <ScopedLockType> ScopedLock;
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/basics/StringUtilities.h>
|
||||
#include <ripple/common/make_SSLContext.h>
|
||||
#include <ripple/core/Config.h>
|
||||
|
||||
namespace ripple {
|
||||
@@ -88,7 +89,7 @@ bool LocalCredentials::nodeIdentityCreate ()
|
||||
RippleAddress naNodePrivate = RippleAddress::createNodePrivate (naSeed);
|
||||
|
||||
// Make new key.
|
||||
std::string strDh512 (RippleSSLContext::getRawDHParams (512));
|
||||
std::string strDh512 (getRawDHParams (512));
|
||||
|
||||
std::string strDh1024 = strDh512;
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ void startServer ()
|
||||
RPCHandler rhHandler (getApp().getOPs ());
|
||||
|
||||
Resource::Charge loadType = Resource::feeReferenceRPC;
|
||||
Json::Value jvResult = rhHandler.doCommand (jvCommand, Config::ADMIN, loadType);
|
||||
Json::Value jvResult = rhHandler.doCommand (jvCommand, Role::ADMIN, loadType);
|
||||
|
||||
if (!getConfig ().QUIET)
|
||||
std::cerr << "Result: " << jvResult << std::endl;
|
||||
@@ -345,8 +345,9 @@ int run (int argc, char** argv)
|
||||
//
|
||||
if (vm.count ("rpc_ip"))
|
||||
{
|
||||
getConfig ().setRpcIpAndOptionalPort (vm ["rpc_ip"].as <std::string> ());
|
||||
getConfig().overwrite("rpc", "ip", vm["rpc_ip"].as<std::string>());
|
||||
// VFALCO TODO This is currently broken
|
||||
//getConfig ().setRpcIpAndOptionalPort (vm ["rpc_ip"].as <std::string> ());
|
||||
//getConfig().overwrite("rpc", "ip", vm["rpc_ip"].as<std::string>());
|
||||
}
|
||||
|
||||
// Override the RPC destination port number
|
||||
@@ -354,8 +355,9 @@ int run (int argc, char** argv)
|
||||
if (vm.count ("rpc_port"))
|
||||
{
|
||||
// VFALCO TODO This should be a short.
|
||||
getConfig ().setRpcPort (vm ["rpc_port"].as <int> ());
|
||||
getConfig().overwrite("rpc", "port", vm["rpc_port"].as<std::string>());
|
||||
// VFALCO TODO This is currently broken
|
||||
//getConfig ().setRpcPort (vm ["rpc_port"].as <int> ());
|
||||
//getConfig().overwrite("rpc", "port", vm["rpc_port"].as<std::string>());
|
||||
}
|
||||
|
||||
if (vm.count ("quorum"))
|
||||
|
||||
@@ -1,273 +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 <ripple/app/main/ServerHandlerImp.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
ServerHandler::ServerHandler (Stoppable& parent)
|
||||
: Stoppable ("ServerHandler", parent)
|
||||
, Source ("server")
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
ServerHandlerImp::ServerHandlerImp (Stoppable& parent, JobQueue& jobQueue,
|
||||
NetworkOPs& networkOPs, Resource::Manager& resourceManager,
|
||||
RPC::Setup const& setup)
|
||||
: ServerHandler (parent)
|
||||
, m_resourceManager (resourceManager)
|
||||
, m_journal (deprecatedLogs().journal("Server"))
|
||||
, m_jobQueue (jobQueue)
|
||||
, m_networkOPs (networkOPs)
|
||||
, m_server (HTTP::make_Server(
|
||||
*this, deprecatedLogs().journal("Server")))
|
||||
, setup_ (setup)
|
||||
{
|
||||
if (setup_.secure)
|
||||
m_context.reset (RippleSSLContext::createAuthenticated (
|
||||
setup_.ssl_key, setup_.ssl_cert, setup_.ssl_chain));
|
||||
else
|
||||
m_context.reset (RippleSSLContext::createBare());
|
||||
}
|
||||
|
||||
ServerHandlerImp::~ServerHandlerImp()
|
||||
{
|
||||
m_server = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
ServerHandlerImp::setup (beast::Journal journal)
|
||||
{
|
||||
if (! setup_.ip.empty() && setup_.port != 0)
|
||||
{
|
||||
auto ep = beast::IP::Endpoint::from_string (setup_.ip);
|
||||
|
||||
// VFALCO TODO IP address should not have an "unspecified" state
|
||||
//if (! is_unspecified (ep))
|
||||
{
|
||||
HTTP::Port port;
|
||||
|
||||
if (setup_.secure == 0)
|
||||
port.security = HTTP::Port::Security::no_ssl;
|
||||
else if (setup_.secure == 1)
|
||||
port.security = HTTP::Port::Security::allow_ssl;
|
||||
else
|
||||
port.security = HTTP::Port::Security::require_ssl;
|
||||
port.addr = ep.at_port(0);
|
||||
if (setup_.port != 0)
|
||||
port.port = setup_.port;
|
||||
else
|
||||
port.port = ep.port();
|
||||
port.context = m_context.get ();
|
||||
|
||||
std::vector<HTTP::Port> list;
|
||||
list.push_back (port);
|
||||
m_server->ports(list);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
journal.info << "RPC interface: disabled";
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
ServerHandlerImp::onStop()
|
||||
{
|
||||
m_server->close();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
ServerHandlerImp::onAccept (HTTP::Session& session)
|
||||
{
|
||||
// Reject non-loopback connections if RPC_ALLOW_REMOTE is not set
|
||||
if (! setup_.allow_remote &&
|
||||
! beast::IP::is_loopback (session.remoteAddress()))
|
||||
{
|
||||
session.close (false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ServerHandlerImp::onRequest (HTTP::Session& session)
|
||||
{
|
||||
// Check user/password authorization
|
||||
auto const headers = build_map (session.request().headers);
|
||||
if (! HTTPAuthorized (headers))
|
||||
{
|
||||
session.write (HTTPReply (403, "Forbidden"));
|
||||
session.close (true);
|
||||
return;
|
||||
}
|
||||
|
||||
m_jobQueue.addJob (jtCLIENT, "RPC-Client", std::bind (
|
||||
&ServerHandlerImp::processSession, this, std::placeholders::_1,
|
||||
session.detach()));
|
||||
}
|
||||
|
||||
void
|
||||
ServerHandlerImp::onClose (HTTP::Session& session,
|
||||
boost::system::error_code const&)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ServerHandlerImp::onStopped (HTTP::Server&)
|
||||
{
|
||||
stopped();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Dispatched on the job queue
|
||||
void
|
||||
ServerHandlerImp::processSession (Job& job,
|
||||
std::shared_ptr<HTTP::Session> const& session)
|
||||
{
|
||||
session->write (processRequest (to_string(session->body()),
|
||||
session->remoteAddress().at_port(0)));
|
||||
|
||||
if (session->request().keep_alive())
|
||||
{
|
||||
session->complete();
|
||||
}
|
||||
else
|
||||
{
|
||||
session->close (true);
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
ServerHandlerImp::createResponse (
|
||||
int statusCode,
|
||||
std::string const& description)
|
||||
{
|
||||
return HTTPReply (statusCode, description);
|
||||
}
|
||||
|
||||
// VFALCO ARGH! returning a single std::string for the entire response?
|
||||
std::string
|
||||
ServerHandlerImp::processRequest (std::string const& request,
|
||||
beast::IP::Endpoint const& remoteIPAddress)
|
||||
{
|
||||
Json::Value jvRequest;
|
||||
{
|
||||
Json::Reader reader;
|
||||
if ((request.size () > 1000000) ||
|
||||
! reader.parse (request, jvRequest) ||
|
||||
jvRequest.isNull () ||
|
||||
! jvRequest.isObject ())
|
||||
{
|
||||
return createResponse (400, "Unable to parse request");
|
||||
}
|
||||
}
|
||||
|
||||
auto const role = getConfig ().getAdminRole (jvRequest, remoteIPAddress);
|
||||
|
||||
Resource::Consumer usage;
|
||||
|
||||
if (role == Config::ADMIN)
|
||||
usage = m_resourceManager.newAdminEndpoint (remoteIPAddress.to_string());
|
||||
else
|
||||
usage = m_resourceManager.newInboundEndpoint(remoteIPAddress);
|
||||
|
||||
if (usage.disconnect ())
|
||||
return createResponse (503, "Server is overloaded");
|
||||
|
||||
// Parse id now so errors from here on will have the id
|
||||
//
|
||||
// VFALCO NOTE Except that "id" isn't included in the following errors.
|
||||
//
|
||||
Json::Value const id = jvRequest ["id"];
|
||||
|
||||
Json::Value const method = jvRequest ["method"];
|
||||
|
||||
if (method.isNull ())
|
||||
return createResponse (400, "Null method");
|
||||
|
||||
if (! method.isString ())
|
||||
return createResponse (400, "method is not string");
|
||||
|
||||
std::string strMethod = method.asString ();
|
||||
if (strMethod.empty())
|
||||
return createResponse (400, "method is empty");
|
||||
|
||||
// Parse params
|
||||
Json::Value params = jvRequest ["params"];
|
||||
|
||||
if (params.isNull ())
|
||||
params = Json::Value (Json::arrayValue);
|
||||
|
||||
else if (!params.isArray ())
|
||||
return HTTPReply (400, "params unparseable");
|
||||
|
||||
// VFALCO TODO Shouldn't we handle this earlier?
|
||||
//
|
||||
if (role == Config::FORBID)
|
||||
{
|
||||
// VFALCO TODO Needs implementing
|
||||
// FIXME Needs implementing
|
||||
// XXX This needs rate limiting to prevent brute forcing password.
|
||||
return HTTPReply (403, "Forbidden");
|
||||
}
|
||||
|
||||
|
||||
std::string response;
|
||||
RPCHandler rpcHandler (m_networkOPs);
|
||||
Resource::Charge loadType = Resource::feeReferenceRPC;
|
||||
|
||||
m_journal.debug << "Query: " << strMethod << params;
|
||||
|
||||
Json::Value const result (rpcHandler.doRpcCommand (
|
||||
strMethod, params, role, loadType));
|
||||
m_journal.debug << "Reply: " << result;
|
||||
|
||||
usage.charge (loadType);
|
||||
|
||||
response = JSONRPCReply (result, Json::Value (), id);
|
||||
|
||||
return createResponse (200, response);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
ServerHandlerImp::onWrite (beast::PropertyStream::Map& map)
|
||||
{
|
||||
m_server->onWrite (map);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
std::unique_ptr <ServerHandler>
|
||||
make_RPCHTTPServer (beast::Stoppable& parent, JobQueue& jobQueue,
|
||||
NetworkOPs& networkOPs, Resource::Manager& resourceManager,
|
||||
RPC::Setup const& setup)
|
||||
{
|
||||
return std::make_unique <ServerHandlerImp> (
|
||||
parent, jobQueue, networkOPs, resourceManager, setup);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,6 +21,7 @@
|
||||
#define RIPPLE_SHAMAPTREENODE_H
|
||||
|
||||
#include <ripple/app/shamap/SHAMapNodeID.h>
|
||||
#include <ripple/app/shamap/TreeNodeCache.h>
|
||||
#include <ripple/basics/CountedObject.h>
|
||||
#include <ripple/common/TaggedCache.h>
|
||||
|
||||
@@ -203,8 +204,6 @@ private:
|
||||
static std::mutex childLock;
|
||||
};
|
||||
|
||||
using TreeNodeCache = TaggedCache <uint256, SHAMapTreeNode>;
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
|
||||
@@ -17,17 +17,17 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_APP_SHAMAP_TREENODECACHE_H_INCLUDED
|
||||
#define RIPPLE_APP_SHAMAP_TREENODECACHE_H_INCLUDED
|
||||
|
||||
#include <ripple/common/TaggedCache.h>
|
||||
|
||||
namespace ripple {
|
||||
namespace HTTP {
|
||||
|
||||
Port::Port (std::uint16_t port_, beast::IP::Endpoint const& addr_,
|
||||
Security security_, SSLContext* context_)
|
||||
: security (security_)
|
||||
, port (port_)
|
||||
, addr (addr_)
|
||||
, context (context_)
|
||||
{
|
||||
}
|
||||
class SHAMapTreeNode;
|
||||
|
||||
}
|
||||
}
|
||||
using TreeNodeCache = TaggedCache <uint256, SHAMapTreeNode>;
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
@@ -19,13 +19,16 @@
|
||||
|
||||
#include <ripple/common/jsonrpc_fields.h>
|
||||
#include <ripple/rpc/RPCHandler.h>
|
||||
#include <ripple/server/Role.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
WSConnection::WSConnection (Resource::Manager& resourceManager,
|
||||
Resource::Consumer usage, InfoSub::Source& source, bool isPublic,
|
||||
WSConnection::WSConnection (HTTP::Port const& port,
|
||||
Resource::Manager& resourceManager, Resource::Consumer usage,
|
||||
InfoSub::Source& source, bool isPublic,
|
||||
beast::IP::Endpoint const& remoteAddress, boost::asio::io_service& io_service)
|
||||
: InfoSub (source, usage)
|
||||
, port_(port)
|
||||
, m_resourceManager (resourceManager)
|
||||
, m_isPublic (isPublic)
|
||||
, m_remoteAddress (remoteAddress)
|
||||
@@ -154,12 +157,10 @@ Json::Value WSConnection::invokeCommand (Json::Value& jvRequest)
|
||||
RPCHandler mRPCHandler (m_netOPs, std::dynamic_pointer_cast<InfoSub> (this->shared_from_this ()));
|
||||
Json::Value jvResult (Json::objectValue);
|
||||
|
||||
Config::Role const role = m_isPublic
|
||||
? Config::GUEST // Don't check on the public interface.
|
||||
: getConfig ().getAdminRole (
|
||||
jvRequest, m_remoteAddress);
|
||||
Role const role = port_.allow_admin ? adminRole (port_, jvRequest,
|
||||
m_remoteAddress, getConfig().RPC_ADMIN_ALLOW) : Role::GUEST;
|
||||
|
||||
if (Config::FORBID == role)
|
||||
if (Role::FORBID == role)
|
||||
{
|
||||
jvResult[jss::result] = rpcError (rpcFORBIDDEN);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,10 @@
|
||||
#ifndef RIPPLE_WSCONNECTION_H
|
||||
#define RIPPLE_WSCONNECTION_H
|
||||
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/server/Port.h>
|
||||
#include <beast/asio/placeholders.h>
|
||||
#include <memory>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -38,8 +41,9 @@ public:
|
||||
protected:
|
||||
typedef websocketpp::message::data::ptr message_ptr;
|
||||
|
||||
WSConnection (Resource::Manager& resourceManager,
|
||||
Resource::Consumer usage, InfoSub::Source& source, bool isPublic,
|
||||
WSConnection (HTTP::Port const& port,
|
||||
Resource::Manager& resourceManager, Resource::Consumer usage,
|
||||
InfoSub::Source& source, bool isPublic,
|
||||
beast::IP::Endpoint const& remoteAddress, boost::asio::io_service& io_service);
|
||||
|
||||
WSConnection(WSConnection const&) = delete;
|
||||
@@ -59,6 +63,7 @@ public:
|
||||
Json::Value invokeCommand (Json::Value& jvRequest);
|
||||
|
||||
protected:
|
||||
HTTP::Port const& port_;
|
||||
Resource::Manager& m_resourceManager;
|
||||
Resource::Consumer m_usage;
|
||||
bool const m_isPublic;
|
||||
@@ -90,11 +95,15 @@ public:
|
||||
typedef typename boost::weak_ptr<connection> weak_connection_ptr;
|
||||
typedef WSServerHandler <endpoint_type> server_type;
|
||||
|
||||
private:
|
||||
server_type& m_serverHandler;
|
||||
weak_connection_ptr m_connection;
|
||||
|
||||
public:
|
||||
WSConnectionType (Resource::Manager& resourceManager,
|
||||
InfoSub::Source& source, server_type& serverHandler,
|
||||
connection_ptr const& cpConnection)
|
||||
WSConnectionType (Resource::Manager& resourceManager, InfoSub::Source& source,
|
||||
server_type& serverHandler, connection_ptr const& cpConnection)
|
||||
: WSConnection (
|
||||
serverHandler.port(),
|
||||
resourceManager,
|
||||
resourceManager.newInboundEndpoint (cpConnection->get_socket ().remote_endpoint ()),
|
||||
source,
|
||||
@@ -197,10 +206,6 @@ public:
|
||||
m_connection, &m_serverHandler, beast::asio::placeholders::error)));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
server_type& m_serverHandler;
|
||||
weak_connection_ptr m_connection;
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
@@ -43,18 +43,24 @@ class WSDoorImp
|
||||
, protected beast::Thread
|
||||
, beast::LeakChecked <WSDoorImp>
|
||||
{
|
||||
private:
|
||||
typedef RippleRecursiveMutex LockType;
|
||||
typedef std::lock_guard <LockType> ScopedLockType;
|
||||
|
||||
std::shared_ptr<HTTP::Port> port_;
|
||||
Resource::Manager& m_resourceManager;
|
||||
InfoSub::Source& m_source;
|
||||
LockType m_endpointLock;
|
||||
std::shared_ptr<websocketpp::server_autotls> m_endpoint;
|
||||
|
||||
public:
|
||||
WSDoorImp (Resource::Manager& resourceManager,
|
||||
InfoSub::Source& source, std::string const& strIp, int iPort,
|
||||
bool bPublic, boost::asio::ssl::context& ssl_context)
|
||||
WSDoorImp (HTTP::Port const& port, Resource::Manager& resourceManager,
|
||||
InfoSub::Source& source)
|
||||
: WSDoor (source)
|
||||
, Thread ("websocket")
|
||||
, port_(std::make_shared<HTTP::Port>(port))
|
||||
, m_resourceManager (resourceManager)
|
||||
, m_source (source)
|
||||
, m_ssl_context (ssl_context)
|
||||
, mPublic (bPublic)
|
||||
, mIp (strIp)
|
||||
, mPort (iPort)
|
||||
{
|
||||
startThread ();
|
||||
}
|
||||
@@ -67,13 +73,14 @@ public:
|
||||
private:
|
||||
void run ()
|
||||
{
|
||||
WriteLog (lsINFO, WSDoor) << boost::str (
|
||||
boost::format ("Websocket: %s: Listening: %s %d ") %
|
||||
(mPublic ? "Public" : "Private") % mIp % mPort);
|
||||
WriteLog (lsINFO, WSDoor) <<
|
||||
"Websocket: '" << port_->name << "' listening on " <<
|
||||
port_->ip.to_string() << ":" << std::to_string(port_->port) <<
|
||||
(port_->allow_admin ? "(Admin)" : "");
|
||||
|
||||
websocketpp::server_autotls::handler::ptr handler (
|
||||
new WSServerHandler <websocketpp::server_autotls> (
|
||||
m_resourceManager, m_source, m_ssl_context, mPublic));
|
||||
port_, m_resourceManager, m_source));
|
||||
|
||||
{
|
||||
ScopedLockType lock (m_endpointLock);
|
||||
@@ -84,9 +91,7 @@ private:
|
||||
// Call the main-event-loop of the websocket server.
|
||||
try
|
||||
{
|
||||
m_endpoint->listen (
|
||||
boost::asio::ip::tcp::endpoint (
|
||||
boost::asio::ip::address ().from_string (mIp), mPort));
|
||||
m_endpoint->listen (port_->ip, port_->port);
|
||||
}
|
||||
catch (websocketpp::exception& e)
|
||||
{
|
||||
@@ -135,20 +140,6 @@ private:
|
||||
|
||||
signalThreadShouldExit ();
|
||||
}
|
||||
|
||||
private:
|
||||
typedef RippleRecursiveMutex LockType;
|
||||
typedef std::lock_guard <LockType> ScopedLockType;
|
||||
|
||||
Resource::Manager& m_resourceManager;
|
||||
InfoSub::Source& m_source;
|
||||
boost::asio::ssl::context& m_ssl_context;
|
||||
LockType m_endpointLock;
|
||||
|
||||
std::shared_ptr<websocketpp::server_autotls> m_endpoint;
|
||||
bool mPublic;
|
||||
std::string mIp;
|
||||
int mPort;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -160,22 +151,22 @@ WSDoor::WSDoor (Stoppable& parent)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
WSDoor* WSDoor::New (Resource::Manager& resourceManager, InfoSub::Source& source,
|
||||
std::string const& strIp, int iPort, bool bPublic,
|
||||
boost::asio::ssl::context& ssl_context)
|
||||
std::unique_ptr<WSDoor>
|
||||
make_WSDoor (HTTP::Port const& port, Resource::Manager& resourceManager,
|
||||
InfoSub::Source& source)
|
||||
{
|
||||
std::unique_ptr<WSDoor> door;
|
||||
|
||||
try
|
||||
{
|
||||
door = std::make_unique <WSDoorImp> (resourceManager,
|
||||
source, strIp, iPort, bPublic, ssl_context);
|
||||
door = std::make_unique <WSDoorImp> (port, resourceManager, source);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
|
||||
return door.release ();
|
||||
return door;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // ripple
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#ifndef RIPPLE_WSDOOR_H_INCLUDED
|
||||
#define RIPPLE_WSDOOR_H_INCLUDED
|
||||
|
||||
#include <ripple/server/Port.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/** Handles accepting incoming WebSocket connections. */
|
||||
@@ -31,11 +33,14 @@ protected:
|
||||
public:
|
||||
virtual ~WSDoor() = default;
|
||||
|
||||
static WSDoor* New (Resource::Manager& resourceManager,
|
||||
InfoSub::Source& source, std::string const& strIp, int iPort,
|
||||
bool bPublic, boost::asio::ssl::context& ssl_context);
|
||||
// VFALCO TODO Add this member function to prevent races on shutdown
|
||||
//virtual void close() = 0;
|
||||
};
|
||||
|
||||
} // ripple
|
||||
std::unique_ptr<WSDoor>
|
||||
make_WSDoor (HTTP::Port const& port, Resource::Manager& resourceManager,
|
||||
InfoSub::Source& source);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,7 +21,9 @@
|
||||
#define RIPPLE_WSSERVERHANDLER_H_INCLUDED
|
||||
|
||||
#include <ripple/common/jsonrpc_fields.h>
|
||||
#include <ripple/server/Port.h>
|
||||
#include <ripple/app/websocket/WSConnection.h>
|
||||
#include <memory>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -60,6 +62,7 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
std::shared_ptr<HTTP::Port> port_;
|
||||
Resource::Manager& m_resourceManager;
|
||||
InfoSub::Source& m_source;
|
||||
|
||||
@@ -69,31 +72,31 @@ protected:
|
||||
typedef std::lock_guard <LockType> ScopedLockType;
|
||||
LockType mLock;
|
||||
|
||||
private:
|
||||
boost::asio::ssl::context& m_ssl_context;
|
||||
|
||||
protected:
|
||||
// For each connection maintain an associated object to track subscriptions.
|
||||
typedef hash_map <connection_ptr, wsc_ptr> MapType;
|
||||
MapType mMap;
|
||||
bool const mPublic;
|
||||
|
||||
public:
|
||||
WSServerHandler (Resource::Manager& resourceManager,
|
||||
InfoSub::Source& source, boost::asio::ssl::context& ssl_context, bool bPublic)
|
||||
: m_resourceManager (resourceManager)
|
||||
WSServerHandler (std::shared_ptr<HTTP::Port> const& port,
|
||||
Resource::Manager& resourceManager, InfoSub::Source& source)
|
||||
: port_(port)
|
||||
, m_resourceManager (resourceManager)
|
||||
, m_source (source)
|
||||
, m_ssl_context (ssl_context)
|
||||
, mPublic (bPublic)
|
||||
{
|
||||
}
|
||||
|
||||
WSServerHandler(WSServerHandler const&) = delete;
|
||||
WSServerHandler& operator= (WSServerHandler const&) = delete;
|
||||
|
||||
HTTP::Port const&
|
||||
port() const
|
||||
{
|
||||
return *port_;
|
||||
}
|
||||
|
||||
bool getPublic()
|
||||
{
|
||||
return mPublic;
|
||||
return port_->allow_admin;
|
||||
};
|
||||
|
||||
static void ssend (connection_ptr cpClient, message_ptr mpMessage)
|
||||
@@ -403,9 +406,22 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
boost::asio::ssl::context& get_ssl_context ()
|
||||
boost::asio::ssl::context&
|
||||
get_ssl_context ()
|
||||
{
|
||||
return m_ssl_context;
|
||||
return *port_->context;
|
||||
}
|
||||
|
||||
bool
|
||||
plain_only()
|
||||
{
|
||||
return port_->protocol.count("wss") == 0;
|
||||
}
|
||||
|
||||
bool
|
||||
secure_only()
|
||||
{
|
||||
return port_->protocol.count("ws") == 0;
|
||||
}
|
||||
|
||||
// Respond to http requests.
|
||||
|
||||
@@ -1,133 +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_COMMON_SSLCONTEXT_H_INCLUDED
|
||||
#define RIPPLE_COMMON_SSLCONTEXT_H_INCLUDED
|
||||
|
||||
#include <boost/asio/ssl/context.hpp>
|
||||
#include <beast/utility/noexcept.h>
|
||||
#include <string>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/** Simple base class for passing a context around.
|
||||
This lets derived classes hide their implementation from the headers.
|
||||
*/
|
||||
class SSLContext
|
||||
{
|
||||
public:
|
||||
virtual ~SSLContext ();
|
||||
|
||||
// Saves typing
|
||||
typedef boost::asio::ssl::context ContextType;
|
||||
|
||||
inline ContextType& get () noexcept
|
||||
{
|
||||
return m_context;
|
||||
}
|
||||
|
||||
inline ContextType const& get () const noexcept
|
||||
{
|
||||
return m_context;
|
||||
}
|
||||
|
||||
// implicit conversion
|
||||
inline operator ContextType& () noexcept
|
||||
{
|
||||
return get ();
|
||||
}
|
||||
|
||||
inline operator ContextType const& () const noexcept
|
||||
{
|
||||
return get ();
|
||||
}
|
||||
|
||||
protected:
|
||||
explicit SSLContext (ContextType& context);
|
||||
|
||||
SSLContext(SSLContext const&) = delete;
|
||||
SSLContext& operator= (SSLContext const&) = delete;
|
||||
|
||||
ContextType& m_context;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** The SSL contexts used by Ripple.
|
||||
|
||||
This is what Ripple uses for its secure connections. The ECDSA curve
|
||||
parameters are predefined and verified to be secure. The context is set to
|
||||
sslv23, Transport Layer Security / General. This is primarily used for
|
||||
peer to peer servers that don't care about certificates or
|
||||
identity verification.
|
||||
*/
|
||||
// VFALCO NOTE The comment above is out of date
|
||||
class RippleSSLContext : public SSLContext
|
||||
{
|
||||
public:
|
||||
/** Retrieve raw DH parameters.
|
||||
This is in the format expected by the OpenSSL function d2i_DHparams.
|
||||
The vector is binary. An empty vector means the key size is unsupported.
|
||||
@note The string may contain nulls in the middle. Use size() to
|
||||
determine the actual size.
|
||||
*/
|
||||
static std::string getRawDHParams (int keySize);
|
||||
|
||||
/** Creates a bare SSL context with just sslv23 set.
|
||||
This is used for RPC connections.
|
||||
*/
|
||||
static RippleSSLContext* createBare ();
|
||||
|
||||
/** Creates a suitable for WebSocket without authentication.
|
||||
This is for WebSocket connections that don't use certificates.
|
||||
*/
|
||||
static RippleSSLContext* createWebSocket ();
|
||||
|
||||
/** Create a context that allows anonymous connections.
|
||||
No certificates are required. Peers use this context.
|
||||
If the cipher list is invalid, a fatal error is raised.
|
||||
*/
|
||||
static RippleSSLContext* createAnonymous (std::string const& cipherList);
|
||||
|
||||
/** Create a context with authentication requirements.
|
||||
This is used for WebSocket connections.
|
||||
The authentication credentials are loaded from the files with
|
||||
the specified names. If an error occurs, a fatal error is raised.
|
||||
*/
|
||||
static RippleSSLContext* createAuthenticated (
|
||||
std::string key_file, std::string cert_file, std::string chain_file);
|
||||
|
||||
protected:
|
||||
explicit RippleSSLContext (ContextType& context);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Create a self-signed SSL context that allows anonymous Diffie Hellman. */
|
||||
std::shared_ptr<boost::asio::ssl::context>
|
||||
make_ssl_context();
|
||||
|
||||
/** Create an authenticated SSL context using the specified files. */
|
||||
std::shared_ptr<boost::asio::ssl::context>
|
||||
make_authenticated_ssl_context (std::string const& key_file,
|
||||
std::string const& cert_file, std::string const& chain_file);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/common/RippleSSLContext.h>
|
||||
#include <ripple/common/make_SSLContext.h>
|
||||
#include <ripple/common/seconds_clock.h>
|
||||
#include <beast/container/aged_unordered_set.h>
|
||||
#include <beast/module/core/diagnostic/FatalError.h>
|
||||
@@ -27,8 +27,8 @@
|
||||
#include <stdexcept>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
namespace openssl {
|
||||
namespace detail {
|
||||
|
||||
template <class>
|
||||
struct custom_delete;
|
||||
@@ -60,6 +60,15 @@ struct custom_delete <X509>
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct custom_delete <DH>
|
||||
{
|
||||
void operator() (DH* dh) const
|
||||
{
|
||||
DH_free(dh);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
using custom_delete_unique_ptr = std::unique_ptr <T, custom_delete <T>>;
|
||||
|
||||
@@ -158,79 +167,59 @@ static void ssl_ctx_use_privatekey (SSL_CTX* const ctx, evp_pkey_ptr& key)
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace openssl
|
||||
|
||||
class RippleSSLContextImp : public RippleSSLContext
|
||||
{
|
||||
private:
|
||||
boost::asio::ssl::context m_context;
|
||||
|
||||
// track when SSL connections have last negotiated
|
||||
|
||||
struct StaticData
|
||||
{
|
||||
StaticData() : set (ripple::get_seconds_clock ())
|
||||
{
|
||||
}
|
||||
|
||||
std::mutex lock;
|
||||
beast::aged_unordered_set <SSL const*> set;
|
||||
|
||||
StaticData()
|
||||
: set (ripple::get_seconds_clock ())
|
||||
{ }
|
||||
};
|
||||
|
||||
public:
|
||||
RippleSSLContextImp ()
|
||||
: RippleSSLContext (m_context)
|
||||
, m_context (boost::asio::ssl::context::sslv23)
|
||||
using dh_ptr = custom_delete_unique_ptr<DH>;
|
||||
|
||||
static
|
||||
dh_ptr
|
||||
make_DH(std::string const& params)
|
||||
{
|
||||
auto const* p (
|
||||
reinterpret_cast <std::uint8_t const*>(¶ms [0]));
|
||||
DH* const dh = d2i_DHparams (nullptr, &p, params.size ());
|
||||
if (p == nullptr)
|
||||
beast::FatalError ("d2i_DHparams returned nullptr.",
|
||||
__FILE__, __LINE__);
|
||||
return dh_ptr(dh);
|
||||
}
|
||||
|
||||
~RippleSSLContextImp ()
|
||||
static
|
||||
DH*
|
||||
getDH (int keyLength)
|
||||
{
|
||||
if (keyLength == 512 || keyLength == 1024)
|
||||
{
|
||||
static dh_ptr dh512 = make_DH(getRawDHParams (keyLength));
|
||||
return dh512.get ();
|
||||
}
|
||||
else
|
||||
{
|
||||
beast::FatalError ("unsupported key length", __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
static DH* tmp_dh_handler (SSL*, int, int key_length)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static
|
||||
DH*
|
||||
tmp_dh_handler (SSL*, int, int key_length)
|
||||
{
|
||||
return DHparams_dup (getDH (key_length));
|
||||
}
|
||||
|
||||
static bool disallowRenegotiation (SSL const* ssl, bool isNew);
|
||||
|
||||
static void info_handler (SSL const* ssl, int event, int);
|
||||
|
||||
// Pretty prints an error message
|
||||
static std::string error_message (std::string const& what,
|
||||
boost::system::error_code const& ec);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
static std::string getRawDHParams (int keySize);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Does common initialization for all but the bare context type.
|
||||
static void initCommon (boost::asio::ssl::context& context);
|
||||
void initCommon ();
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
static void initAnonymous (boost::asio::ssl::context& context,
|
||||
std::string const& cipherList);
|
||||
void initAnonymous (std::string const& cipherList);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
static void initAuthenticated (boost::asio::ssl::context& context,
|
||||
std::string key_file, std::string cert_file, std::string chain_file);
|
||||
|
||||
void initAuthenticated (
|
||||
std::string key_file, std::string cert_file, std::string chain_file);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
static DH* getDH (int keyLength);
|
||||
};
|
||||
|
||||
bool RippleSSLContextImp::disallowRenegotiation (SSL const* ssl, bool isNew)
|
||||
static
|
||||
bool
|
||||
disallowRenegotiation (SSL const* ssl, bool isNew)
|
||||
{
|
||||
// Do not allow a connection to renegotiate
|
||||
// more than once every 4 minutes
|
||||
@@ -268,7 +257,9 @@ bool RippleSSLContextImp::disallowRenegotiation (SSL const* ssl, bool isNew)
|
||||
return false;
|
||||
}
|
||||
|
||||
void RippleSSLContextImp::info_handler (SSL const* ssl, int event, int)
|
||||
static
|
||||
void
|
||||
info_handler (SSL const* ssl, int event, int)
|
||||
{
|
||||
if ((ssl->s3) && (event & SSL_CB_HANDSHAKE_START))
|
||||
{
|
||||
@@ -277,7 +268,9 @@ void RippleSSLContextImp::info_handler (SSL const* ssl, int event, int)
|
||||
}
|
||||
}
|
||||
|
||||
std::string RippleSSLContextImp::error_message (std::string const& what,
|
||||
static
|
||||
std::string
|
||||
error_message (std::string const& what,
|
||||
boost::system::error_code const& ec)
|
||||
{
|
||||
std::stringstream ss;
|
||||
@@ -288,40 +281,9 @@ std::string RippleSSLContextImp::error_message (std::string const& what,
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string RippleSSLContextImp::getRawDHParams (int keySize)
|
||||
{
|
||||
std::string params;
|
||||
|
||||
// Original code provided the 512-bit keySize parameters
|
||||
// when 1024 bits were requested so we will do the same.
|
||||
if (keySize == 1024)
|
||||
keySize = 512;
|
||||
|
||||
switch (keySize)
|
||||
{
|
||||
case 512:
|
||||
{
|
||||
// These are the DH parameters that OpenCoin has chosen for Ripple
|
||||
//
|
||||
std::uint8_t const raw [] = {
|
||||
0x30, 0x46, 0x02, 0x41, 0x00, 0x98, 0x15, 0xd2, 0xd0, 0x08, 0x32, 0xda,
|
||||
0xaa, 0xac, 0xc4, 0x71, 0xa3, 0x1b, 0x11, 0xf0, 0x6c, 0x62, 0xb2, 0x35,
|
||||
0x8a, 0x10, 0x92, 0xc6, 0x0a, 0xa3, 0x84, 0x7e, 0xaf, 0x17, 0x29, 0x0b,
|
||||
0x70, 0xef, 0x07, 0x4f, 0xfc, 0x9d, 0x6d, 0x87, 0x99, 0x19, 0x09, 0x5b,
|
||||
0x6e, 0xdb, 0x57, 0x72, 0x4a, 0x7e, 0xcd, 0xaf, 0xbd, 0x3a, 0x97, 0x55,
|
||||
0x51, 0x77, 0x5a, 0x34, 0x7c, 0xe8, 0xc5, 0x71, 0x63, 0x02, 0x01, 0x02
|
||||
};
|
||||
|
||||
params.resize (sizeof (raw));
|
||||
std::copy (raw, raw + sizeof (raw), params.begin ());
|
||||
}
|
||||
break;
|
||||
};
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
void RippleSSLContextImp::initCommon (boost::asio::ssl::context& context)
|
||||
static
|
||||
void
|
||||
initCommon (boost::asio::ssl::context& context)
|
||||
{
|
||||
context.set_options (
|
||||
boost::asio::ssl::context::default_workarounds |
|
||||
@@ -338,12 +300,9 @@ void RippleSSLContextImp::initCommon (boost::asio::ssl::context& context)
|
||||
info_handler);
|
||||
}
|
||||
|
||||
void RippleSSLContextImp::initCommon ()
|
||||
{
|
||||
initCommon(m_context);
|
||||
}
|
||||
|
||||
void RippleSSLContextImp::initAnonymous (
|
||||
static
|
||||
void
|
||||
initAnonymous (
|
||||
boost::asio::ssl::context& context, std::string const& cipherList)
|
||||
{
|
||||
initCommon(context);
|
||||
@@ -367,12 +326,9 @@ void RippleSSLContextImp::initAnonymous (
|
||||
ssl_ctx_use_privatekey (ctx, pkey);
|
||||
}
|
||||
|
||||
void RippleSSLContextImp::initAnonymous (std::string const& cipherList)
|
||||
{
|
||||
initAnonymous(m_context, cipherList);
|
||||
}
|
||||
|
||||
void RippleSSLContextImp::initAuthenticated (boost::asio::ssl::context& context,
|
||||
static
|
||||
void
|
||||
initAuthenticated (boost::asio::ssl::context& context,
|
||||
std::string key_file, std::string cert_file, std::string chain_file)
|
||||
{
|
||||
initCommon (context);
|
||||
@@ -468,138 +424,53 @@ void RippleSSLContextImp::initAuthenticated (boost::asio::ssl::context& context,
|
||||
}
|
||||
}
|
||||
|
||||
void RippleSSLContextImp::initAuthenticated (
|
||||
std::string key_file, std::string cert_file, std::string chain_file)
|
||||
{
|
||||
initAuthenticated (m_context, key_file, cert_file, chain_file);
|
||||
}
|
||||
} // detail
|
||||
} // openssl
|
||||
|
||||
// A simple RAII container for a DH
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
std::string
|
||||
getRawDHParams (int keySize)
|
||||
{
|
||||
std::string params;
|
||||
|
||||
// Original code provided the 512-bit keySize parameters
|
||||
// when 1024 bits were requested so we will do the same.
|
||||
if (keySize == 1024)
|
||||
keySize = 512;
|
||||
|
||||
switch (keySize)
|
||||
{
|
||||
case 512:
|
||||
{
|
||||
// These are the DH parameters that OpenCoin has chosen for Ripple
|
||||
//
|
||||
class ScopedDHPointer
|
||||
{
|
||||
private:
|
||||
ScopedDHPointer (ScopedDHPointer const&) = delete;
|
||||
ScopedDHPointer& operator= (ScopedDHPointer const&) = delete;
|
||||
|
||||
public:
|
||||
// Construct from an existing DH
|
||||
//
|
||||
explicit ScopedDHPointer (DH* dh)
|
||||
: m_dh (dh)
|
||||
{
|
||||
}
|
||||
|
||||
// Construct from raw DH params
|
||||
//
|
||||
explicit ScopedDHPointer (std::string const& params)
|
||||
{
|
||||
auto const* p (
|
||||
reinterpret_cast <std::uint8_t const*>(¶ms [0]));
|
||||
m_dh = d2i_DHparams (nullptr, &p, params.size ());
|
||||
if (m_dh == nullptr)
|
||||
beast::FatalError ("d2i_DHparams returned nullptr.",
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
~ScopedDHPointer ()
|
||||
{
|
||||
if (m_dh != nullptr)
|
||||
DH_free (m_dh);
|
||||
}
|
||||
|
||||
operator DH* () const
|
||||
{
|
||||
return get ();
|
||||
}
|
||||
|
||||
DH* get () const
|
||||
{
|
||||
return m_dh;
|
||||
}
|
||||
|
||||
private:
|
||||
DH* m_dh;
|
||||
std::uint8_t const raw [] = {
|
||||
0x30, 0x46, 0x02, 0x41, 0x00, 0x98, 0x15, 0xd2, 0xd0, 0x08, 0x32, 0xda,
|
||||
0xaa, 0xac, 0xc4, 0x71, 0xa3, 0x1b, 0x11, 0xf0, 0x6c, 0x62, 0xb2, 0x35,
|
||||
0x8a, 0x10, 0x92, 0xc6, 0x0a, 0xa3, 0x84, 0x7e, 0xaf, 0x17, 0x29, 0x0b,
|
||||
0x70, 0xef, 0x07, 0x4f, 0xfc, 0x9d, 0x6d, 0x87, 0x99, 0x19, 0x09, 0x5b,
|
||||
0x6e, 0xdb, 0x57, 0x72, 0x4a, 0x7e, 0xcd, 0xaf, 0xbd, 0x3a, 0x97, 0x55,
|
||||
0x51, 0x77, 0x5a, 0x34, 0x7c, 0xe8, 0xc5, 0x71, 0x63, 0x02, 0x01, 0x02
|
||||
};
|
||||
|
||||
DH* RippleSSLContextImp::getDH (int keyLength)
|
||||
{
|
||||
if (keyLength == 512 || keyLength == 1024)
|
||||
{
|
||||
static ScopedDHPointer dh512 (getRawDHParams (keyLength));
|
||||
|
||||
return dh512.get ();
|
||||
params.resize (sizeof (raw));
|
||||
std::copy (raw, raw + sizeof (raw), params.begin ());
|
||||
}
|
||||
else
|
||||
{
|
||||
beast::FatalError ("unsupported key length", __FILE__, __LINE__);
|
||||
break;
|
||||
};
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
RippleSSLContext::RippleSSLContext (ContextType& context)
|
||||
: SSLContext (context)
|
||||
{
|
||||
}
|
||||
|
||||
RippleSSLContext* RippleSSLContext::createBare ()
|
||||
{
|
||||
std::unique_ptr <RippleSSLContextImp> context (new RippleSSLContextImp ());
|
||||
return context.release ();
|
||||
}
|
||||
|
||||
RippleSSLContext* RippleSSLContext::createWebSocket ()
|
||||
{
|
||||
std::unique_ptr <RippleSSLContextImp> context (new RippleSSLContextImp ());
|
||||
context->initCommon ();
|
||||
return context.release ();
|
||||
}
|
||||
|
||||
RippleSSLContext* RippleSSLContext::createAnonymous (std::string const& cipherList)
|
||||
{
|
||||
std::unique_ptr <RippleSSLContextImp> context (new RippleSSLContextImp ());
|
||||
context->initAnonymous (cipherList);
|
||||
return context.release ();
|
||||
}
|
||||
|
||||
RippleSSLContext* RippleSSLContext::createAuthenticated (
|
||||
std::string key_file, std::string cert_file, std::string chain_file)
|
||||
{
|
||||
std::unique_ptr <RippleSSLContextImp> context (new RippleSSLContextImp ());
|
||||
context->initAuthenticated (key_file, cert_file, chain_file);
|
||||
return context.release ();
|
||||
}
|
||||
|
||||
std::string RippleSSLContext::getRawDHParams (int keySize)
|
||||
{
|
||||
return RippleSSLContextImp::getRawDHParams (keySize);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
SSLContext::SSLContext (ContextType& context)
|
||||
: m_context (context)
|
||||
{
|
||||
}
|
||||
|
||||
SSLContext::~SSLContext ()
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Create a self-signed SSL context that allows anonymous Diffie Hellman. */
|
||||
std::shared_ptr<boost::asio::ssl::context>
|
||||
make_ssl_context()
|
||||
make_SSLContext()
|
||||
{
|
||||
std::shared_ptr<boost::asio::ssl::context> context =
|
||||
std::make_shared<boost::asio::ssl::context> (
|
||||
boost::asio::ssl::context::sslv23);
|
||||
// By default, allow anonymous DH.
|
||||
RippleSSLContextImp::initAnonymous (
|
||||
openssl::detail::initAnonymous (
|
||||
*context, "ALL:!LOW:!EXP:!MD5:@STRENGTH");
|
||||
// VFALCO NOTE, It seems the WebSocket context never has
|
||||
// set_verify_mode called, for either setting of WEBSOCKET_SECURE
|
||||
@@ -607,17 +478,17 @@ make_ssl_context()
|
||||
return context;
|
||||
}
|
||||
|
||||
/** Create an authenticated SSL context using the specified files. */
|
||||
std::shared_ptr<boost::asio::ssl::context>
|
||||
make_authenticated_ssl_context (std::string const& key_file,
|
||||
make_SSLContextAuthed (std::string const& key_file,
|
||||
std::string const& cert_file, std::string const& chain_file)
|
||||
{
|
||||
std::shared_ptr<boost::asio::ssl::context> context =
|
||||
std::make_shared<boost::asio::ssl::context> (
|
||||
boost::asio::ssl::context::sslv23);
|
||||
RippleSSLContextImp::initAuthenticated(*context,
|
||||
openssl::detail::initAuthenticated(*context,
|
||||
key_file, cert_file, chain_file);
|
||||
return context;
|
||||
}
|
||||
|
||||
}
|
||||
} // ripple
|
||||
|
||||
49
src/ripple/common/make_SSLContext.h
Normal file
49
src/ripple/common/make_SSLContext.h
Normal file
@@ -0,0 +1,49 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_COMMON_MAKE_SSLCONTEXT_H_INCLUDED
|
||||
#define RIPPLE_COMMON_MAKE_SSLCONTEXT_H_INCLUDED
|
||||
|
||||
#include <boost/asio/ssl/context.hpp>
|
||||
#include <beast/utility/noexcept.h>
|
||||
#include <string>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/** Retrieve raw DH parameters.
|
||||
This is in the format expected by the OpenSSL function d2i_DHparams.
|
||||
The vector is binary. An empty vector means the key size is unsupported.
|
||||
@note The string may contain nulls in the middle. Use size() to
|
||||
determine the actual size.
|
||||
*/
|
||||
std::string
|
||||
getRawDHParams(int keySize);
|
||||
|
||||
/** Create a self-signed SSL context that allows anonymous Diffie Hellman. */
|
||||
std::shared_ptr<boost::asio::ssl::context>
|
||||
make_SSLContext();
|
||||
|
||||
/** Create an authenticated SSL context using the specified files. */
|
||||
std::shared_ptr<boost::asio::ssl::context>
|
||||
make_SSLContextAuthed (std::string const& key_file,
|
||||
std::string const& cert_file, std::string const& chain_file);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -62,8 +62,6 @@ parseKeyValueSection (IniFileSections& secSource, std::string const& strSection)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const int SYSTEM_PEER_PORT = 6561;
|
||||
|
||||
enum SizedItemName
|
||||
{
|
||||
siSweepInterval,
|
||||
@@ -151,69 +149,9 @@ public:
|
||||
// DEPRECATED
|
||||
boost::filesystem::path VALIDATORS_FILE; // As specifed in rippled.cfg.
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Settings related to RPC
|
||||
|
||||
/** Get the client or server RPC IP address.
|
||||
@note The string may not always be in a valid parsable state.
|
||||
@return A string representing the address.
|
||||
*/
|
||||
std::string getRpcIP () const { return m_rpcIP; }
|
||||
|
||||
/** Get the client or server RPC port number.
|
||||
@note The port number may be invalid (out of range or zero)
|
||||
@return The RPC port number.
|
||||
*/
|
||||
int getRpcPort () const { return m_rpcPort; }
|
||||
|
||||
/** Set the client or server RPC IP and optional port.
|
||||
@note The string is not syntax checked.
|
||||
@param newAddress A string in the format <ip-address>[':'<port-number>]
|
||||
*/
|
||||
void setRpcIpAndOptionalPort (std::string const& newAddress);
|
||||
|
||||
/** Set the client or server RPC IP.
|
||||
@note The string is not syntax-checked.
|
||||
@param newIP A string representing the IP address to use.
|
||||
*/
|
||||
void setRpcIP (std::string const& newIP) { m_rpcIP = newIP; }
|
||||
|
||||
/** Set the client or server RPC port number.
|
||||
@note The port number is not range checked.
|
||||
@param newPort The RPC port number to use.
|
||||
*/
|
||||
void setRpcPort (int newPort) { m_rpcPort = newPort; }
|
||||
|
||||
/** Convert the RPC/port combination to a readable string.
|
||||
*/
|
||||
std::string const getRpcAddress ()
|
||||
{
|
||||
return m_rpcIP + ":" + std::to_string (m_rpcPort);
|
||||
}
|
||||
|
||||
/** Determine the level of administrative permission to grant.
|
||||
*/
|
||||
// VFALCO TODO Get this out of here
|
||||
enum Role
|
||||
{
|
||||
GUEST,
|
||||
USER,
|
||||
ADMIN,
|
||||
FORBID
|
||||
};
|
||||
Role getAdminRole (Json::Value const& params, beast::IP::Endpoint const& remoteIp) const;
|
||||
|
||||
/** Listening port number for peer connections. */
|
||||
int peerListeningPort;
|
||||
|
||||
/** List of Validators entries from rippled.cfg */
|
||||
std::vector <std::string> validators;
|
||||
|
||||
private:
|
||||
std::string m_rpcIP;
|
||||
int m_rpcPort; // VFALCO TODO This should be a short.
|
||||
|
||||
private:
|
||||
/** The folder where new module databases should be located */
|
||||
beast::File m_moduleDbPath;
|
||||
@@ -318,39 +256,15 @@ public:
|
||||
int VALIDATION_QUORUM; // Minimum validations to consider ledger authoritative
|
||||
|
||||
// Peer networking parameters
|
||||
std::string PEER_IP;
|
||||
bool PEER_PRIVATE; // True to ask peers not to relay current IP.
|
||||
unsigned int PEERS_MAX;
|
||||
|
||||
// Websocket networking parameters
|
||||
std::string WEBSOCKET_PUBLIC_IP; // XXX Going away. Merge with the inbound peer connction.
|
||||
int WEBSOCKET_PUBLIC_PORT;
|
||||
int WEBSOCKET_PUBLIC_SECURE;
|
||||
|
||||
std::string WEBSOCKET_IP;
|
||||
int WEBSOCKET_PORT;
|
||||
int WEBSOCKET_SECURE;
|
||||
|
||||
int WEBSOCKET_PING_FREQ;
|
||||
|
||||
std::string WEBSOCKET_SSL_CERT;
|
||||
std::string WEBSOCKET_SSL_CHAIN;
|
||||
std::string WEBSOCKET_SSL_KEY;
|
||||
|
||||
// RPC parameters
|
||||
std::vector<beast::IP::Endpoint> RPC_ADMIN_ALLOW;
|
||||
std::string RPC_ADMIN_PASSWORD;
|
||||
std::string RPC_ADMIN_USER;
|
||||
std::string RPC_PASSWORD;
|
||||
std::string RPC_USER;
|
||||
bool RPC_ALLOW_REMOTE;
|
||||
Json::Value RPC_STARTUP;
|
||||
|
||||
int RPC_SECURE;
|
||||
std::string RPC_SSL_CERT;
|
||||
std::string RPC_SSL_CHAIN;
|
||||
std::string RPC_SSL_KEY;
|
||||
|
||||
// Path searching
|
||||
int PATH_SEARCH_OLD;
|
||||
int PATH_SEARCH;
|
||||
@@ -399,37 +313,11 @@ public:
|
||||
int getSize (SizedItemName);
|
||||
void setup (std::string const& strConf, bool bQuiet);
|
||||
void load ();
|
||||
|
||||
private:
|
||||
void build_legacy();
|
||||
};
|
||||
|
||||
// VFALCO DEPRECATED
|
||||
extern Config& getConfig();
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace RPC {
|
||||
|
||||
struct Setup
|
||||
{
|
||||
bool allow_remote = false;
|
||||
std::string admin_user;
|
||||
std::string admin_password;
|
||||
std::string ip;
|
||||
int port = 5001;
|
||||
std::string user;
|
||||
std::string password;
|
||||
int secure = 0;
|
||||
std::string ssl_cert;
|
||||
std::string ssl_chain;
|
||||
std::string ssl_key;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
RPC::Setup
|
||||
setup_RPC (Section const& s);
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,12 +22,7 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
// VFALCO NOTE
|
||||
//
|
||||
// Please use this style for all new sections
|
||||
// And if you're feeling generous, convert all the
|
||||
// existing macros to this format as well.
|
||||
//
|
||||
// VFALCO DEPRECATED in favor of the BasicConfig interface
|
||||
struct ConfigSection
|
||||
{
|
||||
static std::string nodeDatabase () { return "node_db"; }
|
||||
@@ -58,23 +53,10 @@ struct ConfigSection
|
||||
#define SECTION_PATH_SEARCH "path_search"
|
||||
#define SECTION_PATH_SEARCH_FAST "path_search_fast"
|
||||
#define SECTION_PATH_SEARCH_MAX "path_search_max"
|
||||
#define SECTION_PEER_IP "peer_ip"
|
||||
#define SECTION_PEER_PORT "peer_port"
|
||||
#define SECTION_PEER_PRIVATE "peer_private"
|
||||
#define SECTION_PEERS_MAX "peers_max"
|
||||
#define SECTION_RPC_ALLOW_REMOTE "rpc_allow_remote"
|
||||
#define SECTION_RPC_ADMIN_ALLOW "rpc_admin_allow"
|
||||
#define SECTION_RPC_ADMIN_USER "rpc_admin_user"
|
||||
#define SECTION_RPC_ADMIN_PASSWORD "rpc_admin_password"
|
||||
#define SECTION_RPC_IP "rpc_ip"
|
||||
#define SECTION_RPC_PORT "rpc_port"
|
||||
#define SECTION_RPC_USER "rpc_user"
|
||||
#define SECTION_RPC_PASSWORD "rpc_password"
|
||||
#define SECTION_RPC_STARTUP "rpc_startup"
|
||||
#define SECTION_RPC_SECURE "rpc_secure"
|
||||
#define SECTION_RPC_SSL_CERT "rpc_ssl_cert"
|
||||
#define SECTION_RPC_SSL_CHAIN "rpc_ssl_chain"
|
||||
#define SECTION_RPC_SSL_KEY "rpc_ssl_key"
|
||||
#define SECTION_SMS_FROM "sms_from"
|
||||
#define SECTION_SMS_KEY "sms_key"
|
||||
#define SECTION_SMS_SECRET "sms_secret"
|
||||
@@ -87,16 +69,7 @@ struct ConfigSection
|
||||
#define SECTION_VALIDATORS_FILE "validators_file"
|
||||
#define SECTION_VALIDATION_QUORUM "validation_quorum"
|
||||
#define SECTION_VALIDATION_SEED "validation_seed"
|
||||
#define SECTION_WEBSOCKET_PUBLIC_IP "websocket_public_ip"
|
||||
#define SECTION_WEBSOCKET_PUBLIC_PORT "websocket_public_port"
|
||||
#define SECTION_WEBSOCKET_PUBLIC_SECURE "websocket_public_secure"
|
||||
#define SECTION_WEBSOCKET_PING_FREQ "websocket_ping_frequency"
|
||||
#define SECTION_WEBSOCKET_IP "websocket_ip"
|
||||
#define SECTION_WEBSOCKET_PORT "websocket_port"
|
||||
#define SECTION_WEBSOCKET_SECURE "websocket_secure"
|
||||
#define SECTION_WEBSOCKET_SSL_CERT "websocket_ssl_cert"
|
||||
#define SECTION_WEBSOCKET_SSL_CHAIN "websocket_ssl_chain"
|
||||
#define SECTION_WEBSOCKET_SSL_KEY "websocket_ssl_key"
|
||||
#define SECTION_VALIDATORS "validators"
|
||||
#define SECTION_VALIDATORS_SITE "validators_site"
|
||||
|
||||
|
||||
@@ -223,32 +223,13 @@ parseAddresses (OutputSequence& out, InputIterator first, InputIterator last,
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
Config::Config ()
|
||||
: m_rpcPort (5001)
|
||||
{
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// VFALCO NOTE Clean member area
|
||||
//
|
||||
|
||||
peerListeningPort = SYSTEM_PEER_PORT;
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// Defaults
|
||||
//
|
||||
|
||||
RPC_SECURE = 0;
|
||||
WEBSOCKET_PORT = 6562;
|
||||
WEBSOCKET_PUBLIC_PORT = 6563;
|
||||
WEBSOCKET_PUBLIC_SECURE = 1;
|
||||
WEBSOCKET_SECURE = 0;
|
||||
WEBSOCKET_PING_FREQ = (5 * 60);
|
||||
|
||||
RPC_ALLOW_REMOTE = false;
|
||||
RPC_ADMIN_ALLOW.push_back (beast::IP::Endpoint::from_string("127.0.0.1"));
|
||||
|
||||
PEER_PRIVATE = false;
|
||||
@@ -419,7 +400,6 @@ void Config::load ()
|
||||
std::string strTemp;
|
||||
|
||||
build (secConfig);
|
||||
build_legacy();
|
||||
|
||||
// XXX Leak
|
||||
IniFileSections::mapped_type* smtTmp;
|
||||
@@ -484,8 +464,6 @@ void Config::load ()
|
||||
|
||||
(void) getSingleSection (secConfig, SECTION_VALIDATORS_SITE, VALIDATORS_SITE);
|
||||
|
||||
(void) getSingleSection (secConfig, SECTION_PEER_IP, PEER_IP);
|
||||
|
||||
if (getSingleSection (secConfig, SECTION_PEER_PRIVATE, strTemp))
|
||||
PEER_PRIVATE = beast::lexicalCastThrow <bool> (strTemp);
|
||||
|
||||
@@ -504,18 +482,8 @@ void Config::load ()
|
||||
parsedAddresses.cbegin (), parsedAddresses.cend ());
|
||||
}
|
||||
|
||||
(void) getSingleSection (secConfig, SECTION_RPC_ADMIN_PASSWORD, RPC_ADMIN_PASSWORD);
|
||||
(void) getSingleSection (secConfig, SECTION_RPC_ADMIN_USER, RPC_ADMIN_USER);
|
||||
(void) getSingleSection (secConfig, SECTION_RPC_IP, m_rpcIP);
|
||||
(void) getSingleSection (secConfig, SECTION_RPC_PASSWORD, RPC_PASSWORD);
|
||||
(void) getSingleSection (secConfig, SECTION_RPC_USER, RPC_USER);
|
||||
|
||||
insightSettings = parseKeyValueSection (secConfig, SECTION_INSIGHT);
|
||||
|
||||
//---------------------------------------
|
||||
//
|
||||
// VFALCO BEGIN CLEAN
|
||||
//
|
||||
nodeDatabase = parseKeyValueSection (
|
||||
secConfig, ConfigSection::nodeDatabase ());
|
||||
|
||||
@@ -525,20 +493,6 @@ void Config::load ()
|
||||
importNodeDatabase = parseKeyValueSection (
|
||||
secConfig, ConfigSection::importNodeDatabase ());
|
||||
|
||||
if (getSingleSection (secConfig, SECTION_PEER_PORT, strTemp))
|
||||
peerListeningPort = beast::lexicalCastThrow <int> (strTemp);
|
||||
|
||||
//
|
||||
// VFALCO END CLEAN
|
||||
//
|
||||
//---------------------------------------
|
||||
|
||||
if (getSingleSection (secConfig, SECTION_RPC_PORT, strTemp))
|
||||
m_rpcPort = beast::lexicalCastThrow <int> (strTemp);
|
||||
|
||||
if (getSingleSection (secConfig, SECTION_RPC_ALLOW_REMOTE, strTemp))
|
||||
RPC_ALLOW_REMOTE = beast::lexicalCastThrow <bool> (strTemp);
|
||||
|
||||
if (getSingleSection (secConfig, SECTION_NODE_SIZE, strTemp))
|
||||
{
|
||||
if (strTemp == "tiny")
|
||||
@@ -565,37 +519,9 @@ void Config::load ()
|
||||
if (getSingleSection (secConfig, SECTION_ELB_SUPPORT, strTemp))
|
||||
ELB_SUPPORT = beast::lexicalCastThrow <bool> (strTemp);
|
||||
|
||||
(void) getSingleSection (secConfig, SECTION_WEBSOCKET_IP, WEBSOCKET_IP);
|
||||
|
||||
if (getSingleSection (secConfig, SECTION_WEBSOCKET_PORT, strTemp))
|
||||
WEBSOCKET_PORT = beast::lexicalCastThrow <int> (strTemp);
|
||||
|
||||
(void) getSingleSection (secConfig, SECTION_WEBSOCKET_PUBLIC_IP, WEBSOCKET_PUBLIC_IP);
|
||||
|
||||
if (getSingleSection (secConfig, SECTION_WEBSOCKET_PUBLIC_PORT, strTemp))
|
||||
WEBSOCKET_PUBLIC_PORT = beast::lexicalCastThrow <int> (strTemp);
|
||||
|
||||
if (getSingleSection (secConfig, SECTION_WEBSOCKET_SECURE, strTemp))
|
||||
WEBSOCKET_SECURE = beast::lexicalCastThrow <int> (strTemp);
|
||||
|
||||
if (getSingleSection (secConfig, SECTION_WEBSOCKET_PUBLIC_SECURE, strTemp))
|
||||
WEBSOCKET_PUBLIC_SECURE = beast::lexicalCastThrow <int> (strTemp);
|
||||
|
||||
if (getSingleSection (secConfig, SECTION_WEBSOCKET_PING_FREQ, strTemp))
|
||||
WEBSOCKET_PING_FREQ = beast::lexicalCastThrow <int> (strTemp);
|
||||
|
||||
getSingleSection (secConfig, SECTION_WEBSOCKET_SSL_CERT, WEBSOCKET_SSL_CERT);
|
||||
getSingleSection (secConfig, SECTION_WEBSOCKET_SSL_CHAIN, WEBSOCKET_SSL_CHAIN);
|
||||
getSingleSection (secConfig, SECTION_WEBSOCKET_SSL_KEY, WEBSOCKET_SSL_KEY);
|
||||
|
||||
if (getSingleSection (secConfig, SECTION_RPC_SECURE, strTemp))
|
||||
RPC_SECURE = beast::lexicalCastThrow <int> (strTemp);
|
||||
|
||||
getSingleSection (secConfig, SECTION_RPC_SSL_CERT, RPC_SSL_CERT);
|
||||
getSingleSection (secConfig, SECTION_RPC_SSL_CHAIN, RPC_SSL_CHAIN);
|
||||
getSingleSection (secConfig, SECTION_RPC_SSL_KEY, RPC_SSL_KEY);
|
||||
|
||||
|
||||
getSingleSection (secConfig, SECTION_SSL_VERIFY_FILE, SSL_VERIFY_FILE);
|
||||
getSingleSection (secConfig, SECTION_SSL_VERIFY_DIR, SSL_VERIFY_DIR);
|
||||
|
||||
@@ -816,150 +742,9 @@ beast::URL Config::getValidatorsURL () const
|
||||
return beast::parse_URL (VALIDATORS_SITE).second;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void Config::setRpcIpAndOptionalPort (std::string const& newAddress)
|
||||
{
|
||||
beast::String const s (newAddress.c_str ());
|
||||
|
||||
int const colonPosition = s.lastIndexOfChar (':');
|
||||
|
||||
if (colonPosition != -1)
|
||||
{
|
||||
beast::String const ipPart = s.substring (0, colonPosition);
|
||||
beast::String const portPart = s.substring (colonPosition + 1, s.length ());
|
||||
|
||||
setRpcIP (ipPart.toRawUTF8 ());
|
||||
setRpcPort (portPart.getIntValue ());
|
||||
}
|
||||
else
|
||||
{
|
||||
setRpcIP (newAddress);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
Config::Role Config::getAdminRole (Json::Value const& params, beast::IP::Endpoint const& remoteIp) const
|
||||
{
|
||||
Config::Role role (Config::FORBID);
|
||||
|
||||
bool const bPasswordSupplied =
|
||||
params.isMember ("admin_user") ||
|
||||
params.isMember ("admin_password");
|
||||
|
||||
bool const bPasswordRequired =
|
||||
! this->RPC_ADMIN_USER.empty () ||
|
||||
! this->RPC_ADMIN_PASSWORD.empty ();
|
||||
|
||||
bool bPasswordWrong;
|
||||
|
||||
if (bPasswordSupplied)
|
||||
{
|
||||
if (bPasswordRequired)
|
||||
{
|
||||
// Required, and supplied, check match
|
||||
bPasswordWrong =
|
||||
(this->RPC_ADMIN_USER !=
|
||||
(params.isMember ("admin_user") ? params["admin_user"].asString () : ""))
|
||||
||
|
||||
(this->RPC_ADMIN_PASSWORD !=
|
||||
(params.isMember ("admin_user") ? params["admin_password"].asString () : ""));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not required, but supplied
|
||||
bPasswordWrong = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Required but not supplied,
|
||||
bPasswordWrong = bPasswordRequired;
|
||||
}
|
||||
|
||||
// Meets IP restriction for admin.
|
||||
beast::IP::Endpoint const remote_addr (remoteIp.at_port (0));
|
||||
bool bAdminIP = false;
|
||||
|
||||
for (auto const& allow_addr : RPC_ADMIN_ALLOW)
|
||||
{
|
||||
if (allow_addr == remote_addr)
|
||||
{
|
||||
bAdminIP = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bPasswordWrong // Wrong
|
||||
|| (bPasswordSupplied && !bAdminIP)) // Supplied and doesn't meet IP filter.
|
||||
{
|
||||
role = Config::FORBID;
|
||||
}
|
||||
// If supplied, password is correct.
|
||||
else
|
||||
{
|
||||
// Allow admin, if from admin IP and no password is required or it was supplied and correct.
|
||||
role = bAdminIP && (!bPasswordRequired || bPasswordSupplied) ? Config::ADMIN : Config::GUEST;
|
||||
}
|
||||
|
||||
return role;
|
||||
}
|
||||
|
||||
beast::File const& Config::getModuleDatabasePath ()
|
||||
{
|
||||
return m_moduleDbPath;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
Config::build_legacy ()
|
||||
{
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// [rpc]
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
remap("rpc_allow_remote", "allow_remote", "rpc");
|
||||
//remap("rpc_admin_allow", "admin_allow", "rpc"); // Not a key-value pair
|
||||
remap("rpc_admin_user", "admin_user", "rpc");
|
||||
remap("rpc_admin_password", "admin_password", "rpc");
|
||||
remap("rpc_ip", "ip", "rpc");
|
||||
remap("rpc_port", "port", "rpc");
|
||||
remap("rpc_user", "user", "rpc");
|
||||
remap("rpc_password", "password", "rpc");
|
||||
//remap("rpc_startup", "startup", "rpc"); // Not a key-value pair
|
||||
remap("rpc_secure", "secure", "rpc");
|
||||
remap("rpc_ssl_cert", "ssl_cert", "rpc");
|
||||
remap("rpc_ssl_chain", "ssl_chain", "rpc");
|
||||
remap("rpc_ssl_key", "ssl_key", "rpc");
|
||||
|
||||
#if DUMP_CONFIG
|
||||
beast::debug_ostream log;
|
||||
log << (BasicConfig const&)*this;
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
RPC::Setup
|
||||
setup_RPC (Section const& s)
|
||||
{
|
||||
RPC::Setup c;
|
||||
set (c.allow_remote, "allow_remote", s);
|
||||
set (c.admin_user, "admin_user", s);
|
||||
set (c.admin_password, "admin_password", s);
|
||||
set (c.ip, "ip", s);
|
||||
set (c.port, "port", s);
|
||||
set (c.user, "user", s);
|
||||
set (c.password, "password", s);
|
||||
set (c.secure, "secure", s);
|
||||
set (c.ssl_cert, "ssl_cert", s);
|
||||
set (c.ssl_chain, "ssl_chain", s);
|
||||
set (c.ssl_key, "ssl_key", s);
|
||||
return c;
|
||||
}
|
||||
|
||||
} // ripple
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
# HTTP Server
|
||||
|
||||
A generic HTTP server. This is used for doing asynchronous RPC
|
||||
currently, although it could be expanded to perform more activities
|
||||
such as reporting to the elastic load balancer or providing server
|
||||
statistics.
|
||||
@@ -1,146 +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_SERVER_H_INCLUDED
|
||||
#define RIPPLE_HTTP_SERVER_H_INCLUDED
|
||||
|
||||
#include <ripple/basics/BasicConfig.h>
|
||||
#include <ripple/common/RippleSSLContext.h>
|
||||
#include <beast/net/IPEndpoint.h>
|
||||
#include <beast/utility/Journal.h>
|
||||
#include <beast/utility/PropertyStream.h>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
|
||||
namespace ripple {
|
||||
namespace HTTP {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Configuration information for a server listening port. */
|
||||
struct Port
|
||||
{
|
||||
enum class Security
|
||||
{
|
||||
no_ssl,
|
||||
allow_ssl,
|
||||
require_ssl
|
||||
};
|
||||
|
||||
Security security = Security::no_ssl;
|
||||
std::uint16_t port = 0;
|
||||
beast::IP::Endpoint addr;
|
||||
SSLContext* context = nullptr;
|
||||
|
||||
Port() = default;
|
||||
Port (std::uint16_t port_, beast::IP::Endpoint const& addr_,
|
||||
Security security_, SSLContext* context_);
|
||||
|
||||
static
|
||||
void
|
||||
parse (Port& result, Section const& section, std::ostream& log);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
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 when we have a complete HTTP request. */
|
||||
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;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Multi-threaded, asynchronous HTTP server. */
|
||||
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;
|
||||
|
||||
virtual
|
||||
void
|
||||
onWrite (beast::PropertyStream::Map& map) = 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;
|
||||
|
||||
/** Parse configuration settings into a list of ports. */
|
||||
static
|
||||
std::vector<Port>
|
||||
parse (BasicConfig const& config, std::ostream& log);
|
||||
};
|
||||
|
||||
/** Create the HTTP server using the specified handler. */
|
||||
std::unique_ptr<Server>
|
||||
make_Server (Handler& handler, beast::Journal journal);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} // HTTP
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
@@ -1 +0,0 @@
|
||||
# HTTP Server TODO
|
||||
@@ -1,126 +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_SSLPEER_H_INCLUDED
|
||||
#define RIPPLE_HTTP_SSLPEER_H_INCLUDED
|
||||
|
||||
#include <ripple/http/impl/Peer.h>
|
||||
|
||||
namespace ripple {
|
||||
namespace HTTP {
|
||||
|
||||
class SSLPeer
|
||||
: public Peer <SSLPeer>
|
||||
, public std::enable_shared_from_this <SSLPeer>
|
||||
{
|
||||
private:
|
||||
friend class Peer <SSLPeer>;
|
||||
using next_layer_type = boost::asio::ip::tcp::socket;
|
||||
using socket_type = boost::asio::ssl::stream <next_layer_type&>;
|
||||
next_layer_type next_layer_;
|
||||
socket_type socket_;
|
||||
|
||||
public:
|
||||
template <class ConstBufferSequence>
|
||||
SSLPeer (Door& door, beast::Journal journal, endpoint_type endpoint,
|
||||
ConstBufferSequence const& buffers, next_layer_type&& socket);
|
||||
|
||||
void
|
||||
run();
|
||||
|
||||
private:
|
||||
void
|
||||
do_handshake (boost::asio::yield_context yield);
|
||||
|
||||
void
|
||||
do_request();
|
||||
|
||||
void
|
||||
do_close();
|
||||
|
||||
void
|
||||
on_shutdown (error_code ec);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class ConstBufferSequence>
|
||||
SSLPeer::SSLPeer (Door& door, beast::Journal journal,
|
||||
endpoint_type endpoint, ConstBufferSequence const& buffers,
|
||||
boost::asio::ip::tcp::socket&& socket)
|
||||
: Peer (door, socket.get_io_service(), journal, endpoint, buffers)
|
||||
, next_layer_ (std::move(socket))
|
||||
, socket_ (next_layer_, door_.port().context->get())
|
||||
{
|
||||
}
|
||||
|
||||
// Called when the acceptor accepts our socket.
|
||||
void
|
||||
SSLPeer::run ()
|
||||
{
|
||||
door_.server().handler().onAccept (session());
|
||||
if (! socket_.lowest_layer().is_open())
|
||||
return;
|
||||
|
||||
boost::asio::spawn (strand_, std::bind (&SSLPeer::do_handshake,
|
||||
shared_from_this(), std::placeholders::_1));
|
||||
}
|
||||
|
||||
void
|
||||
SSLPeer::do_handshake (boost::asio::yield_context yield)
|
||||
{
|
||||
error_code ec;
|
||||
start_timer();
|
||||
read_buf_.consume(socket_.async_handshake(
|
||||
socket_type::server, read_buf_.data(), yield[ec]));
|
||||
cancel_timer();
|
||||
if (ec)
|
||||
return fail (ec, "handshake");
|
||||
boost::asio::spawn (strand_, std::bind (&SSLPeer::do_read,
|
||||
shared_from_this(), std::placeholders::_1));
|
||||
}
|
||||
|
||||
void
|
||||
SSLPeer::do_request()
|
||||
{
|
||||
++request_count_;
|
||||
door_.server().handler().onRequest (session());
|
||||
}
|
||||
|
||||
void
|
||||
SSLPeer::do_close()
|
||||
{
|
||||
error_code ec;
|
||||
start_timer();
|
||||
socket_.async_shutdown (strand_.wrap (std::bind (
|
||||
&SSLPeer::on_shutdown, shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
cancel_timer();
|
||||
}
|
||||
|
||||
void
|
||||
SSLPeer::on_shutdown (error_code ec)
|
||||
{
|
||||
socket_.lowest_layer().close(ec);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,74 +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 <ripple/http/Server.h>
|
||||
#include <ripple/http/impl/ServerImpl.h>
|
||||
#include <beast/cxx14/memory.h> // <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace ripple {
|
||||
namespace HTTP {
|
||||
|
||||
std::unique_ptr<Server>
|
||||
make_Server (Handler& handler, beast::Journal journal)
|
||||
{
|
||||
return std::make_unique<ServerImpl>(handler, journal);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
Port::parse (Port& port,
|
||||
Section const& section, std::ostream& log)
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<Port>
|
||||
Server::parse (BasicConfig const& config, std::ostream& log)
|
||||
{
|
||||
std::vector <Port> result;
|
||||
|
||||
if (! config.exists("doors"))
|
||||
{
|
||||
log <<
|
||||
"Missing section: [doors]\n";
|
||||
return result;
|
||||
}
|
||||
|
||||
Port common;
|
||||
Port::parse (common, config["doors"], log);
|
||||
|
||||
auto const& names = config.section("doors").values();
|
||||
for (auto const& name : names)
|
||||
{
|
||||
if (! config.exists(name))
|
||||
{
|
||||
log <<
|
||||
"Missing section: [" << name << "]\n";
|
||||
//throw std::
|
||||
}
|
||||
result.push_back(common);
|
||||
Port::parse (result.back(), config[name], log);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,71 +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_TYPES_H_INCLUDED
|
||||
#define RIPPLE_HTTP_TYPES_H_INCLUDED
|
||||
|
||||
namespace ripple {
|
||||
namespace HTTP {
|
||||
|
||||
typedef boost::system::error_code error_code;
|
||||
typedef boost::asio::ip::tcp Protocol;
|
||||
typedef boost::asio::ip::address address;
|
||||
typedef Protocol::endpoint endpoint_t;
|
||||
typedef Protocol::acceptor acceptor;
|
||||
typedef Protocol::socket socket;
|
||||
|
||||
inline std::string to_string (address const& addr)
|
||||
{
|
||||
return addr.to_string();
|
||||
}
|
||||
|
||||
inline std::string to_string (endpoint_t const& endpoint)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << to_string (endpoint.address());
|
||||
if (endpoint.port() != 0)
|
||||
ss << ":" << std::dec << endpoint.port();
|
||||
return std::string (ss.str());
|
||||
}
|
||||
|
||||
inline endpoint_t to_asio (Port const& port)
|
||||
{
|
||||
if (port.addr.is_v4())
|
||||
{
|
||||
beast::IP::AddressV4 v4 (port.addr.to_v4());
|
||||
std::string const& s (to_string (v4));
|
||||
return endpoint_t (address().from_string (s), port.port);
|
||||
}
|
||||
|
||||
//IP::Endpoint::V6 v6 (ep.v6());
|
||||
return endpoint_t ();
|
||||
}
|
||||
|
||||
inline beast::IP::Endpoint from_asio (endpoint_t const& endpoint)
|
||||
{
|
||||
std::stringstream ss (to_string (endpoint));
|
||||
beast::IP::Endpoint ep;
|
||||
ss >> ep;
|
||||
return ep;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -17,11 +17,12 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/common/jsonrpc_fields.h>
|
||||
#include <ripple/basics/ArraySize.h>
|
||||
#include <ripple/rpc/ErrorCodes.h>
|
||||
#include <ripple/server/ServerHandler.h>
|
||||
#include <ripple/net/RPCCall.h>
|
||||
#include <ripple/net/RPCErr.h>
|
||||
#include <ripple/net/RPCUtil.h>
|
||||
#include <boost/regex.hpp>
|
||||
#include <iostream>
|
||||
|
||||
@@ -38,6 +39,42 @@ static inline bool isSwitchChar (char c)
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// HTTP protocol
|
||||
//
|
||||
// This ain't Apache. We're just using HTTP header for the length field
|
||||
// and to be compatible with other JSON-RPC implementations.
|
||||
//
|
||||
|
||||
std::string createHTTPPost (
|
||||
std::string const& strHost,
|
||||
std::string const& strPath,
|
||||
std::string const& strMsg,
|
||||
std::map<std::string, std::string> const& mapRequestHeaders)
|
||||
{
|
||||
std::ostringstream s;
|
||||
|
||||
// CHECKME this uses a different version than the replies below use. Is
|
||||
// this by design or an accident or should it be using
|
||||
// BuildInfo::getFullVersionString () as well?
|
||||
|
||||
s << "POST "
|
||||
<< (strPath.empty () ? "/" : strPath)
|
||||
<< " HTTP/1.0\r\n"
|
||||
<< "User-Agent: " SYSTEM_NAME "-json-rpc/v1\r\n"
|
||||
<< "Host: " << strHost << "\r\n"
|
||||
<< "Content-Type: application/json\r\n"
|
||||
<< "Content-Length: " << strMsg.size () << "\r\n"
|
||||
<< "Accept: application/json\r\n";
|
||||
|
||||
for (auto const& item : mapRequestHeaders)
|
||||
s << item.first << ": " << item.second << "\r\n";
|
||||
|
||||
s << "\r\n" << strMsg;
|
||||
|
||||
return s.str ();
|
||||
}
|
||||
|
||||
class RPCParser
|
||||
{
|
||||
private:
|
||||
@@ -887,6 +924,24 @@ public:
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
|
||||
// but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
|
||||
// unspecified (HTTP errors and contents of 'error').
|
||||
//
|
||||
// 1.0 spec: http://json-rpc.org/wiki/specification
|
||||
// 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
|
||||
//
|
||||
|
||||
std::string JSONRPCRequest (std::string const& strMethod, Json::Value const& params, Json::Value const& id)
|
||||
{
|
||||
Json::Value request;
|
||||
request[jss::method] = strMethod;
|
||||
request[jss::params] = params;
|
||||
request[jss::id] = id;
|
||||
return to_string (request) + "\n";
|
||||
}
|
||||
|
||||
struct RPCCallImp
|
||||
{
|
||||
// VFALCO NOTE Is this a to-do comment or a doc comment?
|
||||
@@ -909,7 +964,7 @@ struct RPCCallImp
|
||||
if (iStatus == 401)
|
||||
throw std::runtime_error ("incorrect rpcuser or rpcpassword (authorization failed)");
|
||||
else if ((iStatus >= 400) && (iStatus != 400) && (iStatus != 404) && (iStatus != 500)) // ?
|
||||
throw std::runtime_error (std::string ("server returned HTTP error %d") + std::to_string (iStatus));
|
||||
throw std::runtime_error (std::string ("server returned HTTP error ") + std::to_string (iStatus));
|
||||
else if (strData.empty ())
|
||||
throw std::runtime_error ("no response from server");
|
||||
|
||||
@@ -943,7 +998,6 @@ struct RPCCallImp
|
||||
WriteLog (lsDEBUG, RPCParser) << "requestRPC: strPath='" << strPath << "'";
|
||||
|
||||
std::ostream osRequest (&sb);
|
||||
|
||||
osRequest <<
|
||||
createHTTPPost (
|
||||
strHost,
|
||||
@@ -987,35 +1041,35 @@ int RPCCall::fromCommandLine (const std::vector<std::string>& vCmd)
|
||||
}
|
||||
else
|
||||
{
|
||||
auto setup = setup_RPC (getConfig()["rpc"]);
|
||||
auto const setup = setup_ServerHandler(getConfig(), std::cerr);
|
||||
|
||||
Json::Value jvParams (Json::arrayValue);
|
||||
|
||||
if (!setup.client.admin_user.empty ())
|
||||
jvRequest["admin_user"] = setup.client.admin_user;
|
||||
|
||||
if (!setup.client.admin_password.empty ())
|
||||
jvRequest["admin_password"] = setup.client.admin_password;
|
||||
|
||||
jvParams.append (jvRequest);
|
||||
|
||||
if (!setup.admin_user.empty ())
|
||||
jvRequest["admin_user"] = setup.admin_user;
|
||||
|
||||
if (!setup.admin_password.empty ())
|
||||
jvRequest["admin_password"] = setup.admin_password;
|
||||
|
||||
{
|
||||
boost::asio::io_service isService;
|
||||
|
||||
fromNetwork (
|
||||
isService,
|
||||
setup.ip,
|
||||
setup.port,
|
||||
setup.admin_user,
|
||||
setup.admin_password,
|
||||
setup.client.ip,
|
||||
setup.client.port,
|
||||
setup.client.user,
|
||||
setup.client.password,
|
||||
"",
|
||||
jvRequest.isMember ("method") // Allow parser to rewrite method.
|
||||
? jvRequest["method"].asString () : vCmd[0],
|
||||
jvParams, // Parsed, execute.
|
||||
setup.secure != 0, // Use SSL
|
||||
setup.client.secure != 0, // Use SSL
|
||||
std::bind (RPCCallImp::callRPCHandler, &jvOutput,
|
||||
std::placeholders::_1));
|
||||
|
||||
isService.run(); // This blocks until there is no more outstanding async calls.
|
||||
}
|
||||
|
||||
if (jvOutput.isMember ("result"))
|
||||
{
|
||||
|
||||
@@ -1,144 +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 <ripple/common/RippleSSLContext.h>
|
||||
#include <ripple/net/RPCDoor.h>
|
||||
#include <ripple/net/impl/RPCServerImp.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class RPCDoorImp : public RPCDoor, public beast::LeakChecked <RPCDoorImp>
|
||||
{
|
||||
public:
|
||||
RPCDoorImp (boost::asio::io_service& io_service, RPCServer::Handler& handler)
|
||||
: m_rpcServerHandler (handler)
|
||||
, mAcceptor (io_service,
|
||||
boost::asio::ip::tcp::endpoint (boost::asio::ip::address::from_string (getConfig ().getRpcIP ()), getConfig ().getRpcPort ()))
|
||||
, mDelayTimer (io_service)
|
||||
, m_sslContext ((getConfig ().RPC_SECURE == 0) ?
|
||||
RippleSSLContext::createBare () :
|
||||
RippleSSLContext::createAuthenticated (
|
||||
getConfig ().RPC_SSL_KEY,
|
||||
getConfig ().RPC_SSL_CERT,
|
||||
getConfig ().RPC_SSL_CHAIN))
|
||||
{
|
||||
WriteLog (lsINFO, RPCDoor) <<
|
||||
"RPC port: " << getConfig ().getRpcAddress() <<
|
||||
" allow remote: " << getConfig ().RPC_ALLOW_REMOTE;
|
||||
|
||||
startListening ();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
~RPCDoorImp ()
|
||||
{
|
||||
WriteLog (lsINFO, RPCDoor) <<
|
||||
"RPC port: " << getConfig ().getRpcAddress() <<
|
||||
" allow remote: " << getConfig ().RPC_ALLOW_REMOTE;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void startListening ()
|
||||
{
|
||||
RPCServerImp::pointer new_connection (std::make_shared <RPCServerImp> (
|
||||
std::ref (mAcceptor.get_io_service ()),
|
||||
std::ref (m_sslContext->get ()),
|
||||
std::ref (m_rpcServerHandler)));
|
||||
|
||||
mAcceptor.set_option (boost::asio::ip::tcp::acceptor::reuse_address (true));
|
||||
|
||||
mAcceptor.async_accept (new_connection->getRawSocket (),
|
||||
new_connection->getRemoteEndpoint (),
|
||||
std::bind (&RPCDoorImp::handleConnect, this,
|
||||
new_connection, beast::asio::placeholders::error));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
bool isClientAllowed (std::string const& ip)
|
||||
{
|
||||
if (getConfig ().RPC_ALLOW_REMOTE)
|
||||
return true;
|
||||
|
||||
// VFALCO TODO Represent ip addresses as a structure. Use isLoopback() member here
|
||||
//
|
||||
if (ip == "127.0.0.1")
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void handleConnect (RPCServerImp::pointer new_connection,
|
||||
boost::system::error_code const& error)
|
||||
{
|
||||
bool delay = false;
|
||||
|
||||
if (!error)
|
||||
{
|
||||
// Restrict callers by IP
|
||||
std::string client_ip (
|
||||
new_connection->getRemoteEndpoint ().address ().to_string ());
|
||||
|
||||
if (! isClientAllowed (client_ip))
|
||||
{
|
||||
startListening ();
|
||||
return;
|
||||
}
|
||||
|
||||
new_connection->getSocket ().async_handshake (AutoSocket::ssl_socket::server,
|
||||
std::bind (&RPCServer::connected, new_connection));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (error == boost::system::errc::too_many_files_open)
|
||||
delay = true;
|
||||
|
||||
WriteLog (lsINFO, RPCDoor) << "RPCDoorImp::handleConnect Error: " << error;
|
||||
}
|
||||
|
||||
if (delay)
|
||||
{
|
||||
mDelayTimer.expires_from_now (boost::posix_time::milliseconds (1000));
|
||||
mDelayTimer.async_wait (std::bind (&RPCDoorImp::startListening, this));
|
||||
}
|
||||
else
|
||||
{
|
||||
startListening ();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
RPCServer::Handler& m_rpcServerHandler;
|
||||
boost::asio::ip::tcp::acceptor mAcceptor;
|
||||
boost::asio::deadline_timer mDelayTimer;
|
||||
std::unique_ptr <RippleSSLContext> m_sslContext;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// VFALCO TODO Return std::unique_ptr here
|
||||
RPCDoor* RPCDoor::New (boost::asio::io_service& io_service, RPCServer::Handler& handler)
|
||||
{
|
||||
return new RPCDoorImp (io_service, handler);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,10 +21,15 @@
|
||||
#define RIPPLE_OVERLAY_OVERLAY_H_INCLUDED
|
||||
|
||||
#include <ripple/overlay/Peer.h>
|
||||
#include <ripple/server/Handoff.h>
|
||||
#include <beast/asio/ssl_bundle.h>
|
||||
#include <beast/http/message.h>
|
||||
#include <beast/threads/Stoppable.h>
|
||||
#include <beast/utility/PropertyStream.h>
|
||||
#include <memory>
|
||||
#include <beast/cxx14/type_traits.h> // <type_traits>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
|
||||
namespace boost { namespace asio { namespace ssl { class context; } } }
|
||||
|
||||
@@ -66,6 +71,20 @@ public:
|
||||
|
||||
virtual ~Overlay() = default;
|
||||
|
||||
/** Accept a legacy protocol handshake connection. */
|
||||
virtual
|
||||
void
|
||||
onLegacyPeerHello (std::unique_ptr<beast::asio::ssl_bundle>&& ssl_bundle,
|
||||
boost::asio::const_buffer buffer,
|
||||
boost::asio::ip::tcp::endpoint remote_address) = 0;
|
||||
|
||||
/** Conditionally accept an incoming HTTP request. */
|
||||
virtual
|
||||
Handoff
|
||||
onHandoff (std::unique_ptr <beast::asio::ssl_bundle>&& bundle,
|
||||
beast::http::message&& request,
|
||||
boost::asio::ip::tcp::endpoint remote_address) = 0;
|
||||
|
||||
/** Establish a peer connection to the specified endpoint.
|
||||
The call returns immediately, the connection attempt is
|
||||
performed asynchronously.
|
||||
|
||||
@@ -65,10 +65,10 @@ custom fields to communicate protocol specific information:
|
||||
GET / HTTP/1.1
|
||||
User-Agent: Ripple-0.26.0
|
||||
Local-Address: 192.168.0.101:8421
|
||||
Remote-Address: 208.239.76.97:51234
|
||||
Upgrade: Ripple/1.2, Ripple/1.3
|
||||
Connection: Upgrade
|
||||
Connect-As: Leaf, Peer
|
||||
Content-Length: 0
|
||||
Accept-Encoding: identity, zlib, snappy
|
||||
Protocol-Public-Key: aBRoQibi2jpDofohooFuzZi9nEzKw9Zdfc4ExVNmuXHaJpSPh8uJ
|
||||
Protocol-Session-Cookie: 71ED064155FFADFA38782C5E0158CB26
|
||||
@@ -79,9 +79,8 @@ HTTP response indicating the connection status:
|
||||
|
||||
```
|
||||
HTTP/1.1 101 Switching Protocols
|
||||
Server: Ripple-0.26.0-rc1
|
||||
Local-Address: 192.168.0.101:8421
|
||||
Remote-Address: 63.104.209.13:8421
|
||||
Server: Ripple-0.26.5
|
||||
Remote-Address: 63.104.209.13
|
||||
Upgrade: Ripple/1.2
|
||||
Connection: Upgrade
|
||||
Connect-As: Leaf
|
||||
@@ -90,6 +89,22 @@ Protocol-Public-Key: aBRoQibi2jpDofohooFuzZi9nEzKw9Zdfc4ExVNmuXHaJpSPh8uJ
|
||||
Protocol-Session-Cookie: 71ED064155FFADFA38782C5E0158CB26
|
||||
```
|
||||
|
||||
If the remote peer has no available slots, the HTTP status code 503 (Service
|
||||
Unavailable) is returned, with an optional content body in JSON format that
|
||||
may contain additional information such as IP and port addresses of other
|
||||
servers that may have open slots:
|
||||
|
||||
```
|
||||
HTTP/1.1 503 Service Unavailable
|
||||
Server: Ripple-0.26.5
|
||||
Remote-Address: 63.104.209.13
|
||||
Content-Length: 253
|
||||
Content-Type: application/json
|
||||
{"peer-ips":["54.68.219.39:51235","54.187.191.179:51235",
|
||||
"107.150.55.21:6561","54.186.230.77:51235","54.187.110.243:51235",
|
||||
"85.127.34.221:51235","50.43.33.236:51235","54.187.138.75:51235"]}
|
||||
```
|
||||
|
||||
### Fields
|
||||
|
||||
* *URL*
|
||||
@@ -113,15 +128,12 @@ Protocol-Session-Cookie: 71ED064155FFADFA38782C5E0158CB26
|
||||
Contains information about the software providing the response. The
|
||||
specification is identical to RFC2616 Section 14.38.
|
||||
|
||||
* `Local-Address`
|
||||
* `Remote-Address` (optional)
|
||||
|
||||
This field must be present and contain the string representation of the
|
||||
IP and port address of the local end of the connection as seen by the peer.
|
||||
|
||||
* `Remote-Address`
|
||||
|
||||
This field must be present and contain the string representation of the
|
||||
IP and port address of the remote end of the connection as seen by the peer.
|
||||
This optional field contains the string representation of the IP
|
||||
address of the remote end of the connection as seen by the peer.
|
||||
By observing values of this field from a sufficient number of different
|
||||
servers, a peer making outgoing connections can deduce its own IP address.
|
||||
|
||||
* `Upgrade`
|
||||
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/common/RippleSSLContext.h>
|
||||
#include <ripple/common/make_SSLContext.h>
|
||||
#include <ripple/server/JsonWriter.h>
|
||||
#include <ripple/overlay/impl/OverlayImpl.h>
|
||||
#include <ripple/overlay/impl/PeerDoor.h>
|
||||
#include <ripple/overlay/impl/PeerImp.h>
|
||||
#include <ripple/peerfinder/make_Manager.h>
|
||||
#include <beast/ByteOrder.h>
|
||||
@@ -100,8 +100,8 @@ OverlayImpl::Timer::on_timer (error_code ec)
|
||||
}
|
||||
|
||||
overlay_.m_peerFinder->once_per_second();
|
||||
overlay_.sendpeers();
|
||||
overlay_.autoconnect();
|
||||
overlay_.sendEndpoints();
|
||||
overlay_.autoConnect();
|
||||
|
||||
timer_.expires_from_now (std::chrono::seconds(1));
|
||||
timer_.async_wait(overlay_.strand_.wrap(std::bind(
|
||||
@@ -114,8 +114,8 @@ OverlayImpl::Timer::on_timer (error_code ec)
|
||||
OverlayImpl::OverlayImpl (
|
||||
Setup const& setup,
|
||||
Stoppable& parent,
|
||||
ServerHandler& serverHandler,
|
||||
Resource::Manager& resourceManager,
|
||||
SiteFiles::Manager& siteFiles,
|
||||
beast::File const& pathToDbFileOrDirectory,
|
||||
Resolver& resolver,
|
||||
boost::asio::io_service& io_service)
|
||||
@@ -125,6 +125,7 @@ OverlayImpl::OverlayImpl (
|
||||
, strand_ (io_service_)
|
||||
, setup_(setup)
|
||||
, journal_ (deprecatedLogs().journal("Overlay"))
|
||||
, serverHandler_(serverHandler)
|
||||
, m_resourceManager (resourceManager)
|
||||
, m_peerFinder (PeerFinder::make_Manager (*this, io_service,
|
||||
pathToDbFileOrDirectory, get_seconds_clock(),
|
||||
@@ -146,50 +147,113 @@ OverlayImpl::~OverlayImpl ()
|
||||
cond_.wait (lock, [this] { return list_.empty(); });
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
OverlayImpl::accept (socket_type&& socket)
|
||||
OverlayImpl::onLegacyPeerHello (
|
||||
std::unique_ptr<beast::asio::ssl_bundle>&& ssl_bundle,
|
||||
boost::asio::const_buffer buffer,
|
||||
boost::asio::ip::tcp::endpoint remote_address)
|
||||
{
|
||||
// An error getting an endpoint means the connection closed.
|
||||
// Just do nothing and the socket will be closed by the caller.
|
||||
boost::system::error_code ec;
|
||||
auto const local_endpoint_native (socket.local_endpoint (ec));
|
||||
if (ec)
|
||||
return;
|
||||
auto const remote_endpoint_native (socket.remote_endpoint (ec));
|
||||
error_code ec;
|
||||
auto const local_endpoint (ssl_bundle->socket.local_endpoint(ec));
|
||||
if (ec)
|
||||
return;
|
||||
|
||||
auto const local_endpoint (
|
||||
beast::IPAddressConversion::from_asio (local_endpoint_native));
|
||||
auto const remote_endpoint (
|
||||
beast::IPAddressConversion::from_asio (remote_endpoint_native));
|
||||
auto const slot = m_peerFinder->new_inbound_slot (
|
||||
beast::IPAddressConversion::from_asio(local_endpoint),
|
||||
beast::IPAddressConversion::from_asio(remote_address));
|
||||
|
||||
PeerFinder::Slot::ptr const slot (m_peerFinder->new_inbound_slot (
|
||||
local_endpoint, remote_endpoint));
|
||||
addpeer (std::make_shared<PeerImp>(std::move(ssl_bundle),
|
||||
boost::asio::const_buffers_1(buffer),
|
||||
beast::IPAddressConversion::from_asio(remote_address),
|
||||
*this, m_resourceManager, *m_peerFinder, slot));
|
||||
}
|
||||
|
||||
Handoff
|
||||
OverlayImpl::onHandoff (std::unique_ptr <beast::asio::ssl_bundle>&& ssl_bundle,
|
||||
beast::http::message&& request,
|
||||
boost::asio::ip::tcp::endpoint remote_address)
|
||||
{
|
||||
Handoff handoff;
|
||||
if (! isPeerUpgrade(request))
|
||||
return handoff;
|
||||
|
||||
error_code ec;
|
||||
auto const local_endpoint (ssl_bundle->socket.local_endpoint(ec));
|
||||
if (ec)
|
||||
{
|
||||
// log?
|
||||
// Since we don't call std::move the socket will be closed.
|
||||
handoff.moved = false;
|
||||
return handoff;
|
||||
}
|
||||
|
||||
// TODO Validate HTTP request
|
||||
|
||||
auto const slot = m_peerFinder->new_inbound_slot (
|
||||
beast::IPAddressConversion::from_asio(local_endpoint),
|
||||
beast::IPAddressConversion::from_asio(remote_address));
|
||||
|
||||
#if 0
|
||||
if (slot == nullptr)
|
||||
return;
|
||||
|
||||
PeerImp::ptr const peer (std::make_shared <PeerImp> (
|
||||
std::move (socket), remote_endpoint, *this, m_resourceManager,
|
||||
*m_peerFinder, slot, setup_.context));
|
||||
|
||||
#else
|
||||
// For now, always redirect.
|
||||
if (true)
|
||||
#endif
|
||||
{
|
||||
std::lock_guard <decltype(mutex_)> lock (mutex_);
|
||||
{
|
||||
std::pair <PeersBySlot::iterator, bool> const result (
|
||||
m_peers.emplace (slot, peer));
|
||||
assert (result.second);
|
||||
(void) result.second;
|
||||
// Full, give them some addresses
|
||||
handoff.response = makeRedirectResponse(slot, request);
|
||||
handoff.keep_alive = request.keep_alive();
|
||||
return handoff;
|
||||
}
|
||||
list_.emplace(peer.get(), peer);
|
||||
|
||||
// This has to happen while holding the lock,
|
||||
// otherwise the socket might not be canceled during a stop.
|
||||
peer->start();
|
||||
addpeer (std::make_shared<PeerImp>(std::move(ssl_bundle),
|
||||
std::move(request), beast::IPAddressConversion::from_asio(remote_address),
|
||||
*this, m_resourceManager, *m_peerFinder, slot));
|
||||
handoff.moved = true;
|
||||
return handoff;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool
|
||||
OverlayImpl::isPeerUpgrade(beast::http::message const& request)
|
||||
{
|
||||
if (! request.upgrade())
|
||||
return false;
|
||||
if (request.headers["Upgrade"] != "Ripple/1.2")
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<HTTP::Writer>
|
||||
OverlayImpl::makeRedirectResponse (PeerFinder::Slot::ptr const& slot,
|
||||
beast::http::message const& request)
|
||||
{
|
||||
Json::Value json(Json::objectValue);
|
||||
{
|
||||
auto const result = m_peerFinder->redirect(slot);
|
||||
Json::Value& ips = (json["peer-ips"] = Json::arrayValue);
|
||||
for (auto const& _ : m_peerFinder->redirect(slot))
|
||||
ips.append(_.address.to_string());
|
||||
}
|
||||
|
||||
beast::http::message m;
|
||||
m.request(false);
|
||||
m.status(503);
|
||||
m.reason("Service Unavailable");
|
||||
m.version(request.version());
|
||||
if (request.version() == std::make_pair(1, 0))
|
||||
{
|
||||
//?
|
||||
}
|
||||
auto const response = HTTP::make_JsonWriter (m, json);
|
||||
return response;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
OverlayImpl::connect (beast::IP::Endpoint const& remote_endpoint)
|
||||
{
|
||||
@@ -201,24 +265,8 @@ OverlayImpl::connect (beast::IP::Endpoint const& remote_endpoint)
|
||||
if (slot == nullptr)
|
||||
return;
|
||||
|
||||
PeerImp::ptr const peer (std::make_shared <PeerImp> (
|
||||
remote_endpoint, io_service_, *this, m_resourceManager,
|
||||
*m_peerFinder, slot, setup_.context));
|
||||
|
||||
{
|
||||
std::lock_guard <decltype(mutex_)> lock (mutex_);
|
||||
{
|
||||
std::pair <PeersBySlot::iterator, bool> const result (
|
||||
m_peers.emplace (slot, peer));
|
||||
assert (result.second);
|
||||
(void) result.second;
|
||||
}
|
||||
list_.emplace(peer.get(), peer);
|
||||
|
||||
// This has to happen while holding the lock,
|
||||
// otherwise the socket might not be canceled during a stop.
|
||||
peer->start ();
|
||||
}
|
||||
addpeer (std::make_shared <PeerImp> (remote_endpoint, io_service_, *this,
|
||||
m_resourceManager, *m_peerFinder, slot, setup_.context));
|
||||
}
|
||||
|
||||
Peer::ShortId
|
||||
@@ -254,18 +302,16 @@ OverlayImpl::onPrepare ()
|
||||
|
||||
config.outPeers = config.calcOutPeers();
|
||||
|
||||
config.wantIncoming =
|
||||
(! getConfig ().PEER_PRIVATE) &&
|
||||
(getConfig().peerListeningPort != 0);
|
||||
auto const port = serverHandler_.setup().overlay.port;
|
||||
|
||||
config.wantIncoming =
|
||||
(! getConfig ().PEER_PRIVATE) && (port != 0);
|
||||
// if it's a private peer or we are running as standalone
|
||||
// automatic connections would defeat the purpose.
|
||||
config.autoConnect =
|
||||
!getConfig().RUN_STANDALONE &&
|
||||
!getConfig().PEER_PRIVATE;
|
||||
|
||||
config.listeningPort = getConfig().peerListeningPort;
|
||||
|
||||
config.listeningPort = port;
|
||||
config.features = "";
|
||||
|
||||
// Enforce business rules
|
||||
@@ -311,14 +357,6 @@ OverlayImpl::onPrepare ()
|
||||
m_peerFinder->addFixedPeer (name, addresses);
|
||||
});
|
||||
}
|
||||
|
||||
// Configure the peer doors, which allow the server to accept incoming
|
||||
// peer connections:
|
||||
if (! getConfig ().RUN_STANDALONE)
|
||||
{
|
||||
m_doorDirect = make_PeerDoor (*this, getConfig ().PEER_IP,
|
||||
getConfig ().peerListeningPort, io_service_);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -334,11 +372,6 @@ OverlayImpl::onStart ()
|
||||
void
|
||||
OverlayImpl::onStop ()
|
||||
{
|
||||
if (m_doorDirect)
|
||||
m_doorDirect->stop();
|
||||
if (m_doorProxy)
|
||||
m_doorProxy->stop();
|
||||
|
||||
strand_.dispatch(std::bind(&OverlayImpl::close, this));
|
||||
}
|
||||
|
||||
@@ -470,6 +503,14 @@ OverlayImpl::remove (Child& child)
|
||||
checkStopped();
|
||||
}
|
||||
|
||||
// Caller must hold the mutex
|
||||
void
|
||||
OverlayImpl::checkStopped ()
|
||||
{
|
||||
if (isStopping() && areChildrenStopped () && list_.empty())
|
||||
stopped();
|
||||
}
|
||||
|
||||
void
|
||||
OverlayImpl::close()
|
||||
{
|
||||
@@ -487,19 +528,35 @@ OverlayImpl::close()
|
||||
}
|
||||
}
|
||||
|
||||
// Check for the stopped condition
|
||||
// Caller must hold the mutex
|
||||
void
|
||||
OverlayImpl::checkStopped ()
|
||||
OverlayImpl::addpeer (std::shared_ptr<PeerImp> const& peer)
|
||||
{
|
||||
if (isStopping() && areChildrenStopped () && list_.empty())
|
||||
stopped();
|
||||
std::lock_guard <decltype(mutex_)> lock (mutex_);
|
||||
{
|
||||
std::pair <PeersBySlot::iterator, bool> const result (
|
||||
m_peers.emplace (peer->slot(), peer));
|
||||
assert (result.second);
|
||||
(void) result.second;
|
||||
}
|
||||
list_.emplace(peer.get(), peer);
|
||||
|
||||
// This has to happen while holding the lock,
|
||||
// otherwise the socket might not be canceled during a stop.
|
||||
peer->start();
|
||||
}
|
||||
|
||||
void
|
||||
OverlayImpl::sendpeers()
|
||||
OverlayImpl::autoConnect()
|
||||
{
|
||||
auto const result = m_peerFinder->sendpeers();
|
||||
auto const result = m_peerFinder->autoconnect();
|
||||
for (auto addr : result)
|
||||
connect (addr);
|
||||
}
|
||||
|
||||
void
|
||||
OverlayImpl::sendEndpoints()
|
||||
{
|
||||
auto const result = m_peerFinder->buildEndpointsForPeers();
|
||||
for (auto const& e : result)
|
||||
{
|
||||
// VFALCO TODO Make sure this doesn't race with closing the peer
|
||||
@@ -515,13 +572,6 @@ OverlayImpl::sendpeers()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OverlayImpl::autoconnect()
|
||||
{
|
||||
auto const result = m_peerFinder->autoconnect();
|
||||
for (auto addr : result)
|
||||
connect (addr);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -540,7 +590,7 @@ setup_Overlay (BasicConfig const& config)
|
||||
setup.promote = Overlay::Promote::always;
|
||||
else
|
||||
setup.promote = Overlay::Promote::automatic;
|
||||
setup.context = make_ssl_context();
|
||||
setup.context = make_SSLContext();
|
||||
return setup;
|
||||
}
|
||||
|
||||
@@ -548,14 +598,14 @@ std::unique_ptr <Overlay>
|
||||
make_Overlay (
|
||||
Overlay::Setup const& setup,
|
||||
beast::Stoppable& parent,
|
||||
ServerHandler& serverHandler,
|
||||
Resource::Manager& resourceManager,
|
||||
SiteFiles::Manager& siteFiles,
|
||||
beast::File const& pathToDbFileOrDirectory,
|
||||
Resolver& resolver,
|
||||
boost::asio::io_service& io_service)
|
||||
{
|
||||
return std::make_unique <OverlayImpl> (setup, parent, resourceManager,
|
||||
siteFiles, pathToDbFileOrDirectory, resolver, io_service);
|
||||
return std::make_unique <OverlayImpl> (setup, parent, serverHandler,
|
||||
resourceManager, pathToDbFileOrDirectory, resolver, io_service);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,7 +21,8 @@
|
||||
#define RIPPLE_OVERLAY_OVERLAYIMPL_H_INCLUDED
|
||||
|
||||
#include <ripple/overlay/Overlay.h>
|
||||
|
||||
#include <ripple/server/Handoff.h>
|
||||
#include <ripple/server/ServerHandler.h>
|
||||
#include <ripple/common/Resolver.h>
|
||||
#include <ripple/common/seconds_clock.h>
|
||||
#include <ripple/common/UnorderedContainers.h>
|
||||
@@ -42,7 +43,6 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class PeerDoor;
|
||||
class PeerImp;
|
||||
|
||||
class OverlayImpl : public Overlay
|
||||
@@ -106,6 +106,8 @@ private:
|
||||
|
||||
Setup setup_;
|
||||
beast::Journal journal_;
|
||||
ServerHandler& serverHandler_;
|
||||
|
||||
Resource::Manager& m_resourceManager;
|
||||
|
||||
std::unique_ptr <PeerFinder::Manager> m_peerFinder;
|
||||
@@ -119,12 +121,6 @@ private:
|
||||
/** Tracks peers by their session ID */
|
||||
PeerByShortId m_shortIdMap;
|
||||
|
||||
/** The peer door for regular SSL connections */
|
||||
std::unique_ptr <PeerDoor> m_doorDirect;
|
||||
|
||||
/** The peer door for proxy connections */
|
||||
std::unique_ptr <PeerDoor> m_doorProxy;
|
||||
|
||||
/** The resolver we use for peer hostnames */
|
||||
Resolver& m_resolver;
|
||||
|
||||
@@ -135,9 +131,9 @@ private:
|
||||
|
||||
public:
|
||||
OverlayImpl (Setup const& setup, Stoppable& parent,
|
||||
Resource::Manager& resourceManager, SiteFiles::Manager& siteFiles,
|
||||
beast::File const& pathToDbFileOrDirectory, Resolver& resolver,
|
||||
boost::asio::io_service& io_service);
|
||||
ServerHandler& serverHandler, Resource::Manager& resourceManager,
|
||||
beast::File const& pathToDbFileOrDirectory,
|
||||
Resolver& resolver, boost::asio::io_service& io_service);
|
||||
|
||||
~OverlayImpl ();
|
||||
|
||||
@@ -147,19 +143,28 @@ public:
|
||||
return setup_;
|
||||
}
|
||||
|
||||
ServerHandler&
|
||||
serverHandler()
|
||||
{
|
||||
return serverHandler_;
|
||||
}
|
||||
|
||||
void
|
||||
onLegacyPeerHello (std::unique_ptr<beast::asio::ssl_bundle>&& ssl_bundle,
|
||||
boost::asio::const_buffer buffer,
|
||||
boost::asio::ip::tcp::endpoint remote_address) override;
|
||||
|
||||
Handoff
|
||||
onHandoff (std::unique_ptr <beast::asio::ssl_bundle>&& bundle,
|
||||
beast::http::message&& request,
|
||||
boost::asio::ip::tcp::endpoint remote_address) override;
|
||||
|
||||
PeerSequence
|
||||
getActivePeers() override;
|
||||
|
||||
Peer::ptr
|
||||
findPeerByShortID (Peer::ShortId const& id) override;
|
||||
|
||||
/** Process an incoming connection using the Peer protocol.
|
||||
The caller transfers ownership of the socket via rvalue move.
|
||||
@param socket A socket in the accepted state.
|
||||
*/
|
||||
void
|
||||
accept (socket_type&& socket);
|
||||
|
||||
Peer::ShortId
|
||||
next_id();
|
||||
|
||||
@@ -186,6 +191,13 @@ private:
|
||||
OverlayImpl (OverlayImpl const&) = delete;
|
||||
OverlayImpl& operator= (OverlayImpl const&) = delete;
|
||||
|
||||
bool
|
||||
isPeerUpgrade (beast::http::message const& request);
|
||||
|
||||
std::shared_ptr<HTTP::Writer>
|
||||
makeRedirectResponse (PeerFinder::Slot::ptr const& slot,
|
||||
beast::http::message const& request);
|
||||
|
||||
void
|
||||
connect (beast::IP::Endpoint const& remote_endpoint) override;
|
||||
|
||||
@@ -225,17 +237,20 @@ private:
|
||||
void
|
||||
remove (Child& child);
|
||||
|
||||
void
|
||||
close();
|
||||
|
||||
void
|
||||
checkStopped ();
|
||||
|
||||
void
|
||||
sendpeers();
|
||||
close();
|
||||
|
||||
void
|
||||
autoconnect();
|
||||
addpeer (std::shared_ptr<PeerImp> const& peer);
|
||||
|
||||
void
|
||||
autoConnect();
|
||||
|
||||
void
|
||||
sendEndpoints();
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
@@ -1,145 +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 <ripple/overlay/impl/OverlayImpl.h>
|
||||
#include <ripple/overlay/impl/PeerDoor.h>
|
||||
#include <beast/asio/placeholders.h>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class PeerDoorImp
|
||||
: public PeerDoor
|
||||
, public beast::LeakChecked <PeerDoorImp>
|
||||
{
|
||||
private:
|
||||
using socket_type = boost::asio::ip::tcp::socket;
|
||||
|
||||
OverlayImpl& m_overlay;
|
||||
beast::Journal m_journal;
|
||||
boost::asio::ip::tcp::acceptor m_acceptor;
|
||||
boost::asio::deadline_timer m_acceptDelay;
|
||||
socket_type m_socket;
|
||||
|
||||
public:
|
||||
PeerDoorImp (OverlayImpl& overlay,
|
||||
boost::asio::ip::tcp::endpoint const &ep,
|
||||
boost::asio::io_service& io_service)
|
||||
: m_overlay (overlay)
|
||||
, m_journal (deprecatedLogs().journal("PeerDoor"))
|
||||
, m_acceptor (io_service, ep)
|
||||
, m_acceptDelay (io_service)
|
||||
, m_socket (io_service)
|
||||
{
|
||||
m_journal.info <<
|
||||
"Listening on " << beast::IPAddressConversion::from_asio (
|
||||
m_acceptor.local_endpoint());
|
||||
async_accept();
|
||||
}
|
||||
|
||||
void
|
||||
stop()
|
||||
{
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
m_acceptDelay.cancel (ec);
|
||||
}
|
||||
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
m_acceptor.cancel (ec);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Initiating function for performing an asynchronous accept
|
||||
//
|
||||
void async_accept ()
|
||||
{
|
||||
m_acceptor.async_accept (m_socket,
|
||||
std::bind (&PeerDoorImp::handleAccept, this,
|
||||
beast::asio::placeholders::error));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Called when the deadline timer wait completes
|
||||
//
|
||||
void handleTimer (boost::system::error_code ec)
|
||||
{
|
||||
if (ec == boost::asio::error::operation_aborted)
|
||||
return;
|
||||
|
||||
async_accept ();
|
||||
}
|
||||
|
||||
// Called when the accept socket wait completes
|
||||
//
|
||||
void handleAccept (boost::system::error_code ec)
|
||||
{
|
||||
if (ec == boost::asio::error::operation_aborted)
|
||||
return;
|
||||
|
||||
bool delay = false;
|
||||
|
||||
if (! ec)
|
||||
{
|
||||
m_overlay.accept (std::move(m_socket));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ec == boost::system::errc::too_many_files_open)
|
||||
delay = true;
|
||||
|
||||
m_journal.info << "Error " << ec;
|
||||
}
|
||||
|
||||
m_socket.close(ec);
|
||||
|
||||
if (delay)
|
||||
{
|
||||
m_acceptDelay.expires_from_now (boost::posix_time::milliseconds (500));
|
||||
m_acceptDelay.async_wait (std::bind (&PeerDoorImp::handleTimer,
|
||||
this, beast::asio::placeholders::error));
|
||||
}
|
||||
else
|
||||
{
|
||||
async_accept ();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
std::unique_ptr<PeerDoor>
|
||||
make_PeerDoor (OverlayImpl& overlay, std::string const& ip, int port,
|
||||
boost::asio::io_service& io_service)
|
||||
{
|
||||
// You have to listen on something!
|
||||
bassert(port != 0);
|
||||
|
||||
boost::asio::ip::tcp::endpoint ep(
|
||||
boost::asio::ip::address ().from_string (
|
||||
ip.empty () ? "0.0.0.0" : ip), port);
|
||||
|
||||
return std::make_unique<PeerDoorImp>(overlay, ep, io_service);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,23 +17,25 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/server/ServerHandler.h>
|
||||
#include <ripple/basics/StringUtilities.h>
|
||||
#include <ripple/json/json_reader.h>
|
||||
#include <ripple/overlay/impl/PeerImp.h>
|
||||
#include <ripple/overlay/impl/Tuning.h>
|
||||
#include <beast/streams/debug_ostream.h>
|
||||
#include <functional>
|
||||
#include <beast/cxx14/memory.h> // <memory>
|
||||
#include <sstream>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
PeerImp::PeerImp (socket_type&& socket, beast::IP::Endpoint remoteAddress,
|
||||
PeerImp::PeerImp (std::unique_ptr<beast::asio::ssl_bundle>&& ssl_bundle,
|
||||
beast::http::message&& request, beast::IP::Endpoint remoteAddress,
|
||||
OverlayImpl& overlay, Resource::Manager& resourceManager,
|
||||
PeerFinder::Manager& peerFinder, PeerFinder::Slot::ptr const& slot,
|
||||
std::shared_ptr<boost::asio::ssl::context> const& context)
|
||||
PeerFinder::Manager& peerFinder, PeerFinder::Slot::ptr const& slot)
|
||||
: Child (overlay)
|
||||
, journal_ (deprecatedLogs().journal("Peer"))
|
||||
, ssl_bundle_(std::make_unique<beast::asio::ssl_bundle>(
|
||||
context, std::move(socket)))
|
||||
, ssl_bundle_(std::move(ssl_bundle))
|
||||
, socket_ (ssl_bundle_->socket)
|
||||
, stream_ (ssl_bundle_->stream)
|
||||
, strand_ (socket_.get_io_service())
|
||||
@@ -81,6 +83,16 @@ PeerImp::~PeerImp ()
|
||||
void
|
||||
PeerImp::start()
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
timer_.expires_from_now (nodeVerifySeconds, ec);
|
||||
timer_.async_wait (strand_.wrap (std::bind (&PeerImp::handleVerifyTimer,
|
||||
shared_from_this (), beast::asio::placeholders::error)));
|
||||
if (ec)
|
||||
{
|
||||
journal_.error << "Failed to set verify timer.";
|
||||
return detach ("start");
|
||||
}
|
||||
|
||||
if (m_inbound)
|
||||
do_accept();
|
||||
else
|
||||
@@ -298,20 +310,9 @@ void PeerImp::do_connect ()
|
||||
journal_.info << "Connecting to " << remote_address_;
|
||||
|
||||
usage_ = resourceManager_.newOutboundEndpoint (remote_address_);
|
||||
|
||||
if (usage_.disconnect ())
|
||||
return detach ("do_connect");
|
||||
|
||||
boost::system::error_code ec;
|
||||
timer_.expires_from_now (nodeVerifySeconds, ec);
|
||||
timer_.async_wait (strand_.wrap (std::bind (&PeerImp::handleVerifyTimer,
|
||||
shared_from_this (), beast::asio::placeholders::error)));
|
||||
if (ec)
|
||||
{
|
||||
journal_.error << "Failed to set verify timer.";
|
||||
return detach ("do_connect");
|
||||
}
|
||||
|
||||
stream_.next_layer().async_connect (
|
||||
beast::IPAddressConversion::to_asio_endpoint (remote_address_),
|
||||
strand_.wrap (std::bind (&PeerImp::on_connect,
|
||||
@@ -434,6 +435,70 @@ PeerImp::on_write_http_request (error_code ec, std::size_t bytes_transferred)
|
||||
beast::asio::placeholders::bytes_transferred)));
|
||||
}
|
||||
|
||||
template <class = void>
|
||||
boost::asio::ip::tcp::endpoint
|
||||
parse_endpoint (std::string const& s, boost::system::error_code& ec)
|
||||
{
|
||||
beast::IP::Endpoint bep;
|
||||
std::istringstream is(s);
|
||||
is >> bep;
|
||||
if (is.fail())
|
||||
{
|
||||
ec = boost::system::errc::make_error_code(
|
||||
boost::system::errc::invalid_argument);
|
||||
return boost::asio::ip::tcp::endpoint{};
|
||||
}
|
||||
|
||||
return beast::IPAddressConversion::to_asio_endpoint(bep);
|
||||
}
|
||||
|
||||
template <class Streambuf>
|
||||
void
|
||||
PeerImp::processResponse (beast::http::message const& m,
|
||||
Streambuf const& body)
|
||||
{
|
||||
if (http_message_->status() == 503)
|
||||
{
|
||||
Json::Value json;
|
||||
Json::Reader r;
|
||||
auto const success = r.parse(to_string(body), json);
|
||||
if (success)
|
||||
{
|
||||
if (json.isObject() && json.isMember("peer-ips"))
|
||||
{
|
||||
Json::Value const& ips = json["peer-ips"];
|
||||
if (ips.isArray())
|
||||
{
|
||||
std::vector<boost::asio::ip::tcp::endpoint> eps;
|
||||
eps.reserve(ips.size());
|
||||
for (auto const& v : ips)
|
||||
{
|
||||
if (v.isString())
|
||||
{
|
||||
error_code ec;
|
||||
auto const ep = parse_endpoint(v.asString(), ec);
|
||||
if (!ec)
|
||||
eps.push_back(ep);
|
||||
}
|
||||
}
|
||||
peerFinder_.onRedirects(beast::IPAddressConversion::
|
||||
to_asio_endpoint(remote_address_), eps);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (http_message_->status() != 200)
|
||||
{
|
||||
if (journal_.info) journal_.info <<
|
||||
"HTTP Response: " << m.status() << " " << m.reason();
|
||||
detach("processResponse");
|
||||
return;
|
||||
}
|
||||
|
||||
do_protocol_start();
|
||||
}
|
||||
|
||||
// Called repeatedly with the http response data
|
||||
void
|
||||
PeerImp::on_read_http_response (error_code ec, std::size_t bytes_transferred)
|
||||
@@ -452,22 +517,7 @@ PeerImp::on_read_http_response (error_code ec, std::size_t bytes_transferred)
|
||||
read_buffer_.consume (bytes_consumed);
|
||||
if (http_parser_->complete())
|
||||
{
|
||||
//
|
||||
// TODO Apply response to connection state, then:
|
||||
// - Go into protocol loop, or
|
||||
// - Submit a new request (call on_write_http_request), or
|
||||
// - Close the connection.
|
||||
//
|
||||
if (http_message_->status() != 200)
|
||||
{
|
||||
journal_.info <<
|
||||
"HTTP Response: " << http_message_->reason() <<
|
||||
"(" << http_message_->status() << ")";
|
||||
detach("on_read_http_response");
|
||||
return;
|
||||
}
|
||||
do_protocol_start ();
|
||||
return;
|
||||
return processResponse(*http_message_, http_body_);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -512,6 +562,11 @@ void PeerImp::do_accept ()
|
||||
return;
|
||||
}
|
||||
|
||||
// VFALCO Hack to receive a legacy protocol connection
|
||||
// from the HTTP server
|
||||
if (read_buffer_.size() > 0)
|
||||
return do_protocol_start();
|
||||
|
||||
stream_.set_verify_mode (boost::asio::ssl::verify_none);
|
||||
stream_.async_handshake (boost::asio::ssl::stream_base::server,
|
||||
strand_.wrap (std::bind (&PeerImp::on_accept_ssl,
|
||||
@@ -2267,7 +2322,6 @@ PeerImp::sendHello ()
|
||||
secureCookie_, vchSig);
|
||||
|
||||
protocol::TMHello h;
|
||||
|
||||
h.set_protoversion (to_packed (BuildInfo::getCurrentProtocol()));
|
||||
h.set_protoversionmin (to_packed (BuildInfo::getMinimumProtocol()));
|
||||
h.set_fullversion (BuildInfo::getFullVersionString ());
|
||||
@@ -2275,7 +2329,8 @@ PeerImp::sendHello ()
|
||||
h.set_nodepublic (getApp().getLocalCredentials ().getNodePublic (
|
||||
).humanNodePublic ());
|
||||
h.set_nodeproof (&vchSig[0], vchSig.size ());
|
||||
h.set_ipv4port (getConfig ().peerListeningPort);
|
||||
// DEPRECATED
|
||||
h.set_ipv4port (overlay_.serverHandler().setup().overlay.port);
|
||||
h.set_testnet (false);
|
||||
|
||||
// We always advertise ourselves as private in the HELLO message. This
|
||||
|
||||
@@ -178,18 +178,24 @@ private:
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
/** Create an incoming peer from the specified socket */
|
||||
PeerImp (socket_type&& socket, beast::IP::Endpoint remoteAddress,
|
||||
OverlayImpl& overlay, Resource::Manager& resourceManager,
|
||||
PeerFinder::Manager& peerFinder, PeerFinder::Slot::ptr const& slot,
|
||||
std::shared_ptr<boost::asio::ssl::context> const& context);
|
||||
PeerImp (PeerImp const&) = delete;
|
||||
PeerImp& operator= (PeerImp const&) = delete;
|
||||
|
||||
/** Create an outgoing peer
|
||||
@note Construction of outbound peers is a two step process: a second
|
||||
call is needed (to connect or accept) but we cannot make it from
|
||||
inside the constructor because you cannot call shared_from_this
|
||||
from inside constructors.
|
||||
*/
|
||||
/** Create an incoming legacy peer from an established ssl connection. */
|
||||
template <class ConstBufferSequence>
|
||||
PeerImp (std::unique_ptr<beast::asio::ssl_bundle>&& ssl_bundle,
|
||||
ConstBufferSequence const& buffer, beast::IP::Endpoint remoteAddress,
|
||||
OverlayImpl& overlay, Resource::Manager& resourceManager,
|
||||
PeerFinder::Manager& peerFinder,
|
||||
PeerFinder::Slot::ptr const& slot);
|
||||
|
||||
/** Create an active incoming peer from an established ssl connection. */
|
||||
PeerImp (std::unique_ptr<beast::asio::ssl_bundle>&& ssl_bundle,
|
||||
beast::http::message&& request, beast::IP::Endpoint remoteAddress,
|
||||
OverlayImpl& overlay, Resource::Manager& resourceManager,
|
||||
PeerFinder::Manager& peerFinder, PeerFinder::Slot::ptr const& slot);
|
||||
|
||||
/** Create an outgoing peer. */
|
||||
PeerImp (beast::IP::Endpoint remoteAddress, boost::asio::io_service& io_service,
|
||||
OverlayImpl& overlay, Resource::Manager& resourceManager,
|
||||
PeerFinder::Manager& peerFinder, PeerFinder::Slot::ptr const& slot,
|
||||
@@ -198,10 +204,13 @@ public:
|
||||
virtual
|
||||
~PeerImp ();
|
||||
|
||||
PeerImp (PeerImp const&) = delete;
|
||||
PeerImp& operator= (PeerImp const&) = delete;
|
||||
PeerFinder::Slot::ptr const&
|
||||
slot()
|
||||
{
|
||||
return slot_;
|
||||
}
|
||||
|
||||
// Begin asynchronous initiation function calls
|
||||
// Work-around for calling shared_from_this in constructors
|
||||
void
|
||||
start();
|
||||
|
||||
@@ -296,6 +305,10 @@ private:
|
||||
void
|
||||
on_write_http_request (error_code ec, std::size_t bytes_transferred);
|
||||
|
||||
template <class Streambuf>
|
||||
void
|
||||
processResponse (beast::http::message const& m, Streambuf const& body);
|
||||
|
||||
void
|
||||
on_read_http_response (error_code ec, std::size_t bytes_transferred);
|
||||
|
||||
@@ -506,6 +519,32 @@ private:
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class ConstBufferSequence>
|
||||
PeerImp::PeerImp (std::unique_ptr<beast::asio::ssl_bundle>&& ssl_bundle,
|
||||
ConstBufferSequence const& buffer, beast::IP::Endpoint remoteAddress,
|
||||
OverlayImpl& overlay, Resource::Manager& resourceManager,
|
||||
PeerFinder::Manager& peerFinder,
|
||||
PeerFinder::Slot::ptr const& slot)
|
||||
: Child (overlay)
|
||||
, journal_ (deprecatedLogs().journal("Peer"))
|
||||
, ssl_bundle_(std::move(ssl_bundle))
|
||||
, socket_ (ssl_bundle_->socket)
|
||||
, stream_ (ssl_bundle_->stream)
|
||||
, strand_ (socket_.get_io_service())
|
||||
, timer_ (socket_.get_io_service())
|
||||
, remote_address_ (remoteAddress)
|
||||
, resourceManager_ (resourceManager)
|
||||
, peerFinder_ (peerFinder)
|
||||
, overlay_ (overlay)
|
||||
, m_inbound (true)
|
||||
, state_ (stateConnected)
|
||||
, slot_ (slot)
|
||||
, message_stream_(*this)
|
||||
{
|
||||
read_buffer_.commit(boost::asio::buffer_copy(read_buffer_.prepare(
|
||||
boost::asio::buffer_size(buffer)), buffer));
|
||||
}
|
||||
|
||||
template <class FwdIt, class>
|
||||
void
|
||||
PeerImp::send_endpoints (FwdIt first, FwdIt last)
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
#ifndef RIPPLE_OVERLAY_MAKE_OVERLAY_H_INCLUDED
|
||||
#define RIPPLE_OVERLAY_MAKE_OVERLAY_H_INCLUDED
|
||||
|
||||
#include <ripple/server/ServerHandler.h>
|
||||
#include <ripple/overlay/Overlay.h>
|
||||
#include <ripple/resource/api/Manager.h>
|
||||
#include <ripple/sitefiles/Sitefiles.h>
|
||||
#include <ripple/common/Resolver.h>
|
||||
#include <beast/threads/Stoppable.h>
|
||||
#include <beast/module/core/files/File.h>
|
||||
@@ -31,9 +31,6 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
// VFALCO This is separated so that users of the Overlay interface do not need
|
||||
// to know about creation details such as asio or ssl.
|
||||
|
||||
Overlay::Setup
|
||||
setup_Overlay (BasicConfig const& config);
|
||||
|
||||
@@ -42,8 +39,8 @@ std::unique_ptr <Overlay>
|
||||
make_Overlay (
|
||||
Overlay::Setup const& setup,
|
||||
beast::Stoppable& parent,
|
||||
ServerHandler& serverHandler,
|
||||
Resource::Manager& resourceManager,
|
||||
SiteFiles::Manager& siteFiles,
|
||||
beast::File const& pathToDbFileOrDirectory,
|
||||
Resolver& resolver,
|
||||
boost::asio::io_service& io_service);
|
||||
|
||||
@@ -225,7 +225,7 @@ public:
|
||||
|
||||
virtual
|
||||
std::vector<std::pair<Slot::ptr, std::vector<Endpoint>>>
|
||||
sendpeers() = 0;
|
||||
buildEndpointsForPeers() = 0;
|
||||
|
||||
/** Perform periodic activity.
|
||||
This should be called once per second.
|
||||
|
||||
@@ -589,7 +589,7 @@ public:
|
||||
}
|
||||
|
||||
std::vector<std::pair<Slot::ptr, std::vector<Endpoint>>>
|
||||
sendpeers()
|
||||
buildEndpointsForPeers()
|
||||
{
|
||||
std::vector<std::pair<Slot::ptr, std::vector<Endpoint>>> result;
|
||||
|
||||
|
||||
@@ -198,9 +198,9 @@ public:
|
||||
}
|
||||
|
||||
std::vector<std::pair<Slot::ptr, std::vector<Endpoint>>>
|
||||
sendpeers() override
|
||||
buildEndpointsForPeers() override
|
||||
{
|
||||
return m_logic.sendpeers();
|
||||
return m_logic.buildEndpointsForPeers();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#ifndef RIPPLE_APP_RPC_HANDLER
|
||||
#define RIPPLE_APP_RPC_HANDLER
|
||||
|
||||
#include <ripple/app/main/ServerHandler.h>
|
||||
#include <ripple/server/Role.h>
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/net/InfoSub.h>
|
||||
|
||||
@@ -36,20 +36,20 @@ public:
|
||||
|
||||
Json::Value doCommand (
|
||||
Json::Value const& request,
|
||||
Config::Role role,
|
||||
Role role,
|
||||
Resource::Charge& loadType);
|
||||
|
||||
Json::Value doRpcCommand (
|
||||
std::string const& command,
|
||||
Json::Value const& params,
|
||||
Config::Role role,
|
||||
Role role,
|
||||
Resource::Charge& loadType);
|
||||
|
||||
private:
|
||||
NetworkOPs& netOps_;
|
||||
InfoSub::pointer infoSub_;
|
||||
|
||||
Config::Role role_ = Config::FORBID;
|
||||
Role role_ = Role::FORBID;
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
@@ -103,7 +103,7 @@ Json::Value doAccountTx (RPC::Context& context)
|
||||
{
|
||||
auto txns = context.netOps_.getTxsAccountB (
|
||||
raAccount, uLedgerMin, uLedgerMax, bForward, resumeToken, limit,
|
||||
context.role_ == Config::ADMIN);
|
||||
context.role_ == Role::ADMIN);
|
||||
|
||||
for (auto& it: txns)
|
||||
{
|
||||
@@ -124,7 +124,7 @@ Json::Value doAccountTx (RPC::Context& context)
|
||||
{
|
||||
auto txns = context.netOps_.getTxsAccount (
|
||||
raAccount, uLedgerMin, uLedgerMax, bForward, resumeToken, limit,
|
||||
context.role_ == Config::ADMIN);
|
||||
context.role_ == Role::ADMIN);
|
||||
|
||||
for (auto& it: txns)
|
||||
{
|
||||
|
||||
@@ -126,7 +126,7 @@ Json::Value doAccountTxOld (RPC::Context& context)
|
||||
{
|
||||
auto txns = context.netOps_.getAccountTxsB (
|
||||
raAccount, uLedgerMin, uLedgerMax, bDescending, offset, limit,
|
||||
context.role_ == Config::ADMIN);
|
||||
context.role_ == Role::ADMIN);
|
||||
|
||||
for (auto it = txns.begin (), end = txns.end (); it != end; ++it)
|
||||
{
|
||||
@@ -148,7 +148,7 @@ Json::Value doAccountTxOld (RPC::Context& context)
|
||||
{
|
||||
auto txns = context.netOps_.getAccountTxs (
|
||||
raAccount, uLedgerMin, uLedgerMax, bDescending, offset, limit,
|
||||
context.role_ == Config::ADMIN);
|
||||
context.role_ == Role::ADMIN);
|
||||
|
||||
for (auto it = txns.begin (), end = txns.end (); it != end; ++it)
|
||||
{
|
||||
|
||||
@@ -46,7 +46,7 @@ Json::Value doConnect (RPC::Context& context)
|
||||
if(context.params_.isMember ("port"))
|
||||
iPort = context.params_["port"].asInt ();
|
||||
else
|
||||
iPort = SYSTEM_PEER_PORT;
|
||||
iPort = 6561;
|
||||
|
||||
auto ip = beast::IP::Endpoint::from_string(
|
||||
context.params_["ip"].asString ());
|
||||
|
||||
@@ -67,7 +67,7 @@ Json::Value doLedger (RPC::Context& context)
|
||||
if (bFull || bAccounts)
|
||||
{
|
||||
|
||||
if (context.role_ != Config::ADMIN)
|
||||
if (context.role_ != Role::ADMIN)
|
||||
{
|
||||
// Until some sane way to get full ledgers has been implemented,
|
||||
// disallow retrieving all state nodes.
|
||||
@@ -75,7 +75,7 @@ Json::Value doLedger (RPC::Context& context)
|
||||
}
|
||||
|
||||
if (getApp().getFeeTrack().isLoadedLocal() &&
|
||||
context.role_ != Config::ADMIN)
|
||||
context.role_ != Role::ADMIN)
|
||||
{
|
||||
WriteLog (lsDEBUG, Peer) << "Too busy to give full ledger";
|
||||
return rpcError(rpcTOO_BUSY);
|
||||
|
||||
@@ -73,7 +73,7 @@ Json::Value doLedgerData (RPC::Context& context)
|
||||
limit = jLimit.asInt ();
|
||||
}
|
||||
|
||||
if ((limit < 0) || ((limit > maxLimit) && (context.role_ != Config::ADMIN)))
|
||||
if ((limit < 0) || ((limit > maxLimit) && (context.role_ != Role::ADMIN)))
|
||||
limit = maxLimit;
|
||||
|
||||
Json::Value jvReply = Json::objectValue;
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace ripple {
|
||||
// This interface is deprecated.
|
||||
Json::Value doRipplePathFind (RPC::Context& context)
|
||||
{
|
||||
RPC::LegacyPathFind lpf (context.role_ == Config::ADMIN);
|
||||
RPC::LegacyPathFind lpf (context.role_ == Role::ADMIN);
|
||||
if (!lpf.isOk ())
|
||||
return rpcError (rpcTOO_BUSY);
|
||||
|
||||
@@ -192,7 +192,7 @@ Json::Value doRipplePathFind (RPC::Context& context)
|
||||
&& context.params_["depth"].isIntegral())
|
||||
{
|
||||
int rLev = context.params_["search_depth"].asInt ();
|
||||
if ((rLev < level) || (context.role_ == Config::ADMIN))
|
||||
if ((rLev < level) || (context.role_ == Role::ADMIN))
|
||||
level = rLev;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ Json::Value doServerInfo (RPC::Context& context)
|
||||
Json::Value ret (Json::objectValue);
|
||||
|
||||
ret["info"] = context.netOps_.getServerInfo (
|
||||
true, context.role_ == Config::ADMIN);
|
||||
true, context.role_ == Role::ADMIN);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ Json::Value doServerState (RPC::Context& context)
|
||||
Json::Value ret (Json::objectValue);
|
||||
|
||||
ret["state"] = context.netOps_.getServerInfo (
|
||||
false, context.role_ == Config::ADMIN);
|
||||
false, context.role_ == Role::ADMIN);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ Json::Value doSubmit (RPC::Context& context)
|
||||
try
|
||||
{
|
||||
(void) context.netOps_.processTransaction (
|
||||
tpTrans, context.role_ == Config::ADMIN, true,
|
||||
tpTrans, context.role_ == Role::ADMIN, true,
|
||||
context.params_.isMember ("fail_hard")
|
||||
&& context.params_["fail_hard"].asBool ());
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ Json::Value doSubscribe (RPC::Context& context)
|
||||
|
||||
if (context.params_.isMember ("url"))
|
||||
{
|
||||
if (context.role_ != Config::ADMIN)
|
||||
if (context.role_ != Role::ADMIN)
|
||||
return rpcError (rpcNO_PERMISSION);
|
||||
|
||||
std::string strUrl = context.params_["url"].asString ();
|
||||
@@ -114,7 +114,7 @@ Json::Value doSubscribe (RPC::Context& context)
|
||||
if (streamName == "server")
|
||||
{
|
||||
context.netOps_.subServer (ispSub, jvResult,
|
||||
context.role_ == Config::ADMIN);
|
||||
context.role_ == Role::ADMIN);
|
||||
}
|
||||
else if (streamName == "ledger")
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@ Json::Value doTxHistory (RPC::Context& context)
|
||||
|
||||
unsigned int startIndex = context.params_["start"].asUInt ();
|
||||
|
||||
if ((startIndex > 10000) && (context.role_ != Config::ADMIN))
|
||||
if ((startIndex > 10000) && (context.role_ != Role::ADMIN))
|
||||
return rpcError (rpcNO_PERMISSION);
|
||||
|
||||
Json::Value obj;
|
||||
|
||||
@@ -37,7 +37,7 @@ Json::Value doUnsubscribe (RPC::Context& context)
|
||||
|
||||
if (context.params_.isMember ("url"))
|
||||
{
|
||||
if (context.role_ != Config::ADMIN)
|
||||
if (context.role_ != Role::ADMIN)
|
||||
return rpcError (rpcNO_PERMISSION);
|
||||
|
||||
std::string strUrl = context.params_["url"].asString ();
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace ripple {
|
||||
// secret: <string> // optional
|
||||
// }
|
||||
//
|
||||
// This command requires Config::ADMIN access because it makes no sense to ask
|
||||
// This command requires Role::ADMIN access because it makes no sense to ask
|
||||
// an untrusted server for this.
|
||||
Json::Value doValidationCreate (RPC::Context& context)
|
||||
{
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#define RIPPLE_RPC_CONTEXT
|
||||
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/server/ServerHandler.h>
|
||||
|
||||
namespace ripple {
|
||||
namespace RPC {
|
||||
@@ -33,7 +34,7 @@ struct Context
|
||||
Resource::Charge& loadType_;
|
||||
NetworkOPs& netOps_;
|
||||
InfoSub::pointer infoSub_;
|
||||
Config::Role role_;
|
||||
Role role_;
|
||||
};
|
||||
|
||||
} // RPC
|
||||
|
||||
@@ -42,66 +42,66 @@ class HandlerTable {
|
||||
|
||||
HandlerTable HANDLERS({
|
||||
// Request-response methods
|
||||
{ "account_info", &doAccountInfo, Config::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "account_currencies", &doAccountCurrencies, Config::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "account_lines", &doAccountLines, Config::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "account_offers", &doAccountOffers, Config::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "account_tx", &doAccountTxSwitch, Config::USER, NEEDS_NETWORK_CONNECTION },
|
||||
{ "blacklist", &doBlackList, Config::ADMIN, NO_CONDITION },
|
||||
{ "book_offers", &doBookOffers, Config::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "connect", &doConnect, Config::ADMIN, NO_CONDITION },
|
||||
{ "consensus_info", &doConsensusInfo, Config::ADMIN, NO_CONDITION },
|
||||
{ "get_counts", &doGetCounts, Config::ADMIN, NO_CONDITION },
|
||||
{ "internal", &doInternal, Config::ADMIN, NO_CONDITION },
|
||||
{ "feature", &doFeature, Config::ADMIN, NO_CONDITION },
|
||||
{ "fetch_info", &doFetchInfo, Config::ADMIN, NO_CONDITION },
|
||||
{ "ledger", &doLedger, Config::USER, NEEDS_NETWORK_CONNECTION },
|
||||
{ "ledger_accept", &doLedgerAccept, Config::ADMIN, NEEDS_CURRENT_LEDGER },
|
||||
{ "ledger_cleaner", &doLedgerCleaner, Config::ADMIN, NEEDS_NETWORK_CONNECTION },
|
||||
{ "ledger_closed", &doLedgerClosed, Config::USER, NEEDS_CLOSED_LEDGER },
|
||||
{ "ledger_current", &doLedgerCurrent, Config::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "ledger_data", &doLedgerData, Config::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "ledger_entry", &doLedgerEntry, Config::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "ledger_header", &doLedgerHeader, Config::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "ledger_request", &doLedgerRequest, Config::ADMIN, NO_CONDITION },
|
||||
{ "log_level", &doLogLevel, Config::ADMIN, NO_CONDITION },
|
||||
{ "logrotate", &doLogRotate, Config::ADMIN, NO_CONDITION },
|
||||
{ "owner_info", &doOwnerInfo, Config::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "peers", &doPeers, Config::ADMIN, NO_CONDITION },
|
||||
{ "path_find", &doPathFind, Config::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "ping", &doPing, Config::USER, NO_CONDITION },
|
||||
{ "print", &doPrint, Config::ADMIN, NO_CONDITION },
|
||||
// { "profile", &doProfile, Config::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "proof_create", &doProofCreate, Config::ADMIN, NO_CONDITION },
|
||||
{ "proof_solve", &doProofSolve, Config::ADMIN, NO_CONDITION },
|
||||
{ "proof_verify", &doProofVerify, Config::ADMIN, NO_CONDITION },
|
||||
{ "random", &doRandom, Config::USER, NO_CONDITION },
|
||||
{ "ripple_path_find", &doRipplePathFind, Config::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "sign", &doSign, Config::USER, NO_CONDITION },
|
||||
{ "submit", &doSubmit, Config::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "server_info", &doServerInfo, Config::USER, NO_CONDITION },
|
||||
{ "server_state", &doServerState, Config::USER, NO_CONDITION },
|
||||
{ "sms", &doSMS, Config::ADMIN, NO_CONDITION },
|
||||
{ "stop", &doStop, Config::ADMIN, NO_CONDITION },
|
||||
{ "transaction_entry", &doTransactionEntry, Config::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "tx", &doTx, Config::USER, NEEDS_NETWORK_CONNECTION },
|
||||
{ "tx_history", &doTxHistory, Config::USER, NO_CONDITION },
|
||||
{ "unl_add", &doUnlAdd, Config::ADMIN, NO_CONDITION },
|
||||
{ "unl_delete", &doUnlDelete, Config::ADMIN, NO_CONDITION },
|
||||
{ "unl_list", &doUnlList, Config::ADMIN, NO_CONDITION },
|
||||
{ "unl_load", &doUnlLoad, Config::ADMIN, NO_CONDITION },
|
||||
{ "unl_network", &doUnlNetwork, Config::ADMIN, NO_CONDITION },
|
||||
{ "unl_reset", &doUnlReset, Config::ADMIN, NO_CONDITION },
|
||||
{ "unl_score", &doUnlScore, Config::ADMIN, NO_CONDITION },
|
||||
{ "validation_create", &doValidationCreate, Config::ADMIN, NO_CONDITION },
|
||||
{ "validation_seed", &doValidationSeed, Config::ADMIN, NO_CONDITION },
|
||||
{ "wallet_accounts", &doWalletAccounts, Config::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "wallet_propose", &doWalletPropose, Config::ADMIN, NO_CONDITION },
|
||||
{ "wallet_seed", &doWalletSeed, Config::ADMIN, NO_CONDITION },
|
||||
{ "account_info", &doAccountInfo, Role::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "account_currencies", &doAccountCurrencies, Role::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "account_lines", &doAccountLines, Role::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "account_offers", &doAccountOffers, Role::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "account_tx", &doAccountTxSwitch, Role::USER, NEEDS_NETWORK_CONNECTION },
|
||||
{ "blacklist", &doBlackList, Role::ADMIN, NO_CONDITION },
|
||||
{ "book_offers", &doBookOffers, Role::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "connect", &doConnect, Role::ADMIN, NO_CONDITION },
|
||||
{ "consensus_info", &doConsensusInfo, Role::ADMIN, NO_CONDITION },
|
||||
{ "get_counts", &doGetCounts, Role::ADMIN, NO_CONDITION },
|
||||
{ "internal", &doInternal, Role::ADMIN, NO_CONDITION },
|
||||
{ "feature", &doFeature, Role::ADMIN, NO_CONDITION },
|
||||
{ "fetch_info", &doFetchInfo, Role::ADMIN, NO_CONDITION },
|
||||
{ "ledger", &doLedger, Role::USER, NEEDS_NETWORK_CONNECTION },
|
||||
{ "ledger_accept", &doLedgerAccept, Role::ADMIN, NEEDS_CURRENT_LEDGER },
|
||||
{ "ledger_cleaner", &doLedgerCleaner, Role::ADMIN, NEEDS_NETWORK_CONNECTION },
|
||||
{ "ledger_closed", &doLedgerClosed, Role::USER, NEEDS_CLOSED_LEDGER },
|
||||
{ "ledger_current", &doLedgerCurrent, Role::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "ledger_data", &doLedgerData, Role::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "ledger_entry", &doLedgerEntry, Role::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "ledger_header", &doLedgerHeader, Role::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "ledger_request", &doLedgerRequest, Role::ADMIN, NO_CONDITION },
|
||||
{ "log_level", &doLogLevel, Role::ADMIN, NO_CONDITION },
|
||||
{ "logrotate", &doLogRotate, Role::ADMIN, NO_CONDITION },
|
||||
{ "owner_info", &doOwnerInfo, Role::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "peers", &doPeers, Role::ADMIN, NO_CONDITION },
|
||||
{ "path_find", &doPathFind, Role::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "ping", &doPing, Role::USER, NO_CONDITION },
|
||||
{ "print", &doPrint, Role::ADMIN, NO_CONDITION },
|
||||
// { "profile", &doProfile, Role::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "proof_create", &doProofCreate, Role::ADMIN, NO_CONDITION },
|
||||
{ "proof_solve", &doProofSolve, Role::ADMIN, NO_CONDITION },
|
||||
{ "proof_verify", &doProofVerify, Role::ADMIN, NO_CONDITION },
|
||||
{ "random", &doRandom, Role::USER, NO_CONDITION },
|
||||
{ "ripple_path_find", &doRipplePathFind, Role::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "sign", &doSign, Role::USER, NO_CONDITION },
|
||||
{ "submit", &doSubmit, Role::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "server_info", &doServerInfo, Role::USER, NO_CONDITION },
|
||||
{ "server_state", &doServerState, Role::USER, NO_CONDITION },
|
||||
{ "sms", &doSMS, Role::ADMIN, NO_CONDITION },
|
||||
{ "stop", &doStop, Role::ADMIN, NO_CONDITION },
|
||||
{ "transaction_entry", &doTransactionEntry, Role::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "tx", &doTx, Role::USER, NEEDS_NETWORK_CONNECTION },
|
||||
{ "tx_history", &doTxHistory, Role::USER, NO_CONDITION },
|
||||
{ "unl_add", &doUnlAdd, Role::ADMIN, NO_CONDITION },
|
||||
{ "unl_delete", &doUnlDelete, Role::ADMIN, NO_CONDITION },
|
||||
{ "unl_list", &doUnlList, Role::ADMIN, NO_CONDITION },
|
||||
{ "unl_load", &doUnlLoad, Role::ADMIN, NO_CONDITION },
|
||||
{ "unl_network", &doUnlNetwork, Role::ADMIN, NO_CONDITION },
|
||||
{ "unl_reset", &doUnlReset, Role::ADMIN, NO_CONDITION },
|
||||
{ "unl_score", &doUnlScore, Role::ADMIN, NO_CONDITION },
|
||||
{ "validation_create", &doValidationCreate, Role::ADMIN, NO_CONDITION },
|
||||
{ "validation_seed", &doValidationSeed, Role::ADMIN, NO_CONDITION },
|
||||
{ "wallet_accounts", &doWalletAccounts, Role::USER, NEEDS_CURRENT_LEDGER },
|
||||
{ "wallet_propose", &doWalletPropose, Role::ADMIN, NO_CONDITION },
|
||||
{ "wallet_seed", &doWalletSeed, Role::ADMIN, NO_CONDITION },
|
||||
|
||||
// Evented methods
|
||||
{ "subscribe", &doSubscribe, Config::USER, NO_CONDITION },
|
||||
{ "unsubscribe", &doUnsubscribe, Config::USER, NO_CONDITION },
|
||||
{ "subscribe", &doSubscribe, Role::USER, NO_CONDITION },
|
||||
{ "unsubscribe", &doUnsubscribe, Role::USER, NO_CONDITION },
|
||||
});
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -40,7 +40,7 @@ struct Handler
|
||||
|
||||
const char* name_;
|
||||
Method method_;
|
||||
Config::Role role_;
|
||||
Role role_;
|
||||
RPC::Condition condition_;
|
||||
};
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ RPCHandler::RPCHandler (NetworkOPs& netOps, InfoSub::pointer infoSub)
|
||||
Json::Value RPCHandler::doRpcCommand (
|
||||
const std::string& strMethod,
|
||||
Json::Value const& jvParams,
|
||||
Config::Role role,
|
||||
Role role,
|
||||
Resource::Charge& loadType)
|
||||
{
|
||||
WriteLog (lsTRACE, RPCHandler)
|
||||
@@ -75,10 +75,10 @@ Json::Value RPCHandler::doRpcCommand (
|
||||
|
||||
Json::Value RPCHandler::doCommand (
|
||||
const Json::Value& params,
|
||||
Config::Role role,
|
||||
Role role,
|
||||
Resource::Charge& loadType)
|
||||
{
|
||||
if (role != Config::ADMIN)
|
||||
if (role != Role::ADMIN)
|
||||
{
|
||||
// VFALCO NOTE Should we also add up the jtRPC jobs?
|
||||
//
|
||||
@@ -105,7 +105,7 @@ Json::Value RPCHandler::doCommand (
|
||||
if (!handler)
|
||||
return rpcError (rpcUNKNOWN_COMMAND);
|
||||
|
||||
if (handler->role_ == Config::ADMIN && role_ != Config::ADMIN)
|
||||
if (handler->role_ == Role::ADMIN && role_ != Role::ADMIN)
|
||||
return rpcError (rpcNO_PERMISSION);
|
||||
|
||||
if ((handler->condition_ & RPC::NEEDS_NETWORK_CONNECTION) &&
|
||||
|
||||
@@ -25,7 +25,6 @@ namespace ripple {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace RPC {
|
||||
|
||||
/** Fill in the fee on behalf of the client.
|
||||
@@ -98,7 +97,7 @@ static Json::Value signPayment(
|
||||
Json::Value& tx_json,
|
||||
RippleAddress const& raSrcAddressID,
|
||||
Ledger::pointer lSnapshot,
|
||||
int role)
|
||||
Role role)
|
||||
{
|
||||
RippleAddress dstAccountID;
|
||||
|
||||
@@ -148,7 +147,7 @@ static Json::Value signPayment(
|
||||
"Cannot build XRP to XRP paths.");
|
||||
|
||||
{
|
||||
LegacyPathFind lpf (role == Config::ADMIN);
|
||||
LegacyPathFind lpf (role == Role::ADMIN);
|
||||
if (!lpf.isOk ())
|
||||
return rpcError (rpcTOO_BUSY);
|
||||
|
||||
@@ -190,12 +189,13 @@ static Json::Value signPayment(
|
||||
// as needed, and then there should be a separate function to
|
||||
// submit the tranaction
|
||||
//
|
||||
Json::Value transactionSign (
|
||||
Json::Value
|
||||
transactionSign (
|
||||
Json::Value params,
|
||||
bool bSubmit,
|
||||
bool bFailHard,
|
||||
NetworkOPs& netOps,
|
||||
int role)
|
||||
Role role)
|
||||
{
|
||||
Json::Value jvResult;
|
||||
|
||||
@@ -245,7 +245,7 @@ Json::Value transactionSign (
|
||||
return rpcError (rpcNO_CURRENT);
|
||||
|
||||
// Check for load
|
||||
if (getApp().getFeeTrack().isLoadedCluster() && (role != Config::ADMIN))
|
||||
if (getApp().getFeeTrack().isLoadedCluster() && (role != Role::ADMIN))
|
||||
return rpcError(rpcTOO_BUSY);
|
||||
|
||||
Ledger::pointer lSnapshot = netOps.getCurrentLedger ();
|
||||
@@ -265,7 +265,7 @@ Json::Value transactionSign (
|
||||
}
|
||||
}
|
||||
|
||||
autofill_fee (params, lSnapshot, jvResult, role == Config::ADMIN);
|
||||
autofill_fee (params, lSnapshot, jvResult, role == Role::ADMIN);
|
||||
if (RPC::contains_error (jvResult))
|
||||
return jvResult;
|
||||
|
||||
@@ -383,7 +383,7 @@ Json::Value transactionSign (
|
||||
{
|
||||
// FIXME: For performance, should use asynch interface
|
||||
tpTrans = netOps.submitTransactionSync (tpTrans,
|
||||
role == Config::ADMIN, true, bFailHard, bSubmit);
|
||||
role == Role::ADMIN, true, bFailHard, bSubmit);
|
||||
|
||||
if (!tpTrans)
|
||||
{
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#ifndef RIPPLE_RPC_TRANSACTIONSIGN_H_INCLUDED
|
||||
#define RIPPLE_RPC_TRANSACTIONSIGN_H_INCLUDED
|
||||
|
||||
#include <ripple/server/ServerHandler.h>
|
||||
|
||||
namespace ripple {
|
||||
namespace RPC {
|
||||
|
||||
@@ -28,7 +30,7 @@ Json::Value transactionSign (
|
||||
bool bSubmit,
|
||||
bool bFailHard,
|
||||
NetworkOPs& netOps,
|
||||
int role);
|
||||
Role role);
|
||||
|
||||
} // RPC
|
||||
} // ripple
|
||||
|
||||
109
src/ripple/server/Handler.h
Normal file
109
src/ripple/server/Handler.h
Normal file
@@ -0,0 +1,109 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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 <beast/asio/ssl_bundle.h>
|
||||
#include <beast/http/message.h>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <memory>
|
||||
|
||||
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. */
|
||||
// DEPRECATED
|
||||
virtual void onAccept (Session& session) = 0;
|
||||
|
||||
/** 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 when a legacy peer protocol handshake is detected.
|
||||
If the called function does not take ownership, then the
|
||||
connection is closed.
|
||||
@param buffer The unconsumed bytes in the protocol handshake
|
||||
@param ssl_bundle The active connection.
|
||||
*/
|
||||
virtual
|
||||
void
|
||||
onLegacyPeerHello (std::unique_ptr<beast::asio::ssl_bundle>&& ssl_bundle,
|
||||
boost::asio::const_buffer buffer,
|
||||
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,
|
||||
beast::http::message&& request,
|
||||
boost::asio::ip::tcp::endpoint remote_address) = 0;
|
||||
|
||||
virtual
|
||||
Handoff
|
||||
onHandoff (Session& session, boost::asio::ip::tcp::socket&& socket,
|
||||
beast::http::message&& request,
|
||||
boost::asio::ip::tcp::endpoint remote_address) = 0;
|
||||
/** @} */
|
||||
|
||||
/** Called when we have a complete HTTP request. */
|
||||
// VFALCO TODO Pass the beast::http::message as a parameter
|
||||
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;
|
||||
};
|
||||
|
||||
} // HTTP
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
@@ -17,19 +17,33 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_HTTP_H_INCLUDED
|
||||
#define RIPPLE_HTTP_H_INCLUDED
|
||||
#ifndef RIPPLE_SERVER_HANDOFF_H_INCLUDED
|
||||
#define RIPPLE_SERVER_HANDOFF_H_INCLUDED
|
||||
|
||||
// VFALCO This entire file is deprecated now, I'm working on a replacement
|
||||
#include <ripple/server/Writer.h>
|
||||
#include <memory>
|
||||
|
||||
// VFALCO NOTE this sucks that we have to include asio in the header
|
||||
// just for HTTPMessage!
|
||||
#include <beast/module/asio/asio.h>
|
||||
namespace ripple {
|
||||
|
||||
#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>
|
||||
/** Used to indicate the result of a server connection handoff. */
|
||||
struct Handoff
|
||||
{
|
||||
// When `true`, the Session will close the socket. The
|
||||
// Handler may optionally take socket ownership using std::move
|
||||
bool moved = false;
|
||||
|
||||
// If response is set, this determines the keep alive
|
||||
bool keep_alive = false;
|
||||
|
||||
// When set, this will be sent back
|
||||
std::shared_ptr<HTTP::Writer> response;
|
||||
|
||||
bool handled() const
|
||||
{
|
||||
return moved || response;
|
||||
}
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
165
src/ripple/server/JsonWriter.h
Normal file
165
src/ripple/server/JsonWriter.h
Normal file
@@ -0,0 +1,165 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_JSONWRITER_H_INCLUDED
|
||||
#define RIPPLE_SERVER_JSONWRITER_H_INCLUDED
|
||||
|
||||
#include <ripple/server/Writer.h>
|
||||
#include <ripple/json/json_value.h>
|
||||
#include <beast/asio/streambuf.h>
|
||||
#include <beast/http/message.h>
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
|
||||
namespace ripple {
|
||||
namespace HTTP {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/** Writer that sends to Streambufs sequentially. */
|
||||
template <class Streambuf>
|
||||
class message_writer : public Writer
|
||||
{
|
||||
private:
|
||||
Streambuf prebody_;
|
||||
Streambuf body_;
|
||||
std::size_t hint_ = 0;
|
||||
std::vector<boost::asio::const_buffer> data_;
|
||||
|
||||
public:
|
||||
message_writer (Streambuf&& prebody, Streambuf&& body);
|
||||
|
||||
bool
|
||||
complete() override;
|
||||
|
||||
bool
|
||||
prepare (std::size_t n, std::function<void(void)>) override;
|
||||
|
||||
std::vector<boost::asio::const_buffer>
|
||||
data() override;
|
||||
|
||||
void
|
||||
consume (std::size_t n) override;
|
||||
|
||||
private:
|
||||
std::vector<boost::asio::const_buffer>
|
||||
data(Streambuf& buf);
|
||||
};
|
||||
|
||||
template <class Streambuf>
|
||||
message_writer<Streambuf>::message_writer (
|
||||
Streambuf&& prebody, Streambuf&& body)
|
||||
: prebody_(std::move(prebody))
|
||||
, body_(std::move(body))
|
||||
{
|
||||
}
|
||||
|
||||
template <class Streambuf>
|
||||
bool
|
||||
message_writer<Streambuf>::complete()
|
||||
{
|
||||
return prebody_.size() == 0 && body_.size() == 0;
|
||||
}
|
||||
|
||||
template <class Streambuf>
|
||||
bool
|
||||
message_writer<Streambuf>::prepare (
|
||||
std::size_t n, std::function<void(void)>)
|
||||
{
|
||||
hint_ = n;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class Streambuf>
|
||||
std::vector<boost::asio::const_buffer>
|
||||
message_writer<Streambuf>::data()
|
||||
{
|
||||
return (prebody_.size() > 0) ?
|
||||
data(prebody_) : data(body_);
|
||||
}
|
||||
|
||||
template <class Streambuf>
|
||||
void
|
||||
message_writer<Streambuf>::consume (std::size_t n)
|
||||
{
|
||||
if (prebody_.size() > 0)
|
||||
return prebody_.consume(n);
|
||||
body_.consume(n);
|
||||
}
|
||||
|
||||
template <class Streambuf>
|
||||
std::vector<boost::asio::const_buffer>
|
||||
message_writer<Streambuf>::data(Streambuf& buf)
|
||||
{
|
||||
data_.resize(0);
|
||||
for (auto iter = buf.data().begin();
|
||||
hint_ > 0 && iter != buf.data().end(); ++iter)
|
||||
{
|
||||
auto const n = std::min(hint_,
|
||||
boost::asio::buffer_size(*iter));
|
||||
data_.emplace_back(boost::asio::buffer_cast<
|
||||
void const*>(*iter), n);
|
||||
hint_ -= n;
|
||||
}
|
||||
return data_;
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
using streambufs_writer = detail::message_writer<beast::asio::streambuf>;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Write a Json::Value to a Streambuf. */
|
||||
template <class Streambuf>
|
||||
void
|
||||
write(Streambuf& buf, Json::Value const& json)
|
||||
{
|
||||
stream(json,
|
||||
[&buf](void const* data, std::size_t n)
|
||||
{
|
||||
buf.commit(boost::asio::buffer_copy(
|
||||
buf.prepare(n), boost::asio::buffer(data, n)));
|
||||
});
|
||||
}
|
||||
|
||||
/** Returns a Writer that streams the provided HTTP message and Json body.
|
||||
The message is modified to include the correct headers.
|
||||
*/
|
||||
template <class = void>
|
||||
std::shared_ptr<Writer>
|
||||
make_JsonWriter (beast::http::message& m, Json::Value const& json)
|
||||
{
|
||||
beast::asio::streambuf prebody;
|
||||
beast::asio::streambuf body;
|
||||
write(body, json);
|
||||
// VFALCO TODO Better way to set a field
|
||||
m.headers.erase ("Content-Length");
|
||||
m.headers.append("Content-Length", std::to_string(body.size()));
|
||||
m.headers.erase ("Content-Type");
|
||||
m.headers.append("Content-Type", "application/json");
|
||||
write(prebody, m);
|
||||
return std::make_shared<streambufs_writer>(
|
||||
std::move(prebody), std::move(body));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
86
src/ripple/server/Port.h
Normal file
86
src/ripple/server/Port.h
Normal file
@@ -0,0 +1,86 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_PORT_H_INCLUDED
|
||||
#define RIPPLE_SERVER_PORT_H_INCLUDED
|
||||
|
||||
#include <beast/utility/ci_char_traits.h>
|
||||
#include <boost/asio/ip/address.hpp>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
namespace boost { namespace asio { namespace ssl { class context; } } }
|
||||
|
||||
namespace ripple {
|
||||
namespace HTTP {
|
||||
|
||||
/** Configuration information for a Server listening port. */
|
||||
struct Port
|
||||
{
|
||||
std::string name;
|
||||
boost::asio::ip::address ip;
|
||||
std::uint16_t port = 0;
|
||||
std::set<std::string, beast::ci_less> protocol;
|
||||
bool allow_admin = false;
|
||||
std::string user;
|
||||
std::string password;
|
||||
std::string admin_user;
|
||||
std::string admin_password;
|
||||
std::string ssl_key;
|
||||
std::string ssl_cert;
|
||||
std::string ssl_chain;
|
||||
std::shared_ptr<boost::asio::ssl::context> context;
|
||||
|
||||
// Returns `true` if any websocket protocols are specified
|
||||
template <class = void>
|
||||
bool
|
||||
websockets() const;
|
||||
|
||||
// Returns a string containing the list of protocols
|
||||
template <class = void>
|
||||
std::string
|
||||
protocols() const;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <class>
|
||||
bool
|
||||
Port::websockets() const
|
||||
{
|
||||
return protocol.count("ws") > 0 || protocol.count("wss") > 0;
|
||||
}
|
||||
|
||||
template <class>
|
||||
std::string
|
||||
Port::protocols() const
|
||||
{
|
||||
std::string s;
|
||||
for (auto iter = protocol.cbegin();
|
||||
iter != protocol.cend(); ++iter)
|
||||
s += (iter != protocol.cbegin() ? "," : "") + *iter;
|
||||
return s;
|
||||
}
|
||||
|
||||
} // HTTP
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
3
src/ripple/server/README.md
Normal file
3
src/ripple/server/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Server
|
||||
|
||||
This contains the HTTP Server and ServerHandler
|
||||
53
src/ripple/server/Role.h
Normal file
53
src/ripple/server/Role.h
Normal file
@@ -0,0 +1,53 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_ROLE_H_INCLUDED
|
||||
#define RIPPLE_SERVER_ROLE_H_INCLUDED
|
||||
|
||||
#include <ripple/server/Port.h>
|
||||
#include <ripple/json/json_value.h>
|
||||
#include <beast/net/IPEndpoint.h>
|
||||
#include <vector>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/** Indicates the level of administrative permission to grant. */
|
||||
enum class Role
|
||||
{
|
||||
GUEST,
|
||||
USER,
|
||||
ADMIN,
|
||||
FORBID
|
||||
};
|
||||
|
||||
/** Return the allowed privilege role.
|
||||
jsonRPC must meet the requirements of the JSON-RPC
|
||||
specification. It must be of type Object, containing the key params
|
||||
which is an array with at least one object. Inside this object
|
||||
are the optional keys 'admin_user' and 'admin_password' used to
|
||||
validate the credentials.
|
||||
*/
|
||||
Role
|
||||
adminRole (HTTP::Port const& port, Json::Value const& jsonRPC,
|
||||
beast::IP::Endpoint const& remoteIp,
|
||||
std::vector<beast::IP::Endpoint> const& admin_allow);
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
73
src/ripple/server/Server.h
Normal file
73
src/ripple/server/Server.h
Normal file
@@ -0,0 +1,73 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_SERVER_H_INCLUDED
|
||||
#define RIPPLE_SERVER_SERVER_H_INCLUDED
|
||||
|
||||
#include <ripple/server/Port.h>
|
||||
#include <beast/utility/Journal.h>
|
||||
#include <beast/utility/PropertyStream.h>
|
||||
|
||||
namespace ripple {
|
||||
namespace HTTP {
|
||||
|
||||
/** Multi-threaded, asynchronous HTTP server. */
|
||||
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;
|
||||
|
||||
virtual
|
||||
void
|
||||
onWrite (beast::PropertyStream::Map& map) = 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;
|
||||
};
|
||||
|
||||
} // HTTP
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
@@ -17,13 +17,17 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_APP_MAIN_SERVERHANDLER_H_INCLUDED
|
||||
#define RIPPLE_APP_MAIN_SERVERHANDLER_H_INCLUDED
|
||||
#ifndef RIPPLE_SERVER_SERVERHANDLER_H_INCLUDED
|
||||
#define RIPPLE_SERVER_SERVERHANDLER_H_INCLUDED
|
||||
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/basics/BasicConfig.h>
|
||||
#include <ripple/server/Port.h>
|
||||
#include <ripple/overlay/Overlay.h>
|
||||
#include <beast/utility/Journal.h>
|
||||
#include <beast/utility/PropertyStream.h>
|
||||
#include <beast/cxx14/memory.h> // <memory>
|
||||
#include <boost/asio/ip/address.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -35,6 +39,35 @@ protected:
|
||||
ServerHandler (Stoppable& parent);
|
||||
|
||||
public:
|
||||
struct Setup
|
||||
{
|
||||
std::vector<HTTP::Port> ports;
|
||||
|
||||
// Memberspace
|
||||
struct client_t
|
||||
{
|
||||
bool secure;
|
||||
std::string ip;
|
||||
std::uint16_t port;
|
||||
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;
|
||||
};
|
||||
|
||||
virtual
|
||||
~ServerHandler() = default;
|
||||
|
||||
@@ -44,13 +77,18 @@ public:
|
||||
*/
|
||||
virtual
|
||||
void
|
||||
setup (beast::Journal journal) = 0;
|
||||
setup (Setup const& setup, beast::Journal journal) = 0;
|
||||
|
||||
/** Returns the setup associated with the handler. */
|
||||
virtual
|
||||
Setup const&
|
||||
setup() const = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr <ServerHandler>
|
||||
make_ServerHandler (beast::Stoppable& parent, JobQueue& jobQueue,
|
||||
NetworkOPs& networkOPs, Resource::Manager& resourceManager,
|
||||
RPC::Setup const& setup);
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
ServerHandler::Setup
|
||||
setup_ServerHandler (BasicConfig const& c, std::ostream& log);
|
||||
|
||||
} // ripple
|
||||
|
||||
@@ -17,16 +17,18 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_HTTP_SESSION_H_INCLUDED
|
||||
#define RIPPLE_HTTP_SESSION_H_INCLUDED
|
||||
#ifndef RIPPLE_SERVER_SESSION_H_INCLUDED
|
||||
#define RIPPLE_SERVER_SESSION_H_INCLUDED
|
||||
|
||||
#include <ripple/server/Writer.h>
|
||||
#include <beast/http/body.h>
|
||||
#include <beast/http/message.h>
|
||||
#include <beast/net/IPEndpoint.h>
|
||||
#include <beast/utility/Journal.h>
|
||||
#include <beast/module/asio/HTTPRequest.h>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -56,6 +58,11 @@ public:
|
||||
beast::Journal
|
||||
journal() = 0;
|
||||
|
||||
/** Returns the Port settings for this connection. */
|
||||
virtual
|
||||
Port const&
|
||||
port() = 0;
|
||||
|
||||
/** Returns the remote address of the connection. */
|
||||
virtual
|
||||
beast::IP::Endpoint
|
||||
@@ -97,6 +104,12 @@ public:
|
||||
virtual
|
||||
void
|
||||
write (void const* buffer, std::size_t bytes) = 0;
|
||||
|
||||
virtual
|
||||
void
|
||||
write (std::shared_ptr <Writer> const& writer,
|
||||
bool keep_alive) = 0;
|
||||
|
||||
/** @} */
|
||||
|
||||
/** Detach the session.
|
||||
64
src/ripple/server/Writer.h
Normal file
64
src/ripple/server/Writer.h
Normal file
@@ -0,0 +1,64 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_WRITER_H_INCLUDED
|
||||
#define RIPPLE_SERVER_WRITER_H_INCLUDED
|
||||
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
namespace ripple {
|
||||
namespace HTTP {
|
||||
|
||||
class Writer
|
||||
{
|
||||
public:
|
||||
virtual ~Writer() = default;
|
||||
|
||||
/** Returns `true` if there is no more data to pull. */
|
||||
virtual
|
||||
bool
|
||||
complete() = 0;
|
||||
|
||||
/** Removes bytes from the input sequence. */
|
||||
virtual
|
||||
void
|
||||
consume (std::size_t bytes) = 0;
|
||||
|
||||
/** Add data to the input sequence.
|
||||
@param bytes A hint to the number of bytes desired.
|
||||
@param resume A functor to later resume execution.
|
||||
@return `true` if the writer is ready to provide more data.
|
||||
*/
|
||||
virtual
|
||||
bool
|
||||
prepare (std::size_t bytes,
|
||||
std::function<void(void)> resume) = 0;
|
||||
|
||||
/** Returns a ConstBufferSequence representing the input sequence. */
|
||||
virtual
|
||||
std::vector<boost::asio::const_buffer>
|
||||
data() = 0;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -17,9 +17,9 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/http/impl/Door.h>
|
||||
#include <ripple/http/impl/PlainPeer.h>
|
||||
#include <ripple/http/impl/SSLPeer.h>
|
||||
#include <ripple/server/impl/Door.h>
|
||||
#include <ripple/server/impl/PlainPeer.h>
|
||||
#include <ripple/server/impl/SSLPeer.h>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <beast/asio/placeholders.h>
|
||||
#include <beast/asio/ssl_bundle.h>
|
||||
@@ -93,11 +93,11 @@ Door::Child::~Child()
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
Door::detector::detector (Door& door, socket_type&& socket,
|
||||
endpoint_type endpoint)
|
||||
endpoint_type remote_address)
|
||||
: Child(door)
|
||||
, socket_(std::move(socket))
|
||||
, timer_(socket_.get_io_service())
|
||||
, remote_endpoint_ (endpoint)
|
||||
, remote_address_(remote_address)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -144,27 +144,35 @@ Door::detector::do_detect (boost::asio::yield_context yield)
|
||||
error_code unused;
|
||||
timer_.cancel(unused);
|
||||
if (! ec)
|
||||
return door_.create(ssl, std::move(buf),
|
||||
std::move(socket_), remote_endpoint_);
|
||||
return door_.create(ssl, buf.data(),
|
||||
std::move(socket_), remote_address_);
|
||||
if (ec != boost::asio::error::operation_aborted)
|
||||
if (door_.server_.journal().trace) door_.server_.journal().trace <<
|
||||
"Error detecting ssl: " << ec.message() <<
|
||||
" from " << remote_endpoint_;
|
||||
" from " << remote_address_;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
Door::Door (boost::asio::io_service& io_service,
|
||||
ServerImpl& server, Port const& port)
|
||||
: port_(port)
|
||||
: port_(std::make_shared<Port>(port))
|
||||
, server_(server)
|
||||
, acceptor_(io_service)
|
||||
, strand_(io_service)
|
||||
, ssl_ (
|
||||
port_->protocol.count("https") > 0 ||
|
||||
//port_->protocol.count("wss") > 0 ||
|
||||
port_->protocol.count("peer") > 0)
|
||||
, plain_ (
|
||||
//port_->protocol.count("ws") > 0 ||
|
||||
port_->protocol.count("http") > 0)
|
||||
{
|
||||
server_.add (*this);
|
||||
|
||||
error_code ec;
|
||||
endpoint_type const local_address = to_asio(port);
|
||||
endpoint_type const local_address =
|
||||
endpoint_type(port.ip, port.port);
|
||||
|
||||
acceptor_.open(local_address.protocol(), ec);
|
||||
if (ec)
|
||||
@@ -206,7 +214,7 @@ Door::Door (boost::asio::io_service& io_service,
|
||||
}
|
||||
|
||||
if (server_.journal().info) server_.journal().info <<
|
||||
"Bound to endpoint " << to_string (acceptor_.local_endpoint());
|
||||
"Bound to endpoint " << acceptor_.local_endpoint();
|
||||
}
|
||||
|
||||
Door::~Door()
|
||||
@@ -263,52 +271,28 @@ Door::add (std::shared_ptr<Child> const& child)
|
||||
list_.emplace(child.get(), child);
|
||||
}
|
||||
|
||||
template <class ConstBufferSequence>
|
||||
void
|
||||
Door::create (bool ssl, beast::asio::streambuf&& buf,
|
||||
Door::create (bool ssl, ConstBufferSequence const& buffers,
|
||||
socket_type&& socket, endpoint_type remote_address)
|
||||
{
|
||||
if (server_.closed())
|
||||
return;
|
||||
error_code ec;
|
||||
switch (port_.security)
|
||||
{
|
||||
case Port::Security::no_ssl:
|
||||
if (ssl)
|
||||
ec = boost::system::errc::make_error_code (
|
||||
boost::system::errc::invalid_argument);
|
||||
|
||||
case Port::Security::require_ssl:
|
||||
if (! ssl)
|
||||
ec = boost::system::errc::make_error_code (
|
||||
boost::system::errc::invalid_argument);
|
||||
|
||||
case Port::Security::allow_ssl:
|
||||
if (! ec)
|
||||
{
|
||||
if (ssl)
|
||||
{
|
||||
auto const peer = std::make_shared <SSLPeer> (*this,
|
||||
server_.journal(), remote_address, buf.data(),
|
||||
server_.journal(), remote_address, buffers,
|
||||
std::move(socket));
|
||||
add(peer);
|
||||
peer->run();
|
||||
return;
|
||||
return peer->run();
|
||||
}
|
||||
|
||||
auto const peer = std::make_shared <PlainPeer> (*this,
|
||||
server_.journal(), remote_address, buf.data(),
|
||||
server_.journal(), remote_address, buffers,
|
||||
std::move(socket));
|
||||
add(peer);
|
||||
peer->run();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (ec)
|
||||
if (server_.journal().trace) server_.journal().trace <<
|
||||
"Error detecting ssl: " << ec.message() <<
|
||||
" from " << remote_address;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -317,9 +301,9 @@ Door::do_accept (boost::asio::yield_context yield)
|
||||
for(;;)
|
||||
{
|
||||
error_code ec;
|
||||
endpoint_type endpoint;
|
||||
endpoint_type remote_address;
|
||||
socket_type socket (acceptor_.get_io_service());
|
||||
acceptor_.async_accept (socket, endpoint, yield[ec]);
|
||||
acceptor_.async_accept (socket, remote_address, yield[ec]);
|
||||
if (ec && ec != boost::asio::error::operation_aborted)
|
||||
if (server_.journal().error) server_.journal().error <<
|
||||
"accept: " << ec.message();
|
||||
@@ -327,29 +311,19 @@ Door::do_accept (boost::asio::yield_context yield)
|
||||
break;
|
||||
if (ec)
|
||||
continue;
|
||||
if (port_.security == Port::Security::no_ssl)
|
||||
{
|
||||
auto const peer = std::make_shared <PlainPeer> (*this,
|
||||
server_.journal(), endpoint, boost::asio::null_buffers(),
|
||||
std::move(socket));
|
||||
add(peer);
|
||||
peer->run();
|
||||
}
|
||||
else if (port_.security == Port::Security::require_ssl)
|
||||
{
|
||||
auto const peer = std::make_shared <SSLPeer> (*this,
|
||||
server_.journal(), endpoint, boost::asio::null_buffers(),
|
||||
std::move(socket));
|
||||
add(peer);
|
||||
peer->run();
|
||||
}
|
||||
else
|
||||
|
||||
if (ssl_ && plain_)
|
||||
{
|
||||
auto const c = std::make_shared <detector> (
|
||||
*this, std::move(socket), endpoint);
|
||||
*this, std::move(socket), remote_address);
|
||||
add(c);
|
||||
c->run();
|
||||
}
|
||||
else if (ssl_ || plain_)
|
||||
{
|
||||
create(ssl_, boost::asio::null_buffers{},
|
||||
std::move(socket), remote_address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,11 +17,10 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_HTTP_DOOR_H_INCLUDED
|
||||
#define RIPPLE_HTTP_DOOR_H_INCLUDED
|
||||
#ifndef RIPPLE_SERVER_DOOR_H_INCLUDED
|
||||
#define RIPPLE_SERVER_DOOR_H_INCLUDED
|
||||
|
||||
#include <ripple/http/impl/ServerImpl.h>
|
||||
#include <ripple/http/impl/Types.h>
|
||||
#include <ripple/server/impl/ServerImpl.h>
|
||||
#include <beast/asio/streambuf.h>
|
||||
#include <boost/asio/basic_waitable_timer.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
@@ -71,11 +70,11 @@ private:
|
||||
private:
|
||||
socket_type socket_;
|
||||
timer_type timer_;
|
||||
endpoint_type remote_endpoint_;
|
||||
endpoint_type remote_address_;
|
||||
|
||||
public:
|
||||
detector (Door& door, socket_type&& socket,
|
||||
endpoint_type endpoint);
|
||||
endpoint_type remote_address);
|
||||
void run();
|
||||
void close() override;
|
||||
|
||||
@@ -84,7 +83,7 @@ private:
|
||||
void do_detect (yield_context yield);
|
||||
};
|
||||
|
||||
Port port_;
|
||||
std::shared_ptr<Port> port_;
|
||||
ServerImpl& server_;
|
||||
acceptor_type acceptor_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
@@ -92,6 +91,8 @@ private:
|
||||
std::condition_variable cond_;
|
||||
boost::container::flat_map<
|
||||
Child*, std::weak_ptr<Child>> list_;
|
||||
bool ssl_;
|
||||
bool plain_;
|
||||
|
||||
public:
|
||||
Door (boost::asio::io_service& io_service,
|
||||
@@ -113,7 +114,7 @@ public:
|
||||
Port const&
|
||||
port() const
|
||||
{
|
||||
return port_;
|
||||
return *port_;
|
||||
}
|
||||
|
||||
// Work-around because we can't call shared_from_this in ctor
|
||||
@@ -132,7 +133,8 @@ public:
|
||||
private:
|
||||
void add (std::shared_ptr<Child> const& child);
|
||||
|
||||
void create (bool ssl, beast::asio::streambuf&& buf,
|
||||
template <class ConstBufferSequence>
|
||||
void create (bool ssl, ConstBufferSequence const& buffers,
|
||||
socket_type&& socket, endpoint_type remote_address);
|
||||
|
||||
void do_accept (yield_context yield);
|
||||
@@ -17,23 +17,17 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/server/impl/JSONRPCUtil.h>
|
||||
#include <ripple/common/jsonrpc_fields.h>
|
||||
#include <ripple/data/protocol/BuildInfo.h>
|
||||
#include <ripple/core/SystemParameters.h>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
unsigned int const gMaxHTTPHeaderSize = 0x02000000;
|
||||
|
||||
std::string gFormatStr ("v1");
|
||||
|
||||
// VFALCO TODO clean up this nonsense
|
||||
std::string FormatFullVersion ()
|
||||
{
|
||||
return (gFormatStr);
|
||||
}
|
||||
|
||||
|
||||
Json::Value JSONRPCError (int code, std::string const& message)
|
||||
{
|
||||
Json::Value error (Json::objectValue);
|
||||
@@ -44,42 +38,6 @@ Json::Value JSONRPCError (int code, std::string const& message)
|
||||
return error;
|
||||
}
|
||||
|
||||
//
|
||||
// HTTP protocol
|
||||
//
|
||||
// This ain't Apache. We're just using HTTP header for the length field
|
||||
// and to be compatible with other JSON-RPC implementations.
|
||||
//
|
||||
|
||||
std::string createHTTPPost (
|
||||
std::string const& strHost,
|
||||
std::string const& strPath,
|
||||
std::string const& strMsg,
|
||||
std::map<std::string, std::string> const& mapRequestHeaders)
|
||||
{
|
||||
std::ostringstream s;
|
||||
|
||||
// CHECKME this uses a different version than the replies below use. Is
|
||||
// this by design or an accident or should it be using
|
||||
// BuildInfo::getFullVersionString () as well?
|
||||
|
||||
s << "POST "
|
||||
<< (strPath.empty () ? "/" : strPath)
|
||||
<< " HTTP/1.0\r\n"
|
||||
<< "User-Agent: " SYSTEM_NAME "-json-rpc/" << FormatFullVersion () << "\r\n"
|
||||
<< "Host: " << strHost << "\r\n"
|
||||
<< "Content-Type: application/json\r\n"
|
||||
<< "Content-Length: " << strMsg.size () << "\r\n"
|
||||
<< "Accept: application/json\r\n";
|
||||
|
||||
for (auto const& item : mapRequestHeaders)
|
||||
s << item.first << ": " << item.second << "\r\n";
|
||||
|
||||
s << "\r\n" << strMsg;
|
||||
|
||||
return s.str ();
|
||||
}
|
||||
|
||||
std::string getHTTPHeaderTimestamp ()
|
||||
{
|
||||
// CHECKME This is probably called often enough that optimizing it makes
|
||||
@@ -114,8 +72,7 @@ std::string HTTPReply (int nStatus, std::string const& strMsg)
|
||||
// CHECKME this returns a different version than the replies below. Is
|
||||
// this by design or an accident or should it be using
|
||||
// BuildInfo::getFullVersionString () as well?
|
||||
ret.append ("Server: " SYSTEM_NAME "-json-rpc/");
|
||||
ret.append (FormatFullVersion ());
|
||||
ret.append ("Server: " SYSTEM_NAME "-json-rpc/v1");
|
||||
ret.append ("\r\n");
|
||||
|
||||
// Be careful in modifying this! If you change the contents you MUST
|
||||
@@ -152,8 +109,9 @@ std::string HTTPReply (int nStatus, std::string const& strMsg)
|
||||
|
||||
ret.append ("Connection: Keep-Alive\r\n");
|
||||
|
||||
if (getConfig ().RPC_ALLOW_REMOTE)
|
||||
ret.append ("Access-Control-Allow-Origin: *\r\n");
|
||||
// VFALCO TODO Determine if/when this header should be added
|
||||
//if (getConfig ().RPC_ALLOW_REMOTE)
|
||||
// ret.append ("Access-Control-Allow-Origin: *\r\n");
|
||||
|
||||
ret.append ("Content-Length: ");
|
||||
ret.append (std::to_string(strMsg.size () + 2));
|
||||
@@ -242,67 +200,6 @@ int ReadHTTP (std::basic_istream<char>& stream, std::map<std::string, std::strin
|
||||
return nStatus;
|
||||
}
|
||||
|
||||
std::string DecodeBase64 (std::string s)
|
||||
{
|
||||
// FIXME: This performs badly
|
||||
BIO* b64, *bmem;
|
||||
|
||||
char* buffer = static_cast<char*> (calloc (s.size (), sizeof (char)));
|
||||
|
||||
b64 = BIO_new (BIO_f_base64 ());
|
||||
BIO_set_flags (b64, BIO_FLAGS_BASE64_NO_NL);
|
||||
bmem = BIO_new_mem_buf (const_cast<char*> (s.data ()), s.size ());
|
||||
bmem = BIO_push (b64, bmem);
|
||||
BIO_read (bmem, buffer, s.size ());
|
||||
BIO_free_all (bmem);
|
||||
|
||||
std::string result (buffer);
|
||||
free (buffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool HTTPAuthorized (const std::map<std::string, std::string>& mapHeaders)
|
||||
{
|
||||
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 false;
|
||||
|
||||
std::string strUserPass64 = it->second.substr (6);
|
||||
boost::trim (strUserPass64);
|
||||
std::string strUserPass = DecodeBase64 (strUserPass64);
|
||||
std::string::size_type nColon = strUserPass.find (":");
|
||||
|
||||
if (nColon == std::string::npos)
|
||||
return false;
|
||||
|
||||
std::string strUser = strUserPass.substr (0, nColon);
|
||||
std::string strPassword = strUserPass.substr (nColon + 1);
|
||||
return (strUser == getConfig ().RPC_USER) && (strPassword == getConfig ().RPC_PASSWORD);
|
||||
}
|
||||
|
||||
//
|
||||
// JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
|
||||
// but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
|
||||
// unspecified (HTTP errors and contents of 'error').
|
||||
//
|
||||
// 1.0 spec: http://json-rpc.org/wiki/specification
|
||||
// 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http
|
||||
//
|
||||
|
||||
std::string JSONRPCRequest (std::string const& strMethod, Json::Value const& params, Json::Value const& id)
|
||||
{
|
||||
Json::Value request;
|
||||
request[jss::method] = strMethod;
|
||||
request[jss::params] = params;
|
||||
request[jss::id] = id;
|
||||
return to_string (request) + "\n";
|
||||
}
|
||||
|
||||
std::string JSONRPCReply (Json::Value const& result, Json::Value const& error, Json::Value const& id)
|
||||
{
|
||||
Json::Value reply (Json::objectValue);
|
||||
@@ -17,35 +17,23 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_NET_RPC_RPCUTIL_H_INCLUDED
|
||||
#define RIPPLE_NET_RPC_RPCUTIL_H_INCLUDED
|
||||
#ifndef RIPPLE_SERVER_JSONRPCUTIL_H_INCLUDED
|
||||
#define RIPPLE_SERVER_JSONRPCUTIL_H_INCLUDED
|
||||
|
||||
#include <ripple/json/json_value.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
// VFALCO TODO Wrap these up into a class. It looks like they just do some
|
||||
// convenience packaging of JSON data from the pieces. It looks
|
||||
// Ripple client protocol-specific.
|
||||
//
|
||||
extern std::string JSONRPCRequest (std::string const& strMethod, Json::Value const& params,
|
||||
Json::Value const& id);
|
||||
// VFALCO These functions are all deprecated they are inefficient and have poor signatures.
|
||||
|
||||
extern std::string JSONRPCReply (Json::Value const& result, Json::Value const& error, Json::Value const& id);
|
||||
|
||||
extern Json::Value JSONRPCError (int code, std::string const& message);
|
||||
|
||||
extern std::string createHTTPPost (std::string const& strHost, std::string const& strPath, std::string const& strMsg,
|
||||
const std::map<std::string, std::string>& mapRequestHeaders);
|
||||
|
||||
// VFALCO This needs to be rewritten to use beast::http::message
|
||||
extern std::string HTTPReply (int nStatus, std::string const& strMsg);
|
||||
|
||||
// VFALCO TODO Create a HTTPHeaders class with a nice interface instead of the std::map
|
||||
//
|
||||
extern bool HTTPAuthorized (std::map <std::string, std::string> const& mapHeaders);
|
||||
|
||||
// VFALCO NOTE This one looks like it does some sort of stream i/o
|
||||
//
|
||||
extern int ReadHTTP (std::basic_istream<char>& stream,
|
||||
std::map<std::string, std::string>& mapHeadersRet,
|
||||
std::string& strMessageRet);
|
||||
@@ -17,14 +17,13 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_HTTP_PEER_H_INCLUDED
|
||||
#define RIPPLE_HTTP_PEER_H_INCLUDED
|
||||
#ifndef RIPPLE_SERVER_PEER_H_INCLUDED
|
||||
#define RIPPLE_SERVER_PEER_H_INCLUDED
|
||||
|
||||
#include <ripple/http/impl/Door.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/server/impl/Door.h>
|
||||
#include <ripple/server/Session.h>
|
||||
#include <ripple/server/impl/ServerImpl.h>
|
||||
#include <beast/asio/IPAddressConversion.h>
|
||||
#include <beast/asio/placeholders.h>
|
||||
#include <beast/asio/ssl.h> // for is_short_read?
|
||||
#include <beast/http/message.h>
|
||||
@@ -54,12 +53,14 @@ class Peer
|
||||
{
|
||||
protected:
|
||||
using clock_type = std::chrono::system_clock;
|
||||
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 yield_context = boost::asio::yield_context;
|
||||
|
||||
enum
|
||||
{
|
||||
// Size of our receive buffer
|
||||
// Size of our read/write buffer
|
||||
bufferSize = 4 * 1024,
|
||||
|
||||
// Max seconds without completing a message
|
||||
@@ -85,7 +86,7 @@ protected:
|
||||
boost::asio::io_service::work work_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
waitable_timer timer_;
|
||||
endpoint_type endpoint_;
|
||||
endpoint_type remote_address_;
|
||||
beast::Journal journal_;
|
||||
|
||||
std::string id_;
|
||||
@@ -111,7 +112,7 @@ protected:
|
||||
public:
|
||||
template <class ConstBufferSequence>
|
||||
Peer (Door& door, boost::asio::io_service& io_service,
|
||||
beast::Journal journal, endpoint_type endpoint,
|
||||
beast::Journal journal, endpoint_type remote_address,
|
||||
ConstBufferSequence const& buffers);
|
||||
|
||||
virtual
|
||||
@@ -145,10 +146,14 @@ protected:
|
||||
on_timer (error_code ec);
|
||||
|
||||
void
|
||||
do_read (boost::asio::yield_context yield);
|
||||
do_read (yield_context yield);
|
||||
|
||||
void
|
||||
do_write (boost::asio::yield_context yield);
|
||||
do_write (yield_context yield);
|
||||
|
||||
void
|
||||
do_writer (std::shared_ptr <Writer> const& writer,
|
||||
bool keep_alive, yield_context yield);
|
||||
|
||||
virtual
|
||||
void
|
||||
@@ -166,10 +171,16 @@ protected:
|
||||
return door_.server().journal();
|
||||
}
|
||||
|
||||
Port const&
|
||||
port() override
|
||||
{
|
||||
return door_.port();
|
||||
}
|
||||
|
||||
beast::IP::Endpoint
|
||||
remoteAddress() override
|
||||
{
|
||||
return from_asio (endpoint_);
|
||||
return beast::IPAddressConversion::from_asio(remote_address_);
|
||||
}
|
||||
|
||||
beast::http::message&
|
||||
@@ -187,6 +198,10 @@ protected:
|
||||
void
|
||||
write (void const* buffer, std::size_t bytes) override;
|
||||
|
||||
void
|
||||
write (std::shared_ptr <Writer> const& writer,
|
||||
bool keep_alive) override;
|
||||
|
||||
std::shared_ptr<Session>
|
||||
detach() override;
|
||||
|
||||
@@ -202,13 +217,13 @@ protected:
|
||||
template <class Impl>
|
||||
template <class ConstBufferSequence>
|
||||
Peer<Impl>::Peer (Door& door, boost::asio::io_service& io_service,
|
||||
beast::Journal journal, endpoint_type endpoint,
|
||||
beast::Journal journal, endpoint_type remote_address,
|
||||
ConstBufferSequence const& buffers)
|
||||
: Child(door)
|
||||
, work_ (io_service)
|
||||
, strand_ (io_service)
|
||||
, timer_ (io_service)
|
||||
, endpoint_ (endpoint)
|
||||
, remote_address_ (remote_address)
|
||||
, journal_ (journal)
|
||||
{
|
||||
read_buf_.commit(boost::asio::buffer_copy(read_buf_.prepare (
|
||||
@@ -217,7 +232,7 @@ Peer<Impl>::Peer (Door& door, boost::asio::io_service& io_service,
|
||||
nid_ = ++sid;
|
||||
id_ = std::string("#") + std::to_string(nid_) + " ";
|
||||
if (journal_.trace) journal_.trace << id_ <<
|
||||
"accept: " << endpoint.address();
|
||||
"accept: " << remote_address_.address();
|
||||
when_ = clock_type::now();
|
||||
when_str_ = beast::Time::getCurrentTime().formatted (
|
||||
"%Y-%b-%d %H:%M:%S").toStdString();
|
||||
@@ -251,7 +266,7 @@ Peer<Impl>::close()
|
||||
(void(Peer::*)(void))&Peer::close,
|
||||
impl().shared_from_this()));
|
||||
error_code ec;
|
||||
impl().socket_.lowest_layer().close(ec);
|
||||
impl().stream_.lowest_layer().close(ec);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -265,7 +280,7 @@ Peer<Impl>::fail (error_code ec, char const* what)
|
||||
ec_ = ec;
|
||||
if (journal_.trace) journal_.trace << id_ <<
|
||||
std::string(what) << ": " << ec.message();
|
||||
impl().socket_.lowest_layer().close (ec);
|
||||
impl().stream_.lowest_layer().close (ec);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,7 +323,7 @@ Peer<Impl>::on_timer (error_code ec)
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
Peer<Impl>::do_read (boost::asio::yield_context yield)
|
||||
Peer<Impl>::do_read (yield_context yield)
|
||||
{
|
||||
complete_ = false;
|
||||
|
||||
@@ -322,7 +337,7 @@ Peer<Impl>::do_read (boost::asio::yield_context yield)
|
||||
{
|
||||
start_timer();
|
||||
auto const bytes_transferred = boost::asio::async_read (
|
||||
impl().socket_, read_buf_.prepare (bufferSize),
|
||||
impl().stream_, read_buf_.prepare (bufferSize),
|
||||
boost::asio::transfer_at_least(1), yield[ec]);
|
||||
cancel_timer();
|
||||
|
||||
@@ -375,7 +390,7 @@ Peer<Impl>::do_read (boost::asio::yield_context yield)
|
||||
// The write queue must not be empty upon entry.
|
||||
template <class Impl>
|
||||
void
|
||||
Peer<Impl>::do_write (boost::asio::yield_context yield)
|
||||
Peer<Impl>::do_write (yield_context yield)
|
||||
{
|
||||
error_code ec;
|
||||
std::size_t bytes = 0;
|
||||
@@ -405,7 +420,7 @@ Peer<Impl>::do_write (boost::asio::yield_context yield)
|
||||
break;
|
||||
|
||||
start_timer();
|
||||
bytes = boost::asio::async_write (impl().socket_,
|
||||
bytes = boost::asio::async_write (impl().stream_,
|
||||
boost::asio::buffer (data, bytes),
|
||||
boost::asio::transfer_at_least(1), yield[ec]);
|
||||
cancel_timer();
|
||||
@@ -424,6 +439,45 @@ Peer<Impl>::do_write (boost::asio::yield_context yield)
|
||||
impl().shared_from_this(), std::placeholders::_1));
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
Peer<Impl>::do_writer (std::shared_ptr <Writer> const& writer,
|
||||
bool keep_alive, yield_context yield)
|
||||
{
|
||||
std::function <void(void)> resume;
|
||||
{
|
||||
auto const p = impl().shared_from_this();
|
||||
resume = std::function <void(void)>(
|
||||
[this, p, writer, keep_alive]()
|
||||
{
|
||||
boost::asio::spawn (strand_, std::bind (
|
||||
&Peer<Impl>::do_writer, p, writer, keep_alive,
|
||||
std::placeholders::_1));
|
||||
});
|
||||
}
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if (! writer->prepare (bufferSize, resume))
|
||||
return;
|
||||
error_code ec;
|
||||
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");
|
||||
writer->consume(bytes_transferred);
|
||||
if (writer->complete())
|
||||
break;
|
||||
}
|
||||
|
||||
if (! keep_alive)
|
||||
return do_close();
|
||||
|
||||
boost::asio::spawn (strand_, std::bind (&Peer<Impl>::do_read,
|
||||
impl().shared_from_this(), std::placeholders::_1));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Send a copy of the data.
|
||||
@@ -446,6 +500,17 @@ Peer<Impl>::write (void const* buffer, std::size_t bytes)
|
||||
impl().shared_from_this(), std::placeholders::_1));
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
Peer<Impl>::write (std::shared_ptr <Writer> const& writer,
|
||||
bool keep_alive)
|
||||
{
|
||||
boost::asio::spawn (strand_, std::bind (
|
||||
&Peer<Impl>::do_writer, impl().shared_from_this(),
|
||||
writer, keep_alive, std::placeholders::_1));
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
// Make the Session asynchronous
|
||||
template <class Impl>
|
||||
std::shared_ptr<Session>
|
||||
@@ -454,6 +519,7 @@ Peer<Impl>::detach()
|
||||
return impl().shared_from_this();
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
// Called to indicate the response has been written (but not sent)
|
||||
template <class Impl>
|
||||
void
|
||||
@@ -474,6 +540,7 @@ Peer<Impl>::complete()
|
||||
impl().shared_from_this(), std::placeholders::_1));
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
// Called from the Handler to close the session.
|
||||
template <class Impl>
|
||||
void
|
||||
@@ -494,7 +561,7 @@ Peer<Impl>::close (bool graceful)
|
||||
}
|
||||
|
||||
error_code ec;
|
||||
impl().socket_.lowest_layer().close (ec);
|
||||
impl().stream_.lowest_layer().close (ec);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,10 +17,11 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_HTTP_PLAINPEER_H_INCLUDED
|
||||
#define RIPPLE_HTTP_PLAINPEER_H_INCLUDED
|
||||
#ifndef RIPPLE_SERVER_PLAINPEER_H_INCLUDED
|
||||
#define RIPPLE_SERVER_PLAINPEER_H_INCLUDED
|
||||
|
||||
#include <ripple/http/impl/Peer.h>
|
||||
#include <ripple/server/impl/Peer.h>
|
||||
#include <memory>
|
||||
|
||||
namespace ripple {
|
||||
namespace HTTP {
|
||||
@@ -32,7 +33,8 @@ class PlainPeer
|
||||
private:
|
||||
friend class Peer <PlainPeer>;
|
||||
using socket_type = boost::asio::ip::tcp::socket;
|
||||
socket_type socket_;
|
||||
|
||||
socket_type stream_;
|
||||
|
||||
public:
|
||||
template <class ConstBufferSequence>
|
||||
@@ -54,10 +56,10 @@ private:
|
||||
|
||||
template <class ConstBufferSequence>
|
||||
PlainPeer::PlainPeer (Door& door, beast::Journal journal,
|
||||
endpoint_type endpoint, ConstBufferSequence const& buffers,
|
||||
boost::asio::ip::tcp::socket&& socket)
|
||||
: Peer (door, socket.get_io_service(), journal, endpoint, buffers)
|
||||
, socket_(std::move(socket))
|
||||
endpoint_type remote_address, ConstBufferSequence const& buffers,
|
||||
socket_type&& socket)
|
||||
: Peer (door, socket.get_io_service(), journal, remote_address, buffers)
|
||||
, stream_(std::move(socket))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -65,7 +67,7 @@ void
|
||||
PlainPeer::run ()
|
||||
{
|
||||
door_.server().handler().onAccept (session());
|
||||
if (! socket_.is_open())
|
||||
if (! stream_.is_open())
|
||||
return;
|
||||
|
||||
boost::asio::spawn (strand_, std::bind (&PlainPeer::do_read,
|
||||
@@ -74,28 +76,37 @@ PlainPeer::run ()
|
||||
|
||||
void
|
||||
PlainPeer::do_request()
|
||||
{
|
||||
// Perform half-close when Connection: close and not SSL
|
||||
error_code ec;
|
||||
if (! message_.keep_alive())
|
||||
socket_.shutdown (socket_type::shutdown_receive, ec);
|
||||
|
||||
if (! ec)
|
||||
{
|
||||
++request_count_;
|
||||
door_.server().handler().onRequest (session());
|
||||
auto const what = door_.server().handler().onHandoff (session(),
|
||||
std::move(stream_), std::move(message_), remote_address_);
|
||||
if (what.moved)
|
||||
return;
|
||||
error_code ec;
|
||||
if (what.response)
|
||||
{
|
||||
// half-close on Connection: close
|
||||
if (! what.keep_alive)
|
||||
stream_.shutdown (socket_type::shutdown_receive, ec);
|
||||
if (ec)
|
||||
return fail (ec, "request");
|
||||
return write(what.response, what.keep_alive);
|
||||
}
|
||||
|
||||
// Perform half-close when Connection: close and not SSL
|
||||
if (! message_.keep_alive())
|
||||
stream_.shutdown (socket_type::shutdown_receive, ec);
|
||||
if (ec)
|
||||
fail (ec, "request");
|
||||
return fail (ec, "request");
|
||||
// legacy
|
||||
door_.server().handler().onRequest (session());
|
||||
}
|
||||
|
||||
void
|
||||
PlainPeer::do_close()
|
||||
{
|
||||
error_code ec;
|
||||
socket_.shutdown (socket_type::shutdown_send, ec);
|
||||
stream_.shutdown (socket_type::shutdown_send, ec);
|
||||
}
|
||||
|
||||
}
|
||||
93
src/ripple/server/impl/Role.cpp
Normal file
93
src/ripple/server/impl/Role.cpp
Normal 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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/server/Role.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
Role
|
||||
adminRole (HTTP::Port const& port, Json::Value const& params,
|
||||
beast::IP::Endpoint const& remoteIp,
|
||||
std::vector<beast::IP::Endpoint> const& admin_allow)
|
||||
{
|
||||
Role role (Role::FORBID);
|
||||
|
||||
bool const bPasswordSupplied =
|
||||
params.isMember ("admin_user") ||
|
||||
params.isMember ("admin_password");
|
||||
|
||||
bool const bPasswordRequired =
|
||||
! port.admin_user.empty() || ! port.admin_password.empty();
|
||||
|
||||
bool bPasswordWrong;
|
||||
|
||||
if (bPasswordSupplied)
|
||||
{
|
||||
if (bPasswordRequired)
|
||||
{
|
||||
// Required, and supplied, check match
|
||||
bPasswordWrong =
|
||||
(port.admin_user !=
|
||||
(params.isMember ("admin_user") ? params["admin_user"].asString () : ""))
|
||||
||
|
||||
(port.admin_password !=
|
||||
(params.isMember ("admin_user") ? params["admin_password"].asString () : ""));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not required, but supplied
|
||||
bPasswordWrong = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Required but not supplied,
|
||||
bPasswordWrong = bPasswordRequired;
|
||||
}
|
||||
|
||||
// Meets IP restriction for admin.
|
||||
beast::IP::Endpoint const remote_addr (remoteIp.at_port (0));
|
||||
bool bAdminIP = false;
|
||||
|
||||
// VFALCO TODO Don't use this!
|
||||
for (auto const& allow_addr : admin_allow)
|
||||
{
|
||||
if (allow_addr == remote_addr)
|
||||
{
|
||||
bAdminIP = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bPasswordWrong // Wrong
|
||||
|| (bPasswordSupplied && !bAdminIP)) // Supplied and doesn't meet IP filter.
|
||||
{
|
||||
role = Role::FORBID;
|
||||
}
|
||||
// If supplied, password is correct.
|
||||
else
|
||||
{
|
||||
// Allow admin, if from admin IP and no password is required or it was supplied and correct.
|
||||
role = bAdminIP && (!bPasswordRequired || bPasswordSupplied) ? Role::ADMIN : Role::GUEST;
|
||||
}
|
||||
|
||||
return role;
|
||||
}
|
||||
|
||||
}
|
||||
203
src/ripple/server/impl/SSLPeer.h
Normal file
203
src/ripple/server/impl/SSLPeer.h
Normal file
@@ -0,0 +1,203 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_SSLPEER_H_INCLUDED
|
||||
#define RIPPLE_SERVER_SSLPEER_H_INCLUDED
|
||||
|
||||
#include <ripple/server/impl/Peer.h>
|
||||
#include <beast/asio/ssl_bundle.h>
|
||||
#include <beast/cxx14/memory.h> // <memory>
|
||||
|
||||
namespace ripple {
|
||||
namespace HTTP {
|
||||
|
||||
class SSLPeer
|
||||
: public Peer <SSLPeer>
|
||||
, public std::enable_shared_from_this <SSLPeer>
|
||||
{
|
||||
private:
|
||||
friend class Peer <SSLPeer>;
|
||||
using socket_type = boost::asio::ip::tcp::socket;
|
||||
using stream_type = boost::asio::ssl::stream <socket_type&>;
|
||||
|
||||
std::unique_ptr<beast::asio::ssl_bundle> ssl_bundle_;
|
||||
stream_type& stream_;
|
||||
|
||||
public:
|
||||
template <class ConstBufferSequence>
|
||||
SSLPeer (Door& door, beast::Journal journal, endpoint_type remote_address,
|
||||
ConstBufferSequence const& buffers, socket_type&& socket);
|
||||
|
||||
void
|
||||
run();
|
||||
|
||||
private:
|
||||
void
|
||||
do_handshake (yield_context yield);
|
||||
|
||||
void
|
||||
do_request();
|
||||
|
||||
void
|
||||
do_close();
|
||||
|
||||
void
|
||||
on_shutdown (error_code ec);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Detects the legacy peer protocol handshake. */
|
||||
template <class Socket, class StreamBuf, class Yield>
|
||||
static
|
||||
std::pair <boost::system::error_code, bool>
|
||||
detect_peer_protocol (Socket& socket, StreamBuf& buf, Yield yield)
|
||||
{
|
||||
std::pair<boost::system::error_code, bool> result;
|
||||
result.second = false;
|
||||
for(;;)
|
||||
{
|
||||
std::size_t const max = 6; // max bytes needed
|
||||
unsigned char data[max];
|
||||
auto const n = boost::asio::buffer_copy(
|
||||
boost::asio::buffer(data), buf.data());
|
||||
|
||||
/* Protocol messages are framed by a 6 byte header which includes
|
||||
a big-endian 4-byte length followed by a big-endian 2-byte type.
|
||||
The type for 'hello' is 1.
|
||||
*/
|
||||
if (n>=1 && data[0] != 0)
|
||||
break;;
|
||||
if (n>=2 && data[1] != 0)
|
||||
break;
|
||||
if (n>=5 && data[4] != 0)
|
||||
break;
|
||||
if (n>=6)
|
||||
{
|
||||
if (data[5] == 1)
|
||||
result.second = true;
|
||||
break;
|
||||
}
|
||||
std::size_t const bytes_transferred = boost::asio::async_read(
|
||||
socket, buf.prepare(max - n), boost::asio::transfer_at_least(1),
|
||||
yield[result.first]);
|
||||
if (result.first)
|
||||
break;
|
||||
buf.commit(bytes_transferred);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class ConstBufferSequence>
|
||||
SSLPeer::SSLPeer (Door& door, beast::Journal journal,
|
||||
endpoint_type remote_address, ConstBufferSequence const& buffers,
|
||||
socket_type&& socket)
|
||||
: Peer (door, 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)
|
||||
{
|
||||
}
|
||||
|
||||
// Called when the acceptor accepts our socket.
|
||||
void
|
||||
SSLPeer::run()
|
||||
{
|
||||
door_.server().handler().onAccept (session());
|
||||
if (! stream_.lowest_layer().is_open())
|
||||
return;
|
||||
|
||||
boost::asio::spawn (strand_, std::bind (&SSLPeer::do_handshake,
|
||||
shared_from_this(), std::placeholders::_1));
|
||||
}
|
||||
|
||||
void
|
||||
SSLPeer::do_handshake (yield_context 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();
|
||||
if (ec)
|
||||
return fail (ec, "handshake");
|
||||
bool const legacy = port().protocol.count("peer") > 0;
|
||||
bool const http =
|
||||
port().protocol.count("peer") > 0 ||
|
||||
//|| port().protocol.count("wss") > 0
|
||||
port().protocol.count("https") > 0;
|
||||
if (legacy)
|
||||
{
|
||||
auto const result = detect_peer_protocol(stream_, read_buf_, yield);
|
||||
if (result.first)
|
||||
return fail (result.first, "detect_legacy_handshake");
|
||||
if (result.second)
|
||||
{
|
||||
std::vector<std::uint8_t> storage (read_buf_.size());
|
||||
boost::asio::mutable_buffers_1 buffer (
|
||||
boost::asio::mutable_buffer(storage.data(), storage.size()));
|
||||
boost::asio::buffer_copy(buffer, read_buf_.data());
|
||||
return door_.server().handler().onLegacyPeerHello(
|
||||
std::move(ssl_bundle_), buffer, remote_address_);
|
||||
}
|
||||
}
|
||||
if (http)
|
||||
{
|
||||
boost::asio::spawn (strand_, std::bind (&SSLPeer::do_read,
|
||||
shared_from_this(), std::placeholders::_1));
|
||||
return;
|
||||
}
|
||||
// this will be destroyed
|
||||
}
|
||||
|
||||
void
|
||||
SSLPeer::do_request()
|
||||
{
|
||||
++request_count_;
|
||||
auto const what = door_.server().handler().onHandoff (session(),
|
||||
std::move(ssl_bundle_), std::move(message_), remote_address_);
|
||||
if (what.moved)
|
||||
return;
|
||||
if (what.response)
|
||||
return write(what.response, what.keep_alive);
|
||||
// legacy
|
||||
door_.server().handler().onRequest (session());
|
||||
}
|
||||
|
||||
void
|
||||
SSLPeer::do_close()
|
||||
{
|
||||
start_timer();
|
||||
stream_.async_shutdown (strand_.wrap (std::bind (
|
||||
&SSLPeer::on_shutdown, shared_from_this(),
|
||||
std::placeholders::_1)));
|
||||
cancel_timer();
|
||||
}
|
||||
|
||||
void
|
||||
SSLPeer::on_shutdown (error_code ec)
|
||||
{
|
||||
stream_.lowest_layer().close(ec);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
739
src/ripple/server/impl/ServerHandlerImp.cpp
Normal file
739
src/ripple/server/impl/ServerHandlerImp.cpp
Normal file
@@ -0,0 +1,739 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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/app/main/Application.h>
|
||||
#include <ripple/server/make_ServerHandler.h>
|
||||
#include <ripple/server/impl/JSONRPCUtil.h>
|
||||
#include <ripple/server/impl/ServerHandlerImp.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
#include <ripple/common/make_SSLContext.h>
|
||||
#include <ripple/core/JobQueue.h>
|
||||
#include <ripple/server/make_Server.h>
|
||||
#include <ripple/overlay/Overlay.h>
|
||||
#include <ripple/resource/api/Manager.h>
|
||||
#include <ripple/resource/api/Fees.h>
|
||||
#include <beast/cxx14/algorithm.h> // <algorithm>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
ServerHandler::ServerHandler (Stoppable& parent)
|
||||
: Stoppable ("ServerHandler", parent)
|
||||
, Source ("server")
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
ServerHandlerImp::ServerHandlerImp (Stoppable& parent,
|
||||
boost::asio::io_service& io_service, JobQueue& jobQueue,
|
||||
NetworkOPs& networkOPs, Resource::Manager& resourceManager)
|
||||
: ServerHandler (parent)
|
||||
, m_resourceManager (resourceManager)
|
||||
, m_journal (deprecatedLogs().journal("Server"))
|
||||
, m_jobQueue (jobQueue)
|
||||
, m_networkOPs (networkOPs)
|
||||
, m_server (HTTP::make_Server(
|
||||
*this, io_service, deprecatedLogs().journal("Server")))
|
||||
{
|
||||
}
|
||||
|
||||
ServerHandlerImp::~ServerHandlerImp()
|
||||
{
|
||||
m_server = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
ServerHandlerImp::setup (Setup const& setup, beast::Journal journal)
|
||||
{
|
||||
setup_ = setup;
|
||||
m_server->ports (setup.ports);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
ServerHandlerImp::onStop()
|
||||
{
|
||||
m_server->close();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
ServerHandlerImp::onAccept (HTTP::Session& session)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
ServerHandlerImp::onAccept (HTTP::Session& session,
|
||||
boost::asio::ip::tcp::endpoint endpoint)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ServerHandlerImp::onLegacyPeerHello (
|
||||
std::unique_ptr<beast::asio::ssl_bundle>&& ssl_bundle,
|
||||
boost::asio::const_buffer buffer,
|
||||
boost::asio::ip::tcp::endpoint remote_address)
|
||||
{
|
||||
// VFALCO TODO Inject Overlay
|
||||
getApp().overlay().onLegacyPeerHello(std::move(ssl_bundle),
|
||||
buffer, remote_address);
|
||||
}
|
||||
|
||||
auto
|
||||
ServerHandlerImp::onHandoff (HTTP::Session& session,
|
||||
std::unique_ptr <beast::asio::ssl_bundle>&& bundle,
|
||||
beast::http::message&& request,
|
||||
boost::asio::ip::tcp::endpoint remote_address) ->
|
||||
Handoff
|
||||
{
|
||||
if (session.port().protocol.count("wss") > 0 &&
|
||||
isWebsocketUpgrade (request))
|
||||
{
|
||||
// Pass to websockets
|
||||
Handoff handoff;
|
||||
// handoff.moved = true;
|
||||
return handoff;
|
||||
}
|
||||
if (session.port().protocol.count("peer") > 0)
|
||||
return getApp().overlay().onHandoff (std::move(bundle),
|
||||
std::move(request), remote_address);
|
||||
// Pass through to legacy onRequest
|
||||
return Handoff{};
|
||||
}
|
||||
|
||||
auto
|
||||
ServerHandlerImp::onHandoff (HTTP::Session& session,
|
||||
boost::asio::ip::tcp::socket&& socket,
|
||||
beast::http::message&& request,
|
||||
boost::asio::ip::tcp::endpoint remote_address) ->
|
||||
Handoff
|
||||
{
|
||||
if (session.port().protocol.count("ws") > 0 &&
|
||||
isWebsocketUpgrade (request))
|
||||
{
|
||||
// Pass to websockets
|
||||
Handoff handoff;
|
||||
// handoff.moved = true;
|
||||
return handoff;
|
||||
}
|
||||
// Pass through to legacy onRequest
|
||||
return Handoff{};
|
||||
}
|
||||
|
||||
void
|
||||
ServerHandlerImp::onRequest (HTTP::Session& session)
|
||||
{
|
||||
// Check user/password authorization
|
||||
if (! authorized (session.port(),
|
||||
build_map(session.request().headers)))
|
||||
{
|
||||
session.write (HTTPReply (403, "Forbidden"));
|
||||
session.close (true);
|
||||
return;
|
||||
}
|
||||
|
||||
m_jobQueue.addJob (jtCLIENT, "RPC-Client", std::bind (
|
||||
&ServerHandlerImp::processSession, this, std::placeholders::_1,
|
||||
session.detach()));
|
||||
}
|
||||
|
||||
void
|
||||
ServerHandlerImp::onClose (HTTP::Session& session,
|
||||
boost::system::error_code const&)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ServerHandlerImp::onStopped (HTTP::Server&)
|
||||
{
|
||||
stopped();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Dispatched on the job queue
|
||||
void
|
||||
ServerHandlerImp::processSession (Job& job,
|
||||
std::shared_ptr<HTTP::Session> const& session)
|
||||
{
|
||||
session->write (processRequest (session->port(),
|
||||
to_string(session->body()), session->remoteAddress().at_port(0)));
|
||||
|
||||
if (session->request().keep_alive())
|
||||
{
|
||||
session->complete();
|
||||
}
|
||||
else
|
||||
{
|
||||
session->close (true);
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
ServerHandlerImp::createResponse (
|
||||
int statusCode,
|
||||
std::string const& description)
|
||||
{
|
||||
return HTTPReply (statusCode, description);
|
||||
}
|
||||
|
||||
// VFALCO ARGH! returning a single std::string for the entire response?
|
||||
std::string
|
||||
ServerHandlerImp::processRequest (HTTP::Port const& port,
|
||||
std::string const& request, beast::IP::Endpoint const& remoteIPAddress)
|
||||
{
|
||||
Json::Value jsonRPC;
|
||||
{
|
||||
Json::Reader reader;
|
||||
if ((request.size () > 1000000) ||
|
||||
! reader.parse (request, jsonRPC) ||
|
||||
jsonRPC.isNull () ||
|
||||
! jsonRPC.isObject ())
|
||||
{
|
||||
return createResponse (400, "Unable to parse request");
|
||||
}
|
||||
}
|
||||
|
||||
auto const& admin_allow = getConfig().RPC_ADMIN_ALLOW;
|
||||
auto role = Role::FORBID;
|
||||
if (jsonRPC.isObject() && jsonRPC.isMember("params") &&
|
||||
jsonRPC["params"].isArray() && jsonRPC["params"].size() > 0 &&
|
||||
jsonRPC["params"][Json::UInt(0)].isObject())
|
||||
role = adminRole(port, jsonRPC["params"][Json::UInt(0)],
|
||||
remoteIPAddress, admin_allow);
|
||||
else
|
||||
role = adminRole(port, Json::objectValue,
|
||||
remoteIPAddress, admin_allow);
|
||||
|
||||
Resource::Consumer usage;
|
||||
|
||||
if (role == Role::ADMIN)
|
||||
usage = m_resourceManager.newAdminEndpoint (remoteIPAddress.to_string());
|
||||
else
|
||||
usage = m_resourceManager.newInboundEndpoint(remoteIPAddress);
|
||||
|
||||
if (usage.disconnect ())
|
||||
return createResponse (503, "Server is overloaded");
|
||||
|
||||
// Parse id now so errors from here on will have the id
|
||||
//
|
||||
// VFALCO NOTE Except that "id" isn't included in the following errors.
|
||||
//
|
||||
Json::Value const id = jsonRPC ["id"];
|
||||
|
||||
Json::Value const method = jsonRPC ["method"];
|
||||
|
||||
if (method.isNull ())
|
||||
return createResponse (400, "Null method");
|
||||
|
||||
if (! method.isString ())
|
||||
return createResponse (400, "method is not string");
|
||||
|
||||
std::string strMethod = method.asString ();
|
||||
if (strMethod.empty())
|
||||
return createResponse (400, "method is empty");
|
||||
|
||||
// Parse params
|
||||
Json::Value params = jsonRPC ["params"];
|
||||
|
||||
if (params.isNull ())
|
||||
params = Json::Value (Json::arrayValue);
|
||||
|
||||
else if (!params.isArray ())
|
||||
return HTTPReply (400, "params unparseable");
|
||||
|
||||
// VFALCO TODO Shouldn't we handle this earlier?
|
||||
//
|
||||
if (role == Role::FORBID)
|
||||
{
|
||||
// VFALCO TODO Needs implementing
|
||||
// FIXME Needs implementing
|
||||
// XXX This needs rate limiting to prevent brute forcing password.
|
||||
return HTTPReply (403, "Forbidden");
|
||||
}
|
||||
|
||||
|
||||
std::string response;
|
||||
RPCHandler rpcHandler (m_networkOPs);
|
||||
Resource::Charge loadType = Resource::feeReferenceRPC;
|
||||
|
||||
m_journal.debug << "Query: " << strMethod << params;
|
||||
|
||||
Json::Value const result (rpcHandler.doRpcCommand (
|
||||
strMethod, params, role, loadType));
|
||||
m_journal.debug << "Reply: " << result;
|
||||
|
||||
usage.charge (loadType);
|
||||
|
||||
response = JSONRPCReply (result, Json::Value (), id);
|
||||
|
||||
return createResponse (200, response);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Returns `true` if the HTTP request is a Websockets Upgrade
|
||||
// http://en.wikipedia.org/wiki/HTTP/1.1_Upgrade_header#Use_with_WebSockets
|
||||
bool
|
||||
ServerHandlerImp::isWebsocketUpgrade (beast::http::message const& request)
|
||||
{
|
||||
if (request.upgrade())
|
||||
return request.headers["Upgrade"] == "websocket";
|
||||
return false;
|
||||
}
|
||||
|
||||
// VFALCO DEPRECATED
|
||||
static std::string
|
||||
DecodeBase64 (std::string s)
|
||||
{
|
||||
// FIXME: This performs badly
|
||||
BIO* b64, *bmem;
|
||||
// Its 2014 and we're using calloc?
|
||||
char* buffer = static_cast<char*> (calloc (s.size (), sizeof (char)));
|
||||
b64 = BIO_new (BIO_f_base64 ());
|
||||
BIO_set_flags (b64, BIO_FLAGS_BASE64_NO_NL);
|
||||
bmem = BIO_new_mem_buf (const_cast<char*> (s.data ()), s.size ());
|
||||
bmem = BIO_push (b64, bmem);
|
||||
BIO_read (bmem, buffer, s.size ());
|
||||
BIO_free_all (bmem);
|
||||
std::string result (buffer);
|
||||
free (buffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
// VFALCO TODO Rewrite to use beast::http::headers
|
||||
bool
|
||||
ServerHandlerImp::authorized (HTTP::Port const& port,
|
||||
std::map<std::string, std::string> const& h)
|
||||
{
|
||||
if (port.user.empty() || port.password.empty())
|
||||
return true;
|
||||
|
||||
auto const it = h.find ("authorization");
|
||||
if ((it == h.end ()) || (it->second.substr (0, 6) != "Basic "))
|
||||
return false;
|
||||
std::string strUserPass64 = it->second.substr (6);
|
||||
boost::trim (strUserPass64);
|
||||
std::string strUserPass = DecodeBase64 (strUserPass64);
|
||||
std::string::size_type nColon = strUserPass.find (":");
|
||||
if (nColon == std::string::npos)
|
||||
return false;
|
||||
std::string strUser = strUserPass.substr (0, nColon);
|
||||
std::string strPassword = strUserPass.substr (nColon + 1);
|
||||
return strUser == port.user && strPassword == port.password;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
ServerHandlerImp::onWrite (beast::PropertyStream::Map& map)
|
||||
{
|
||||
m_server->onWrite (map);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Copied from Config::getAdminRole and modified to use the Port
|
||||
Role
|
||||
adminRole (HTTP::Port const& port,
|
||||
Json::Value const& params, beast::IP::Endpoint const& remoteIp)
|
||||
{
|
||||
Role role (Role::FORBID);
|
||||
|
||||
bool const bPasswordSupplied =
|
||||
params.isMember ("admin_user") ||
|
||||
params.isMember ("admin_password");
|
||||
|
||||
bool const bPasswordRequired =
|
||||
! port.admin_user.empty() || ! port.admin_password.empty();
|
||||
|
||||
bool bPasswordWrong;
|
||||
|
||||
if (bPasswordSupplied)
|
||||
{
|
||||
if (bPasswordRequired)
|
||||
{
|
||||
// Required, and supplied, check match
|
||||
bPasswordWrong =
|
||||
(port.admin_user !=
|
||||
(params.isMember ("admin_user") ? params["admin_user"].asString () : ""))
|
||||
||
|
||||
(port.admin_password !=
|
||||
(params.isMember ("admin_user") ? params["admin_password"].asString () : ""));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not required, but supplied
|
||||
bPasswordWrong = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Required but not supplied,
|
||||
bPasswordWrong = bPasswordRequired;
|
||||
}
|
||||
|
||||
// Meets IP restriction for admin.
|
||||
beast::IP::Endpoint const remote_addr (remoteIp.at_port (0));
|
||||
bool bAdminIP = false;
|
||||
|
||||
for (auto const& allow_addr : getConfig().RPC_ADMIN_ALLOW)
|
||||
{
|
||||
if (allow_addr == remote_addr)
|
||||
{
|
||||
bAdminIP = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bPasswordWrong // Wrong
|
||||
|| (bPasswordSupplied && !bAdminIP)) // Supplied and doesn't meet IP filter.
|
||||
{
|
||||
role = Role::FORBID;
|
||||
}
|
||||
// If supplied, password is correct.
|
||||
else
|
||||
{
|
||||
// Allow admin, if from admin IP and no password is required or it was supplied and correct.
|
||||
role = bAdminIP && (!bPasswordRequired || bPasswordSupplied) ? Role::ADMIN : Role::GUEST;
|
||||
}
|
||||
|
||||
return role;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Parse a comma-delimited list of values.
|
||||
std::vector<std::string>
|
||||
parse_csv (std::string const& in, std::ostream& log)
|
||||
{
|
||||
auto first = in.cbegin();
|
||||
auto const last = in.cend();
|
||||
std::vector<std::string> result;
|
||||
if (first != last)
|
||||
{
|
||||
static boost::regex const re(
|
||||
"^" // start of line
|
||||
"(?:\\s*)" // whitespace (optional)
|
||||
"([a-zA-Z][_a-zA-Z0-9]*)" // identifier
|
||||
"(?:\\s*)" // whitespace (optional)
|
||||
"(?:,?)" // comma (optional)
|
||||
"(?:\\s*)" // whitespace (optional)
|
||||
, boost::regex_constants::optimize
|
||||
);
|
||||
for(;;)
|
||||
{
|
||||
boost::smatch m;
|
||||
if (! boost::regex_search(first, last, m, re,
|
||||
boost::regex_constants::match_continuous))
|
||||
{
|
||||
log << "Expected <identifier>\n";
|
||||
throw std::exception();
|
||||
}
|
||||
result.push_back(m[1]);
|
||||
first = m[0].second;
|
||||
if (first == last)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Intermediate structure used for parsing
|
||||
struct ParsedPort
|
||||
{
|
||||
std::string name;
|
||||
std::set<std::string, beast::ci_less> protocol;
|
||||
std::string user;
|
||||
std::string password;
|
||||
std::string admin_user;
|
||||
std::string admin_password;
|
||||
std::string ssl_key;
|
||||
std::string ssl_cert;
|
||||
std::string ssl_chain;
|
||||
|
||||
boost::optional<boost::asio::ip::address> ip;
|
||||
boost::optional<std::uint16_t> port;
|
||||
boost::optional<bool> allow_admin;
|
||||
};
|
||||
|
||||
void
|
||||
parse_Port (ParsedPort& port, Section const& section, std::ostream& log)
|
||||
{
|
||||
{
|
||||
auto result = section.find("ip");
|
||||
if (result.second)
|
||||
{
|
||||
try
|
||||
{
|
||||
port.ip = boost::asio::ip::address::from_string(result.first);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
log << "Invalid value '" << result.first <<
|
||||
"' for key 'ip' in [" << section.name() << "]\n";
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto const result = section.find("port");
|
||||
if (result.second)
|
||||
{
|
||||
auto const ul = std::stoul(result.first);
|
||||
if (ul > std::numeric_limits<std::uint16_t>::max())
|
||||
{
|
||||
log <<
|
||||
"Value '" << result.first << "' for key 'port' is out of range\n";
|
||||
throw std::exception();
|
||||
}
|
||||
if (ul == 0)
|
||||
{
|
||||
log <<
|
||||
"Value '0' for key 'port' is invalid\n";
|
||||
throw std::exception();
|
||||
}
|
||||
port.port = static_cast<std::uint16_t>(ul);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto const result = section.find("protocol");
|
||||
if (result.second)
|
||||
{
|
||||
for (auto const& s : parse_csv(result.first, log))
|
||||
port.protocol.insert(s);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto const result = section.find("admin");
|
||||
if (result.second)
|
||||
{
|
||||
if (result.first == "no")
|
||||
{
|
||||
port.allow_admin = false;
|
||||
}
|
||||
else if (result.first == "allow")
|
||||
{
|
||||
port.allow_admin = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
log << "Invalid value '" << result.first <<
|
||||
"' for key 'admin' in [" << section.name() << "]\n";
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set(port.user, "user", section);
|
||||
set(port.password, "password", section);
|
||||
set(port.admin_user, "admin_user", section);
|
||||
set(port.admin_password, "admin_password", section);
|
||||
set(port.ssl_key, "ssl_key", section);
|
||||
set(port.ssl_cert, "ssl_cert", section);
|
||||
set(port.ssl_chain, "ssl_chain", section);
|
||||
}
|
||||
|
||||
HTTP::Port
|
||||
to_Port(ParsedPort const& parsed, std::ostream& log)
|
||||
{
|
||||
HTTP::Port p;
|
||||
p.name = parsed.name;
|
||||
|
||||
if (! parsed.ip)
|
||||
{
|
||||
log << "Missing 'ip' in [" << p.name << "]\n";
|
||||
throw std::exception();
|
||||
}
|
||||
p.ip = *parsed.ip;
|
||||
|
||||
if (! parsed.port)
|
||||
{
|
||||
log << "Missing 'port' in [" << p.name << "]\n";
|
||||
throw std::exception();
|
||||
}
|
||||
else if (*parsed.port == 0)
|
||||
{
|
||||
log << "Port " << *parsed.port << "in [" << p.name << "] is invalid\n";
|
||||
throw std::exception();
|
||||
}
|
||||
p.port = *parsed.port;
|
||||
|
||||
if (! parsed.allow_admin)
|
||||
p.allow_admin = false;
|
||||
else
|
||||
p.allow_admin = *parsed.allow_admin;
|
||||
|
||||
if (parsed.protocol.empty())
|
||||
{
|
||||
log << "Missing 'protocol' in [" << p.name << "]\n";
|
||||
throw std::exception();
|
||||
}
|
||||
p.protocol = parsed.protocol;
|
||||
if (p.websockets() &&
|
||||
(parsed.protocol.count("peer") > 0 ||
|
||||
parsed.protocol.count("http") > 0 ||
|
||||
parsed.protocol.count("https") > 0))
|
||||
{
|
||||
log << "Invalid protocol combination in [" << p.name << "]\n";
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
p.user = parsed.user;
|
||||
p.password = parsed.password;
|
||||
p.admin_user = parsed.admin_user;
|
||||
p.admin_password = parsed.admin_password;
|
||||
p.ssl_key = parsed.ssl_key;
|
||||
p.ssl_cert = parsed.ssl_cert;
|
||||
p.ssl_chain = parsed.ssl_chain;
|
||||
|
||||
if (p.ssl_key.empty() && p.ssl_cert.empty() &&
|
||||
p.ssl_chain.empty())
|
||||
p.context = make_SSLContext();
|
||||
else
|
||||
p.context = make_SSLContextAuthed (
|
||||
p.ssl_key, p.ssl_cert, p.ssl_chain);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
std::vector<HTTP::Port>
|
||||
parse_Ports (BasicConfig const& config, std::ostream& log)
|
||||
{
|
||||
std::vector<HTTP::Port> result;
|
||||
|
||||
if (! config.exists("server"))
|
||||
{
|
||||
log <<
|
||||
"Missing section: [server]\n";
|
||||
return result;
|
||||
}
|
||||
|
||||
ParsedPort common;
|
||||
parse_Port (common, config["server"], log);
|
||||
|
||||
auto const& names = config.section("server").values();
|
||||
result.reserve(names.size());
|
||||
for (auto const& name : names)
|
||||
{
|
||||
if (! config.exists(name))
|
||||
{
|
||||
log <<
|
||||
"Missing section: [" << name << "]\n";
|
||||
throw std::exception();
|
||||
}
|
||||
ParsedPort parsed = common;
|
||||
parsed.name = name;
|
||||
parse_Port(parsed, config[name], log);
|
||||
result.push_back(to_Port(parsed, log));
|
||||
}
|
||||
|
||||
std::size_t count = 0;
|
||||
for (auto const& p : result)
|
||||
if (p.protocol.count("peer") > 0)
|
||||
++count;
|
||||
if (count > 1)
|
||||
{
|
||||
log << "Error: More than one peer protocol configured in [server]\n";
|
||||
throw std::exception();
|
||||
}
|
||||
if (count == 0)
|
||||
log << "Warning: No peer protocol configured\n";
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Fill out the client portion of the Setup
|
||||
void
|
||||
setup_Client (ServerHandler::Setup& setup)
|
||||
{
|
||||
decltype(setup.ports)::const_iterator iter;
|
||||
for (iter = setup.ports.cbegin();
|
||||
iter != setup.ports.cend(); ++iter)
|
||||
if (iter->protocol.count("http") > 0 ||
|
||||
iter->protocol.count("https") > 0)
|
||||
break;
|
||||
if (iter == setup.ports.cend())
|
||||
return;
|
||||
setup.client.secure =
|
||||
iter->protocol.count("https") > 0;
|
||||
setup.client.ip = iter->ip.to_string();
|
||||
// VFALCO HACK! to make localhost work
|
||||
if (setup.client.ip == "0.0.0.0")
|
||||
setup.client.ip = "127.0.0.1";
|
||||
setup.client.port = iter->port;
|
||||
setup.client.user = iter->user;
|
||||
setup.client.password = iter->password;
|
||||
setup.client.admin_user = iter->admin_user;
|
||||
setup.client.admin_password = iter->admin_password;
|
||||
}
|
||||
|
||||
// Fill out the overlay portion of the Setup
|
||||
void
|
||||
setup_Overlay (ServerHandler::Setup& setup)
|
||||
{
|
||||
auto const iter = std::find_if(setup.ports.cbegin(), setup.ports.cend(),
|
||||
[](HTTP::Port const& port)
|
||||
{
|
||||
return port.protocol.count("peer") > 0;
|
||||
});
|
||||
if (iter == setup.ports.cend())
|
||||
{
|
||||
setup.overlay.port = 0;
|
||||
return;
|
||||
}
|
||||
setup.overlay.ip = iter->ip;
|
||||
setup.overlay.port = iter->port;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ServerHandler::Setup
|
||||
setup_ServerHandler (BasicConfig const& config, std::ostream& log)
|
||||
{
|
||||
ServerHandler::Setup setup;
|
||||
setup.ports = detail::parse_Ports (config, log);
|
||||
detail::setup_Client(setup);
|
||||
detail::setup_Overlay(setup);
|
||||
return setup;
|
||||
}
|
||||
|
||||
std::unique_ptr <ServerHandler>
|
||||
make_ServerHandler (beast::Stoppable& parent,
|
||||
boost::asio::io_service& io_service, JobQueue& jobQueue,
|
||||
NetworkOPs& networkOPs, Resource::Manager& resourceManager)
|
||||
{
|
||||
return std::make_unique <ServerHandlerImp> (parent, io_service,
|
||||
jobQueue, networkOPs, resourceManager);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,12 +17,12 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_APP_MAIN_SERVERHANDLERIMP_H_INCLUDED
|
||||
#define RIPPLE_APP_MAIN_SERVERHANDLERIMP_H_INCLUDED
|
||||
#ifndef RIPPLE_SERVER_SERVERHANDLERIMP_H_INCLUDED
|
||||
#define RIPPLE_SERVER_SERVERHANDLERIMP_H_INCLUDED
|
||||
|
||||
#include <ripple/app/main/ServerHandler.h>
|
||||
#include <ripple/common/RippleSSLContext.h>
|
||||
#include <ripple/http/Session.h>
|
||||
#include <ripple/core/Job.h>
|
||||
#include <ripple/server/ServerHandler.h>
|
||||
#include <ripple/server/Session.h>
|
||||
#include <ripple/rpc/RPCHandler.h>
|
||||
|
||||
namespace ripple {
|
||||
@@ -39,19 +39,24 @@ private:
|
||||
JobQueue& m_jobQueue;
|
||||
NetworkOPs& m_networkOPs;
|
||||
std::unique_ptr<HTTP::Server> m_server;
|
||||
std::unique_ptr <RippleSSLContext> m_context;
|
||||
RPC::Setup setup_;
|
||||
Setup setup_;
|
||||
|
||||
public:
|
||||
ServerHandlerImp (Stoppable& parent, JobQueue& jobQueue,
|
||||
NetworkOPs& networkOPs, Resource::Manager& resourceManager,
|
||||
RPC::Setup const& setup);
|
||||
ServerHandlerImp (Stoppable& parent, boost::asio::io_service& io_service,
|
||||
JobQueue& jobQueue, NetworkOPs& networkOPs,
|
||||
Resource::Manager& resourceManager);
|
||||
|
||||
~ServerHandlerImp();
|
||||
|
||||
private:
|
||||
void
|
||||
setup (beast::Journal journal) override;
|
||||
setup (Setup const& setup, beast::Journal journal) override;
|
||||
|
||||
Setup const&
|
||||
setup() const override
|
||||
{
|
||||
return setup_;
|
||||
}
|
||||
|
||||
//
|
||||
// Stoppable
|
||||
@@ -67,6 +72,25 @@ private:
|
||||
void
|
||||
onAccept (HTTP::Session& session) override;
|
||||
|
||||
bool
|
||||
onAccept (HTTP::Session& session,
|
||||
boost::asio::ip::tcp::endpoint endpoint) override;
|
||||
|
||||
void
|
||||
onLegacyPeerHello (std::unique_ptr<beast::asio::ssl_bundle>&& ssl_bundle,
|
||||
boost::asio::const_buffer buffer,
|
||||
boost::asio::ip::tcp::endpoint remote_address) override;
|
||||
|
||||
Handoff
|
||||
onHandoff (HTTP::Session& session,
|
||||
std::unique_ptr <beast::asio::ssl_bundle>&& bundle,
|
||||
beast::http::message&& request,
|
||||
boost::asio::ip::tcp::endpoint remote_address) override;
|
||||
|
||||
Handoff
|
||||
onHandoff (HTTP::Session& session, boost::asio::ip::tcp::socket&& socket,
|
||||
beast::http::message&& request,
|
||||
boost::asio::ip::tcp::endpoint remote_address) override;
|
||||
void
|
||||
onRequest (HTTP::Session& session) override;
|
||||
|
||||
@@ -87,7 +111,7 @@ private:
|
||||
createResponse (int statusCode, std::string const& description);
|
||||
|
||||
std::string
|
||||
processRequest (std::string const& request,
|
||||
processRequest (HTTP::Port const& port, std::string const& request,
|
||||
beast::IP::Endpoint const& remoteIPAddress);
|
||||
|
||||
//
|
||||
@@ -96,15 +120,16 @@ private:
|
||||
|
||||
void
|
||||
onWrite (beast::PropertyStream::Map& map) override;
|
||||
|
||||
private:
|
||||
bool
|
||||
isWebsocketUpgrade (beast::http::message const& request);
|
||||
|
||||
bool
|
||||
authorized (HTTP::Port const& port,
|
||||
std::map<std::string, std::string> const& h);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
std::unique_ptr <ServerHandler>
|
||||
make_RPCHTTPServer (beast::Stoppable& parent, JobQueue& jobQueue,
|
||||
NetworkOPs& networkOPs, Resource::Manager& resourceManager,
|
||||
RPC::Setup const& setup);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -17,8 +17,12 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/http/impl/ServerImpl.h>
|
||||
#include <ripple/http/impl/Peer.h>
|
||||
#if DOXYGEN
|
||||
#include <ripple/server/README.md>
|
||||
#endif
|
||||
|
||||
#include <ripple/server/impl/ServerImpl.h>
|
||||
#include <ripple/server/impl/Peer.h>
|
||||
#include <beast/chrono/chrono_io.h>
|
||||
#include <boost/chrono/chrono_io.hpp>
|
||||
#include <cassert>
|
||||
@@ -32,15 +36,15 @@
|
||||
namespace ripple {
|
||||
namespace HTTP {
|
||||
|
||||
ServerImpl::ServerImpl (Handler& handler, beast::Journal journal)
|
||||
ServerImpl::ServerImpl (Handler& handler,
|
||||
boost::asio::io_service& io_service, beast::Journal journal)
|
||||
: handler_ (handler)
|
||||
, journal_ (journal)
|
||||
, io_service_ (io_service)
|
||||
, strand_ (io_service_)
|
||||
, work_ (boost::in_place (std::ref (io_service_)))
|
||||
, work_ (boost::in_place (std::ref(io_service)))
|
||||
, hist_{}
|
||||
{
|
||||
thread_ = std::thread (std::bind (
|
||||
&ServerImpl::run, this));
|
||||
}
|
||||
|
||||
ServerImpl::~ServerImpl()
|
||||
@@ -52,7 +56,6 @@ ServerImpl::~ServerImpl()
|
||||
while (! list_.empty())
|
||||
cond_.wait(lock);
|
||||
}
|
||||
thread_.join();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -61,6 +64,7 @@ ServerImpl::ports (std::vector<Port> const& ports)
|
||||
if (closed())
|
||||
throw std::logic_error("ports() on closed HTTP::Server");
|
||||
for(auto const& _ : ports)
|
||||
if (! _.websockets())
|
||||
std::make_shared<Door>(
|
||||
io_service_, *this, _)->run();
|
||||
}
|
||||
@@ -198,13 +202,13 @@ ServerImpl::ceil_log2 (unsigned long long x)
|
||||
return y;
|
||||
}
|
||||
|
||||
void
|
||||
ServerImpl::run()
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
std::unique_ptr<Server>
|
||||
make_Server (Handler& handler,
|
||||
boost::asio::io_service& io_service, beast::Journal journal)
|
||||
{
|
||||
static std::atomic <int> id;
|
||||
beast::Thread::setCurrentThreadName (
|
||||
std::string("HTTP::Server #") + std::to_string (++id));
|
||||
io_service_.run();
|
||||
return std::make_unique<ServerImpl>(handler, io_service, journal);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,11 +17,12 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_HTTP_SERVERIMPL_H_INCLUDED
|
||||
#define RIPPLE_HTTP_SERVERIMPL_H_INCLUDED
|
||||
#ifndef RIPPLE_SERVER_SERVERIMPL_H_INCLUDED
|
||||
#define RIPPLE_SERVER_SERVERIMPL_H_INCLUDED
|
||||
|
||||
#include <ripple/common/seconds_clock.h>
|
||||
#include <ripple/http/Server.h>
|
||||
#include <ripple/server/Handler.h>
|
||||
#include <ripple/server/Server.h>
|
||||
#include <beast/intrusive/List.h>
|
||||
#include <beast/threads/SharedData.h>
|
||||
#include <beast/threads/Thread.h>
|
||||
@@ -77,20 +78,22 @@ private:
|
||||
typedef std::vector <std::shared_ptr<Door>> Doors;
|
||||
|
||||
Handler& handler_;
|
||||
std::thread thread_;
|
||||
beast::Journal journal_;
|
||||
boost::asio::io_service& io_service_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::optional <boost::asio::io_service::work> work_;
|
||||
|
||||
std::mutex mutable mutex_;
|
||||
std::condition_variable cond_;
|
||||
list_type list_;
|
||||
beast::Journal journal_;
|
||||
boost::asio::io_service io_service_;
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::optional <boost::asio::io_service::work> work_;
|
||||
std::deque <Stat> stats_;
|
||||
std::array <std::size_t, 64> hist_;
|
||||
int high_ = 0;
|
||||
|
||||
std::array <std::size_t, 64> hist_;
|
||||
|
||||
public:
|
||||
ServerImpl (Handler& handler, beast::Journal journal);
|
||||
ServerImpl (Handler& handler,
|
||||
boost::asio::io_service& io_service, beast::Journal journal);
|
||||
|
||||
~ServerImpl();
|
||||
|
||||
@@ -138,9 +141,6 @@ private:
|
||||
static
|
||||
int
|
||||
ceil_log2 (unsigned long long x);
|
||||
|
||||
void
|
||||
run();
|
||||
};
|
||||
|
||||
|
||||
@@ -17,23 +17,23 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_NET_BASICS_RPCDOOR_H_INCLUDED
|
||||
#define RIPPLE_NET_BASICS_RPCDOOR_H_INCLUDED
|
||||
#ifndef RIPPLE_SERVER_MAKE_SERVER_H_INCLUDED
|
||||
#define RIPPLE_SERVER_MAKE_SERVER_H_INCLUDED
|
||||
|
||||
#include <ripple/net/RPCServer.h>
|
||||
#include <ripple/server/Handler.h>
|
||||
#include <ripple/server/Server.h>
|
||||
#include <beast/utility/Journal.h>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
|
||||
namespace ripple {
|
||||
namespace HTTP {
|
||||
|
||||
/** Listening socket for RPC requests.
|
||||
*/
|
||||
class RPCDoor
|
||||
{
|
||||
public:
|
||||
static RPCDoor* New (boost::asio::io_service& io_service, RPCServer::Handler& handler);
|
||||
|
||||
virtual ~RPCDoor () { }
|
||||
};
|
||||
/** 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);
|
||||
|
||||
} // HTTP
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
@@ -17,30 +17,25 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_PEERDOOR_H_INCLUDED
|
||||
#define RIPPLE_PEERDOOR_H_INCLUDED
|
||||
#ifndef RIPPLE_SERVER_MAKE_SERVERHANDLER_H_INCLUDED
|
||||
#define RIPPLE_SERVER_MAKE_SERVERHANDLER_H_INCLUDED
|
||||
|
||||
#include <ripple/overlay/impl/OverlayImpl.h>
|
||||
#include <ripple/core/Config.h>
|
||||
#include <ripple/server/Server.h>
|
||||
#include <ripple/overlay/Overlay.h>
|
||||
#include <ripple/server/ServerHandler.h>
|
||||
#include <beast/utility/Journal.h>
|
||||
#include <beast/utility/PropertyStream.h>
|
||||
#include <beast/cxx14/memory.h> // <memory>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
/** Handles incoming connections from peers. */
|
||||
class PeerDoor
|
||||
{
|
||||
public:
|
||||
virtual
|
||||
~PeerDoor() = default;
|
||||
std::unique_ptr <ServerHandler>
|
||||
make_ServerHandler (beast::Stoppable& parent, boost::asio::io_service& io_service,
|
||||
JobQueue& jobQueue, NetworkOPs& networkOPs, Resource::Manager& resourceManager);
|
||||
|
||||
virtual
|
||||
void stop() = 0;
|
||||
};
|
||||
|
||||
// VFALCO DEPRECATED This will be replaced by a universal door
|
||||
std::unique_ptr <PeerDoor>
|
||||
make_PeerDoor (OverlayImpl& overlay, std::string const& ip, int port,
|
||||
boost::asio::io_service& io_service);
|
||||
|
||||
}
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
@@ -17,11 +17,12 @@
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <ripple/common/RippleSSLContext.h>
|
||||
#include <ripple/http/Session.h>
|
||||
#include <ripple/http/Server.h>
|
||||
#include <ripple/common/make_SSLContext.h>
|
||||
#include <ripple/server/Server.h>
|
||||
#include <ripple/server/Session.h>
|
||||
#include <beast/unit_test/suite.h>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <chrono>
|
||||
#include <stdexcept>
|
||||
#include <thread>
|
||||
@@ -37,6 +38,35 @@ public:
|
||||
testPort = 1001
|
||||
};
|
||||
|
||||
class TestThread
|
||||
{
|
||||
private:
|
||||
boost::asio::io_service io_service_;
|
||||
boost::optional<boost::asio::io_service::work> work_;
|
||||
std::thread thread_;
|
||||
|
||||
public:
|
||||
TestThread()
|
||||
: work_(boost::in_place(std::ref(io_service_)))
|
||||
, thread_([&]() { this->io_service_.run(); })
|
||||
{
|
||||
}
|
||||
|
||||
~TestThread()
|
||||
{
|
||||
work_ = boost::none;
|
||||
thread_.join();
|
||||
}
|
||||
|
||||
boost::asio::io_service&
|
||||
get_io_service()
|
||||
{
|
||||
return io_service_;
|
||||
}
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
class TestSink : public beast::Journal::Sink
|
||||
{
|
||||
beast::unit_test::suite& suite_;
|
||||
@@ -55,6 +85,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
struct TestHandler : Handler
|
||||
{
|
||||
void
|
||||
@@ -62,6 +94,37 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
onAccept (Session& session,
|
||||
boost::asio::ip::tcp::endpoint endpoint) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
onLegacyPeerHello (std::unique_ptr<beast::asio::ssl_bundle>&& ssl_bundle,
|
||||
boost::asio::const_buffer buffer,
|
||||
boost::asio::ip::tcp::endpoint remote_address) override
|
||||
{
|
||||
}
|
||||
|
||||
Handoff
|
||||
onHandoff (Session& session,
|
||||
std::unique_ptr <beast::asio::ssl_bundle>&& bundle,
|
||||
beast::http::message&& request,
|
||||
boost::asio::ip::tcp::endpoint remote_address) override
|
||||
{
|
||||
return Handoff{};
|
||||
}
|
||||
|
||||
Handoff
|
||||
onHandoff (Session& session, boost::asio::ip::tcp::socket&& socket,
|
||||
beast::http::message&& request,
|
||||
boost::asio::ip::tcp::endpoint remote_address) override
|
||||
{
|
||||
return Handoff{};
|
||||
}
|
||||
|
||||
void
|
||||
onRequest (Session& session) override
|
||||
{
|
||||
@@ -84,6 +147,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Connect to an address
|
||||
template <class Socket>
|
||||
bool
|
||||
@@ -227,16 +292,18 @@ public:
|
||||
run()
|
||||
{
|
||||
TestSink sink {*this};
|
||||
TestThread thread;
|
||||
sink.severity (beast::Journal::Severity::kAll);
|
||||
beast::Journal journal {sink};
|
||||
TestHandler handler;
|
||||
auto s = make_Server (handler, journal);
|
||||
auto s = make_Server (handler,
|
||||
thread.get_io_service(), journal);
|
||||
std::vector<Port> list;
|
||||
std::unique_ptr <RippleSSLContext> c (
|
||||
RippleSSLContext::createBare ());
|
||||
list.emplace_back (testPort, beast::IP::Endpoint (
|
||||
beast::IP::AddressV4 (127, 0, 0, 1), 0),
|
||||
Port::Security::no_ssl, c.get());
|
||||
list.resize(1);
|
||||
list.back().port = testPort;
|
||||
list.back().ip = boost::asio::ip::address::from_string (
|
||||
"127.0.0.1");
|
||||
list.back().protocol.insert("http");
|
||||
s->ports (list);
|
||||
|
||||
test_request();
|
||||
@@ -24,12 +24,10 @@
|
||||
#include <ripple/unity/rpcx.h>
|
||||
#include <ripple/unity/websocket.h>
|
||||
#include <ripple/unity/resource.h>
|
||||
#include <ripple/http/Server.h>
|
||||
#include <ripple/app/impl/BasicApp.cpp>
|
||||
#include <ripple/app/main/CollectorManager.cpp>
|
||||
#include <ripple/app/main/NodeStoreScheduler.cpp>
|
||||
#include <ripple/app/main/FatalErrorReporter.cpp>
|
||||
#include <ripple/app/main/ServerHandlerImp.cpp>
|
||||
#include <ripple/app/tx/TxQueueEntry.h>
|
||||
#include <ripple/app/tx/TxQueueEntry.cpp>
|
||||
#include <ripple/app/tx/TxQueue.cpp>
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
#include <ripple/common/seconds_clock.h>
|
||||
#include <ripple/unity/resource.h>
|
||||
#include <ripple/common/RippleSSLContext.h>
|
||||
|
||||
#include <deque>
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
#include <BeastConfig.h>
|
||||
|
||||
#include <ripple/common/impl/KeyCache.cpp>
|
||||
#include <ripple/common/impl/make_SSLContext.cpp>
|
||||
#include <ripple/common/impl/ResolverAsio.cpp>
|
||||
#include <ripple/common/impl/RippleSSLContext.cpp>
|
||||
#include <ripple/common/impl/TaggedCache.cpp>
|
||||
|
||||
#include <ripple/common/tests/cross_offer.test.cpp>
|
||||
|
||||
@@ -32,9 +32,7 @@
|
||||
#include <ripple/net/impl/HTTPClient.cpp>
|
||||
#include <ripple/net/impl/InfoSub.cpp>
|
||||
#include <ripple/net/impl/RPCCall.cpp>
|
||||
#include <ripple/net/impl/RPCDoor.cpp> // Is this still needed?
|
||||
#include <ripple/net/impl/RPCErr.cpp>
|
||||
#include <ripple/net/impl/RPCServerImp.h>
|
||||
#include <ripple/net/impl/RPCSub.cpp>
|
||||
#include <ripple/net/impl/RPCUtil.cpp>
|
||||
#include <ripple/net/impl/SNTPClient.cpp>
|
||||
|
||||
@@ -32,11 +32,9 @@
|
||||
#include <ripple/net/HTTPRequest.h>
|
||||
#include <ripple/net/HTTPClient.h>
|
||||
#include <ripple/net/RPCServer.h>
|
||||
#include <ripple/net/RPCDoor.h>
|
||||
#include <ripple/net/SNTPClient.h>
|
||||
|
||||
#include <ripple/net/RPCErr.h>
|
||||
#include <ripple/net/RPCUtil.h>
|
||||
#include <ripple/net/RPCCall.h>
|
||||
#include <ripple/net/InfoSub.h>
|
||||
#include <ripple/net/RPCSub.h>
|
||||
|
||||
@@ -23,7 +23,5 @@
|
||||
#include <ripple/overlay/impl/message_name.cpp>
|
||||
#include <ripple/overlay/impl/OverlayImpl.cpp>
|
||||
#include <ripple/overlay/impl/PeerImp.cpp>
|
||||
#include <ripple/overlay/impl/PeerDoor.cpp>
|
||||
|
||||
#include <ripple/overlay/tests/peer_info.test.cpp>
|
||||
|
||||
|
||||
@@ -19,8 +19,9 @@
|
||||
|
||||
#include <BeastConfig.h>
|
||||
|
||||
#include <ripple/http/impl/Door.cpp>
|
||||
#include <ripple/http/impl/Port.cpp>
|
||||
#include <ripple/http/impl/ServerImpl.cpp>
|
||||
#include <ripple/http/impl/Server.cpp>
|
||||
#include <ripple/http/tests/Server.test.cpp>
|
||||
#include <ripple/server/impl/Door.cpp>
|
||||
#include <ripple/server/impl/JSONRPCUtil.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>
|
||||
@@ -51,14 +51,6 @@ public:
|
||||
static void handle_shutdown(autotls_socket_ptr, const boost::system::error_code&) {
|
||||
}
|
||||
|
||||
void set_secure_only() {
|
||||
m_secure_only = true;
|
||||
}
|
||||
|
||||
void set_plain_only() {
|
||||
m_plain_only = true;
|
||||
}
|
||||
|
||||
// should be private friended?
|
||||
autotls_socket::handshake_type get_handshake_type() {
|
||||
if (static_cast< endpoint_type* >(this)->is_server()) {
|
||||
@@ -70,10 +62,12 @@ public:
|
||||
|
||||
class handler_interface {
|
||||
public:
|
||||
virtual ~handler_interface() {}
|
||||
virtual ~handler_interface() = default;
|
||||
|
||||
virtual void on_tcp_init() {};
|
||||
virtual boost::asio::ssl::context& get_ssl_context () = 0;
|
||||
virtual bool plain_only() = 0;
|
||||
virtual bool secure_only() = 0;
|
||||
};
|
||||
|
||||
// Connection specific details
|
||||
@@ -108,8 +102,8 @@ public:
|
||||
m_connection.get_handler()->get_ssl_context());
|
||||
|
||||
m_socket_ptr = autotls_socket_ptr (new autotls_socket (
|
||||
m_endpoint.get_io_service(), ssl_context, m_endpoint.m_secure_only,
|
||||
m_endpoint.m_plain_only));
|
||||
m_endpoint.get_io_service(), ssl_context, m_connection.get_handler()->secure_only(),
|
||||
m_connection.get_handler()->plain_only()));
|
||||
}
|
||||
|
||||
void async_init(boost::function<void(const boost::system::error_code&)> callback)
|
||||
@@ -164,11 +158,12 @@ public:
|
||||
connection_type& m_connection;
|
||||
};
|
||||
protected:
|
||||
autotls (boost::asio::io_service& m) : m_io_service(m), m_secure_only(false), m_plain_only(false) {}
|
||||
autotls (boost::asio::io_service& m) : m_io_service(m)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
boost::asio::io_service& m_io_service;
|
||||
bool m_secure_only;
|
||||
bool m_plain_only;
|
||||
};
|
||||
|
||||
} // namespace socket
|
||||
|
||||
Reference in New Issue
Block a user