Compare commits
9 commits
master
...
feature/rl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ecfe8f9858 | ||
|
|
e33cd275aa | ||
|
|
fb27454cdf | ||
|
|
917e4d348b | ||
|
|
8dd2fbe1b6 | ||
|
|
b99585ca69 | ||
|
|
c1e362a8dd | ||
|
|
13b7cfaec7 | ||
|
|
0cf6f461b6 |
20 changed files with 392 additions and 269 deletions
10
.gitlab-ci.yml
Normal file
10
.gitlab-ci.yml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
include:
|
||||
- template: Jobs/Code-Quality.gitlab-ci.yml
|
||||
|
||||
stages:
|
||||
- test
|
||||
|
||||
trigger_build_peerplays:
|
||||
stage: test
|
||||
script:
|
||||
- "curl -X POST -F token=$CI_JOB_TOKEN -F ref=$REF_NAME https://gitlab.com/api/v4/projects/10735589/trigger/pipeline"
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
|
|
@ -1,3 +1,6 @@
|
|||
[submodule "vendor/secp256k1-zkp"]
|
||||
path = vendor/secp256k1-zkp
|
||||
url = https://github.com/bitshares/secp256k1-zkp.git
|
||||
[submodule "vendor/editline"]
|
||||
path = vendor/editline
|
||||
url = https://github.com/troglobit/editline.git
|
||||
|
|
|
|||
|
|
@ -108,6 +108,54 @@ else ( MSVC )
|
|||
endif ( MSVC )
|
||||
# End configure secp256k1-zkp
|
||||
|
||||
# Configure editline
|
||||
if ( MSVC )
|
||||
# autoconf won't work here, hard code the defines
|
||||
set( EDITLINE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline" )
|
||||
|
||||
file( GLOB EDITLINE_SOURCES "${EDITLINE_DIR}/src/editline.c" )
|
||||
add_library( editline ${EDITLINE_SOURCES} )
|
||||
|
||||
target_include_directories( editline PRIVATE "${EDITLINE_DIR}" PUBLIC "${EDITLINE_DIR}/include" )
|
||||
|
||||
set_target_properties( editline PROPERTIES COMPILE_DEFINITIONS LINKER_LANGUAGE C )
|
||||
else ( MSVC )
|
||||
include(ExternalProject)
|
||||
if ( MINGW )
|
||||
ExternalProject_Add( project_editline
|
||||
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline
|
||||
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline
|
||||
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline/configure --prefix=${CMAKE_CURRENT_BINARY_DIR}/vendor/editline --host=x86_64-w64-mingw32
|
||||
BUILD_COMMAND make
|
||||
INSTALL_COMMAND true
|
||||
BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline/src/project_editline-build/.libs/libeditline.a
|
||||
)
|
||||
else ( MINGW )
|
||||
ExternalProject_Add( project_editline
|
||||
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline
|
||||
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline
|
||||
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline/configure --prefix=${CMAKE_CURRENT_BINARY_DIR}/vendor/editline
|
||||
BUILD_COMMAND make
|
||||
INSTALL_COMMAND true
|
||||
BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline/src/project_editline-build/.libs/libeditline.a
|
||||
)
|
||||
endif ( MINGW )
|
||||
ExternalProject_Add_Step(project_editline autogen
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline
|
||||
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline/autogen.sh
|
||||
DEPENDERS configure
|
||||
)
|
||||
|
||||
ExternalProject_Get_Property(project_editline binary_dir)
|
||||
|
||||
add_library(editline STATIC IMPORTED)
|
||||
set_property(TARGET editline PROPERTY IMPORTED_LOCATION ${binary_dir}/src/.libs/libeditline${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
set_property(TARGET editline PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline/include)
|
||||
add_dependencies(editline project_editline)
|
||||
install( FILES ${binary_dir}/src/.libs/libeditline${CMAKE_STATIC_LIBRARY_SUFFIX} DESTINATION lib/cryptonomex )
|
||||
endif ( MSVC )
|
||||
# End configure editline
|
||||
|
||||
IF( WIN32 )
|
||||
MESSAGE(STATUS "Configuring fc to build on Win32")
|
||||
|
||||
|
|
@ -258,27 +306,17 @@ add_subdirectory( vendor/websocketpp EXCLUDE_FROM_ALL )
|
|||
setup_library( fc SOURCES ${sources} LIBRARY_TYPE STATIC )
|
||||
install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" DESTINATION include )
|
||||
|
||||
# begin readline stuff
|
||||
find_package(Curses)
|
||||
find_package(Readline)
|
||||
|
||||
file(GLOB HEADERS "include/bts/cli/*.hpp")
|
||||
|
||||
if (READLINE_FOUND)
|
||||
target_compile_definitions (fc PRIVATE HAVE_READLINE)
|
||||
set(readline_libraries ${Readline_LIBRARY})
|
||||
if (CURSES_FOUND)
|
||||
list(APPEND readline_libraries ${CURSES_LIBRARY})
|
||||
endif()
|
||||
set(readline_includes ${Readline_INCLUDE_DIR})
|
||||
endif()
|
||||
# begin editline stuff
|
||||
if(WIN32)
|
||||
target_compile_definitions( fc PRIVATE _CRT_NONSTDC_NO_DEPRECATE )
|
||||
else(WIN32)
|
||||
target_compile_definitions( fc PRIVATE HAVE_EDITLINE )
|
||||
set( editline_libraries editline )
|
||||
endif(WIN32)
|
||||
# end readline stuff
|
||||
# end editline stuff
|
||||
|
||||
if( NOT CPP_STANDARD )
|
||||
set( CPP_STANDARD, "-std=c++11" )
|
||||
set( CPP_STANDARD "-std=c++11" )
|
||||
endif()
|
||||
|
||||
IF(WIN32)
|
||||
|
|
@ -360,7 +398,6 @@ target_include_directories(fc
|
|||
${OPENSSL_INCLUDE_DIR}
|
||||
"vendor/diff-match-patch-cpp-stl"
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/vendor/websocketpp
|
||||
"${readline_includes}"
|
||||
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp
|
||||
|
|
@ -370,7 +407,7 @@ target_include_directories(fc
|
|||
IF(NOT WIN32)
|
||||
set(LINK_USR_LOCAL_LIB -L/usr/local/lib)
|
||||
ENDIF()
|
||||
target_link_libraries( fc PUBLIC ${LINK_USR_LOCAL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${readline_libraries} ${ECC_LIB} )
|
||||
target_link_libraries( fc PUBLIC ${LINK_USR_LOCAL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${editline_libraries} ${ECC_LIB} )
|
||||
|
||||
if(MSVC)
|
||||
set_source_files_properties( src/network/http/websocket.cpp PROPERTIES COMPILE_FLAGS "/bigobj" )
|
||||
|
|
@ -495,3 +532,4 @@ ADD_CUSTOM_COMMAND(TARGET fc POST_BUILD ${POST_BUILD_STEP_COMMANDS}
|
|||
)
|
||||
|
||||
MESSAGE(STATUS "Finished fc module configuration...")
|
||||
|
||||
|
|
|
|||
|
|
@ -1,47 +0,0 @@
|
|||
# - Try to find readline include dirs and libraries
|
||||
#
|
||||
# Usage of this module as follows:
|
||||
#
|
||||
# find_package(Readline)
|
||||
#
|
||||
# Variables used by this module, they can change the default behaviour and need
|
||||
# to be set before calling find_package:
|
||||
#
|
||||
# Readline_ROOT_DIR Set this variable to the root installation of
|
||||
# readline if the module has problems finding the
|
||||
# proper installation path.
|
||||
#
|
||||
# Variables defined by this module:
|
||||
#
|
||||
# READLINE_FOUND System has readline, include and lib dirs found
|
||||
# Readline_INCLUDE_DIR The readline include directories.
|
||||
# Readline_LIBRARY The readline library.
|
||||
|
||||
find_path(Readline_ROOT_DIR
|
||||
NAMES include/readline/readline.h
|
||||
)
|
||||
|
||||
find_path(Readline_INCLUDE_DIR
|
||||
NAMES readline/readline.h
|
||||
HINTS ${Readline_ROOT_DIR}/include
|
||||
)
|
||||
|
||||
find_library(Readline_LIBRARY
|
||||
NAMES readline
|
||||
HINTS ${Readline_ROOT_DIR}/lib
|
||||
)
|
||||
|
||||
if(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY)
|
||||
set(READLINE_FOUND TRUE)
|
||||
else(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY)
|
||||
FIND_LIBRARY(Readline_LIBRARY NAMES readline)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Readline DEFAULT_MSG Readline_INCLUDE_DIR Readline_LIBRARY )
|
||||
MARK_AS_ADVANCED(Readline_INCLUDE_DIR Readline_LIBRARY)
|
||||
endif(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY)
|
||||
|
||||
mark_as_advanced(
|
||||
Readline_ROOT_DIR
|
||||
Readline_INCLUDE_DIR
|
||||
Readline_LIBRARY
|
||||
)
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <fc/any.hpp>
|
||||
#include <boost/any.hpp>
|
||||
#include <fc/network/ip.hpp>
|
||||
#include <fc/signals.hpp>
|
||||
|
||||
|
|
@ -26,14 +26,14 @@ namespace fc { namespace http {
|
|||
void on_message_handler( const std::function<void(const std::string&)>& h ) { _on_message = h; }
|
||||
void on_http_handler( const std::function<std::string(const std::string&)>& h ) { _on_http = h; }
|
||||
|
||||
void set_session_data( fc::any d ){ _session_data = std::move(d); }
|
||||
fc::any& get_session_data() { return _session_data; }
|
||||
void set_session_data( boost::any d ){ _session_data = std::move(d); }
|
||||
boost::any& get_session_data() { return _session_data; }
|
||||
|
||||
virtual std::string get_request_header(const std::string& key) = 0;
|
||||
|
||||
fc::signal<void()> closed;
|
||||
private:
|
||||
fc::any _session_data;
|
||||
boost::any _session_data;
|
||||
std::function<void(const std::string&)> _on_message;
|
||||
std::function<string(const std::string&)> _on_http;
|
||||
};
|
||||
|
|
@ -53,6 +53,8 @@ namespace fc { namespace http {
|
|||
uint16_t get_listening_port();
|
||||
void start_accept();
|
||||
|
||||
void stop_listening();
|
||||
void close();
|
||||
private:
|
||||
friend class detail::websocket_server_impl;
|
||||
std::unique_ptr<detail::websocket_server_impl> my;
|
||||
|
|
@ -84,6 +86,10 @@ namespace fc { namespace http {
|
|||
|
||||
websocket_connection_ptr connect( const std::string& uri );
|
||||
websocket_connection_ptr secure_connect( const std::string& uri );
|
||||
|
||||
void close();
|
||||
void synchronous_close();
|
||||
|
||||
private:
|
||||
std::unique_ptr<detail::websocket_client_impl> my;
|
||||
std::unique_ptr<detail::websocket_tls_client_impl> smy;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ namespace fc { namespace rpc {
|
|||
class websocket_api_connection : public api_connection
|
||||
{
|
||||
public:
|
||||
websocket_api_connection( fc::http::websocket_connection& c, uint32_t max_conversion_depth );
|
||||
websocket_api_connection(const std::shared_ptr<fc::http::websocket_connection> &c, uint32_t max_conversion_depth );
|
||||
~websocket_api_connection();
|
||||
|
||||
virtual variant send_call(
|
||||
|
|
@ -29,7 +29,7 @@ namespace fc { namespace rpc {
|
|||
const std::string& message,
|
||||
bool send_message = true );
|
||||
|
||||
fc::http::websocket_connection& _connection;
|
||||
std::shared_ptr<fc::http::websocket_connection> _connection;
|
||||
fc::rpc::state _rpc_state;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -132,14 +132,10 @@ namespace fc { namespace http {
|
|||
typedef websocketpp::transport::asio::tls_socket::endpoint socket_type;
|
||||
};
|
||||
|
||||
typedef websocketpp::transport::asio::endpoint<transport_config>
|
||||
transport_type;
|
||||
typedef websocketpp::transport::asio::endpoint<transport_config> transport_type;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
using websocketpp::connection_hdl;
|
||||
typedef websocketpp::server<asio_with_stub_log> websocket_server_type;
|
||||
typedef websocketpp::server<asio_tls_stub_log> websocket_tls_server_type;
|
||||
|
|
@ -152,7 +148,7 @@ namespace fc { namespace http {
|
|||
:_ws_connection(con){
|
||||
}
|
||||
|
||||
~websocket_connection_impl()
|
||||
virtual ~websocket_connection_impl()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -399,35 +395,26 @@ namespace fc { namespace http {
|
|||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef websocketpp::client<asio_with_stub_log> websocket_client_type;
|
||||
typedef websocketpp::client<asio_tls_stub_log> websocket_tls_client_type;
|
||||
|
||||
typedef websocket_client_type::connection_ptr websocket_client_connection_type;
|
||||
typedef websocket_tls_client_type::connection_ptr websocket_tls_client_connection_type;
|
||||
|
||||
class websocket_client_impl
|
||||
using websocketpp::connection_hdl;
|
||||
|
||||
template<typename T>
|
||||
class generic_websocket_client_impl
|
||||
{
|
||||
public:
|
||||
typedef websocket_client_type::message_ptr message_ptr;
|
||||
|
||||
websocket_client_impl()
|
||||
generic_websocket_client_impl()
|
||||
:_client_thread( fc::thread::current() )
|
||||
{
|
||||
_client.clear_access_channels( websocketpp::log::alevel::all );
|
||||
_client.set_message_handler( [&]( connection_hdl hdl, message_ptr msg ){
|
||||
_client.set_message_handler( [&]( connection_hdl hdl,
|
||||
typename websocketpp::client<T>::message_ptr msg ){
|
||||
_client_thread.async( [&](){
|
||||
idump((msg->get_payload()));
|
||||
wdump((msg->get_payload()));
|
||||
//std::cerr<<"recv: "<<msg->get_payload()<<"\n";
|
||||
auto received = msg->get_payload();
|
||||
fc::async( [=](){
|
||||
|
|
@ -453,73 +440,40 @@ namespace fc { namespace http {
|
|||
|
||||
_client.init_asio( &fc::asio::default_io_service() );
|
||||
}
|
||||
~websocket_client_impl()
|
||||
virtual ~generic_websocket_client_impl()
|
||||
{
|
||||
if(_connection )
|
||||
if( _connection )
|
||||
{
|
||||
_connection->close(0, "client closed");
|
||||
_connection.reset();
|
||||
_closed->wait();
|
||||
}
|
||||
if( _closed )
|
||||
_closed->wait();
|
||||
}
|
||||
|
||||
|
||||
fc::promise<void>::ptr _connected;
|
||||
fc::promise<void>::ptr _closed;
|
||||
fc::thread& _client_thread;
|
||||
websocket_client_type _client;
|
||||
websocketpp::client<T> _client;
|
||||
websocket_connection_ptr _connection;
|
||||
std::string _uri;
|
||||
fc::optional<connection_hdl> _hdl;
|
||||
};
|
||||
|
||||
class websocket_client_impl : public generic_websocket_client_impl<asio_with_stub_log>
|
||||
{};
|
||||
|
||||
|
||||
class websocket_tls_client_impl
|
||||
class websocket_tls_client_impl : public generic_websocket_client_impl<asio_tls_stub_log>
|
||||
{
|
||||
public:
|
||||
typedef websocket_tls_client_type::message_ptr message_ptr;
|
||||
|
||||
websocket_tls_client_impl( const std::string& ca_filename )
|
||||
:_client_thread( fc::thread::current() )
|
||||
: generic_websocket_client_impl()
|
||||
{
|
||||
// ca_filename has special values:
|
||||
// "_none" disables cert checking (potentially insecure!)
|
||||
// "_default" uses default CA's provided by OS
|
||||
|
||||
_client.clear_access_channels( websocketpp::log::alevel::all );
|
||||
_client.set_message_handler( [&]( connection_hdl hdl, message_ptr msg ){
|
||||
_client_thread.async( [&](){
|
||||
idump((msg->get_payload()));
|
||||
_connection->on_message( msg->get_payload() );
|
||||
}).wait();
|
||||
});
|
||||
_client.set_close_handler( [=]( connection_hdl hdl ){
|
||||
if( _connection )
|
||||
{
|
||||
try {
|
||||
_client_thread.async( [&](){
|
||||
ilog(". ${p}", ("p",uint64_t(_connection.get())));
|
||||
if( !_shutting_down && !_closed && _connection )
|
||||
_connection->closed();
|
||||
_connection.reset();
|
||||
} ).wait();
|
||||
} catch ( const fc::exception& e )
|
||||
{
|
||||
if( _closed ) _closed->set_exception( e.dynamic_copy_exception() );
|
||||
}
|
||||
if( _closed ) _closed->set_value();
|
||||
}
|
||||
});
|
||||
_client.set_fail_handler( [=]( connection_hdl hdl ){
|
||||
elog( "." );
|
||||
auto con = _client.get_con_from_hdl(hdl);
|
||||
auto message = con->get_ec().message();
|
||||
if( _connection )
|
||||
_client_thread.async( [&](){ if( _connection ) _connection->closed(); _connection.reset(); } ).wait();
|
||||
if( _connected && !_connected->ready() )
|
||||
_connected->set_exception( exception_ptr( new FC_EXCEPTION( exception, "${message}", ("message",message)) ) );
|
||||
if( _closed )
|
||||
_closed->set_value();
|
||||
});
|
||||
|
||||
//
|
||||
// We need ca_filename to be copied into the closure, as the referenced object might be destroyed by the caller by the time
|
||||
// tls_init_handler() is called. According to [1], capture-by-value results in the desired behavior (i.e. creation of
|
||||
|
|
@ -552,18 +506,8 @@ namespace fc { namespace http {
|
|||
return ctx;
|
||||
});
|
||||
|
||||
_client.init_asio( &fc::asio::default_io_service() );
|
||||
}
|
||||
~websocket_tls_client_impl()
|
||||
{
|
||||
if(_connection )
|
||||
{
|
||||
ilog(".");
|
||||
_shutting_down = true;
|
||||
_connection->close(0, "client closed");
|
||||
_closed->wait();
|
||||
}
|
||||
}
|
||||
virtual ~websocket_tls_client_impl() {}
|
||||
|
||||
std::string get_host()const
|
||||
{
|
||||
|
|
@ -576,20 +520,19 @@ namespace fc { namespace http {
|
|||
return;
|
||||
ctx->set_verify_mode( boost::asio::ssl::verify_peer );
|
||||
if( ca_filename == "_default" )
|
||||
{
|
||||
#if WIN32
|
||||
add_windows_root_certs( *ctx );
|
||||
#else
|
||||
ctx->set_default_verify_paths();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
ctx->load_verify_file( ca_filename );
|
||||
ctx->set_verify_depth(10);
|
||||
ctx->set_verify_callback( boost::asio::ssl::rfc2818_verification( get_host() ) );
|
||||
}
|
||||
|
||||
bool _shutting_down = false;
|
||||
fc::promise<void>::ptr _connected;
|
||||
fc::promise<void>::ptr _closed;
|
||||
fc::thread& _client_thread;
|
||||
websocket_tls_client_type _client;
|
||||
websocket_connection_ptr _connection;
|
||||
std::string _uri;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -622,8 +565,16 @@ namespace fc { namespace http {
|
|||
my->_server.start_accept();
|
||||
}
|
||||
|
||||
void websocket_server::stop_listening()
|
||||
{
|
||||
my->_server.stop_listening();
|
||||
}
|
||||
|
||||
|
||||
void websocket_server::close()
|
||||
{
|
||||
for (auto& connection : my->_connections)
|
||||
my->_server.close(connection.first, websocketpp::close::status::normal, "Goodbye");
|
||||
}
|
||||
|
||||
websocket_tls_server::websocket_tls_server( const string& server_pem, const string& ssl_password ):my( new detail::websocket_tls_server_impl(server_pem, ssl_password) ) {}
|
||||
websocket_tls_server::~websocket_tls_server(){}
|
||||
|
|
@ -646,7 +597,6 @@ namespace fc { namespace http {
|
|||
my->_server.start_accept();
|
||||
}
|
||||
|
||||
|
||||
websocket_tls_client::websocket_tls_client( const std::string& ca_filename ):my( new detail::websocket_tls_client_impl( ca_filename ) ) {}
|
||||
websocket_tls_client::~websocket_tls_client(){ }
|
||||
|
||||
|
|
@ -659,7 +609,7 @@ namespace fc { namespace http {
|
|||
{ try {
|
||||
if( uri.substr(0,4) == "wss:" )
|
||||
return secure_connect(uri);
|
||||
FC_ASSERT( uri.substr(0,3) == "ws:" );
|
||||
FC_ASSERT( uri.substr(0,4) == "wss:" || uri.substr(0,3) == "ws:", "Unsupported protocol" );
|
||||
|
||||
// wlog( "connecting to ${uri}", ("uri",uri));
|
||||
websocketpp::lib::error_code ec;
|
||||
|
|
@ -687,7 +637,8 @@ namespace fc { namespace http {
|
|||
{ try {
|
||||
if( uri.substr(0,3) == "ws:" )
|
||||
return connect(uri);
|
||||
FC_ASSERT( uri.substr(0,4) == "wss:" );
|
||||
FC_ASSERT( uri.substr(0,4) == "wss:" || uri.substr(0,3) == "ws:", "Unsupported protocol" );
|
||||
|
||||
// wlog( "connecting to ${uri}", ("uri",uri));
|
||||
websocketpp::lib::error_code ec;
|
||||
|
||||
|
|
@ -709,6 +660,19 @@ namespace fc { namespace http {
|
|||
return smy->_connection;
|
||||
} FC_CAPTURE_AND_RETHROW( (uri) ) }
|
||||
|
||||
void websocket_client::close()
|
||||
{
|
||||
if (my->_hdl)
|
||||
my->_client.close(*my->_hdl, websocketpp::close::status::normal, "Goodbye");
|
||||
}
|
||||
|
||||
void websocket_client::synchronous_close()
|
||||
{
|
||||
close();
|
||||
if (my->_closed)
|
||||
my->_closed->wait();
|
||||
}
|
||||
|
||||
websocket_connection_ptr websocket_tls_client::connect( const std::string& uri )
|
||||
{ try {
|
||||
// wlog( "connecting to ${uri}", ("uri",uri));
|
||||
|
|
|
|||
158
src/rpc/cli.cpp
158
src/rpc/cli.cpp
|
|
@ -7,22 +7,8 @@
|
|||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_READLINE
|
||||
# include <readline/readline.h>
|
||||
# include <readline/history.h>
|
||||
// I don't know exactly what version of readline we need. I know the 4.2 version that ships on some macs is
|
||||
// missing some functions we require. We're developing against 6.3, but probably anything in the 6.x
|
||||
// series is fine
|
||||
# if RL_VERSION_MAJOR < 6
|
||||
# ifdef _MSC_VER
|
||||
# pragma message("You have an old version of readline installed that might not support some of the features we need")
|
||||
# pragma message("Readline support will not be compiled in")
|
||||
# else
|
||||
# warning "You have an old version of readline installed that might not support some of the features we need"
|
||||
# warning "Readline support will not be compiled in"
|
||||
# endif
|
||||
# undef HAVE_READLINE
|
||||
# endif
|
||||
#ifdef HAVE_EDITLINE
|
||||
# include "editline.h"
|
||||
# ifdef WIN32
|
||||
# include <io.h>
|
||||
# endif
|
||||
|
|
@ -131,61 +117,107 @@ void cli::run()
|
|||
}
|
||||
|
||||
|
||||
char * dupstr (const char* s) {
|
||||
char *r;
|
||||
|
||||
r = (char*) malloc ((strlen (s) + 1));
|
||||
strcpy (r, s);
|
||||
return (r);
|
||||
}
|
||||
|
||||
char* my_generator(const char* text, int state)
|
||||
/****
|
||||
* @brief loop through list of commands, attempting to find a match
|
||||
* @param token what the user typed
|
||||
* @param match sets to 1 if only 1 match was found
|
||||
* @returns the remaining letters of the name of the command or NULL if 1 match not found
|
||||
*/
|
||||
static char *my_rl_complete(char *token, int *match)
|
||||
{
|
||||
static int list_index, len;
|
||||
const char *name;
|
||||
|
||||
if (!state) {
|
||||
list_index = 0;
|
||||
len = strlen (text);
|
||||
}
|
||||
const auto& cmds = cli_commands();
|
||||
const size_t partlen = strlen (token); /* Part of token */
|
||||
|
||||
auto& cmd = cli_commands();
|
||||
|
||||
while( list_index < cmd.size() )
|
||||
std::vector<std::reference_wrapper<const std::string>> matched_cmds;
|
||||
for( const std::string& it : cmds )
|
||||
{
|
||||
name = cmd[list_index].c_str();
|
||||
list_index++;
|
||||
|
||||
if (strncmp (name, text, len) == 0)
|
||||
return (dupstr(name));
|
||||
if( it.compare(0, partlen, token) == 0 )
|
||||
{
|
||||
matched_cmds.push_back( it );
|
||||
}
|
||||
}
|
||||
|
||||
/* If no names matched, then return NULL. */
|
||||
return ((char *)NULL);
|
||||
if( matched_cmds.size() == 0 )
|
||||
return NULL;
|
||||
|
||||
const std::string& first_matched_cmd = matched_cmds[0];
|
||||
if( matched_cmds.size() == 1 )
|
||||
{
|
||||
*match = 1;
|
||||
std::string matched_cmd = first_matched_cmd + " ";
|
||||
return strdup( matched_cmd.c_str() + partlen );
|
||||
}
|
||||
|
||||
size_t first_cmd_len = first_matched_cmd.size();
|
||||
size_t matched_len = partlen;
|
||||
for( ; matched_len < first_cmd_len; ++matched_len )
|
||||
{
|
||||
char next_char = first_matched_cmd[matched_len];
|
||||
bool end = false;
|
||||
for( const std::string& s : matched_cmds )
|
||||
{
|
||||
if( s.size() <= matched_len || s[matched_len] != next_char )
|
||||
{
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( end )
|
||||
break;
|
||||
}
|
||||
|
||||
if( matched_len == partlen )
|
||||
return NULL;
|
||||
|
||||
std::string matched_cmd_part = first_matched_cmd.substr( partlen, matched_len - partlen );
|
||||
return strdup( matched_cmd_part.c_str() );
|
||||
}
|
||||
|
||||
|
||||
static char** cli_completion( const char * text , int start, int end)
|
||||
/***
|
||||
* @brief return an array of matching commands
|
||||
* @param token the incoming text
|
||||
* @param array the resultant array of possible matches
|
||||
* @returns the number of matches
|
||||
*/
|
||||
static int cli_completion(char *token, char ***array)
|
||||
{
|
||||
char **matches;
|
||||
matches = (char **)NULL;
|
||||
auto& cmd = cli_commands();
|
||||
int num_commands = cmd.size();
|
||||
|
||||
#ifdef HAVE_READLINE
|
||||
if (start == 0)
|
||||
matches = rl_completion_matches ((char*)text, &my_generator);
|
||||
else
|
||||
rl_bind_key('\t',rl_abort);
|
||||
#endif
|
||||
char **copy = (char **) malloc (num_commands * sizeof(char *));
|
||||
if (copy == NULL)
|
||||
{
|
||||
// possible out of memory
|
||||
return 0;
|
||||
}
|
||||
int total_matches = 0;
|
||||
|
||||
return (matches);
|
||||
int partlen = strlen(token);
|
||||
|
||||
for (const std::string& it : cmd)
|
||||
{
|
||||
if ( it.compare(0, partlen, token) == 0)
|
||||
{
|
||||
copy[total_matches] = strdup ( it.c_str() );
|
||||
++total_matches;
|
||||
}
|
||||
}
|
||||
*array = copy;
|
||||
|
||||
return total_matches;
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* @brief Read input from the user
|
||||
* @param prompt the prompt to display
|
||||
* @param line what the user typed
|
||||
*/
|
||||
void cli::getline( const fc::string& prompt, fc::string& line)
|
||||
{
|
||||
// getting file descriptor for C++ streams is near impossible
|
||||
// so we just assume it's the same as the C stream...
|
||||
#ifdef HAVE_READLINE
|
||||
#ifdef HAVE_EDITLINE
|
||||
#ifndef WIN32
|
||||
if( isatty( fileno( stdin ) ) )
|
||||
#else
|
||||
|
|
@ -197,8 +229,9 @@ void cli::getline( const fc::string& prompt, fc::string& line)
|
|||
if( _isatty( _fileno( stdin ) ) )
|
||||
#endif
|
||||
{
|
||||
rl_attempted_completion_function = cli_completion;
|
||||
|
||||
el_hist_size = 256;
|
||||
rl_set_complete_func(my_rl_complete);
|
||||
rl_set_list_possib_func(cli_completion);
|
||||
static fc::thread getline_thread("getline");
|
||||
getline_thread.async( [&](){
|
||||
char* line_read = nullptr;
|
||||
|
|
@ -206,10 +239,17 @@ void cli::getline( const fc::string& prompt, fc::string& line)
|
|||
line_read = readline(prompt.c_str());
|
||||
if( line_read == nullptr )
|
||||
FC_THROW_EXCEPTION( fc::eof_exception, "" );
|
||||
rl_bind_key( '\t', rl_complete );
|
||||
if( *line_read )
|
||||
add_history(line_read);
|
||||
line = line_read;
|
||||
try
|
||||
{
|
||||
if (*line_read)
|
||||
add_history(line_read);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
free(line_read);
|
||||
throw;
|
||||
}
|
||||
free(line_read);
|
||||
}).wait();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ websocket_api_connection::~websocket_api_connection()
|
|||
{
|
||||
}
|
||||
|
||||
websocket_api_connection::websocket_api_connection( fc::http::websocket_connection& c, uint32_t max_depth )
|
||||
websocket_api_connection::websocket_api_connection(const std::shared_ptr<fc::http::websocket_connection>& c, uint32_t max_depth )
|
||||
: api_connection(max_depth),_connection(c)
|
||||
{
|
||||
_rpc_state.add_method( "call", [this]( const variants& args ) -> variant
|
||||
|
|
@ -47,9 +47,12 @@ websocket_api_connection::websocket_api_connection( fc::http::websocket_connecti
|
|||
return this->receive_call( 0, method_name, args );
|
||||
} );
|
||||
|
||||
_connection.on_message_handler( [&]( const std::string& msg ){ on_message(msg,true); } );
|
||||
_connection.on_http_handler( [&]( const std::string& msg ){ return on_message(msg,false); } );
|
||||
_connection.closed.connect( [this](){ closed(); } );
|
||||
_connection->on_message_handler( [&]( const std::string& msg ){ on_message(msg,true); } );
|
||||
_connection->on_http_handler( [&]( const std::string& msg ){ return on_message(msg,false); } );
|
||||
_connection->closed.connect( [this](){
|
||||
closed();
|
||||
_connection = nullptr;
|
||||
} );
|
||||
}
|
||||
|
||||
variant websocket_api_connection::send_call(
|
||||
|
|
@ -58,7 +61,7 @@ variant websocket_api_connection::send_call(
|
|||
variants args /* = variants() */ )
|
||||
{
|
||||
auto request = _rpc_state.start_remote_call( "call", {api_id, std::move(method_name), std::move(args) } );
|
||||
_connection.send_message( fc::json::to_string(fc::variant(request, _max_conversion_depth),
|
||||
_connection->send_message( fc::json::to_string(fc::variant(request, _max_conversion_depth),
|
||||
fc::json::stringify_large_ints_and_doubles, _max_conversion_depth ) );
|
||||
return _rpc_state.wait_for_response( *request.id );
|
||||
}
|
||||
|
|
@ -68,7 +71,7 @@ variant websocket_api_connection::send_callback(
|
|||
variants args /* = variants() */ )
|
||||
{
|
||||
auto request = _rpc_state.start_remote_call( "callback", {callback_id, std::move(args) } );
|
||||
_connection.send_message( fc::json::to_string(fc::variant(request, _max_conversion_depth),
|
||||
_connection->send_message( fc::json::to_string(fc::variant(request, _max_conversion_depth),
|
||||
fc::json::stringify_large_ints_and_doubles, _max_conversion_depth ) );
|
||||
return _rpc_state.wait_for_response( *request.id );
|
||||
}
|
||||
|
|
@ -78,7 +81,7 @@ void websocket_api_connection::send_notice(
|
|||
variants args /* = variants() */ )
|
||||
{
|
||||
fc::rpc::request req{ optional<uint64_t>(), "notice", {callback_id, std::move(args)}};
|
||||
_connection.send_message( fc::json::to_string(fc::variant(req, _max_conversion_depth),
|
||||
_connection->send_message( fc::json::to_string(fc::variant(req, _max_conversion_depth),
|
||||
fc::json::stringify_large_ints_and_doubles, _max_conversion_depth ) );
|
||||
}
|
||||
|
||||
|
|
@ -118,7 +121,7 @@ std::string websocket_api_connection::on_message(
|
|||
{
|
||||
auto reply = fc::json::to_string( response( *call.id, result, "2.0" ), fc::json::stringify_large_ints_and_doubles, _max_conversion_depth );
|
||||
if( send_message )
|
||||
_connection.send_message( reply );
|
||||
_connection->send_message( reply );
|
||||
return reply;
|
||||
}
|
||||
}
|
||||
|
|
@ -136,7 +139,7 @@ std::string websocket_api_connection::on_message(
|
|||
auto reply = fc::json::to_string( variant(response( *call.id, error_object{ 1, optexcept->to_string(), fc::variant(*optexcept, _max_conversion_depth)}, "2.0" ), _max_conversion_depth ),
|
||||
fc::json::stringify_large_ints_and_doubles, _max_conversion_depth );
|
||||
if( send_message )
|
||||
_connection.send_message( reply );
|
||||
_connection->send_message( reply );
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ int main( int argc, char** argv )
|
|||
|
||||
fc::http::websocket_server server;
|
||||
server.on_connection([&]( const websocket_connection_ptr& c ){
|
||||
auto wsc = std::make_shared<websocket_api_connection>(*c, MAX_DEPTH);
|
||||
auto wsc = std::make_shared<websocket_api_connection>(c, MAX_DEPTH);
|
||||
auto login = std::make_shared<login_api>();
|
||||
login->calc = calc_api;
|
||||
wsc->register_api(fc::api<login_api>(login));
|
||||
|
|
@ -76,7 +76,7 @@ int main( int argc, char** argv )
|
|||
try {
|
||||
fc::http::websocket_client client;
|
||||
auto con = client.connect( "ws://localhost:8090" );
|
||||
auto apic = std::make_shared<websocket_api_connection>(*con, MAX_DEPTH);
|
||||
auto apic = std::make_shared<websocket_api_connection>(con, MAX_DEPTH);
|
||||
auto remote_login_api = apic->get_remote_api<login_api>();
|
||||
auto remote_calc = remote_login_api->get_calc();
|
||||
remote_calc->on_result( []( uint32_t r ) { elog( "callback result ${r}", ("r",r) ); } );
|
||||
|
|
|
|||
1
vendor/editline
vendored
Submodule
1
vendor/editline
vendored
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 62bba782585c6c18d7a2b27beeb60a45db9abb43
|
||||
3
vendor/websocketpp/changelog.md
vendored
3
vendor/websocketpp/changelog.md
vendored
|
|
@ -1,4 +1,7 @@
|
|||
HEAD
|
||||
- Bug: Change default listen backlog from 0 to socket_base::max_connections.
|
||||
#549. Thank you derwassi and zwelab for reporting and na1pir for providing
|
||||
access to hardware to debug the issue.
|
||||
|
||||
0.7.0 - 2016-02-22
|
||||
- MINOR BREAKING SOCKET POLICY CHANGE: Asio transport socket policy method
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@
|
|||
|
||||
#include "connection_tu2.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
// Include special debugging transport
|
||||
//#include <websocketpp/config/minimal_client.hpp>
|
||||
#include <websocketpp/transport/debug/endpoint.hpp>
|
||||
|
|
@ -172,6 +174,20 @@ void http_func(server* s, websocketpp::connection_hdl hdl) {
|
|||
BOOST_CHECK_EQUAL(con->get_response_msg(), status_code::get_string(status_code::ok));
|
||||
}
|
||||
|
||||
void http_func_with_move(server* s, websocketpp::connection_hdl hdl) {
|
||||
using namespace websocketpp::http;
|
||||
|
||||
server::connection_ptr con = s->get_con_from_hdl(hdl);
|
||||
|
||||
std::string res = con->get_resource();
|
||||
|
||||
con->set_body( std::move(res) );
|
||||
con->set_status(status_code::ok);
|
||||
|
||||
BOOST_CHECK_EQUAL(con->get_response_code(), status_code::ok);
|
||||
BOOST_CHECK_EQUAL(con->get_response_msg(), status_code::get_string(status_code::ok));
|
||||
}
|
||||
|
||||
void defer_http_func(server* s, bool * deferred, websocketpp::connection_hdl hdl) {
|
||||
*deferred = true;
|
||||
|
||||
|
|
@ -237,6 +253,18 @@ BOOST_AUTO_TEST_CASE( http_request ) {
|
|||
BOOST_CHECK_EQUAL(run_server_test(s,input), output);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( http_request_with_move ) {
|
||||
std::string input = "GET /foo/bar HTTP/1.1\r\nHost: www.example.com\r\nOrigin: http://www.example.com\r\n\r\n";
|
||||
std::string output = "HTTP/1.1 200 OK\r\nContent-Length: 8\r\nServer: ";
|
||||
output+=websocketpp::user_agent;
|
||||
output+="\r\n\r\n/foo/bar";
|
||||
|
||||
server s;
|
||||
s.set_http_handler(bind(&http_func_with_move,&s,::_1));
|
||||
|
||||
BOOST_CHECK_EQUAL(run_server_test(s,input), output);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( deferred_http_request ) {
|
||||
std::string input = "GET /foo/bar HTTP/1.1\r\nHost: www.example.com\r\nOrigin: http://www.example.com\r\n\r\n";
|
||||
std::string output = "HTTP/1.1 200 OK\r\nContent-Length: 8\r\nServer: ";
|
||||
|
|
|
|||
|
|
@ -1041,6 +1041,7 @@ public:
|
|||
* @see websocketpp::http::response::set_body
|
||||
*/
|
||||
void set_body(std::string const & value);
|
||||
void set_body( std::string&& value );
|
||||
|
||||
/// Append a header
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include <websocketpp/common/cpp11.hpp>
|
||||
#include <websocketpp/common/memory.hpp>
|
||||
#include <websocketpp/common/platforms.hpp>
|
||||
#include <websocketpp/common/stdint.hpp>
|
||||
#include <websocketpp/common/system_error.hpp>
|
||||
#include <websocketpp/error.hpp>
|
||||
|
||||
|
|
@ -46,7 +47,7 @@
|
|||
namespace websocketpp {
|
||||
namespace extensions {
|
||||
|
||||
/// Implementation of the draft permessage-deflate WebSocket extension
|
||||
/// Implementation of RFC 7692, the permessage-deflate WebSocket extension
|
||||
/**
|
||||
* ### permessage-deflate interface
|
||||
*
|
||||
|
|
@ -174,18 +175,30 @@ namespace websocketpp {
|
|||
namespace extensions {
|
||||
namespace permessage_deflate {
|
||||
|
||||
/// Default value for server_max_window_bits as defined by draft 17
|
||||
/// Default value for server_max_window_bits as defined by RFC 7692
|
||||
static uint8_t const default_server_max_window_bits = 15;
|
||||
/// Minimum value for server_max_window_bits as defined by draft 17
|
||||
/// Minimum value for server_max_window_bits as defined by RFC 7692
|
||||
/**
|
||||
* NOTE: A value of 8 is not actually supported by zlib, the deflate
|
||||
* library that WebSocket++ uses. To preserve backwards compatibility
|
||||
* with RFC 7692 and previous versions of the library a value of 8
|
||||
* is accepted by the library but will always be negotiated as 9.
|
||||
*/
|
||||
static uint8_t const min_server_max_window_bits = 8;
|
||||
/// Maximum value for server_max_window_bits as defined by draft 17
|
||||
/// Maximum value for server_max_window_bits as defined by RFC 7692
|
||||
static uint8_t const max_server_max_window_bits = 15;
|
||||
|
||||
/// Default value for client_max_window_bits as defined by draft 17
|
||||
/// Default value for client_max_window_bits as defined by RFC 7692
|
||||
static uint8_t const default_client_max_window_bits = 15;
|
||||
/// Minimum value for client_max_window_bits as defined by draft 17
|
||||
/// Minimum value for client_max_window_bits as defined by RFC 7692
|
||||
/**
|
||||
* NOTE: A value of 8 is not actually supported by zlib, the deflate
|
||||
* library that WebSocket++ uses. To preserve backwards compatibility
|
||||
* with RFC 7692 and previous versions of the library a value of 8
|
||||
* is accepted by the library but will always be negotiated as 9.
|
||||
*/
|
||||
static uint8_t const min_client_max_window_bits = 8;
|
||||
/// Maximum value for client_max_window_bits as defined by draft 17
|
||||
/// Maximum value for client_max_window_bits as defined by RFC 7692
|
||||
static uint8_t const max_client_max_window_bits = 15;
|
||||
|
||||
namespace mode {
|
||||
|
|
@ -213,7 +226,7 @@ public:
|
|||
, m_server_max_window_bits_mode(mode::accept)
|
||||
, m_client_max_window_bits_mode(mode::accept)
|
||||
, m_initialized(false)
|
||||
, m_compress_buffer_size(16384)
|
||||
, m_compress_buffer_size(8192)
|
||||
{
|
||||
m_dstate.zalloc = Z_NULL;
|
||||
m_dstate.zfree = Z_NULL;
|
||||
|
|
@ -292,6 +305,7 @@ public:
|
|||
}
|
||||
|
||||
m_compress_buffer.reset(new unsigned char[m_compress_buffer_size]);
|
||||
m_decompress_buffer.reset(new unsigned char[m_compress_buffer_size]);
|
||||
if ((m_server_no_context_takeover && is_server) ||
|
||||
(m_client_no_context_takeover && !is_server))
|
||||
{
|
||||
|
|
@ -372,7 +386,7 @@ public:
|
|||
/**
|
||||
* The bits setting is the base 2 logarithm of the maximum window size that
|
||||
* the server must use to compress outgoing messages. The permitted range
|
||||
* is 8 to 15 inclusive. 8 represents a 256 byte window and 15 a 32KiB
|
||||
* is 9 to 15 inclusive. 9 represents a 512 byte window and 15 a 32KiB
|
||||
* window. The default setting is 15.
|
||||
*
|
||||
* Mode Options:
|
||||
|
|
@ -386,6 +400,14 @@ public:
|
|||
* adjusted by the server. A server may unilaterally set this value without
|
||||
* client support.
|
||||
*
|
||||
* NOTE: The permessage-deflate spec specifies that a value of 8 is allowed.
|
||||
* Prior to version 0.8.0 a value of 8 was also allowed by this library.
|
||||
* zlib, the deflate compression library that WebSocket++ uses has always
|
||||
* silently adjusted a value of 8 to 9. In recent versions of zlib (1.2.9
|
||||
* and greater) a value of 8 is now explicitly rejected. WebSocket++ 0.8.0
|
||||
* continues to perform the 8->9 conversion for backwards compatibility
|
||||
* purposes but this should be considered deprecated functionality.
|
||||
*
|
||||
* @param bits The size to request for the outgoing window size
|
||||
* @param mode The mode to use for negotiating this parameter
|
||||
* @return A status code
|
||||
|
|
@ -394,6 +416,12 @@ public:
|
|||
if (bits < min_server_max_window_bits || bits > max_server_max_window_bits) {
|
||||
return error::make_error_code(error::invalid_max_window_bits);
|
||||
}
|
||||
|
||||
// See note in doc comment above about what is happening here
|
||||
if (bits == 8) {
|
||||
bits = 9;
|
||||
}
|
||||
|
||||
m_server_max_window_bits = bits;
|
||||
m_server_max_window_bits_mode = mode;
|
||||
|
||||
|
|
@ -403,8 +431,8 @@ public:
|
|||
/// Limit client LZ77 sliding window size
|
||||
/**
|
||||
* The bits setting is the base 2 logarithm of the window size that the
|
||||
* client must use to compress outgoing messages. The permitted range is 8
|
||||
* to 15 inclusive. 8 represents a 256 byte window and 15 a 32KiB window.
|
||||
* client must use to compress outgoing messages. The permitted range is 9
|
||||
* to 15 inclusive. 9 represents a 512 byte window and 15 a 32KiB window.
|
||||
* The default setting is 15.
|
||||
*
|
||||
* Mode Options:
|
||||
|
|
@ -417,6 +445,14 @@ public:
|
|||
* outgoing window size unilaterally. A server may only limit the client's
|
||||
* window size if the remote client supports that feature.
|
||||
*
|
||||
* NOTE: The permessage-deflate spec specifies that a value of 8 is allowed.
|
||||
* Prior to version 0.8.0 a value of 8 was also allowed by this library.
|
||||
* zlib, the deflate compression library that WebSocket++ uses has always
|
||||
* silently adjusted a value of 8 to 9. In recent versions of zlib (1.2.9
|
||||
* and greater) a value of 8 is now explicitly rejected. WebSocket++ 0.8.0
|
||||
* continues to perform the 8->9 conversion for backwards compatibility
|
||||
* purposes but this should be considered deprecated functionality.
|
||||
*
|
||||
* @param bits The size to request for the outgoing window size
|
||||
* @param mode The mode to use for negotiating this parameter
|
||||
* @return A status code
|
||||
|
|
@ -425,6 +461,12 @@ public:
|
|||
if (bits < min_client_max_window_bits || bits > max_client_max_window_bits) {
|
||||
return error::make_error_code(error::invalid_max_window_bits);
|
||||
}
|
||||
|
||||
// See note in doc comment above about what is happening here
|
||||
if (bits == 8) {
|
||||
bits = 9;
|
||||
}
|
||||
|
||||
m_client_max_window_bits = bits;
|
||||
m_client_max_window_bits_mode = mode;
|
||||
|
||||
|
|
@ -555,7 +597,7 @@ public:
|
|||
|
||||
do {
|
||||
m_istate.avail_out = m_compress_buffer_size;
|
||||
m_istate.next_out = m_compress_buffer.get();
|
||||
m_istate.next_out = m_decompress_buffer.get();
|
||||
|
||||
ret = inflate(&m_istate, Z_SYNC_FLUSH);
|
||||
|
||||
|
|
@ -564,7 +606,7 @@ public:
|
|||
}
|
||||
|
||||
out.append(
|
||||
reinterpret_cast<char *>(m_compress_buffer.get()),
|
||||
reinterpret_cast<char *>(m_decompress_buffer.get()),
|
||||
m_compress_buffer_size - m_istate.avail_out
|
||||
);
|
||||
} while (m_istate.avail_out == 0);
|
||||
|
|
@ -642,11 +684,17 @@ private:
|
|||
* client requested that we use.
|
||||
*
|
||||
* options:
|
||||
* - decline (refuse to use the attribute)
|
||||
* - accept (use whatever the client says)
|
||||
* - largest (use largest possible value)
|
||||
* - decline (ignore value, offer our default instead)
|
||||
* - accept (use the value requested by the client)
|
||||
* - largest (use largest value acceptable to both)
|
||||
* - smallest (use smallest possible value)
|
||||
*
|
||||
* NOTE: As a value of 8 is no longer explicitly supported by zlib but might
|
||||
* be requested for negotiation by an older client/server, if the result of
|
||||
* the negotiation would be to send a value of 8, a value of 9 is offered
|
||||
* instead. This ensures that WebSocket++ will only ever negotiate connections
|
||||
* with compression settings explicitly supported by zlib.
|
||||
*
|
||||
* @param [in] value The value of the attribute from the offer
|
||||
* @param [out] ec A reference to the error code to return errors via
|
||||
*/
|
||||
|
|
@ -678,6 +726,11 @@ private:
|
|||
ec = make_error_code(error::invalid_mode);
|
||||
m_server_max_window_bits = default_server_max_window_bits;
|
||||
}
|
||||
|
||||
// See note in doc comment
|
||||
if (m_server_max_window_bits == 8) {
|
||||
m_server_max_window_bits = 9;
|
||||
}
|
||||
}
|
||||
|
||||
/// Negotiate client_max_window_bits attribute
|
||||
|
|
@ -687,11 +740,17 @@ private:
|
|||
* negotiation mode.
|
||||
*
|
||||
* options:
|
||||
* - decline (refuse to use the attribute)
|
||||
* - accept (use whatever the client says)
|
||||
* - largest (use largest possible value)
|
||||
* - decline (ignore value, offer our default instead)
|
||||
* - accept (use the value requested by the client)
|
||||
* - largest (use largest value acceptable to both)
|
||||
* - smallest (use smallest possible value)
|
||||
*
|
||||
* NOTE: As a value of 8 is no longer explicitly supported by zlib but might
|
||||
* be requested for negotiation by an older client/server, if the result of
|
||||
* the negotiation would be to send a value of 8, a value of 9 is offered
|
||||
* instead. This ensures that WebSocket++ will only ever negotiate connections
|
||||
* with compression settings explicitly supported by zlib.
|
||||
*
|
||||
* @param [in] value The value of the attribute from the offer
|
||||
* @param [out] ec A reference to the error code to return errors via
|
||||
*/
|
||||
|
|
@ -727,6 +786,11 @@ private:
|
|||
ec = make_error_code(error::invalid_mode);
|
||||
m_client_max_window_bits = default_client_max_window_bits;
|
||||
}
|
||||
|
||||
// See note in doc comment
|
||||
if (m_client_max_window_bits == 8) {
|
||||
m_client_max_window_bits = 9;
|
||||
}
|
||||
}
|
||||
|
||||
bool m_enabled;
|
||||
|
|
@ -741,6 +805,7 @@ private:
|
|||
int m_flush;
|
||||
size_t m_compress_buffer_size;
|
||||
lib::unique_ptr_uchar_array m_compress_buffer;
|
||||
lib::unique_ptr_uchar_array m_decompress_buffer;
|
||||
z_stream m_dstate;
|
||||
z_stream m_istate;
|
||||
};
|
||||
|
|
@ -750,3 +815,4 @@ private:
|
|||
} // namespace websocketpp
|
||||
|
||||
#endif // WEBSOCKETPP_PROCESSOR_EXTENSION_PERMESSAGEDEFLATE_HPP
|
||||
|
||||
|
|
|
|||
|
|
@ -575,6 +575,17 @@ void connection<config>::set_body(std::string const & value) {
|
|||
m_response.set_body(value);
|
||||
}
|
||||
|
||||
template <typename config>
|
||||
void connection<config>::set_body( std::string&& value )
|
||||
{
|
||||
if (m_internal_state != istate::PROCESS_HTTP_REQUEST) {
|
||||
throw exception("Call to set_status from invalid state",
|
||||
error::make_error_code(error::invalid_state));
|
||||
}
|
||||
|
||||
m_response.set_body(std::move(value));
|
||||
}
|
||||
|
||||
// TODO: EXCEPTION_FREE
|
||||
template <typename config>
|
||||
void connection<config>::append_header(std::string const & key,
|
||||
|
|
|
|||
|
|
@ -311,10 +311,10 @@ public:
|
|||
* needed.
|
||||
*/
|
||||
timer_ptr set_timer(long duration, timer_handler callback) {
|
||||
timer_ptr new_timer = lib::make_shared<lib::asio::steady_timer>(
|
||||
lib::ref(*m_io_service),
|
||||
lib::asio::milliseconds(duration)
|
||||
);
|
||||
timer_ptr new_timer(
|
||||
new lib::asio::steady_timer(
|
||||
*m_io_service,
|
||||
lib::asio::milliseconds(duration)));
|
||||
|
||||
if (config::enable_multithreading) {
|
||||
new_timer->async_wait(m_strand->wrap(lib::bind(
|
||||
|
|
@ -461,8 +461,7 @@ protected:
|
|||
m_io_service = io_service;
|
||||
|
||||
if (config::enable_multithreading) {
|
||||
m_strand = lib::make_shared<lib::asio::io_service::strand>(
|
||||
lib::ref(*io_service));
|
||||
m_strand.reset(new lib::asio::io_service::strand(*io_service));
|
||||
}
|
||||
|
||||
lib::error_code ec = socket_con_type::init_asio(io_service, m_strand,
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include <websocketpp/uri.hpp>
|
||||
#include <websocketpp/logger/levels.hpp>
|
||||
|
||||
#include <websocketpp/common/asio.hpp>
|
||||
#include <websocketpp/common/functional.hpp>
|
||||
|
||||
#include <sstream>
|
||||
|
|
@ -191,8 +192,7 @@ public:
|
|||
|
||||
m_io_service = ptr;
|
||||
m_external_io_service = true;
|
||||
m_acceptor = lib::make_shared<lib::asio::ip::tcp::acceptor>(
|
||||
lib::ref(*m_io_service));
|
||||
m_acceptor.reset(new lib::asio::ip::tcp::acceptor(*m_io_service));
|
||||
|
||||
m_state = READY;
|
||||
ec = lib::error_code();
|
||||
|
|
@ -314,8 +314,10 @@ public:
|
|||
*
|
||||
* New values affect future calls to listen only.
|
||||
*
|
||||
* A value of zero will use the operating system default. This is the
|
||||
* default value.
|
||||
* The default value is specified as *::asio::socket_base::max_connections
|
||||
* which uses the operating system defined maximum queue length. Your OS
|
||||
* may restrict or silently lower this value. A value of zero may cause
|
||||
* all connections to be rejected.
|
||||
*
|
||||
* @since 0.3.0
|
||||
*
|
||||
|
|
@ -660,9 +662,7 @@ public:
|
|||
* @since 0.3.0
|
||||
*/
|
||||
void start_perpetual() {
|
||||
m_work = lib::make_shared<lib::asio::io_service::work>(
|
||||
lib::ref(*m_io_service)
|
||||
);
|
||||
m_work.reset(new lib::asio::io_service::work(*m_io_service));
|
||||
}
|
||||
|
||||
/// Clears the endpoint's perpetual flag, allowing it to exit when empty
|
||||
|
|
@ -826,8 +826,7 @@ protected:
|
|||
|
||||
// Create a resolver
|
||||
if (!m_resolver) {
|
||||
m_resolver = lib::make_shared<lib::asio::ip::tcp::resolver>(
|
||||
lib::ref(*m_io_service));
|
||||
m_resolver.reset(new lib::asio::ip::tcp::resolver(*m_io_service));
|
||||
}
|
||||
|
||||
tcon->set_uri(u);
|
||||
|
|
|
|||
|
|
@ -168,8 +168,7 @@ protected:
|
|||
return socket::make_error_code(socket::error::invalid_state);
|
||||
}
|
||||
|
||||
m_socket = lib::make_shared<lib::asio::ip::tcp::socket>(
|
||||
lib::ref(*service));
|
||||
m_socket.reset(new lib::asio::ip::tcp::socket(*service));
|
||||
|
||||
m_state = READY;
|
||||
|
||||
|
|
|
|||
|
|
@ -193,8 +193,7 @@ protected:
|
|||
if (!m_context) {
|
||||
return socket::make_error_code(socket::error::invalid_tls_context);
|
||||
}
|
||||
m_socket = lib::make_shared<socket_type>(
|
||||
_WEBSOCKETPP_REF(*service),lib::ref(*m_context));
|
||||
m_socket.reset(new socket_type(*service, *m_context));
|
||||
|
||||
m_io_service = service;
|
||||
m_strand = strand;
|
||||
|
|
|
|||
Loading…
Reference in a new issue