Add permessage-deflate WebSocket support (RIPD-1409):

This also fixes a defect where the Server HTTP header was
incorrectly set in WebSocket Upgrade handshake responses.
This commit is contained in:
Vinnie Falco
2017-02-02 11:07:04 -05:00
committed by Edward Hennis
parent ce7e83f763
commit f6a0345831
5 changed files with 56 additions and 2 deletions

View File

@@ -273,7 +273,41 @@
# keep rippled from connecting to other instances of rippled or
# prevent RPC and WebSocket clients from connecting.
#
# WebSocket permessage-deflate extension options
#
# These settings configure the optional permessage-deflate extension
# options and may appear on any port configuration entry. They are meaningful
# only to ports which have enabled a WebSocket protocol.
#
# permessage_deflate = <flag>
#
# Determines if permessage_deflate extension negotiations are enabled.
# When enabled, clients may request the extension and the server will
# offer the enabled extension in response.
#
# client_max_window_bits = [9..15]
# server_max_window_bits = [9..15]
# client_no_context_takeover = <flag>
# server_no_context_takeover = <flag>
#
# These optional settings control options related to the permessage-deflate
# extension negotiation. For precise definitions of these fields please see
# the RFC 7692, "Compression Extensions for WebSocket":
# https://tools.ietf.org/html/rfc7692
#
# compress_level = [0..9]
#
# When set, determines the amount of compression attempted, where 0 is
# the least amount and 9 is the most amount. Higher levels require more
# CPU resources. Levels 1 through 3 use a fast compression algorithm,
# while levels 4 through 9 use a more compact algorithm which uses more
# CPU resources. If unspecified, a default of 3 is used.
#
# memory_level = [1..9]
#
# When set, determines the relative amount of memory used to hold
# intermediate compression data. Higher numbers can give better compression
# ratios at the cost of higher memory and CPU resources.
#
# [rpc_startup]
#

View File

@@ -830,6 +830,7 @@ to_Port(ParsedPort const& parsed, std::ostream& log)
p.ssl_cert = parsed.ssl_cert;
p.ssl_chain = parsed.ssl_chain;
p.ssl_ciphers = parsed.ssl_ciphers;
p.pmd_options = parsed.pmd_options;
return p;
}

View File

@@ -23,6 +23,7 @@
#include <ripple/basics/BasicConfig.h>
#include <ripple/beast/net/IPEndpoint.h>
#include <beast/core/detail/ci_char_traits.hpp>
#include <beast/websocket/option.hpp>
#include <boost/asio/ip/address.hpp>
#include <cstdint>
#include <memory>
@@ -50,6 +51,7 @@ struct Port
std::string ssl_cert;
std::string ssl_chain;
std::string ssl_ciphers;
beast::websocket::permessage_deflate pmd_options;
std::shared_ptr<boost::asio::ssl::context> context;
// How many incoming connections are allowed on this
@@ -83,6 +85,7 @@ struct ParsedPort
std::string ssl_cert;
std::string ssl_chain;
std::string ssl_ciphers;
beast::websocket::permessage_deflate pmd_options;
int limit = 0;
boost::optional<boost::asio::ip::address> ip;

View File

@@ -110,7 +110,7 @@ protected:
{
template<class Body, class Headers>
void
operator()(beast::http::message<true, Body, Headers>& req)
operator()(beast::http::message<true, Body, Headers>& req) const
{
req.fields.replace("User-Agent",
BuildInfo::getFullVersionString());
@@ -118,7 +118,7 @@ protected:
template<class Body, class Headers>
void
operator()(beast::http::message<false, Body, Headers>& resp)
operator()(beast::http::message<false, Body, Headers>& resp) const
{
resp.fields.replace("Server",
BuildInfo::getFullVersionString());
@@ -194,6 +194,7 @@ run()
return strand_.post(std::bind(
&BaseWSPeer::run, impl().shared_from_this()));
impl().ws_.set_option(beast::websocket::decorate(identity{}));
impl().ws_.set_option(port().pmd_options);
using namespace beast::asio;
impl().ws_.async_accept(request_, strand_.wrap(std::bind(
&BaseWSPeer::on_ws_handshake, impl().shared_from_this(),

View File

@@ -217,6 +217,21 @@ parse_Port (ParsedPort& port, Section const& section, std::ostream& log)
set(port.ssl_cert, "ssl_cert", section);
set(port.ssl_chain, "ssl_chain", section);
set(port.ssl_ciphers, "ssl_ciphers", section);
port.pmd_options.server_enable =
section.value_or("permessage_deflate", false);
port.pmd_options.client_max_window_bits =
section.value_or("client_max_window_bits", 15);
port.pmd_options.server_max_window_bits =
section.value_or("server_max_window_bits", 15);
port.pmd_options.client_no_context_takeover =
section.value_or("client_no_context_takeover", false);
port.pmd_options.server_no_context_takeover =
section.value_or("server_no_context_takeover", false);
port.pmd_options.compLevel =
section.value_or("compress_level", 3);
port.pmd_options.memLevel =
section.value_or("memory_level", 4);
}
} // ripple