Compare commits

..

22 commits

Author SHA1 Message Date
Nathaniel
e5aab9c58b
Add support for auxiliary serialization data
To supplement the new custom serialization feature, we also would like
the ability to use standard reflection-based serialization, but also to
add some extra data in on the side. This is now possible as auxiliary
serialized data. A class can define auxiliary data serializers which will
add additional data to the serialized record generated by the usual
reflection-based serializers.
2022-03-21 08:54:08 -05:00
Nathaniel
213fd5168f
Cleanup and organization
Delete a useless and unused overload of raw::unpack

Also, make the new custom serialization bit work for unreflected types
(they still need typename reflection)
2022-03-21 08:53:24 -05:00
Nathaniel
9a1ea8a0bf
Enable classes to customize their serialization
Add support for classes to define members to customize their
serialization from the default from reflection.
2022-03-21 08:53:08 -05:00
serkixenos
6171e973c7 Merge branch 'bug/285-error-converting-value-to-string' into 'latest-fc'
#285 error converting value to string

See merge request PBSA/tools-libs/peerplays-fc!24
2022-03-04 22:20:05 +00:00
Vlad Dobromyslov
a36e6e71be #285 error converting value to string 2022-03-04 22:20:05 +00:00
serkixenos
1cc740598f Update boost libraries 2022-02-21 15:20:12 -04:00
serkixenos
e433b42e65 Fix Crypto DH test
For reference, checkout
https://github.com/search?q=005aa69c0a97edcc9e8eb887f8b4be8e090b8299&type=commits
2022-02-21 15:19:57 -04:00
serkixenos
86b77c6eb4 Merge branch 'bug/issue34' into 'latest-fc'
Remove OpenSSL related build warnings

See merge request PBSA/tools-libs/peerplays-fc!23
2022-02-10 19:16:44 +00:00
Pavel Baykov
8363f00715 Remove OpenSSL related build warnings 2022-02-10 19:16:44 +00:00
serkixenos
4888839219
Merge pull request #17 from peerplays-network/fc/cleaner-build-log
Remove as much warnings from build log as possible
2021-01-27 13:33:51 +01:00
serkixenos
29d2f72b24 Remove as much warnings from build log as possible 2020-10-29 21:47:30 +01:00
Bobinson K B
0e9259486c Merge branch 'feature/static_variant_update' into 'latest-fc'
static variant update

See merge request PBSA/PeerplaysIO/tools-libs/peerplays-fc!19
2020-10-27 17:33:25 +00:00
Bobinson K B
d8429b8376 Merge branch 'feature/rl-editline' into 'latest-fc'
Feature/readline-editline

See merge request PBSA/PeerplaysIO/tools-libs/peerplays-fc!20
2020-10-27 17:33:01 +00:00
blockc p
5e5c6c91df Feature/readline-editline 2020-10-27 17:32:59 +00:00
pravin-battu
3f4a4468e0 static variant update 2020-10-16 12:12:57 -03:00
Bobinson K B
fb27454cdf Merge branch 'ws-fc-updates' into 'latest-fc'
ws-updates

See merge request PBSA/PeerplaysIO/tools-libs/peerplays-fc!18
2020-08-12 13:00:39 +00:00
blockc p
917e4d348b ws-updates 2020-08-12 13:00:39 +00:00
Bobinson K B
8dd2fbe1b6 Merge branch 'issue-13-fix-websocket' into 'latest-fc'
Issue-13-fix (websocket shutdown)

See merge request PBSA/PeerplaysIO/tools-libs/peerplays-fc!17
2020-08-11 14:53:56 +00:00
Roshan Syed
b99585ca69 Added .gitlab-ci.yml 2020-07-09 13:11:09 +00:00
pravin-battu
c1e362a8dd websocket issue 2020-07-05 22:23:29 -03:00
blockc p
13b7cfaec7 Revert "websocket fix, issue 13"
This reverts commit 0cf6f461b6
2020-07-02 17:07:12 +00:00
pravin-battu
0cf6f461b6 websocket fix, issue 13 2020-07-02 13:34:29 -03:00
54 changed files with 949 additions and 506 deletions

44
.gitlab-ci.yml Normal file
View file

@ -0,0 +1,44 @@
include:
- template: Jobs/Code-Quality.gitlab-ci.yml
stages:
- build
- test
- trigger_build_peerplays
build:
stage: build
script:
- rm -rf .git/modules/vendor ./vendor
- git submodule sync
- git submodule update --init --recursive
- rm -rf build
- mkdir build
- cd build
- cmake -DCMAKE_BUILD_TYPE=Release ..
- make -j$(nproc)
artifacts:
untracked: true
paths:
- build/tests/
tags:
- builder-fc
test:
stage: test
dependencies:
- build
script:
- ./build/tests/all_test
tags:
- builder-fc
when:
- manual
trigger_build_peerplays:
stage: trigger_build_peerplays
dependencies:
- 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
View file

@ -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

View file

@ -40,7 +40,7 @@ endif()
SET (ORIGINAL_LIB_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
SET(BOOST_COMPONENTS)
LIST(APPEND BOOST_COMPONENTS thread date_time filesystem system program_options signals serialization chrono unit_test_framework context locale iostreams)
LIST(APPEND BOOST_COMPONENTS thread date_time filesystem system program_options serialization chrono unit_test_framework context locale iostreams)
SET( Boost_USE_STATIC_LIBS ON CACHE STRING "ON or OFF" )
IF( ECC_IMPL STREQUAL openssl )
@ -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")
@ -168,6 +216,7 @@ set( fc_sources
src/variant.cpp
src/exception.cpp
src/variant_object.cpp
src/static_variant.cpp
src/thread/thread.cpp
src/thread/thread_specific.cpp
src/thread/future.cpp
@ -258,27 +307,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 +399,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,14 +408,14 @@ 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" )
endif(MSVC)
IF(NOT Boost_UNIT_TEST_FRAMEWORK_LIBRARY MATCHES "\\.(a|lib)$")
IF(Boost_UNIT_TEST_FRAMEWORK_LIBRARY MATCHES "\\.(so|dll)$" OR FC_BUILD_DYNAMIC_LIBRARIES)
IF(MSVC)
add_definitions(/DBOOST_TEST_DYN_LINK)
ELSE(MSVC)
@ -495,3 +533,4 @@ ADD_CUSTOM_COMMAND(TARGET fc POST_BUILD ${POST_BUILD_STEP_COMMANDS}
)
MESSAGE(STATUS "Finished fc module configuration...")

View file

@ -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
)

View file

@ -115,7 +115,9 @@ namespace fc {
memcpy(&bi, ve.data(), fc::min<size_t>(ve.size(),sizeof(bi)) );
}
else
memset( &bi, char(0), sizeof(bi) );
for (size_t i = 0; i < bi.size(); i++) {
bi.data[i] = 0;
}
}

View file

@ -3,7 +3,12 @@
#define FC_PACK_MAX_DEPTH 1000
#endif
#ifndef FC_MAX_STRING_OBJECT_DEPTH
// how many levels of nested objects are proceed for string functions
#define FC_MAX_STRING_OBJECT_DEPTH 200
#endif
#ifndef FC_MAX_LOG_OBJECT_DEPTH
// how many levels of nested objects are displayed in log messages
#define FC_MAX_LOG_OBJECT_DEPTH 200
#define FC_MAX_LOG_OBJECT_DEPTH 1000
#endif

View file

@ -8,6 +8,7 @@
#include <openssl/ecdh.h>
#include <openssl/sha.h>
#include <openssl/obj_mac.h>
#include <openssl/bn.h>
/**
* @file openssl.hpp

View file

@ -4,5 +4,5 @@ namespace fc {
/* provides access to the OpenSSL random number generator */
void rand_bytes(char* buf, int count);
void rand_pseudo_bytes(char* buf, int count);
//void rand_pseudo_bytes(char* buf, int count);
} // namespace fc

View file

@ -199,14 +199,6 @@ namespace fc {
vi.value = static_cast<uint32_t>(v);
}
template<typename Stream, typename T> inline void unpack( Stream& s, const T& vi, uint32_t _max_depth )
{
FC_ASSERT( _max_depth > 0 );
T tmp;
fc::raw::unpack( s, tmp, _max_depth - 1 );
FC_ASSERT( vi == tmp );
}
template<typename Stream> inline void pack( Stream& s, const char* v, uint32_t _max_depth )
{
FC_ASSERT( _max_depth > 0 );
@ -403,7 +395,31 @@ namespace fc {
}
};
template<typename IsReflected=fc::false_type>
template<typename...> using void_t = void;
template<typename T, typename=void>
struct has_auxiliary_packing : std::false_type {};
template<typename T>
struct has_auxiliary_packing<T,
void_t<decltype(std::declval<const T>().fc_pack_auxiliary(std::declval<fc::datastream<size_t>&>(), 1)),
decltype(std::declval<T>().fc_unpack_auxiliary(std::declval<fc::datastream<size_t>&>(), 1))>>
: std::true_type {};
template<typename Stream, typename T, std::enable_if_t<has_auxiliary_packing<T>::value, bool> = true>
static inline void pack_auxiliary( Stream& s, const T& v, uint32_t _max_depth ) {
v.fc_pack_auxiliary(s, _max_depth );
}
template<typename Stream, typename T, std::enable_if_t<!has_auxiliary_packing<T>::value, bool> = true>
static inline void pack_auxiliary( Stream&, const T&, uint32_t ) { /* Do nothing */ }
template<typename Stream, typename T, std::enable_if_t<has_auxiliary_packing<T>::value, bool> = true>
static inline void unpack_auxiliary( Stream& s, T& v, uint32_t _max_depth ) {
v.fc_unpack_auxiliary(s, _max_depth );
}
template<typename Stream, typename T, std::enable_if_t<!has_auxiliary_packing<T>::value, bool> = true>
static inline void unpack_auxiliary( Stream&, T&, uint32_t ) { /* Do nothing */ }
template<typename IsReflected=std::false_type>
struct if_reflected {
template<typename Stream, typename T>
static inline void pack( Stream& s, const T& v, uint32_t _max_depth ) {
@ -417,19 +433,53 @@ namespace fc {
}
};
template<>
struct if_reflected<fc::true_type> {
struct if_reflected<std::true_type> {
template<typename Stream, typename T>
static inline void pack( Stream& s, const T& v, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
if_enum< typename fc::reflector<T>::is_enum >::pack( s, v, _max_depth - 1 );
if_enum<T>::pack( s, v, _max_depth - 1 );
pack_auxiliary( s, v, _max_depth - 1 );
}
template<typename Stream, typename T>
static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
if_enum< typename fc::reflector<T>::is_enum >::unpack( s, v, _max_depth - 1 );
if_enum<T>::unpack( s, v, _max_depth - 1 );
unpack_auxiliary( s, v, _max_depth - 1 );
}
};
template<typename T, typename=void>
struct has_custom_packing : std::false_type {};
template<typename T>
struct has_custom_packing<T,
void_t<decltype(std::declval<const T>().fc_pack(std::declval<fc::datastream<size_t>&>(), 1)),
decltype(std::declval<T>().fc_unpack(std::declval<fc::datastream<size_t>&>(), 1))>>
: std::true_type {};
template<typename Stream, typename T, std::enable_if_t<has_custom_packing<T>::value, bool> = true>
static inline void pack( Stream& s, const T& v, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
static_assert(!has_auxiliary_packing<T>::value,
"A class with custom packing must not have auxiliary packing. Pack auxiliary data in custom packer.");
v.fc_pack( s, _max_depth - 1 );
}
template<typename Stream, typename T, std::enable_if_t<!has_custom_packing<T>::value, bool> = true>
static inline void pack( Stream& s, const T& v, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
if_reflected< typename fc::reflector<T>::is_defined >::pack( s, v, _max_depth - 1 );
}
template<typename Stream, typename T, std::enable_if_t<has_custom_packing<T>::value, bool> = true>
static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
v.fc_unpack( s, _max_depth - 1 );
}
template<typename Stream, typename T, std::enable_if_t<!has_custom_packing<T>::value, bool> = true>
static inline void unpack( Stream& s, T& v, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
if_reflected< typename fc::reflector<T>::is_defined >::unpack( s, v, _max_depth - 1 );
}
} // namesapce detail
template<typename Stream, typename T>
@ -620,13 +670,13 @@ namespace fc {
template<typename Stream, typename T>
void pack( Stream& s, const T& v, uint32_t _max_depth ) {
FC_ASSERT( _max_depth > 0 );
fc::raw::detail::if_reflected< typename fc::reflector<T>::is_defined >::pack( s, v, _max_depth - 1 );
fc::raw::detail::pack(s, v, _max_depth);
}
template<typename Stream, typename T>
void unpack( Stream& s, T& v, uint32_t _max_depth )
{ try {
FC_ASSERT( _max_depth > 0 );
fc::raw::detail::if_reflected< typename fc::reflector<T>::is_defined >::unpack( s, v, _max_depth - 1 );
fc::raw::detail::unpack(s, v, _max_depth);
} FC_RETHROW_EXCEPTIONS( warn, "error unpacking ${type}", ("type",fc::get_typename<T>::name() ) ) }
template<typename T>

View file

@ -80,7 +80,6 @@ namespace fc {
template<typename Stream, typename T> void unpack( Stream& s, fc::optional<T>& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T> void unpack( Stream& s, const T& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T> void pack( Stream& s, const fc::optional<T>& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T> void pack( Stream& s, const safe<T>& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename Stream, typename T> void unpack( Stream& s, fc::safe<T>& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
@ -120,6 +119,7 @@ namespace fc {
template<typename T> inline std::vector<char> pack( const T& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename T> inline T unpack( const std::vector<char>& s, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename T> inline void unpack( const std::vector<char>& s, T& tmp, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename T> inline T unpack( const char* d, uint32_t s, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
template<typename T> inline void unpack( const char* d, uint32_t s, T& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH );
} }

View file

@ -15,7 +15,7 @@ namespace fc
{
string endpoint = "127.0.0.1:12201";
string host = "fc"; // the name of the host, source or application that sent this message (just passed through to GELF server)
uint32_t max_object_depth;
uint32_t max_object_depth = FC_MAX_LOG_OBJECT_DEPTH;
};
gelf_appender(const variant& args);

View file

@ -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;

View file

@ -1,6 +1,7 @@
#pragma once
#include <fc/utility.hpp>
#include <assert.h>
#include <string.h>
namespace fc {
@ -23,12 +24,13 @@ namespace fc {
public:
typedef T value_type;
optional():_valid(false){}
optional():_valid(false){ memset(_value, 0, sizeof(_value)); }
~optional(){ reset(); }
optional( optional& o )
:_valid(false)
{
memset(_value, 0, sizeof(_value));
if( o._valid ) new (ptr()) T( *o );
_valid = o._valid;
}
@ -36,6 +38,7 @@ namespace fc {
optional( const optional& o )
:_valid(false)
{
memset(_value, 0, sizeof(_value));
if( o._valid ) new (ptr()) T( *o );
_valid = o._valid;
}
@ -43,6 +46,7 @@ namespace fc {
optional( optional&& o )
:_valid(false)
{
memset(_value, 0, sizeof(_value));
if( o._valid ) new (ptr()) T( fc::move(*o) );
_valid = o._valid;
o.reset();
@ -52,6 +56,7 @@ namespace fc {
optional( const optional<U>& o )
:_valid(false)
{
memset(_value, 0, sizeof(_value));
if( o._valid ) new (ptr()) T( *o );
_valid = o._valid;
}
@ -60,6 +65,7 @@ namespace fc {
optional( optional<U>& o )
:_valid(false)
{
memset(_value, 0, sizeof(_value));
if( o._valid )
{
new (ptr()) T( *o );
@ -71,6 +77,7 @@ namespace fc {
optional( optional<U>&& o )
:_valid(false)
{
memset(_value, 0, sizeof(_value));
if( o._valid ) new (ptr()) T( fc::move(*o) );
_valid = o._valid;
o.reset();
@ -80,6 +87,7 @@ namespace fc {
optional( U&& u )
:_valid(true)
{
memset(_value, 0, sizeof(_value));
new ((char*)ptr()) T( fc::forward<U>(u) );
}

View file

@ -99,16 +99,80 @@ namespace fc
}
};
namespace detail {
template<typename...> using void_t = void;
template<typename C, typename=void>
struct has_auxiliary_variant_data : std::false_type {};
template<typename C>
struct has_auxiliary_variant_data<C,
void_t<decltype(std::declval<const C>().fc_auxiliary_to_variant(std::declval<variant&>(), 1)),
decltype(std::declval<C>().fc_auxiliary_from_variant(std::declval<const variant&>(), 1))>>
: std::true_type {};
template<typename T, std::enable_if_t<has_auxiliary_variant_data<T>::value, bool> = true>
void auxiliary_to_variant( const T& o, variant& v, uint32_t max_depth ) {
variant auxiliary;
o.fc_auxiliary_to_variant(auxiliary, max_depth);
v = mutable_variant_object(std::move(v)).set("Auxiliary Data", std::move(auxiliary));
}
template<typename T, std::enable_if_t<!has_auxiliary_variant_data<T>::value, bool> = true>
void auxiliary_to_variant( const T&, variant&, uint32_t ) { /* Do nothing */ }
template<typename T, std::enable_if_t<has_auxiliary_variant_data<T>::value, bool> = true>
void auxiliary_from_variant( const variant& v, T& o, uint32_t max_depth ) {
auto vo = v.get_object();
auto itr = vo.find("Auxiliary Data");
if (itr != vo.end())
o.fc_auxiliary_from_variant(itr->value(), max_depth);
}
template<typename T, std::enable_if_t<!has_auxiliary_variant_data<T>::value, bool> = true>
void auxiliary_from_variant( const variant&, T&, uint32_t ) { /* Do nothing */ }
template<typename C, typename=void>
struct has_custom_variant_conversion : std::false_type {};
template<typename C>
struct has_custom_variant_conversion<C,
void_t<decltype(std::declval<const C>().fc_to_variant(std::declval<variant&>(), 1)),
decltype(std::declval<C>().fc_from_variant(std::declval<const variant&>(), 1))>>
: std::true_type {};
template<typename T, std::enable_if_t<!has_custom_variant_conversion<T>::value, bool> = true>
void to_variant( const T& o, variant& v, uint32_t max_depth )
{
if_enum<T>::to_variant( o, v, max_depth );
auxiliary_to_variant( o, v, max_depth - 1 );
}
template<typename T, std::enable_if_t<has_custom_variant_conversion<T>::value, bool> = true>
void to_variant( const T& o, variant& v, uint32_t max_depth )
{
static_assert(!has_auxiliary_variant_data<T>::value,
"Classes with custom variant serialization must not have auxiliary variant data. "
"Include auxiliary data in custom serializer.");
o.fc_to_variant(v, max_depth);
}
template<typename T, std::enable_if_t<!has_custom_variant_conversion<T>::value, bool> = true>
void from_variant( const variant& v, T& o, uint32_t max_depth )
{
if_enum<T>::from_variant( v, o, max_depth );
auxiliary_from_variant( v, o, max_depth - 1 );
}
template<typename T, std::enable_if_t<has_custom_variant_conversion<T>::value, bool> = true>
void from_variant( const variant& v, T& o, uint32_t max_depth )
{
o.fc_from_variant(v, max_depth);
}
} // namespace detail
template<typename T>
void to_variant( const T& o, variant& v, uint32_t max_depth )
{
if_enum<typename fc::reflector<T>::is_enum>::to_variant( o, v, max_depth );
detail::to_variant(o, v, max_depth);
}
template<typename T>
void from_variant( const variant& v, T& o, uint32_t max_depth )
{
if_enum<typename fc::reflector<T>::is_enum>::from_variant( v, o, max_depth );
detail::from_variant(v, o, max_depth);
}
}

View file

@ -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;
};

View file

@ -1,4 +1,5 @@
/** This source adapted from https://github.com/kmicklas/variadic-static_variant
/** This source adapted from https://github.com/kmicklas/variadic-static_variant Now available at https://github.com/kmicklas/variadic-variant.
*
* Copyright (C) 2013 Kenneth Micklas
*
@ -13,21 +14,15 @@
#include <stdexcept>
#include <typeinfo>
#include <fc/exception/exception.hpp>
namespace fc {
// Implementation details, the user should not import this:
namespace impl {
template<int N, typename... Ts>
struct storage_ops;
template<typename X, typename... Ts>
struct position;
template<typename... Ts>
struct type_info;
template<typename StaticVariant>
struct copy_construct
{
@ -40,7 +35,6 @@ struct copy_construct
sv.init(v);
}
};
template<typename StaticVariant>
struct move_construct
{
@ -53,25 +47,19 @@ struct move_construct
sv.init( std::move(v) );
}
};
template<int N, typename T, typename... Ts>
struct storage_ops<N, T&, Ts...> {
static void del(int n, void *data) {}
static void con(int n, void *data) {}
template<typename visitor>
static typename visitor::result_type apply(int n, void *data, visitor& v) {}
template<typename visitor>
static typename visitor::result_type apply(int n, void *data, const visitor& v) {}
template<typename visitor>
static typename visitor::result_type apply(int n, const void *data, visitor& v) {}
template<typename visitor>
static typename visitor::result_type apply(int n, const void *data, const visitor& v) {}
};
template<int N, typename T, typename... Ts>
struct storage_ops<N, T, Ts...> {
static void del(int n, void *data) {
@ -82,32 +70,27 @@ struct storage_ops<N, T, Ts...> {
if(n == N) new(reinterpret_cast<T*>(data)) T();
else storage_ops<N + 1, Ts...>::con(n, data);
}
template<typename visitor>
static typename visitor::result_type apply(int n, void *data, visitor& v) {
if(n == N) return v(*reinterpret_cast<T*>(data));
else return storage_ops<N + 1, Ts...>::apply(n, data, v);
}
template<typename visitor>
static typename visitor::result_type apply(int n, void *data, const visitor& v) {
if(n == N) return v(*reinterpret_cast<T*>(data));
else return storage_ops<N + 1, Ts...>::apply(n, data, v);
}
template<typename visitor>
static typename visitor::result_type apply(int n, const void *data, visitor& v) {
if(n == N) return v(*reinterpret_cast<const T*>(data));
else return storage_ops<N + 1, Ts...>::apply(n, data, v);
}
template<typename visitor>
static typename visitor::result_type apply(int n, const void *data, const visitor& v) {
if(n == N) return v(*reinterpret_cast<const T*>(data));
else return storage_ops<N + 1, Ts...>::apply(n, data, v);
}
};
template<int N>
struct storage_ops<N> {
static void del(int n, void *data) {
@ -116,7 +99,6 @@ struct storage_ops<N> {
static void con(int n, void *data) {
FC_THROW_EXCEPTION( fc::assert_exception, "Internal error: static_variant tag is invalid." );
}
template<typename visitor>
static typename visitor::result_type apply(int n, void *data, visitor& v) {
FC_THROW_EXCEPTION( fc::assert_exception, "Internal error: static_variant tag is invalid." );
@ -134,22 +116,18 @@ struct storage_ops<N> {
FC_THROW_EXCEPTION( fc::assert_exception, "Internal error: static_variant tag is invalid." );
}
};
template<typename X>
struct position<X> {
static const int pos = -1;
};
template<typename X, typename... Ts>
struct position<X, X, Ts...> {
static const int pos = 0;
};
template<typename X, typename T, typename... Ts>
struct position<X, T, Ts...> {
static const int pos = position<X, Ts...>::pos != -1 ? position<X, Ts...>::pos + 1 : -1;
};
template<typename T, typename... Ts>
struct type_info<T&, Ts...> {
static const bool no_reference_types = false;
@ -157,7 +135,6 @@ struct type_info<T&, Ts...> {
static const size_t size = type_info<Ts...>::size > sizeof(T&) ? type_info<Ts...>::size : sizeof(T&);
static const size_t count = 1 + type_info<Ts...>::count;
};
template<typename T, typename... Ts>
struct type_info<T, Ts...> {
static const bool no_reference_types = type_info<Ts...>::no_reference_types;
@ -165,7 +142,6 @@ struct type_info<T, Ts...> {
static const size_t size = type_info<Ts...>::size > sizeof(T) ? type_info<Ts...>::size : sizeof(T&);
static const size_t count = 1 + type_info<Ts...>::count;
};
template<>
struct type_info<> {
static const bool no_reference_types = true;
@ -174,48 +150,94 @@ struct type_info<> {
static const size_t size = 0;
};
} // namespace impl
template<typename TTag>
size_t size( TTag )
{
return 0;
}
template<typename TTag, typename A, typename...Ts>
size_t size( TTag tag )
{
if (tag <= 0)
{
return sizeof(A);
}
return size<TTag, Ts...>( --tag );
}
class dynamic_storage
{
char* storage;
public:
dynamic_storage();
~dynamic_storage();
void* data() const;
void alloc( size_t size );
void release();
};
} // namespace impl
template<typename... Types>
class static_variant {
using tag_type = int64_t;
static_assert(impl::type_info<Types...>::no_reference_types, "Reference types are not permitted in static_variant.");
static_assert(impl::type_info<Types...>::no_duplicates, "static_variant type arguments contain duplicate types.");
int _tag;
char storage[impl::type_info<Types...>::size];
template<typename X>
using type_in_typelist = typename std::enable_if<impl::position<X, Types...>::pos != -1, X>::type; // type is in typelist of static_variant.
int _tag;
impl::dynamic_storage storage;
template<typename X, typename = type_in_typelist<X>>
void init(const X& x) {
_tag = impl::position<X, Types...>::pos;
new(storage) X(x);
storage.alloc( sizeof(X) );
new(storage.data()) X(x);
}
template<typename X>
template<typename X, typename = type_in_typelist<X>>
void init(X&& x) {
_tag = impl::position<X, Types...>::pos;
new(storage) X( std::move(x) );
storage.alloc( sizeof(X) );
new(storage.data()) X( std::move(x) );
}
void init(tag_type tag)
{
FC_ASSERT( tag >= 0 );
FC_ASSERT( tag < count() );
_tag = tag;
storage.alloc( impl::size<tag_type, Types...>( tag ) );
impl::storage_ops<0, Types...>::con(_tag, storage.data());
}
void clean()
{
impl::storage_ops<0, Types...>::del(_tag, storage.data() );
storage.release();
}
template<typename StaticVariant>
friend struct impl::copy_construct;
template<typename StaticVariant>
friend struct impl::move_construct;
public:
template<typename X>
template<typename X, typename = type_in_typelist<X>>
struct tag
{
static_assert(
impl::position<X, Types...>::pos != -1,
"Type not in static_variant."
);
static const int value = impl::position<X, Types...>::pos;
};
static_variant()
{
_tag = 0;
impl::storage_ops<0, Types...>::con(0, storage);
init(0);
}
template<typename... Other>
static_variant( const static_variant<Other...>& cpy )
{
@ -225,46 +247,34 @@ public:
{
cpy.visit( impl::copy_construct<static_variant>(*this) );
}
static_variant( static_variant&& mv )
{
mv.visit( impl::move_construct<static_variant>(*this) );
}
template<typename X>
template<typename X, typename = type_in_typelist<X>>
static_variant(const X& v) {
static_assert(
impl::position<X, Types...>::pos != -1,
"Type not in static_variant."
);
init(v);
}
~static_variant() {
impl::storage_ops<0, Types...>::del(_tag, storage);
clean();
}
template<typename X>
template<typename X, typename = type_in_typelist<X>>
static_variant& operator=(const X& v) {
static_assert(
impl::position<X, Types...>::pos != -1,
"Type not in static_variant."
);
this->~static_variant();
clean();
init(v);
return *this;
}
static_variant& operator=( const static_variant& v )
{
if( this == &v ) return *this;
this->~static_variant();
clean();
v.visit( impl::copy_construct<static_variant>(*this) );
return *this;
}
static_variant& operator=( static_variant&& v )
{
if( this == &v ) return *this;
this->~static_variant();
clean();
v.visit( impl::move_construct<static_variant>(*this) );
return *this;
}
@ -276,98 +286,73 @@ public:
{
return a.which() < b.which();
}
template<typename X>
template<typename X, typename = type_in_typelist<X>>
X& get() {
static_assert(
impl::position<X, Types...>::pos != -1,
"Type not in static_variant."
);
if(_tag == impl::position<X, Types...>::pos) {
void* tmp(storage);
return *reinterpret_cast<X*>(tmp);
return *reinterpret_cast<X*>(storage.data());
} else {
FC_THROW_EXCEPTION( fc::assert_exception, "static_variant does not contain a value of type ${t}", ("t",fc::get_typename<X>::name()) );
// std::string("static_variant does not contain value of type ") + typeid(X).name()
// );
}
}
template<typename X>
template<typename X, typename = type_in_typelist<X>>
const X& get() const {
static_assert(
impl::position<X, Types...>::pos != -1,
"Type not in static_variant."
);
if(_tag == impl::position<X, Types...>::pos) {
const void* tmp(storage);
return *reinterpret_cast<const X*>(tmp);
return *reinterpret_cast<const X*>(storage.data());
} else {
FC_THROW_EXCEPTION( fc::assert_exception, "static_variant does not contain a value of type ${t}", ("t",fc::get_typename<X>::name()) );
}
}
template<typename visitor>
typename visitor::result_type visit(visitor& v) {
return impl::storage_ops<0, Types...>::apply(_tag, storage, v);
return impl::storage_ops<0, Types...>::apply(_tag, storage.data(), v);
}
template<typename visitor>
typename visitor::result_type visit(const visitor& v) {
return impl::storage_ops<0, Types...>::apply(_tag, storage, v);
return impl::storage_ops<0, Types...>::apply(_tag, storage.data(), v);
}
template<typename visitor>
typename visitor::result_type visit(visitor& v)const {
return impl::storage_ops<0, Types...>::apply(_tag, storage, v);
return impl::storage_ops<0, Types...>::apply(_tag, storage.data(), v);
}
template<typename visitor>
typename visitor::result_type visit(const visitor& v)const {
return impl::storage_ops<0, Types...>::apply(_tag, storage, v);
return impl::storage_ops<0, Types...>::apply(_tag, storage.data(), v);
}
static int count() { return impl::type_info<Types...>::count; }
void set_which( int w ) {
FC_ASSERT( w >= 0 );
FC_ASSERT( w < count() );
this->~static_variant();
_tag = w;
impl::storage_ops<0, Types...>::con(_tag, storage);
clean();
init(w);
}
int which() const {return _tag;}
};
template<typename Result>
struct visitor {
typedef Result result_type;
};
struct from_static_variant
{
variant& var;
const uint32_t _max_depth;
from_static_variant( variant& dv, uint32_t max_depth ):var(dv),_max_depth(max_depth){}
typedef void result_type;
template<typename T> void operator()( const T& v )const
{
to_variant( v, var, _max_depth );
}
};
struct to_static_variant
{
const variant& var;
const uint32_t _max_depth;
to_static_variant( const variant& dv, uint32_t max_depth ):var(dv),_max_depth(max_depth){}
typedef void result_type;
template<typename T> void operator()( T& v )const
{
from_variant( var, v, _max_depth );
}
};
template<typename... T> void to_variant( const fc::static_variant<T...>& s, fc::variant& v, uint32_t max_depth )
{
FC_ASSERT( max_depth > 0 );
@ -384,6 +369,5 @@ struct visitor {
s.set_which( ar[0].as_uint64() );
s.visit( to_static_variant(ar[1], max_depth - 1) );
}
template<typename... T> struct get_typename { static const char* name() { return typeid(static_variant<T...>).name(); } };
} // namespace fc

View file

@ -2,6 +2,7 @@
#include <fc/utility.hpp>
#include <fc/fwd.hpp>
#include <fc/optional.hpp>
#include <fc/config.hpp>
#ifndef USE_FC_STRING
#include <string>
@ -25,7 +26,7 @@ namespace fc
typedef fc::optional<fc::string> ostring;
class variant_object;
fc::string format_string( const fc::string&, const variant_object&, uint32_t max_object_depth = 200 );
fc::string format_string( const fc::string&, const variant_object&, uint32_t max_object_depth = FC_MAX_STRING_OBJECT_DEPTH );
fc::string trim( const fc::string& );
fc::string to_lower( const fc::string& );
string trim_and_normalize_spaces( const string& s );

View file

@ -1497,7 +1497,10 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex
{
mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint i;
r->m_table_sizes[0] = 288; r->m_table_sizes[1] = 32; TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
for ( i = 0; i <= 143; ++i) *p++ = 8; for ( ; i <= 255; ++i) *p++ = 9; for ( ; i <= 279; ++i) *p++ = 7; for ( ; i <= 287; ++i) *p++ = 8;
for ( i = 0; i <= 143; ++i) *p++ = 8;
for ( ; i <= 255; ++i) *p++ = 9;
for ( ; i <= 279; ++i) *p++ = 7;
for ( ; i <= 287; ++i) *p++ = 8;
}
else
{
@ -2281,7 +2284,11 @@ static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahe
if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) break;
TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE;
}
if (!dist) break; q = (const mz_uint16*)(d->m_dict + probe_pos); if (TDEFL_READ_UNALIGNED_WORD(q) != s01) continue; p = s; probe_len = 32;
if (!dist) break;
q = (const mz_uint16*)(d->m_dict + probe_pos);
if (TDEFL_READ_UNALIGNED_WORD(q) != s01) continue;
p = s;
probe_len = 32;
do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) &&
(TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) );
if (!probe_len)

View file

@ -30,6 +30,7 @@ struct aes_encoder::impl
aes_encoder::aes_encoder()
{
static int init = init_openssl();
(void)init;
}
aes_encoder::~aes_encoder()
@ -70,7 +71,9 @@ uint32_t aes_encoder::encode( const char* plaintxt, uint32_t plaintext_len, char
FC_THROW_EXCEPTION( aes_exception, "error during aes 256 cbc encryption update",
("s", ERR_error_string( ERR_get_error(), nullptr) ) );
}
FC_ASSERT( ciphertext_len == plaintext_len, "", ("ciphertext_len",ciphertext_len)("plaintext_len",plaintext_len) );
int64_t ciphertext_len_i64 = ciphertext_len;
int64_t plaintext_len_i64 = plaintext_len;
FC_ASSERT( ciphertext_len_i64 == plaintext_len_i64, "", ("ciphertext_len",ciphertext_len)("plaintext_len",plaintext_len) );
return ciphertext_len;
}
#if 0
@ -98,6 +101,7 @@ struct aes_decoder::impl
aes_decoder::aes_decoder()
{
static int init = init_openssl();
(void)init;
}
void aes_decoder::init( const fc::sha256& key, const fc::uint128& init_value )
@ -137,7 +141,9 @@ uint32_t aes_decoder::decode( const char* ciphertxt, uint32_t ciphertxt_len, cha
FC_THROW_EXCEPTION( aes_exception, "error during aes 256 cbc decryption update",
("s", ERR_error_string( ERR_get_error(), nullptr) ) );
}
FC_ASSERT( ciphertxt_len == plaintext_len, "", ("ciphertxt_len",ciphertxt_len)("plaintext_len",plaintext_len) );
int64_t ciphertxt_len_i64 = ciphertxt_len;
int64_t plaintext_len_i64 = plaintext_len;
FC_ASSERT( ciphertxt_len_i64 == plaintext_len_i64, "", ("ciphertxt_len",ciphertxt_len)("plaintext_len",plaintext_len) );
return plaintext_len;
}
#if 0
@ -377,63 +383,4 @@ std::vector<char> aes_load( const fc::path& file, const fc::sha512& key )
return aes_decrypt( key, cipher );
} FC_RETHROW_EXCEPTIONS( warn, "", ("file",file) ) }
/* This stuff has to go somewhere, I guess this is as good a place as any...
OpenSSL isn't thread-safe unless you give it access to some mutexes,
so the CRYPTO_set_id_callback() function needs to be called before there's any
chance of OpenSSL being accessed from multiple threads.
*/
struct openssl_thread_config
{
static boost::mutex* openssl_mutexes;
static unsigned long get_thread_id();
static void locking_callback(int mode, int type, const char *file, int line);
openssl_thread_config();
~openssl_thread_config();
};
openssl_thread_config openssl_thread_config_manager;
boost::mutex* openssl_thread_config::openssl_mutexes = nullptr;
unsigned long openssl_thread_config::get_thread_id()
{
#ifdef _WIN32
return (unsigned long)::GetCurrentThreadId();
#else
return (unsigned long)(&fc::thread::current()); // TODO: should expose boost thread id
#endif
}
void openssl_thread_config::locking_callback(int mode, int type, const char *file, int line)
{
if (mode & CRYPTO_LOCK)
openssl_mutexes[type].lock();
else
openssl_mutexes[type].unlock();
}
// Warning: Things get complicated if third-party libraries also try to install their their own
// OpenSSL thread functions. Right now, we don't install our own handlers if another library has
// installed them before us which is a partial solution, but you'd really need to evaluate
// each library that does this to make sure they will play nice.
openssl_thread_config::openssl_thread_config()
{
if (CRYPTO_get_id_callback() == NULL &&
CRYPTO_get_locking_callback() == NULL)
{
openssl_mutexes = new boost::mutex[CRYPTO_num_locks()];
CRYPTO_set_id_callback(&get_thread_id);
CRYPTO_set_locking_callback(&locking_callback);
}
}
openssl_thread_config::~openssl_thread_config()
{
if (CRYPTO_get_id_callback() == &get_thread_id)
{
CRYPTO_set_id_callback(NULL);
CRYPTO_set_locking_callback(NULL);
delete[] openssl_mutexes;
openssl_mutexes = nullptr;
}
}
} // namespace fc

View file

@ -85,8 +85,10 @@ namespace fc { namespace ecc {
ssl_bignum order;
FC_ASSERT( EC_GROUP_get_order( group, order, ctx ) );
private_key_secret bin;
FC_ASSERT( BN_num_bytes( order ) == bin.data_size() );
FC_ASSERT( BN_bn2bin( order, (unsigned char*) bin.data() ) == bin.data_size() );
size_t order_BN_num_bytes = BN_num_bytes( order );
FC_ASSERT( order_BN_num_bytes == bin.data_size() );
size_t order_BN_bn2bin = BN_bn2bin( order, (unsigned char*) bin.data() );
FC_ASSERT( order_BN_bn2bin == bin.data_size() );
return bin;
}
@ -104,8 +106,10 @@ namespace fc { namespace ecc {
FC_ASSERT( EC_GROUP_get_order( group, order, ctx ) );
BN_rshift1( order, order );
private_key_secret bin;
FC_ASSERT( BN_num_bytes( order ) == bin.data_size() );
FC_ASSERT( BN_bn2bin( order, (unsigned char*) bin.data() ) == bin.data_size() );
size_t order_BN_num_bytes = BN_num_bytes( order );
FC_ASSERT( order_BN_num_bytes == bin.data_size() );
size_t order_BN_bn2bin = BN_bn2bin( order, (unsigned char*) bin.data() );
FC_ASSERT( order_BN_bn2bin == bin.data_size() );
return bin;
}

View file

@ -32,6 +32,7 @@ namespace fc { namespace ecc {
static const secp256k1_context_t* ctx = _get_context();
static int init_o = init_openssl();
(void)ctx;
(void)init_o;
}
class public_key_impl

View file

@ -91,6 +91,8 @@ namespace fc {
if( ve.size() )
memcpy(&bi, ve.data(), fc::min<size_t>(ve.size(),sizeof(bi)) );
else
memset( &bi, char(0), sizeof(bi) );
for (size_t i = 0; i < bi.data_size(); i++) {
bi.data()[i] = 0;
}
}
}

View file

@ -8,6 +8,8 @@
#include <string>
#include <stdlib.h>
#include <fc/log/logger.hpp>
namespace fc
{
struct openssl_scope
@ -15,9 +17,6 @@ namespace fc
static path _configurationFilePath;
openssl_scope()
{
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
const boost::filesystem::path& boostPath = _configurationFilePath;
if(boostPath.empty() == false)
{
@ -30,13 +29,16 @@ namespace fc
#endif
}
OPENSSL_config(nullptr);
if (CONF_modules_load_file(_configurationFilePath.string().c_str(), "fc", CONF_MFLAGS_IGNORE_MISSING_FILE) <= 0) {
elog("FATAL: error loading configuration file\n");
ERR_print_errors_fp(stderr);
exit(1);
}
}
~openssl_scope()
{
EVP_cleanup();
ERR_free_strings();
}
};

View file

@ -9,19 +9,21 @@ namespace fc {
void rand_bytes(char* buf, int count)
{
static int init = init_openssl();
(void)init;
int result = RAND_bytes((unsigned char*)buf, count);
if (result != 1)
FC_THROW("Error calling OpenSSL's RAND_bytes(): ${code}", ("code", (uint32_t)ERR_get_error()));
}
void rand_pseudo_bytes(char* buf, int count)
{
static int init = init_openssl();
int result = RAND_pseudo_bytes((unsigned char*)buf, count);
if (result == -1)
FC_THROW("Error calling OpenSSL's RAND_pseudo_bytes(): ${code}", ("code", (uint32_t)ERR_get_error()));
}
//void rand_pseudo_bytes(char* buf, int count)
//{
// static int init = init_openssl();
// (void)init;
//
// int result = RAND_pseudo_bytes((unsigned char*)buf, count);
// if (result == -1)
// FC_THROW("Error calling OpenSSL's RAND_pseudo_bytes(): ${code}", ("code", (uint32_t)ERR_get_error()));
//}
} // namespace fc

View file

@ -106,7 +106,9 @@ bool operator == ( const ripemd160& h1, const ripemd160& h2 ) {
void from_variant( const variant& v, ripemd160& bi, uint32_t max_depth )
{
std::vector<char> ve = v.as< std::vector<char> >( max_depth );
memset( &bi, char(0), sizeof(bi) );
for (size_t i = 0; i < bi.data_size(); i++) {
bi.data()[i] = 0;
}
if( ve.size() )
memcpy( &bi, ve.data(), fc::min<size_t>(ve.size(),sizeof(bi)) );
}

View file

@ -90,7 +90,9 @@ bool operator == ( const sha1& h1, const sha1& h2 ) {
void from_variant( const variant& v, sha1& bi, uint32_t max_depth )
{
std::vector<char> ve = v.as< std::vector<char> >( max_depth );
memset( &bi, char(0), sizeof(bi) );
for (size_t i = 0; i < bi.data_size(); i++) {
bi.data()[i] = 0;
}
if( ve.size() )
memcpy( &bi, ve.data(), fc::min<size_t>(ve.size(),sizeof(bi)) );
}

View file

@ -86,7 +86,9 @@ namespace fc {
void from_variant( const variant& v, sha224& bi, uint32_t max_depth )
{
std::vector<char> ve = v.as< std::vector<char> >( max_depth );
memset( &bi, char(0), sizeof(bi) );
for (size_t i = 0; i < bi.data_size(); i++) {
bi.data()[i] = 0;
}
if( ve.size() )
memcpy( &bi, ve.data(), fc::min<size_t>(ve.size(),sizeof(bi)) );
}

View file

@ -200,7 +200,9 @@ namespace fc {
void from_variant( const variant& v, sha256& bi, uint32_t max_depth )
{
std::vector<char> ve = v.as< std::vector<char> >( max_depth );
memset( &bi, char(0), sizeof(bi) );
for (size_t i = 0; i < bi.data_size(); i++) {
bi.data()[i] = 0;
}
if( ve.size() )
memcpy( &bi, ve.data(), fc::min<size_t>(ve.size(),sizeof(bi)) );
}

View file

@ -92,7 +92,9 @@ namespace fc {
void from_variant( const variant& v, sha512& bi, uint32_t max_depth )
{
std::vector<char> ve = v.as< std::vector<char> >( max_depth );
memset( &bi, char(0), sizeof(bi) );
for (size_t i = 0; i < bi.data_size(); i++) {
bi.data()[i] = 0;
}
if( ve.size() )
memcpy( &bi, ve.data(), fc::min<size_t>(ve.size(),sizeof(bi)) );
}

View file

@ -168,7 +168,8 @@ namespace fc {
filename(p),
flush(true),
rotate(false),
rotation_compression(false)
rotation_compression(false),
max_object_depth(FC_MAX_LOG_OBJECT_DEPTH)
{}
file_appender::file_appender( const variant& args ) :

View file

@ -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 )
{
_connection->close(0, "client closed");
_connection.reset();
}
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));

View file

@ -182,7 +182,7 @@ namespace fc
}
}
} // try
catch (fc::canceled_exception)
catch (fc::canceled_exception&)
{
throw;
}

View file

@ -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 */
std::vector<std::reference_wrapper<const std::string>> matched_cmds;
for( const std::string& it : cmds )
{
if( it.compare(0, partlen, token) == 0 )
{
matched_cmds.push_back( it );
}
}
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() );
}
/***
* @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)
{
auto& cmd = cli_commands();
int num_commands = cmd.size();
while( list_index < cmd.size() )
char **copy = (char **) malloc (num_commands * sizeof(char *));
if (copy == NULL)
{
name = cmd[list_index].c_str();
list_index++;
if (strncmp (name, text, len) == 0)
return (dupstr(name));
// possible out of memory
return 0;
}
int total_matches = 0;
/* If no names matched, then return NULL. */
return ((char *)NULL);
}
int partlen = strlen(token);
static char** cli_completion( const char * text , int start, int end)
for (const std::string& it : cmd)
{
char **matches;
matches = (char **)NULL;
if ( it.compare(0, partlen, token) == 0)
{
copy[total_matches] = strdup ( it.c_str() );
++total_matches;
}
}
*array = copy;
#ifdef HAVE_READLINE
if (start == 0)
matches = rl_completion_matches ((char*)text, &my_generator);
else
rl_bind_key('\t',rl_abort);
#endif
return (matches);
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 );
line = line_read;
try
{
if (*line_read)
add_history(line_read);
line = line_read;
}
catch(...)
{
free(line_read);
throw;
}
free(line_read);
}).wait();
}

View file

@ -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;
}

31
src/static_variant.cpp Normal file
View file

@ -0,0 +1,31 @@
#include <fc/static_variant.hpp>
namespace fc { namespace impl {
dynamic_storage::dynamic_storage() : storage(nullptr) {};
dynamic_storage::~dynamic_storage()
{
release();
}
void* dynamic_storage::data() const
{
FC_ASSERT( storage != nullptr );
return (void*)storage;
}
void dynamic_storage::alloc( size_t size )
{
release();
storage = new char[size];
}
void dynamic_storage::release()
{
delete [] storage;
storage = nullptr;
}
}}

View file

@ -1,6 +1,5 @@
#pragma once
#include <fc/thread/thread.hpp>
#include <boost/context/all.hpp>
#include <fc/exception/exception.hpp>
#include <vector>
@ -9,6 +8,12 @@
#define BOOST_COROUTINES_NO_DEPRECATION_WARNING // Boost 1.61
#define BOOST_COROUTINE_NO_DEPRECATION_WARNING // Boost 1.62
#if BOOST_VERSION >= 106800
#include <boost/context/continuation_fcontext.hpp>
#else
#include <boost/context/all.hpp>
#endif
#if BOOST_VERSION >= 106100
#include <boost/coroutine/stack_allocator.hpp>
namespace bc = boost::context::detail;

View file

@ -13,18 +13,18 @@ namespace fc {
{}
mutex::~mutex() {
if( m_blist )
{
context* c = m_blist;
fc::thread::current().debug("~mutex");
#if 0
while( c ) {
// elog( "still blocking on context %p (%s)", m_blist, (m_blist->cur_task ? m_blist->cur_task->get_desc() : "no current task") );
c = c->next_blocked_mutex;
}
#endif
BOOST_ASSERT( false && "Attempt to free mutex while others are blocking on lock." );
}
// if( m_blist )
// {
// context* c = m_blist;
// fc::thread::current().debug("~mutex");
//#if 0
// while( c ) {
// // elog( "still blocking on context %p (%s)", m_blist, (m_blist->cur_task ? m_blist->cur_task->get_desc() : "no current task") );
// c = c->next_blocked_mutex;
// }
//#endif
// BOOST_ASSERT( false && "Attempt to free mutex while others are blocking on lock." );
// }
}
/**

View file

@ -13,7 +13,7 @@ namespace fc {
bool is_utf8( const std::string& str )
{
auto itr = utf8::find_invalid(str.begin(), str.end());
//auto itr = utf8::find_invalid(str.begin(), str.end());
return utf8::is_valid( str.begin(), str.end() );
}

View file

@ -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) ); } );

View file

@ -86,7 +86,7 @@ static void test_58( const std::string& test, const std::string& expected )
try {
len = fc::from_base58( enc1, buffer, 10 );
BOOST_CHECK( len <= 10 );
} catch ( fc::exception expected ) {}
} catch ( fc::exception& expected ) {}
}
}

View file

@ -53,7 +53,7 @@ BOOST_AUTO_TEST_CASE(dh_test)
alice.p.clear(); alice.p.push_back(100); alice.p.push_back(2);
BOOST_CHECK( !alice.validate() );
alice.p = bob.p;
alice.g = 9;
alice.g = 1;
BOOST_CHECK( !alice.validate() );
// It ain't easy...

View file

@ -33,11 +33,11 @@ BOOST_AUTO_TEST_CASE(rand_test)
check_randomness( buffer, sizeof(buffer) );
}
BOOST_AUTO_TEST_CASE(pseudo_rand_test)
{
char buffer[10013];
fc::rand_pseudo_bytes( buffer, sizeof(buffer) );
check_randomness( buffer, sizeof(buffer) );
}
//BOOST_AUTO_TEST_CASE(pseudo_rand_test)
//{
// char buffer[10013];
// fc::rand_pseudo_bytes( buffer, sizeof(buffer) );
// check_randomness( buffer, sizeof(buffer) );
//}
BOOST_AUTO_TEST_SUITE_END()

View file

@ -335,7 +335,7 @@ BOOST_AUTO_TEST_CASE(recursion_test)
BOOST_AUTO_TEST_CASE(rethrow_test)
{
fc::variants biggie;
for( int i = 0; i < 250; i++ )
for( int i = 0; i < 1010; i++ )
{
fc::variant tmp( std::move(biggie) );
biggie.reserve(1);

View file

@ -3,6 +3,8 @@
#include <fc/container/flat.hpp>
#include <fc/io/raw.hpp>
#include <fc/io/json.hpp>
#include <fc/reflect/variant.hpp>
namespace fc { namespace test {
@ -44,6 +46,66 @@ namespace fc { namespace test {
FC_REFLECT( fc::test::item_wrapper, (v) );
FC_REFLECT( fc::test::item, (level)(w) );
// These are used in the custom_serialization test
static bool custom_serialization_used = false;
// Custom serialized type with a fake serializer that does nothing but set the above bool to true
struct custom_serialized_type {
int a = 1;
std::string b = "Hi!";
bool c = true;
// Override default serialization for reflected types
template<typename Stream>
void fc_pack(Stream&, uint32_t) const {
custom_serialization_used = true;
}
template<typename Stream>
void fc_unpack(Stream&, uint32_t) {
custom_serialization_used = true;
}
void fc_to_variant(fc::variant&, uint32_t) const {
custom_serialization_used = true;
}
void fc_from_variant(const fc::variant&, uint32_t) {
custom_serialization_used = true;
}
};
// Default-serialized type with auxiliary data to serialize
struct auxiliary_serialized_type {
int a = 1;
std::string b = "Hi!";
bool c = true;
// Define auxiliary data
template<typename Stream>
void fc_pack_auxiliary(Stream& s, uint32_t) const {
fc::raw::pack(s, 7);
custom_serialization_used = true;
}
template<typename Stream>
void fc_unpack_auxiliary(Stream& s, uint32_t) {
int data;
fc::raw::unpack(s, data);
BOOST_CHECK_EQUAL(data, 7);
custom_serialization_used = true;
}
void fc_auxiliary_to_variant(fc::variant& v, uint32_t) const {
v = 7;
custom_serialization_used = true;
}
void fc_auxiliary_from_variant(const fc::variant& v, uint32_t) {
BOOST_CHECK_EQUAL(v.as_int64(), 7);
custom_serialization_used = true;
}
};
FC_REFLECT(custom_serialized_type, (a)(b)(c))
FC_REFLECT(auxiliary_serialized_type, (a)(b)(c))
BOOST_AUTO_TEST_SUITE(fc_serialization)
BOOST_AUTO_TEST_CASE( nested_objects_test )
@ -105,4 +167,100 @@ BOOST_AUTO_TEST_CASE( nested_objects_test )
} FC_CAPTURE_LOG_AND_RETHROW ( (0) ) }
BOOST_AUTO_TEST_CASE( unpack_recursion_test )
{
try
{
std::stringstream ss;
int recursion_level = 100000;
uint64_t allocation_per_level = 500000;
for ( int i = 0; i < recursion_level; i++ )
{
fc::raw::pack( ss, fc::unsigned_int( allocation_per_level ) );
fc::raw::pack( ss, static_cast< uint8_t >( fc::variant::array_type ) );
}
std::vector< fc::variant > v;
BOOST_REQUIRE_THROW( fc::raw::unpack( ss, v ), fc::assert_exception );
}
FC_LOG_AND_RETHROW();
}
BOOST_AUTO_TEST_CASE( custom_serialization )
{ try {
custom_serialization_used = false;
// Create our custom serialized type and serialize it; check that only our fake serializer ran
custom_serialized_type obj;
auto packed = fc::raw::pack(obj);
BOOST_CHECK(packed.empty());
BOOST_CHECK(custom_serialization_used);
// Deserializer won't run on an empty vector; put a byte in so deserialization tests can run
packed = {'a'};
// Reset the flag, alter the object, and deserialize it, again checking that only the fake serializer ran
custom_serialization_used = false;
obj.c = false;
fc::raw::unpack(packed, obj);
BOOST_CHECK(obj.c == false);
BOOST_CHECK(custom_serialization_used);
// Reset the flag, deserialize again without existing ref, check if fake serializer ran
custom_serialization_used = false;
auto obj2 = fc::raw::unpack<custom_serialized_type>(packed);
BOOST_CHECK(custom_serialization_used);
// All over again, but for variants instead of binary serialization
fc::variant v(obj, 10);
BOOST_CHECK(v.is_null());
BOOST_CHECK(custom_serialization_used);
custom_serialization_used = false;
fc::to_variant(obj, v, 10);
BOOST_CHECK(custom_serialization_used);
// JSON should be affected too. Check it is.
custom_serialization_used = false;
BOOST_CHECK_EQUAL(fc::json::to_string(obj), "null");
BOOST_CHECK(custom_serialization_used);
custom_serialization_used = false;
obj.c = true;
fc::from_variant(v, obj, 10);
BOOST_CHECK(custom_serialization_used);
BOOST_CHECK(obj.c);
} FC_LOG_AND_RETHROW() }
BOOST_AUTO_TEST_CASE( auxiliary_serialization )
{ try {
custom_serialization_used = false;
// Just serialize and deserialize, text and binary. The class does the checks itself -- we just make sure they ran.
auxiliary_serialized_type obj;
auto packed = fc::raw::pack(obj);
BOOST_CHECK(custom_serialization_used);
custom_serialization_used = false;
obj.a = 0;
obj.b = "Something else";
obj.c = false;
// Why I need this cast to get it to build, I may never know... Nor will I get that hour of my life back.
fc::raw::unpack((const std::vector<char>&)packed, obj);
BOOST_CHECK(custom_serialization_used);
BOOST_CHECK_EQUAL(obj.a, 1);
BOOST_CHECK_EQUAL(obj.b, "Hi!");
BOOST_CHECK_EQUAL(obj.c, true);
custom_serialization_used = false;
fc::variant v;
fc::to_variant(obj, v, 10);
BOOST_CHECK(custom_serialization_used);
custom_serialization_used = false;
obj.a = 0;
obj.b = "Something else";
obj.c = false;
fc::from_variant(v, obj, 10);
BOOST_CHECK(custom_serialization_used);
BOOST_CHECK_EQUAL(obj.a, 1);
BOOST_CHECK_EQUAL(obj.b, "Hi!");
BOOST_CHECK_EQUAL(obj.c, true);
} FC_LOG_AND_RETHROW() }
BOOST_AUTO_TEST_SUITE_END()

1
vendor/editline vendored Submodule

@ -0,0 +1 @@
Subproject commit 62bba782585c6c18d7a2b27beeb60a45db9abb43

View file

@ -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

View file

@ -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: ";

View file

@ -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
/**

View file

@ -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

View file

@ -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,

View file

@ -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,

View file

@ -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);

View file

@ -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;

View file

@ -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;