diff --git a/Builds/VisualStudio2013/RippleD.vcxproj b/Builds/VisualStudio2013/RippleD.vcxproj
index e617f09ff5..b78571b869 100644
--- a/Builds/VisualStudio2013/RippleD.vcxproj
+++ b/Builds/VisualStudio2013/RippleD.vcxproj
@@ -1811,13 +1811,6 @@
-
-
-
- True
-
-
-
@@ -2024,6 +2017,8 @@
+
+
True
@@ -2190,10 +2185,10 @@
True
-
+
True
-
+
True
@@ -2203,12 +2198,12 @@
+
+
-
-
@@ -2371,37 +2366,6 @@
-
- True
-
-
-
-
-
-
-
-
- True
-
-
- True
-
-
- True
-
-
-
-
-
-
-
-
-
-
-
-
- True
-
True
@@ -2460,9 +2424,6 @@
True
-
- True
-
True
@@ -2471,9 +2432,6 @@
True
-
- True
-
True
@@ -2481,16 +2439,12 @@
-
-
-
-
@@ -2615,11 +2569,6 @@
-
- True
-
-
-
True
@@ -3052,6 +3001,62 @@
+
+
+
+
+
+ True
+
+
+
+
+ True
+
+
+
+
+
+
+
+
+ True
+
+
+ True
+
+
+
+
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+
+
+
@@ -3185,8 +3190,6 @@
-
-
..\..\src\hyperleveldb;..\..\src\snappy\config;..\..\src\snappy\snappy;%(AdditionalIncludeDirectories)
..\..\src\hyperleveldb;..\..\src\snappy\config;..\..\src\snappy\snappy;%(AdditionalIncludeDirectories)
@@ -3233,6 +3236,8 @@
+
+
diff --git a/Builds/VisualStudio2013/RippleD.vcxproj.filters b/Builds/VisualStudio2013/RippleD.vcxproj.filters
index c67f11064b..f144100b6a 100644
--- a/Builds/VisualStudio2013/RippleD.vcxproj.filters
+++ b/Builds/VisualStudio2013/RippleD.vcxproj.filters
@@ -364,15 +364,6 @@
{1906827A-5174-9515-DC11-9D11C511E0CB}
-
- {8601C61D-413C-725E-C9E6-BD4F97E40032}
-
-
- {43D68742-4714-D103-EE00-EB10BD045FB6}
-
-
- {AA0D98CC-99E6-61CE-86D7-35156DC4EE55}
-
{BEDCC703-A2C8-FF25-7E1E-3471BD39ED98}
@@ -436,6 +427,15 @@
{93AC3675-D183-4DB4-021E-8F4CA1586866}
+
+ {8A61DBF7-69CB-9043-8312-D44C40EC6AE9}
+
+
+ {B0649154-4449-1172-FF4F-9F7A46908774}
+
+
+ {9BA46DD5-4B0C-3C1D-6F16-93DE8A9B7313}
+
{CB0AC82D-AEA3-F41C-847F-D6ECA4971891}
@@ -2703,15 +2703,6 @@
ripple\app\main
-
- ripple\app\main
-
-
- ripple\app\main
-
-
- ripple\app\main
-
ripple\app\main
@@ -2958,6 +2949,9 @@
ripple\app\shamap
+
+ ripple\app\shamap
+
ripple\app\transactors
@@ -3153,10 +3147,10 @@
ripple\common\impl
-
+
ripple\common\impl
-
+
ripple\common\impl
@@ -3168,15 +3162,15 @@
ripple\common
+
+ ripple\common
+
ripple\common
ripple\common
-
- ripple\common
-
ripple\common
@@ -3378,45 +3372,6 @@
ripple\data\utility
-
- ripple\http\impl
-
-
- ripple\http\impl
-
-
- ripple\http\impl
-
-
- ripple\http\impl
-
-
- ripple\http\impl
-
-
- ripple\http\impl
-
-
- ripple\http\impl
-
-
- ripple\http\impl
-
-
- ripple\http\impl
-
-
- ripple\http\impl
-
-
- ripple\http
-
-
- ripple\http
-
-
- ripple\http\tests
-
ripple\json\impl
@@ -3489,9 +3444,6 @@
ripple\net\impl
-
- ripple\net\impl
-
ripple\net\impl
@@ -3501,9 +3453,6 @@
ripple\net\impl
-
- ripple\net\impl
-
ripple\net\impl
@@ -3513,9 +3462,6 @@
ripple\net
-
- ripple\net
-
ripple\net
@@ -3525,9 +3471,6 @@
ripple\net
-
- ripple\net
-
ripple\net
@@ -3678,12 +3621,6 @@
ripple\overlay\impl
-
- ripple\overlay\impl
-
-
- ripple\overlay\impl
-
ripple\overlay\impl
@@ -4179,6 +4116,81 @@
ripple\rpc
+
+ ripple\server
+
+
+ ripple\server
+
+
+ ripple\server\impl
+
+
+ ripple\server\impl
+
+
+ ripple\server\impl
+
+
+ ripple\server\impl
+
+
+ ripple\server\impl
+
+
+ ripple\server\impl
+
+
+ ripple\server\impl
+
+
+ ripple\server\impl
+
+
+ ripple\server\impl
+
+
+ ripple\server\impl
+
+
+ ripple\server\impl
+
+
+ ripple\server\impl
+
+
+ ripple\server
+
+
+ ripple\server
+
+
+ ripple\server
+
+
+ ripple\server
+
+
+ ripple\server
+
+
+ ripple\server
+
+
+ ripple\server
+
+
+ ripple\server
+
+
+ ripple\server
+
+
+ ripple\server\tests
+
+
+ ripple\server
+
ripple\sitefiles\impl
@@ -4359,9 +4371,6 @@
ripple\unity
-
- ripple\unity
-
ripple\unity
@@ -4419,6 +4428,9 @@
ripple\unity
+
+ ripple\unity
+
ripple\unity
diff --git a/SConstruct b/SConstruct
index f9e9601213..09c63f2f48 100644
--- a/SConstruct
+++ b/SConstruct
@@ -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',
diff --git a/doc/rippled-example.cfg b/doc/rippled-example.cfg
index a7a3c614c0..be613f2af0 100644
--- a/doc/rippled-example.cfg
+++ b/doc/rippled-example.cfg
@@ -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.
+#
+#
+#
+# []
+#
+# A series of key/value pairs that define the settings for the port with
+# the corresponding name. These keys are possible:
+#
+# ip =
+#
+# Required. Determines the IP address of the network interface to bind
+# to. To bind to all available interfaces, uses 0.0.0.0
+#
+# port =
+#
+# 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 =
+# password =
+#
+# 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 =
+# admin_password =
+#
+# 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 =
+# ssl_cert =
+# ssl_chain =
+#
+# 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]
+#
+#
+#
+# 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]
-#
-#
-#
-# 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]
-#
-#
-#
-# 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]
-#
-#
-#
-# A file system path leading to the file with the certificate chain.
-# The chain may include the end certificate.
-#
-#
-#
-# [rpc_ssl_key]
-#
-#
-#
-# 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
-
-
diff --git a/src/ripple/app/main/Application.cpp b/src/ripple/app/main/Application.cpp
index 7659e0fc67..e22961091f 100644
--- a/src/ripple/app/main/Application.cpp
+++ b/src/ripple/app/main/Application.cpp
@@ -24,13 +24,15 @@
#include
#include
#include
-#include
+#include
#include
-#include
#include
#include
#include
#include
+#include
+#include
+#include
#include
#include
#include
@@ -193,12 +195,8 @@ public:
std::unique_ptr mTxnDB;
std::unique_ptr mLedgerDB;
std::unique_ptr mWalletDB;
-
- std::unique_ptr m_wsSSLContext;
- std::unique_ptr m_peers;
- std::unique_ptr m_rpcDoor;
- std::unique_ptr m_wsPublicDoor;
- std::unique_ptr m_wsPrivateDoor;
+ std::unique_ptr m_overlay;
+ std::vector > 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,
- getConfig().getModuleDatabasePath(), *m_resolver,
+ 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));
- }
- 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)
+ if (! port.websockets())
+ continue;
+ auto door = make_WSDoor(port, *m_resourceManager, getOPs());
+ if (door == nullptr)
{
- beast::FatalError ("Could not open the WebSocket private interface.",
- __FILE__, __LINE__);
+ m_journal.fatal << "Could not create Websocket for [" <<
+ port.name << "]";
+ throw std::exception();
}
- }
- 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.
//
diff --git a/src/ripple/app/main/Application.h b/src/ripple/app/main/Application.h
index 4587d568a0..00365fcc3a 100644
--- a/src/ripple/app/main/Application.h
+++ b/src/ripple/app/main/Application.h
@@ -21,6 +21,12 @@
#define RIPPLE_APP_APPLICATION_H_INCLUDED
#include
+#include
+#include
+#include
+#include
+
+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 ScopedLockType;
typedef std::unique_ptr ScopedLock;
diff --git a/src/ripple/app/main/LocalCredentials.cpp b/src/ripple/app/main/LocalCredentials.cpp
index 043795ad2f..91b8730427 100644
--- a/src/ripple/app/main/LocalCredentials.cpp
+++ b/src/ripple/app/main/LocalCredentials.cpp
@@ -18,6 +18,7 @@
//==============================================================================
#include
+#include
#include
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;
diff --git a/src/ripple/app/main/Main.cpp b/src/ripple/app/main/Main.cpp
index 4f5d60c28b..e00106e367 100644
--- a/src/ripple/app/main/Main.cpp
+++ b/src/ripple/app/main/Main.cpp
@@ -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 ());
- getConfig().overwrite("rpc", "ip", vm["rpc_ip"].as());
+ // VFALCO TODO This is currently broken
+ //getConfig ().setRpcIpAndOptionalPort (vm ["rpc_ip"].as ());
+ //getConfig().overwrite("rpc", "ip", vm["rpc_ip"].as());
}
// 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 ());
- getConfig().overwrite("rpc", "port", vm["rpc_port"].as());
+ // VFALCO TODO This is currently broken
+ //getConfig ().setRpcPort (vm ["rpc_port"].as ());
+ //getConfig().overwrite("rpc", "port", vm["rpc_port"].as());
}
if (vm.count ("quorum"))
diff --git a/src/ripple/app/main/ServerHandlerImp.cpp b/src/ripple/app/main/ServerHandlerImp.cpp
deleted file mode 100644
index 9bff3ea297..0000000000
--- a/src/ripple/app/main/ServerHandlerImp.cpp
+++ /dev/null
@@ -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
-
-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 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 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
-make_RPCHTTPServer (beast::Stoppable& parent, JobQueue& jobQueue,
- NetworkOPs& networkOPs, Resource::Manager& resourceManager,
- RPC::Setup const& setup)
-{
- return std::make_unique (
- parent, jobQueue, networkOPs, resourceManager, setup);
-}
-
-}
diff --git a/src/ripple/app/shamap/SHAMapTreeNode.h b/src/ripple/app/shamap/SHAMapTreeNode.h
index cc18186f93..12d49c216d 100644
--- a/src/ripple/app/shamap/SHAMapTreeNode.h
+++ b/src/ripple/app/shamap/SHAMapTreeNode.h
@@ -21,6 +21,7 @@
#define RIPPLE_SHAMAPTREENODE_H
#include
+#include
#include
#include
@@ -203,8 +204,6 @@ private:
static std::mutex childLock;
};
-using TreeNodeCache = TaggedCache ;
-
} // ripple
#endif
diff --git a/src/ripple/http/impl/Port.cpp b/src/ripple/app/shamap/TreeNodeCache.h
similarity index 81%
rename from src/ripple/http/impl/Port.cpp
rename to src/ripple/app/shamap/TreeNodeCache.h
index 0213bfc391..26e614ac78 100644
--- a/src/ripple/http/impl/Port.cpp
+++ b/src/ripple/app/shamap/TreeNodeCache.h
@@ -17,17 +17,17 @@
*/
//==============================================================================
+#ifndef RIPPLE_APP_SHAMAP_TREENODECACHE_H_INCLUDED
+#define RIPPLE_APP_SHAMAP_TREENODECACHE_H_INCLUDED
+
+#include
+
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 ;
+
+} // ripple
+
+#endif
diff --git a/src/ripple/app/websocket/WSConnection.cpp b/src/ripple/app/websocket/WSConnection.cpp
index a62aaf036e..8719ce31c1 100644
--- a/src/ripple/app/websocket/WSConnection.cpp
+++ b/src/ripple/app/websocket/WSConnection.cpp
@@ -19,13 +19,16 @@
#include
#include
+#include
namespace ripple {
-WSConnection::WSConnection (Resource::Manager& resourceManager,
- Resource::Consumer usage, InfoSub::Source& source, bool isPublic,
- beast::IP::Endpoint const& remoteAddress, boost::asio::io_service& io_service)
+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 (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);
}
diff --git a/src/ripple/app/websocket/WSConnection.h b/src/ripple/app/websocket/WSConnection.h
index b374acf5e6..994527802f 100644
--- a/src/ripple/app/websocket/WSConnection.h
+++ b/src/ripple/app/websocket/WSConnection.h
@@ -20,7 +20,10 @@
#ifndef RIPPLE_WSCONNECTION_H
#define RIPPLE_WSCONNECTION_H
+#include
+#include
#include
+#include
namespace ripple {
@@ -38,9 +41,10 @@ public:
protected:
typedef websocketpp::message::data::ptr message_ptr;
- WSConnection (Resource::Manager& resourceManager,
- Resource::Consumer usage, InfoSub::Source& source, bool isPublic,
- beast::IP::Endpoint const& remoteAddress, boost::asio::io_service& io_service);
+ 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;
WSConnection& operator= (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 weak_connection_ptr;
typedef WSServerHandler 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
diff --git a/src/ripple/app/websocket/WSDoor.cpp b/src/ripple/app/websocket/WSDoor.cpp
index dfd7528a0e..b70405ff74 100644
--- a/src/ripple/app/websocket/WSDoor.cpp
+++ b/src/ripple/app/websocket/WSDoor.cpp
@@ -43,18 +43,24 @@ class WSDoorImp
, protected beast::Thread
, beast::LeakChecked
{
+private:
+ typedef RippleRecursiveMutex LockType;
+ typedef std::lock_guard ScopedLockType;
+
+ std::shared_ptr port_;
+ Resource::Manager& m_resourceManager;
+ InfoSub::Source& m_source;
+ LockType m_endpointLock;
+ std::shared_ptr 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(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 (
- 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 ScopedLockType;
-
- Resource::Manager& m_resourceManager;
- InfoSub::Source& m_source;
- boost::asio::ssl::context& m_ssl_context;
- LockType m_endpointLock;
-
- std::shared_ptr 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
+make_WSDoor (HTTP::Port const& port, Resource::Manager& resourceManager,
+ InfoSub::Source& source)
{
- std::unique_ptr door;
+ std::unique_ptr door;
try
{
- door = std::make_unique (resourceManager,
- source, strIp, iPort, bPublic, ssl_context);
+ door = std::make_unique (port, resourceManager, source);
}
catch (...)
{
}
- return door.release ();
+ return door;
+}
+
}
-} // ripple
diff --git a/src/ripple/app/websocket/WSDoor.h b/src/ripple/app/websocket/WSDoor.h
index 64339817cb..6a0e6050a0 100644
--- a/src/ripple/app/websocket/WSDoor.h
+++ b/src/ripple/app/websocket/WSDoor.h
@@ -20,6 +20,8 @@
#ifndef RIPPLE_WSDOOR_H_INCLUDED
#define RIPPLE_WSDOOR_H_INCLUDED
+#include
+
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
+make_WSDoor (HTTP::Port const& port, Resource::Manager& resourceManager,
+ InfoSub::Source& source);
+
+}
#endif
diff --git a/src/ripple/app/websocket/WSServerHandler.h b/src/ripple/app/websocket/WSServerHandler.h
index 75becc5cbe..540e4efce2 100644
--- a/src/ripple/app/websocket/WSServerHandler.h
+++ b/src/ripple/app/websocket/WSServerHandler.h
@@ -21,7 +21,9 @@
#define RIPPLE_WSSERVERHANDLER_H_INCLUDED
#include
+#include
#include
+#include
namespace ripple {
@@ -60,6 +62,7 @@ public:
};
private:
+ std::shared_ptr port_;
Resource::Manager& m_resourceManager;
InfoSub::Source& m_source;
@@ -69,31 +72,31 @@ protected:
typedef std::lock_guard 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 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 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;
- bool getPublic ()
+ HTTP::Port const&
+ port() const
{
- return mPublic;
+ return *port_;
+ }
+
+ bool getPublic()
+ {
+ 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.
diff --git a/src/ripple/common/RippleSSLContext.h b/src/ripple/common/RippleSSLContext.h
deleted file mode 100644
index 1a33e4565a..0000000000
--- a/src/ripple/common/RippleSSLContext.h
+++ /dev/null
@@ -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
-#include
-#include
-
-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
-make_ssl_context();
-
-/** Create an authenticated SSL context using the specified files. */
-std::shared_ptr
-make_authenticated_ssl_context (std::string const& key_file,
- std::string const& cert_file, std::string const& chain_file);
-
-}
-
-#endif
diff --git a/src/ripple/common/impl/RippleSSLContext.cpp b/src/ripple/common/impl/make_SSLContext.cpp
similarity index 66%
rename from src/ripple/common/impl/RippleSSLContext.cpp
rename to src/ripple/common/impl/make_SSLContext.cpp
index 89b4161bb0..c9c21a789e 100644
--- a/src/ripple/common/impl/RippleSSLContext.cpp
+++ b/src/ripple/common/impl/make_SSLContext.cpp
@@ -17,7 +17,7 @@
*/
//==============================================================================
-#include
+#include
#include
#include
#include
@@ -27,8 +27,8 @@
#include
namespace ripple {
-
namespace openssl {
+namespace detail {
template
struct custom_delete;
@@ -60,6 +60,15 @@ struct custom_delete
}
};
+template <>
+struct custom_delete
+{
+ void operator() (DH* dh) const
+ {
+ DH_free(dh);
+ }
+};
+
template
using custom_delete_unique_ptr = std::unique_ptr >;
@@ -158,79 +167,59 @@ static void ssl_ctx_use_privatekey (SSL_CTX* const ctx, evp_pkey_ptr& key)
}
}
-} // namespace openssl
-
-class RippleSSLContextImp : public RippleSSLContext
+// track when SSL connections have last negotiated
+struct StaticData
{
-private:
- boost::asio::ssl::context m_context;
+ std::mutex lock;
+ beast::aged_unordered_set set;
- // track when SSL connections have last negotiated
-
- struct StaticData
- {
- StaticData() : set (ripple::get_seconds_clock ())
- {
- }
-
- std::mutex lock;
- beast::aged_unordered_set set;
- };
-
-public:
- RippleSSLContextImp ()
- : RippleSSLContext (m_context)
- , m_context (boost::asio::ssl::context::sslv23)
- {
- }
-
- ~RippleSSLContextImp ()
- {
- }
-
- 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);
+ StaticData()
+ : set (ripple::get_seconds_clock ())
+ { }
};
-bool RippleSSLContextImp::disallowRenegotiation (SSL const* ssl, bool isNew)
+using dh_ptr = custom_delete_unique_ptr;
+
+static
+dh_ptr
+make_DH(std::string const& params)
+{
+ auto const* p (
+ reinterpret_cast (¶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);
+}
+
+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__);
+ }
+
+ 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)
{
// 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);
-}
-
-// A simple RAII container for a DH
-//
-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 (¶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;
-};
-
-DH* RippleSSLContextImp::getDH (int keyLength)
-{
- if (keyLength == 512 || keyLength == 1024)
- {
- static ScopedDHPointer dh512 (getRawDHParams (keyLength));
-
- return dh512.get ();
- }
- else
- {
- beast::FatalError ("unsupported key length", __FILE__, __LINE__);
- }
-
- return nullptr;
-}
+} // detail
+} // openssl
//------------------------------------------------------------------------------
-RippleSSLContext::RippleSSLContext (ContextType& context)
- : SSLContext (context)
+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
+ //
+ 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;
}
-RippleSSLContext* RippleSSLContext::createBare ()
-{
- std::unique_ptr context (new RippleSSLContextImp ());
- return context.release ();
-}
-
-RippleSSLContext* RippleSSLContext::createWebSocket ()
-{
- std::unique_ptr context (new RippleSSLContextImp ());
- context->initCommon ();
- return context.release ();
-}
-
-RippleSSLContext* RippleSSLContext::createAnonymous (std::string const& cipherList)
-{
- std::unique_ptr 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 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
-make_ssl_context()
+make_SSLContext()
{
std::shared_ptr context =
std::make_shared (
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
-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 context =
std::make_shared (
boost::asio::ssl::context::sslv23);
- RippleSSLContextImp::initAuthenticated(*context,
+ openssl::detail::initAuthenticated(*context,
key_file, cert_file, chain_file);
return context;
}
-}
+} // ripple
+
diff --git a/src/ripple/common/make_SSLContext.h b/src/ripple/common/make_SSLContext.h
new file mode 100644
index 0000000000..64887bdcb1
--- /dev/null
+++ b/src/ripple/common/make_SSLContext.h
@@ -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
+#include
+#include
+
+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
+make_SSLContext();
+
+/** Create an authenticated SSL context using the specified files. */
+std::shared_ptr
+make_SSLContextAuthed (std::string const& key_file,
+ std::string const& cert_file, std::string const& chain_file);
+
+}
+
+#endif
diff --git a/src/ripple/core/Config.h b/src/ripple/core/Config.h
index ad03fa1543..84caf9aacc 100644
--- a/src/ripple/core/Config.h
+++ b/src/ripple/core/Config.h
@@ -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 [':']
- */
- 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 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 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,36 +313,10 @@ public:
int getSize (SizedItemName);
void setup (std::string const& strConf, bool bQuiet);
void load ();
-
-private:
- void build_legacy();
};
-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);
+// VFALCO DEPRECATED
+extern Config& getConfig();
} // ripple
diff --git a/src/ripple/core/ConfigSections.h b/src/ripple/core/ConfigSections.h
index c6bf45ae6c..3e3b7640b6 100644
--- a/src/ripple/core/ConfigSections.h
+++ b/src/ripple/core/ConfigSections.h
@@ -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"
diff --git a/src/ripple/core/impl/Config.cpp b/src/ripple/core/impl/Config.cpp
index 5c69c05ed8..5874b3a67a 100644
--- a/src/ripple/core/impl/Config.cpp
+++ b/src/ripple/core/impl/Config.cpp
@@ -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 (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 (strTemp);
-
- //
- // VFALCO END CLEAN
- //
- //---------------------------------------
-
- if (getSingleSection (secConfig, SECTION_RPC_PORT, strTemp))
- m_rpcPort = beast::lexicalCastThrow (strTemp);
-
- if (getSingleSection (secConfig, SECTION_RPC_ALLOW_REMOTE, strTemp))
- RPC_ALLOW_REMOTE = beast::lexicalCastThrow (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 (strTemp);
- (void) getSingleSection (secConfig, SECTION_WEBSOCKET_IP, WEBSOCKET_IP);
-
- if (getSingleSection (secConfig, SECTION_WEBSOCKET_PORT, strTemp))
- WEBSOCKET_PORT = beast::lexicalCastThrow (strTemp);
-
- (void) getSingleSection (secConfig, SECTION_WEBSOCKET_PUBLIC_IP, WEBSOCKET_PUBLIC_IP);
-
- if (getSingleSection (secConfig, SECTION_WEBSOCKET_PUBLIC_PORT, strTemp))
- WEBSOCKET_PUBLIC_PORT = beast::lexicalCastThrow (strTemp);
-
- if (getSingleSection (secConfig, SECTION_WEBSOCKET_SECURE, strTemp))
- WEBSOCKET_SECURE = beast::lexicalCastThrow (strTemp);
-
- if (getSingleSection (secConfig, SECTION_WEBSOCKET_PUBLIC_SECURE, strTemp))
- WEBSOCKET_PUBLIC_SECURE = beast::lexicalCastThrow (strTemp);
-
if (getSingleSection (secConfig, SECTION_WEBSOCKET_PING_FREQ, strTemp))
WEBSOCKET_PING_FREQ = beast::lexicalCastThrow (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 (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
diff --git a/src/ripple/http/README.md b/src/ripple/http/README.md
deleted file mode 100644
index bf51b45b62..0000000000
--- a/src/ripple/http/README.md
+++ /dev/null
@@ -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.
diff --git a/src/ripple/http/Server.h b/src/ripple/http/Server.h
deleted file mode 100644
index 571cfaabcf..0000000000
--- a/src/ripple/http/Server.h
+++ /dev/null
@@ -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
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-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 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
- parse (BasicConfig const& config, std::ostream& log);
-};
-
-/** Create the HTTP server using the specified handler. */
-std::unique_ptr
-make_Server (Handler& handler, beast::Journal journal);
-
-//------------------------------------------------------------------------------
-
-} // HTTP
-} // ripple
-
-#endif
diff --git a/src/ripple/http/TODO.md b/src/ripple/http/TODO.md
deleted file mode 100644
index 960cda5dd5..0000000000
--- a/src/ripple/http/TODO.md
+++ /dev/null
@@ -1 +0,0 @@
-# HTTP Server TODO
diff --git a/src/ripple/http/impl/SSLPeer.h b/src/ripple/http/impl/SSLPeer.h
deleted file mode 100644
index 1aab1d2c48..0000000000
--- a/src/ripple/http/impl/SSLPeer.h
+++ /dev/null
@@ -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
-
-namespace ripple {
-namespace HTTP {
-
-class SSLPeer
- : public Peer
- , public std::enable_shared_from_this
-{
-private:
- friend class Peer ;
- using next_layer_type = boost::asio::ip::tcp::socket;
- using socket_type = boost::asio::ssl::stream ;
- next_layer_type next_layer_;
- socket_type socket_;
-
-public:
- template
- 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
-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
diff --git a/src/ripple/http/impl/Server.cpp b/src/ripple/http/impl/Server.cpp
deleted file mode 100644
index 81e8cfd73b..0000000000
--- a/src/ripple/http/impl/Server.cpp
+++ /dev/null
@@ -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
-#include
-#include //
-#include
-
-namespace ripple {
-namespace HTTP {
-
-std::unique_ptr
-make_Server (Handler& handler, beast::Journal journal)
-{
- return std::make_unique(handler, journal);
-}
-
-//------------------------------------------------------------------------------
-
-void
-Port::parse (Port& port,
- Section const& section, std::ostream& log)
-{
-}
-
-std::vector
-Server::parse (BasicConfig const& config, std::ostream& log)
-{
- std::vector 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;
-}
-
-}
-}
diff --git a/src/ripple/http/impl/Types.h b/src/ripple/http/impl/Types.h
deleted file mode 100644
index e404176632..0000000000
--- a/src/ripple/http/impl/Types.h
+++ /dev/null
@@ -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
diff --git a/src/ripple/net/impl/RPCCall.cpp b/src/ripple/net/impl/RPCCall.cpp
index 3061aefc26..066d0af187 100644
--- a/src/ripple/net/impl/RPCCall.cpp
+++ b/src/ripple/net/impl/RPCCall.cpp
@@ -17,11 +17,12 @@
*/
//==============================================================================
+#include
#include
#include
+#include
#include
#include
-#include
#include
#include
@@ -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 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& 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,
- "",
- jvRequest.isMember ("method") // Allow parser to rewrite method.
- ? jvRequest["method"].asString () : vCmd[0],
- jvParams, // Parsed, execute.
- setup.secure != 0, // Use SSL
- std::bind (RPCCallImp::callRPCHandler, &jvOutput,
- std::placeholders::_1));
-
- isService.run (); // This blocks until there is no more outstanding async calls.
+ {
+ boost::asio::io_service isService;
+ fromNetwork (
+ isService,
+ 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.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"))
{
diff --git a/src/ripple/net/impl/RPCDoor.cpp b/src/ripple/net/impl/RPCDoor.cpp
deleted file mode 100644
index e6179bdca4..0000000000
--- a/src/ripple/net/impl/RPCDoor.cpp
+++ /dev/null
@@ -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
-#include
-#include
-
-namespace ripple {
-
-class RPCDoorImp : public RPCDoor, public beast::LeakChecked
-{
-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 (
- 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 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);
-}
-
-}
diff --git a/src/ripple/overlay/Overlay.h b/src/ripple/overlay/Overlay.h
index f399b66e92..5eb9794bb3 100644
--- a/src/ripple/overlay/Overlay.h
+++ b/src/ripple/overlay/Overlay.h
@@ -21,10 +21,15 @@
#define RIPPLE_OVERLAY_OVERLAY_H_INCLUDED
#include
+#include
+#include
+#include
#include
#include
#include
#include //
+#include
+#include
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&& 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 && 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.
diff --git a/src/ripple/overlay/README.md b/src/ripple/overlay/README.md
index 9e597d6746..f892386ae6 100644
--- a/src/ripple/overlay/README.md
+++ b/src/ripple/overlay/README.md
@@ -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`
diff --git a/src/ripple/overlay/impl/OverlayImpl.cpp b/src/ripple/overlay/impl/OverlayImpl.cpp
index 586a3985f2..130a6b2de3 100644
--- a/src/ripple/overlay/impl/OverlayImpl.cpp
+++ b/src/ripple/overlay/impl/OverlayImpl.cpp
@@ -17,9 +17,9 @@
*/
//==============================================================================
-#include
+#include
+#include
#include
-#include
#include
#include
#include
@@ -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&& 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));
-
- if (slot == nullptr)
- return;
-
- PeerImp::ptr const peer (std::make_shared (
- std::move (socket), remote_endpoint, *this, m_resourceManager,
- *m_peerFinder, slot, setup_.context));
-
- {
- std::lock_guard lock (mutex_);
- {
- std::pair 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(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 && 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)
+#else
+ // For now, always redirect.
+ if (true)
+#endif
+ {
+ // Full, give them some addresses
+ handoff.response = makeRedirectResponse(slot, request);
+ handoff.keep_alive = request.keep_alive();
+ return handoff;
+ }
+
+ addpeer (std::make_shared(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
+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 (
- remote_endpoint, io_service_, *this, m_resourceManager,
- *m_peerFinder, slot, setup_.context));
-
- {
- std::lock_guard lock (mutex_);
- {
- std::pair 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 (remote_endpoint, io_service_, *this,
+ m_resourceManager, *m_peerFinder, slot, setup_.context));
}
Peer::ShortId
@@ -245,7 +293,7 @@ OverlayImpl::remove (PeerFinder::Slot::ptr const& slot)
//--------------------------------------------------------------------------
void
-OverlayImpl::onPrepare ()
+OverlayImpl::onPrepare()
{
PeerFinder::Config config;
@@ -254,22 +302,20 @@ 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
- config.applyTuning ();
+ config.applyTuning();
m_peerFinder->setConfig (config);
@@ -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 const& peer)
{
- if (isStopping() && areChildrenStopped () && list_.empty())
- stopped();
+ std::lock_guard lock (mutex_);
+ {
+ std::pair 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
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 (setup, parent, resourceManager,
- siteFiles, pathToDbFileOrDirectory, resolver, io_service);
+ return std::make_unique (setup, parent, serverHandler,
+ resourceManager, pathToDbFileOrDirectory, resolver, io_service);
}
}
diff --git a/src/ripple/overlay/impl/OverlayImpl.h b/src/ripple/overlay/impl/OverlayImpl.h
index adcf8f7813..cabbc948a6 100644
--- a/src/ripple/overlay/impl/OverlayImpl.h
+++ b/src/ripple/overlay/impl/OverlayImpl.h
@@ -21,7 +21,8 @@
#define RIPPLE_OVERLAY_OVERLAYIMPL_H_INCLUDED
#include
-
+#include
+#include
#include
#include
#include
@@ -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 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 m_doorDirect;
-
- /** The peer door for proxy connections */
- std::unique_ptr