diff --git a/.gitignore b/.gitignore index 7b8c2497..8a45f518 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,7 @@ libobelisk.pc /src/bitcoin_server +build-libbitcoin-server +console/bs +libbitcoin-server.pc + diff --git a/.travis.yml b/.travis.yml index ddd5e152..a182e82d 100755 --- a/.travis.yml +++ b/.travis.yml @@ -85,9 +85,9 @@ script: # Download and build libbitcoin-server and all dependencies. - if [[ $OSX && $CLANG && $STATIC ]]; then CC=$CC CXX=$CXX ./install.sh --enable-isystem --without-consensus --disable-shared --build-boost --build-zmq --prefix=$TRAVIS_BUILD_DIR/my-prefix; fi - if [[ $LINUX && $CLANG && $STATIC ]]; then CC=$CC CXX=$CXX ./install.sh --enable-isystem --disable-shared --build-boost --build-zmq --prefix=$TRAVIS_BUILD_DIR/my-prefix CFLAGS='-Os' CXXFLAGS='-Os'; fi - - if [[ $LINUX && $GCC && $STATIC ]]; then CC=$CC CXX=$CXX ./install.sh --enable-isystem --build-boost --build-zmq --disable-shared --build-dir=my-build --prefix=$TRAVIS_BUILD_DIR/my-prefix --with-bash-completiondir=$TRAVIS_BUILD_DIR/my-prefix/share/bash-completion/completions CFLAGS='-Og -g --coverage' CXXFLAGS='-Og -g --coverage'; fi - - if [[ $OSX && $CLANG && $DYNAMIC ]]; then CC=$CC CXX=$CXX ./install.sh --enable-isystem --build-zmq --disable-static --with-bash-completiondir; fi - - if [[ $LINUX && $CLANG && $DYNAMIC ]]; then CC=$CC CXX=$CXX ./install.sh --enable-isystem --build-boost --build-zmq --disable-ndebug --disable-static --prefix=$TRAVIS_BUILD_DIR/my-prefix CFLAGS='-Os' CXXFLAGS='-Os'; fi + - if [[ $LINUX && $GCC && $STATIC ]]; then CC=$CC CXX=$CXX ./install.sh --enable-isystem --build-boost --build-zmq --build-mbedtls --disable-shared --build-dir=my-build --prefix=$TRAVIS_BUILD_DIR/my-prefix --with-bash-completiondir=$TRAVIS_BUILD_DIR/my-prefix/share/bash-completion/completions CFLAGS='-Og -g --coverage' CXXFLAGS='-Og -g --coverage'; fi + - if [[ $OSX && $CLANG && $DYNAMIC ]]; then CC=$CC CXX=$CXX ./install.sh --enable-isystem --build-zmq --build-mbedtls --disable-static --with-bash-completiondir; fi + - if [[ $LINUX && $CLANG && $DYNAMIC ]]; then CC=$CC CXX=$CXX ./install.sh --enable-isystem --build-boost --build-zmq --build-mbedtls --disable-ndebug --disable-static --prefix=$TRAVIS_BUILD_DIR/my-prefix CFLAGS='-Os' CXXFLAGS='-Os'; fi - if [[ $LINUX && $GCC && $DYNAMIC ]]; then CC=$CC CXX=$CXX ./install.sh --enable-isystem --without-consensus --disable-static --build-boost --build-zmq --with-bash-completiondir=$TRAVIS_BUILD_DIR/my-prefix/share/bash-completion/completions --prefix=$TRAVIS_BUILD_DIR/my-prefix CFLAGS='-Os -s' CXXFLAGS='-Os -s'; fi after_success: diff --git a/Makefile.am b/Makefile.am index 205ff081..d75f09a4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -32,8 +32,8 @@ doc_DATA = \ # src/libbitcoin-server.la => ${libdir} #------------------------------------------------------------------------------ lib_LTLIBRARIES = src/libbitcoin-server.la -src_libbitcoin_server_la_CPPFLAGS = -I${srcdir}/include -DSYSCONFDIR=\"${sysconfdir}\" ${bitcoin_protocol_BUILD_CPPFLAGS} ${bitcoin_node_BUILD_CPPFLAGS} -src_libbitcoin_server_la_LIBADD = ${bitcoin_protocol_LIBS} ${bitcoin_node_LIBS} +src_libbitcoin_server_la_CPPFLAGS = -I${srcdir}/include -DSYSCONFDIR=\"${sysconfdir}\" ${mbedtls} ${bitcoin_protocol_BUILD_CPPFLAGS} ${bitcoin_node_BUILD_CPPFLAGS} ${mbedtls_BUILD_CPPFLAGS} +src_libbitcoin_server_la_LIBADD = ${bitcoin_protocol_LIBS} ${bitcoin_node_LIBS} ${mbedtls_LIBS} src_libbitcoin_server_la_SOURCES = \ src/configuration.cpp \ src/parser.cpp \ @@ -50,6 +50,19 @@ src_libbitcoin_server_la_SOURCES = \ src/services/heartbeat_service.cpp \ src/services/query_service.cpp \ src/services/transaction_service.cpp \ + src/web/block_socket.cpp \ + src/web/heartbeat_socket.cpp \ + src/web/json_string.cpp \ + src/web/query_socket.cpp \ + src/web/socket.cpp \ + src/web/transaction_socket.cpp \ + src/web/http/connection.cpp \ + src/web/http/connection.hpp \ + src/web/http/http.hpp \ + src/web/http/manager.cpp \ + src/web/http/manager.hpp \ + src/web/http/utilities.cpp \ + src/web/http/utilities.hpp \ src/workers/authenticator.cpp \ src/workers/notification_worker.cpp \ src/workers/query_worker.cpp @@ -61,8 +74,8 @@ if WITH_TESTS TESTS = libbitcoin-server-test_runner.sh check_PROGRAMS = test/libbitcoin-server-test -test_libbitcoin_server_test_CPPFLAGS = -I${srcdir}/include ${bitcoin_protocol_BUILD_CPPFLAGS} ${bitcoin_node_BUILD_CPPFLAGS} -test_libbitcoin_server_test_LDADD = src/libbitcoin-server.la ${boost_unit_test_framework_LIBS} ${bitcoin_protocol_LIBS} ${bitcoin_node_LIBS} +test_libbitcoin_server_test_CPPFLAGS = -I${srcdir}/include ${mbedtls} ${bitcoin_protocol_BUILD_CPPFLAGS} ${bitcoin_node_BUILD_CPPFLAGS} ${mbedtls_BUILD_CPPFLAGS} +test_libbitcoin_server_test_LDADD = src/libbitcoin-server.la ${boost_unit_test_framework_LIBS} ${bitcoin_protocol_LIBS} ${bitcoin_node_LIBS} ${mbedtls_LIBS} test_libbitcoin_server_test_SOURCES = \ test/main.cpp \ test/server.cpp \ @@ -75,8 +88,8 @@ endif WITH_TESTS if WITH_CONSOLE bin_PROGRAMS = console/bs -console_bs_CPPFLAGS = -I${srcdir}/include ${bitcoin_protocol_BUILD_CPPFLAGS} ${bitcoin_node_BUILD_CPPFLAGS} -console_bs_LDADD = src/libbitcoin-server.la ${bitcoin_protocol_LIBS} ${bitcoin_node_LIBS} +console_bs_CPPFLAGS = -I${srcdir}/include ${mbedtls} ${bitcoin_protocol_BUILD_CPPFLAGS} ${bitcoin_node_BUILD_CPPFLAGS} ${mbedtls_BUILD_CPPFLAGS} +console_bs_LDADD = src/libbitcoin-server.la ${bitcoin_protocol_LIBS} ${bitcoin_node_LIBS} ${mbedtls_LIBS} console_bs_SOURCES = \ console/executor.cpp \ console/executor.hpp \ @@ -119,6 +132,15 @@ include_bitcoin_server_services_HEADERS = \ include/bitcoin/server/services/query_service.hpp \ include/bitcoin/server/services/transaction_service.hpp +include_bitcoin_server_webdir = ${includedir}/bitcoin/server/web +include_bitcoin_server_web_HEADERS = \ + include/bitcoin/server/web/block_socket.hpp \ + include/bitcoin/server/web/heartbeat_socket.hpp \ + include/bitcoin/server/web/json_string.hpp \ + include/bitcoin/server/web/query_socket.hpp \ + include/bitcoin/server/web/socket.hpp \ + include/bitcoin/server/web/transaction_socket.hpp + include_bitcoin_server_workersdir = ${includedir}/bitcoin/server/workers include_bitcoin_server_workers_HEADERS = \ include/bitcoin/server/workers/authenticator.hpp \ diff --git a/builds/msvc/vs2013/libbitcoin-server/libbitcoin-server.vcxproj b/builds/msvc/vs2013/libbitcoin-server/libbitcoin-server.vcxproj index 8eebda8a..2eb7b115 100644 --- a/builds/msvc/vs2013/libbitcoin-server/libbitcoin-server.vcxproj +++ b/builds/msvc/vs2013/libbitcoin-server/libbitcoin-server.vcxproj @@ -88,6 +88,15 @@ + + + + + + + + + @@ -111,9 +120,19 @@ + + + + + + + + + + diff --git a/builds/msvc/vs2013/libbitcoin-server/libbitcoin-server.vcxproj.filters b/builds/msvc/vs2013/libbitcoin-server/libbitcoin-server.vcxproj.filters index 7923d969..f36fd810 100644 --- a/builds/msvc/vs2013/libbitcoin-server/libbitcoin-server.vcxproj.filters +++ b/builds/msvc/vs2013/libbitcoin-server/libbitcoin-server.vcxproj.filters @@ -8,28 +8,31 @@ - {73CE0AC2-ECB2-4E8D-0000-000000000005} + {73CE0AC2-ECB2-4E8D-0000-000000000007} - {73CE0AC2-ECB2-4E8D-0000-000000000006} + {73CE0AC2-ECB2-4E8D-0000-000000000008} - {73CE0AC2-ECB2-4E8D-0000-000000000007} + {73CE0AC2-ECB2-4E8D-0000-000000000009} - {73CE0AC2-ECB2-4E8D-0000-000000000008} + {73CE0AC2-ECB2-4E8D-0000-00000000000A} - {73CE0AC2-ECB2-4E8D-0000-000000000009} + {73CE0AC2-ECB2-4E8D-0000-00000000000B} - {73CE0AC2-ECB2-4E8D-0000-00000000000A} + {73CE0AC2-ECB2-4E8D-0000-00000000000C} + + + {73CE0AC2-ECB2-4E8D-0000-00000000000D} - {73CE0AC2-ECB2-4E8D-0000-00000000000B} + {73CE0AC2-ECB2-4E8D-0000-00000000000E} - {73CE0AC2-ECB2-4E8D-0000-00000000000C} + {73CE0AC2-ECB2-4E8D-0000-00000000000F} {73CE0AC2-ECB2-4E8D-0000-000000000000} @@ -43,9 +46,15 @@ {73CE0AC2-ECB2-4E8D-0000-000000000003} - + {73CE0AC2-ECB2-4E8D-0000-000000000004} + + {73CE0AC2-ECB2-4E8D-0000-000000000006} + + + {73CE0AC2-ECB2-4E8D-0000-000000000005} + @@ -93,6 +102,33 @@ src + + src\web + + + src\web + + + src\web\http + + + src\web\http + + + src\web\http + + + src\web + + + src\web + + + src\web + + + src\web + src\workers @@ -158,6 +194,24 @@ include\bitcoin\server + + include\bitcoin\server\web + + + include\bitcoin\server\web + + + include\bitcoin\server\web + + + include\bitcoin\server\web + + + include\bitcoin\server\web + + + include\bitcoin\server\web + include\bitcoin\server\workers @@ -167,6 +221,18 @@ include\bitcoin\server\workers + + src\web\http + + + src\web\http + + + src\web\http + + + src\web\http + resource diff --git a/builds/msvc/vs2015/libbitcoin-server/libbitcoin-server.vcxproj b/builds/msvc/vs2015/libbitcoin-server/libbitcoin-server.vcxproj index 1411220b..c4fd46ca 100644 --- a/builds/msvc/vs2015/libbitcoin-server/libbitcoin-server.vcxproj +++ b/builds/msvc/vs2015/libbitcoin-server/libbitcoin-server.vcxproj @@ -88,6 +88,15 @@ + + + + + + + + + @@ -111,9 +120,19 @@ + + + + + + + + + + diff --git a/builds/msvc/vs2015/libbitcoin-server/libbitcoin-server.vcxproj.filters b/builds/msvc/vs2015/libbitcoin-server/libbitcoin-server.vcxproj.filters index 02e5b4a7..9e337f07 100644 --- a/builds/msvc/vs2015/libbitcoin-server/libbitcoin-server.vcxproj.filters +++ b/builds/msvc/vs2015/libbitcoin-server/libbitcoin-server.vcxproj.filters @@ -8,28 +8,31 @@ - {73CE0AC2-ECB2-4E8D-0000-000000000005} + {73CE0AC2-ECB2-4E8D-0000-000000000007} - {73CE0AC2-ECB2-4E8D-0000-000000000006} + {73CE0AC2-ECB2-4E8D-0000-000000000008} - {73CE0AC2-ECB2-4E8D-0000-000000000007} + {73CE0AC2-ECB2-4E8D-0000-000000000009} - {73CE0AC2-ECB2-4E8D-0000-000000000008} + {73CE0AC2-ECB2-4E8D-0000-00000000000A} - {73CE0AC2-ECB2-4E8D-0000-000000000009} + {73CE0AC2-ECB2-4E8D-0000-00000000000B} - {73CE0AC2-ECB2-4E8D-0000-00000000000A} + {73CE0AC2-ECB2-4E8D-0000-00000000000C} + + + {73CE0AC2-ECB2-4E8D-0000-00000000000D} - {73CE0AC2-ECB2-4E8D-0000-00000000000B} + {73CE0AC2-ECB2-4E8D-0000-00000000000E} - {73CE0AC2-ECB2-4E8D-0000-00000000000C} + {73CE0AC2-ECB2-4E8D-0000-00000000000F} {73CE0AC2-ECB2-4E8D-0000-000000000000} @@ -43,9 +46,15 @@ {73CE0AC2-ECB2-4E8D-0000-000000000003} - + {73CE0AC2-ECB2-4E8D-0000-000000000004} + + {73CE0AC2-ECB2-4E8D-0000-000000000006} + + + {73CE0AC2-ECB2-4E8D-0000-000000000005} + @@ -93,6 +102,33 @@ src + + src\web + + + src\web + + + src\web\http + + + src\web\http + + + src\web\http + + + src\web + + + src\web + + + src\web + + + src\web + src\workers @@ -158,6 +194,24 @@ include\bitcoin\server + + include\bitcoin\server\web + + + include\bitcoin\server\web + + + include\bitcoin\server\web + + + include\bitcoin\server\web + + + include\bitcoin\server\web + + + include\bitcoin\server\web + include\bitcoin\server\workers @@ -167,6 +221,18 @@ include\bitcoin\server\workers + + src\web\http + + + src\web\http + + + src\web\http + + + src\web\http + resource diff --git a/builds/msvc/vs2017/libbitcoin-server/libbitcoin-server.vcxproj b/builds/msvc/vs2017/libbitcoin-server/libbitcoin-server.vcxproj index 9e48b669..04ac3610 100644 --- a/builds/msvc/vs2017/libbitcoin-server/libbitcoin-server.vcxproj +++ b/builds/msvc/vs2017/libbitcoin-server/libbitcoin-server.vcxproj @@ -88,6 +88,15 @@ + + + + + + + + + @@ -111,9 +120,19 @@ + + + + + + + + + + diff --git a/builds/msvc/vs2017/libbitcoin-server/libbitcoin-server.vcxproj.filters b/builds/msvc/vs2017/libbitcoin-server/libbitcoin-server.vcxproj.filters index 3f410f19..252de7e8 100644 --- a/builds/msvc/vs2017/libbitcoin-server/libbitcoin-server.vcxproj.filters +++ b/builds/msvc/vs2017/libbitcoin-server/libbitcoin-server.vcxproj.filters @@ -8,28 +8,31 @@ - {73CE0AC2-ECB2-4E8D-0000-000000000005} + {73CE0AC2-ECB2-4E8D-0000-000000000007} - {73CE0AC2-ECB2-4E8D-0000-000000000006} + {73CE0AC2-ECB2-4E8D-0000-000000000008} - {73CE0AC2-ECB2-4E8D-0000-000000000007} + {73CE0AC2-ECB2-4E8D-0000-000000000009} - {73CE0AC2-ECB2-4E8D-0000-000000000008} + {73CE0AC2-ECB2-4E8D-0000-00000000000A} - {73CE0AC2-ECB2-4E8D-0000-000000000009} + {73CE0AC2-ECB2-4E8D-0000-00000000000B} - {73CE0AC2-ECB2-4E8D-0000-00000000000A} + {73CE0AC2-ECB2-4E8D-0000-00000000000C} + + + {73CE0AC2-ECB2-4E8D-0000-00000000000D} - {73CE0AC2-ECB2-4E8D-0000-00000000000B} + {73CE0AC2-ECB2-4E8D-0000-00000000000E} - {73CE0AC2-ECB2-4E8D-0000-00000000000C} + {73CE0AC2-ECB2-4E8D-0000-00000000000F} {73CE0AC2-ECB2-4E8D-0000-000000000000} @@ -43,9 +46,15 @@ {73CE0AC2-ECB2-4E8D-0000-000000000003} - + {73CE0AC2-ECB2-4E8D-0000-000000000004} + + {73CE0AC2-ECB2-4E8D-0000-000000000006} + + + {73CE0AC2-ECB2-4E8D-0000-000000000005} + @@ -93,6 +102,33 @@ src + + src\web + + + src\web + + + src\web\http + + + src\web\http + + + src\web\http + + + src\web + + + src\web + + + src\web + + + src\web + src\workers @@ -158,6 +194,24 @@ include\bitcoin\server + + include\bitcoin\server\web + + + include\bitcoin\server\web + + + include\bitcoin\server\web + + + include\bitcoin\server\web + + + include\bitcoin\server\web + + + include\bitcoin\server\web + include\bitcoin\server\workers @@ -167,6 +221,18 @@ include\bitcoin\server\workers + + src\web\http + + + src\web\http + + + src\web\http + + + src\web\http + resource diff --git a/configure.ac b/configure.ac index 8f110e9c..8e1619e6 100644 --- a/configure.ac +++ b/configure.ac @@ -117,6 +117,17 @@ AC_ARG_WITH([console], AC_MSG_RESULT([$with_console]) AM_CONDITIONAL([WITH_CONSOLE], [test x$with_console != xno]) +# Implement --with-mbedtls and output ${mbedtls}. +#------------------------------------------------------------------------------ +AC_MSG_CHECKING([--with-mbedtls option]) +AC_ARG_WITH([mbedtls], + AS_HELP_STRING([--with-mbedtls], + [Compile with MbedTLS. @<:@default=no@:>@]), + [with_mbedtls=$withval], + [with_mbedtls=no]) +AC_MSG_RESULT([$with_mbedtls]) +AS_CASE([${with_mbedtls}], [yes], AC_SUBST([mbedtls], [-DWITH_MBEDTLS])) + # Implement --enable-ndebug and define NDEBUG. #------------------------------------------------------------------------------ AC_MSG_CHECKING([--enable-ndebug option]) @@ -245,6 +256,22 @@ AS_CASE([${enable_isystem}],[yes], AC_MSG_NOTICE([bitcoin_protocol_BUILD_CPPFLAGS : ${bitcoin_protocol_BUILD_CPPFLAGS}]) +# Require mbedtls of at least version 2.12.0 and output ${mbedtls_CPPFLAGS/LIBS/PKG}. +#------------------------------------------------------------------------------ +AS_CASE([${with_mbedtls}], [yes], + [AC_SUBST([mbedtls_INCLUDEDIR], []) + AC_SUBST([mbedtls_OTHER_CPPFLAGS], []) + AC_SUBST([mbedtls_CPPFLAGS], []) + AC_SUBST([mbedtls_ISYS_CPPFLAGS], []) + AC_SUBST([mbedtls_LIBS], ["-lmbedtls -lmbedcrypto -lmbedx509"]) + AC_MSG_NOTICE([mbedtls presumed, not detected - absence of -lmbedtls -lmbedcrypto -lmbedx509 may result in link error.])], []) + +AS_CASE([${enable_isystem}],[yes], + [AC_SUBST([mbedtls_BUILD_CPPFLAGS], [${mbedtls_ISYS_CPPFLAGS}])], + [AC_SUBST([mbedtls_BUILD_CPPFLAGS], [${mbedtls_CPPFLAGS}])]) + +AC_MSG_NOTICE([mbedtls_BUILD_CPPFLAGS : ${mbedtls_BUILD_CPPFLAGS}]) + # Set flags. #============================================================================== diff --git a/data/bs.cfg b/data/bs.cfg index 5cceba91..ee7579bf 100644 --- a/data/bs.cfg +++ b/data/bs.cfg @@ -195,9 +195,9 @@ send_high_water = 100 receive_high_water = 100 # The time limit to complete the connection handshake, defaults to 30. handshake_seconds = 30 -# Disable public endpoints, defaults to false. +# Disable all public endpoints, defaults to false. secure_only = false -# The number of query worker threads per endpoint, defaults to 1 (0 disables service). +# The number of query worker threads, defaults to 1 (0 disables service). query_workers = 1 # The maximum number of query subscriptions, defaults to 1000 (0 disables subscribe). subscription_limit = 1000 @@ -209,33 +209,62 @@ heartbeat_service_seconds = 5 block_service_enabled = true # Enable the transaction publishing service, defaults to true. transaction_service_enabled = true +# Allowed client IP address, multiple entries allowed. +#client_address = 127.0.0.1 +# Blocked client IP address, multiple entries allowed. +#blacklist = 127.0.0.1 + +[websockets] +# The secure query websocket endpoint, defaults to 'tcp://*:9061'. +secure_query_endpoint = tcp://*:9061 +# The secure heartbeat websocket endpoint, defaults to 'tcp://*:9062'. +secure_heartbeat_endpoint = tcp://*:9062 +# The secure block publishing websocket endpoint, defaults to 'tcp://*:9063'. +secure_block_endpoint = tcp://*:9063 +# The secure transaction publishing websocket endpoint, defaults to 'tcp://*:9064'. +secure_transaction_endpoint = tcp://*:9064 +# The public query websocket endpoint, defaults to 'tcp://*:9071'. +public_query_endpoint = tcp://*:9071 +# The public heartbeat websocket endpoint, defaults to 'tcp://*:9072'. +public_heartbeat_endpoint = tcp://*:9072 +# The public block publishing websocket endpoint, defaults to 'tcp://*:9073'. +public_block_endpoint = tcp://*:9073 +# The public transaction publishing websocket endpoint, defaults to 'tcp://*:9074'. +public_transaction_endpoint = tcp://*:9074 +# Enable websocket endpoints, defaults to true. +enabled = true +# The optional directory for serving files via HTTP/S, defaults to 'web'. +root = web +# The SSL certificate authority file, defaults to 'ca.pem', enables secure endpoints. +ca_certificate = ca.pem +# The SSL private key file, defaults to 'key.pem', enables secure endpoints. +server_private_key = key.pem +# The SSL certificate file, defaults to 'server.pem', enables secure endpoints. +server_certificate = server.pem +# The SSL client certificates directory, defaults to 'clients'. +client_certificates = clients -# The secure query endpoint, defaults to 'tcp://*:9081'. +[zeromq] +# The secure query zeromq endpoint, defaults to 'tcp://*:9081'. secure_query_endpoint = tcp://*:9081 -# The secure heartbeat endpoint, defaults to 'tcp://*:9082'. +# The secure heartbeat zeromq endpoint, defaults to 'tcp://*:9082'. secure_heartbeat_endpoint = tcp://*:9082 -# The secure block publishing endpoint, defaults to 'tcp://*:9083'. +# The secure block publishing zeromq endpoint, defaults to 'tcp://*:9083'. secure_block_endpoint = tcp://*:9083 -# The secure transaction publishing endpoint, defaults to 'tcp://*:9084'. +# The secure transaction publishing zeromq endpoint, defaults to 'tcp://*:9084'. secure_transaction_endpoint = tcp://*:9084 - -# The public query endpoint, defaults to 'tcp://*:9091'. +# The public query zeromq endpoint, defaults to 'tcp://*:9091'. public_query_endpoint = tcp://*:9091 -# The public heartbeat endpoint, defaults to 'tcp://*:9092'. +# The public heartbeat zeromq endpoint, defaults to 'tcp://*:9092'. public_heartbeat_endpoint = tcp://*:9092 -# The public block publishing endpoint, defaults to 'tcp://*:9093'. +# The public block publishing zeromq endpoint, defaults to 'tcp://*:9093'. public_block_endpoint = tcp://*:9093 -# The public transaction publishing endpoint, defaults to 'tcp://*:9094'. +# The public transaction publishing zeromq endpoint, defaults to 'tcp://*:9094'. public_transaction_endpoint = tcp://*:9094 - # The Z85-encoded private key of the server, enables secure endpoints. #server_private_key = # Allowed Z85-encoded public key of the client, multiple entries allowed. #client_public_key = -# Allowed client IP address, multiple entries allowed. -#client_address = 127.0.0.1 -# Blocked client IP address, multiple entries allowed. -#blacklist = 127.0.0.1 [bitcoin] # The difficulty retargeting factor, defaults to 4. diff --git a/include/bitcoin/server.hpp b/include/bitcoin/server.hpp index e30ef396..8ba5e763 100644 --- a/include/bitcoin/server.hpp +++ b/include/bitcoin/server.hpp @@ -33,6 +33,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include #include #include diff --git a/include/bitcoin/server/define.hpp b/include/bitcoin/server/define.hpp index 37bbf03e..af831b2d 100644 --- a/include/bitcoin/server/define.hpp +++ b/include/bitcoin/server/define.hpp @@ -39,11 +39,12 @@ // Log name. #define LOG_SERVER "server" +#define LOG_SERVER_HTTP "http" // Avoid namespace conflict between boost::placeholders and std::placeholders. #define BOOST_BIND_NO_PLACEHOLDERS -// Include boost only here, so placeholders exclusion works. +#include #include #include #include diff --git a/include/bitcoin/server/parser.hpp b/include/bitcoin/server/parser.hpp index af0e0248..bd6238d0 100644 --- a/include/bitcoin/server/parser.hpp +++ b/include/bitcoin/server/parser.hpp @@ -20,8 +20,7 @@ #define LIBBITCOIN_SERVER_PARSER_HPP #include -#include -#include +#include #include namespace libbitcoin { diff --git a/include/bitcoin/server/server_node.hpp b/include/bitcoin/server/server_node.hpp index e977d8ef..685591f1 100644 --- a/include/bitcoin/server/server_node.hpp +++ b/include/bitcoin/server/server_node.hpp @@ -31,6 +31,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -109,6 +113,8 @@ class BCS_API server_node authenticator authenticator_; query_service secure_query_service_; query_service public_query_service_; + + // Zeromq services heartbeat_service secure_heartbeat_service_; heartbeat_service public_heartbeat_service_; block_service secure_block_service_; @@ -117,6 +123,18 @@ class BCS_API server_node transaction_service public_transaction_service_; notification_worker secure_notification_worker_; notification_worker public_notification_worker_; + + // Websocket services +#ifdef WITH_MBEDTLS + query_socket secure_query_websockets_; + heartbeat_socket secure_heartbeat_websockets_; + block_socket secure_block_websockets_; + transaction_socket secure_transaction_websockets_; +#endif + query_socket public_query_websockets_; + heartbeat_socket public_heartbeat_websockets_; + block_socket public_block_websockets_; + transaction_socket public_transaction_websockets_; }; } // namespace server diff --git a/include/bitcoin/server/settings.hpp b/include/bitcoin/server/settings.hpp index cea21ca8..8ef1624f 100644 --- a/include/bitcoin/server/settings.hpp +++ b/include/bitcoin/server/settings.hpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -30,7 +29,7 @@ namespace libbitcoin { namespace server { -/// Common database configuration settings, properties not thread safe. +/// Common server configuration settings, properties not thread safe. class BCS_API settings { public: @@ -40,36 +39,60 @@ class BCS_API settings /// Helpers. asio::duration heartbeat_interval() const; asio::duration subscription_expiration() const; - const config::endpoint& query_endpoint(bool secure) const; - const config::endpoint& heartbeat_endpoint(bool secure) const; - const config::endpoint& block_endpoint(bool secure) const; - const config::endpoint& transaction_endpoint(bool secure) const; - /// Properties. + const config::endpoint& zeromq_query_endpoint(bool secure) const; + const config::endpoint& zeromq_heartbeat_endpoint(bool secure) const; + const config::endpoint& zeromq_block_endpoint(bool secure) const; + const config::endpoint& zeromq_transaction_endpoint(bool secure) const; + + const config::endpoint& websockets_query_endpoint(bool secure) const; + const config::endpoint& websockets_heartbeat_endpoint(bool secure) const; + const config::endpoint& websockets_block_endpoint(bool secure) const; + const config::endpoint& websockets_transaction_endpoint(bool secure) const; + + /// [server] bool priority; bool secure_only; - uint16_t query_workers; uint32_t subscription_limit; uint32_t subscription_expiration_minutes; uint32_t heartbeat_service_seconds; bool block_service_enabled; bool transaction_service_enabled; + config::authority::list client_addresses; + config::authority::list blacklists; - config::endpoint secure_query_endpoint; - config::endpoint secure_heartbeat_endpoint; - config::endpoint secure_block_endpoint; - config::endpoint secure_transaction_endpoint; + /// [websockets] + config::endpoint websockets_secure_query_endpoint; + config::endpoint websockets_secure_heartbeat_endpoint; + config::endpoint websockets_secure_block_endpoint; + config::endpoint websockets_secure_transaction_endpoint; - config::endpoint public_query_endpoint; - config::endpoint public_heartbeat_endpoint; - config::endpoint public_block_endpoint; - config::endpoint public_transaction_endpoint; + config::endpoint websockets_public_query_endpoint; + config::endpoint websockets_public_heartbeat_endpoint; + config::endpoint websockets_public_block_endpoint; + config::endpoint websockets_public_transaction_endpoint; - config::sodium server_private_key; - config::sodium::list client_public_keys; - config::authority::list client_addresses; - config::authority::list blacklists; + bool websockets_enabled; + boost::filesystem::path websockets_root; + boost::filesystem::path websockets_ca_certificate; + boost::filesystem::path websockets_server_private_key; + boost::filesystem::path websockets_server_certificate; + boost::filesystem::path websockets_client_certificates; + + /// [zeromq] + config::endpoint zeromq_secure_query_endpoint; + config::endpoint zeromq_secure_heartbeat_endpoint; + config::endpoint zeromq_secure_block_endpoint; + config::endpoint zeromq_secure_transaction_endpoint; + + config::endpoint zeromq_public_query_endpoint; + config::endpoint zeromq_public_heartbeat_endpoint; + config::endpoint zeromq_public_block_endpoint; + config::endpoint zeromq_public_transaction_endpoint; + + config::sodium zeromq_server_private_key; + config::sodium::list zeromq_client_public_keys; }; } // namespace server diff --git a/include/bitcoin/server/web/block_socket.hpp b/include/bitcoin/server/web/block_socket.hpp new file mode 100644 index 00000000..026e153d --- /dev/null +++ b/include/bitcoin/server/web/block_socket.hpp @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2011-2017 libbitcoin developers (see AUTHORS) + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#ifndef LIBBITCOIN_SERVER_WEB_BLOCK_SOCKET_HPP +#define LIBBITCOIN_SERVER_WEB_BLOCK_SOCKET_HPP + +#include +#include +#include + +namespace libbitcoin { +namespace server { + +class server_node; + +// This class is thread safe. +// Subscribe to block acceptances into the long chain from a dedicated +// socket endpoint. +class BCS_API block_socket + : public socket +{ +public: + typedef std::shared_ptr ptr; + + /// Construct a block socket service endpoint. + block_socket(bc::protocol::zmq::authenticator& authenticator, + server_node& node, bool secure); + +protected: + // Implement the service. + virtual void work() override; + + virtual const config::endpoint& zeromq_endpoint() const override; + virtual const config::endpoint& websocket_endpoint() const override; + +private: + bool handle_block(bc::protocol::zmq::socket& subscriber); +}; + +} // namespace server +} // namespace libbitcoin + +#endif diff --git a/include/bitcoin/server/web/heartbeat_socket.hpp b/include/bitcoin/server/web/heartbeat_socket.hpp new file mode 100644 index 00000000..3b2b7162 --- /dev/null +++ b/include/bitcoin/server/web/heartbeat_socket.hpp @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2011-2017 libbitcoin developers (see AUTHORS) + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#ifndef LIBBITCOIN_SERVER_WEB_HEARTBEAT_SOCKET_HPP +#define LIBBITCOIN_SERVER_WEB_HEARTBEAT_SOCKET_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace libbitcoin { +namespace server { + +class server_node; + +// This class is thread safe. +// Subscribe to a pulse from a dedicated socket endpoint. +class BCS_API heartbeat_socket + : public socket +{ +public: + typedef std::shared_ptr ptr; + + /// Construct a heartbeat socket service endpoint. + heartbeat_socket(bc::protocol::zmq::authenticator& authenticator, + server_node& node, bool secure); + +protected: + + // Implement the service. + virtual void work() override; + + virtual const config::endpoint& zeromq_endpoint() const override; + virtual const config::endpoint& websocket_endpoint() const override; + +private: + bool handle_heartbeat(bc::protocol::zmq::socket& subscriber); +}; + +} // namespace server +} // namespace libbitcoin + +#endif diff --git a/include/bitcoin/server/web/json_string.hpp b/include/bitcoin/server/web/json_string.hpp new file mode 100644 index 00000000..37d7ac8b --- /dev/null +++ b/include/bitcoin/server/web/json_string.hpp @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2011-2017 libbitcoin developers (see AUTHORS) + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#ifndef LIBBITCOIN_SERVER_WEB_JSON_STRING_HPP +#define LIBBITCOIN_SERVER_WEB_JSON_STRING_HPP + +#include +#include + +namespace libbitcoin { +namespace server { +namespace web { + +// Object to JSON converters. +//----------------------------------------------------------------------------- + +std::string to_json(const boost::property_tree::ptree& tree); +std::string to_json(uint64_t height, uint32_t id); +std::string to_json(const int code, const std::string message, uint32_t id); +std::string to_json(const std::error_code& code, uint32_t id); +std::string to_json(const bc::chain::header& header, uint32_t id); +std::string to_json(const bc::chain::block& block, uint32_t id); +std::string to_json(const bc::chain::block& block, uint32_t height, + uint32_t id); +std::string to_json(const bc::chain::transaction& transaction, uint32_t id); + +} // namespace web +} // namespace server +} // namespace libbitcoin + +#endif diff --git a/include/bitcoin/server/web/query_socket.hpp b/include/bitcoin/server/web/query_socket.hpp new file mode 100644 index 00000000..48c9afde --- /dev/null +++ b/include/bitcoin/server/web/query_socket.hpp @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2011-2017 libbitcoin developers (see AUTHORS) + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#ifndef LIBBITCOIN_SERVER_WEB_QUERY_SOCKET_HPP +#define LIBBITCOIN_SERVER_WEB_QUERY_SOCKET_HPP + +#include +#include +#include +#include +#include +#include + +namespace libbitcoin { +namespace server { + +class server_node; + +// This class is thread safe. +// Submit queries and address subscriptions and receive address +// notifications on a dedicated socket endpoint. +class BCS_API query_socket + : public socket +{ +public: + typedef std::shared_ptr ptr; + + /// Construct a query socket service endpoint. + query_socket(bc::protocol::zmq::authenticator& authenticator, + server_node& node, bool secure); + +protected: + // Implement the socket. + virtual void work() override; + + virtual bool start_websocket_handler() override; + + // Initialize the query specific zmq socket. + virtual void handle_websockets() override; + + virtual const config::endpoint& zeromq_endpoint() const override; + virtual const config::endpoint& websocket_endpoint() const override; + virtual const std::shared_ptr service() + const override; + + const config::endpoint& query_endpoint() const; + +private: + bool handle_query(bc::protocol::zmq::socket& dealer); + + std::shared_ptr service_; +}; + +} // namespace server +} // namespace libbitcoin + +#endif diff --git a/include/bitcoin/server/web/socket.hpp b/include/bitcoin/server/web/socket.hpp new file mode 100644 index 00000000..b7b8394f --- /dev/null +++ b/include/bitcoin/server/web/socket.hpp @@ -0,0 +1,170 @@ +/** + * Copyright (c) 2011-2017 libbitcoin developers (see AUTHORS) + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#ifndef LIBBITCOIN_SERVER_WEB_SOCKET_HPP +#define LIBBITCOIN_SERVER_WEB_SOCKET_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef WITH_MBEDTLS +extern "C" +{ +int https_random(void*, uint8_t* buffer, size_t length); +} +#endif + +namespace libbitcoin { +namespace server { + +class server_node; + +// Forward declarations in the http namespace. +namespace http +{ +class manager; +class connection; +enum class event : uint8_t; +typedef std::shared_ptr connection_ptr; +} // namespace http + +class BCS_API socket + : public bc::protocol::zmq::worker +{ +public: + typedef http::connection_ptr connection_ptr; + + // Tracks websocket queries via the query_work_map. Used for + // matching websocket client requests to zmq query responses. + struct query_work_item + { + // Constructor provided for in-place construction. + query_work_item(uint32_t id, uint32_t correlation_id, + connection_ptr connection, const std::string& command, + const std::string& arguments) + : id(id), + correlation_id(correlation_id), + command(command), + arguments(arguments), + connection(connection) + { + } + + uint32_t id; + uint32_t correlation_id; + std::string command; + std::string arguments; + connection_ptr connection; + }; + + typedef std::function encode_handler; + + typedef std::function decode_handler; + + // Handles translation of incoming JSON to zmq protocol methods and + // converting the result back to JSON for web clients. + struct handlers + { + std::string command; + encode_handler encode; + decode_handler decode; + }; + + typedef std::unordered_map query_work_map; + typedef std::unordered_map + connection_work_map; + typedef std::unordered_map> + query_correlation_map; + typedef std::unordered_map handler_map; + + /// Construct a socket class. + socket(bc::protocol::zmq::authenticator& authenticator, server_node& node, + bool secure, const std::string& domain); + + /// Start the service. + bool start() override; + + size_t connection_count() const; + void add_connection(connection_ptr& connection); + void remove_connection(connection_ptr& connection); + void notify_query_work(connection_ptr& connection, + const std::string& method, const uint32_t id, + const std::string& parameters); + +protected: + // Initialize the websocket event loop and start a thread to poll events. + virtual bool start_websocket_handler(); + + // Terminate the websocket event loop. + virtual bool stop_websocket_handler(); + + virtual void handle_websockets(); + + virtual const config::endpoint& zeromq_endpoint() const = 0; + virtual const config::endpoint& websocket_endpoint() const = 0; + virtual const std::shared_ptr service() const; + + // Send a message to the websocket client. + void send(connection_ptr connection, const std::string& json); + + // Send a message to every connected websocket client. + void broadcast(const std::string& json); + + // The zmq socket operates on only this one thread. + bc::protocol::zmq::authenticator& authenticator_; + const bool secure_; + const std::string security_; + const bc::server::settings& server_settings_; + const bc::protocol::settings& protocol_settings_; + // handlers_ is effectively const. + handler_map handlers_; + + // For query socket, service() is used to retrieve the zmq socket + // connected to the query_socket service. This socket operates on + // only the below member thread_. + std::shared_ptr thread_; + std::promise thread_status_; + + // Used by the query_socket class. + uint32_t sequence_; + connection_work_map connections_; + query_correlation_map correlations_; + mutable upgrade_mutex correlation_lock_; + +private: + static bool handle_event(connection_ptr& connection, + const http::event event, const void* data); + + std::shared_ptr manager_; + const std::string domain_; + const boost::filesystem::path document_root_; +}; + +} // namespace server +} // namespace libbitcoin + +#endif diff --git a/include/bitcoin/server/web/transaction_socket.hpp b/include/bitcoin/server/web/transaction_socket.hpp new file mode 100644 index 00000000..27a2a083 --- /dev/null +++ b/include/bitcoin/server/web/transaction_socket.hpp @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2011-2017 libbitcoin developers (see AUTHORS) + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#ifndef LIBBITCOIN_SERVER_WEB_TRANSACTION_SOCKET_HPP +#define LIBBITCOIN_SERVER_WEB_TRANSACTION_SOCKET_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace libbitcoin { +namespace server { + +class server_node; + +// This class is thread safe. +// Subscribe to transaction acceptances into the transaction memory +// pool from a dedicated socket endpoint. +class BCS_API transaction_socket + : public socket +{ +public: + typedef std::shared_ptr ptr; + + /// Construct a transaction socket service endpoint. + transaction_socket(bc::protocol::zmq::authenticator& authenticator, + server_node& node, bool secure); + +protected: + + // Implement the service. + virtual void work() override; + + virtual const config::endpoint& zeromq_endpoint() const override; + virtual const config::endpoint& websocket_endpoint() const override; + +private: + bool handle_transaction(bc::protocol::zmq::socket& subscriber); +}; + +} // namespace server +} // namespace libbitcoin + +#endif diff --git a/include/bitcoin/server/workers/notification_worker.hpp b/include/bitcoin/server/workers/notification_worker.hpp index 1269a119..d03c8fe3 100644 --- a/include/bitcoin/server/workers/notification_worker.hpp +++ b/include/bitcoin/server/workers/notification_worker.hpp @@ -32,7 +32,7 @@ #include #include -// Include after bitcoin.hpp (placeholders). +// Include after define.hpp (placeholders). #include #include diff --git a/install.sh b/install.sh index 5a01effd..61e7b6f6 100755 --- a/install.sh +++ b/install.sh @@ -8,8 +8,11 @@ # Script to build and install libbitcoin-server. # # Script options: +# --with-mbedtls Compile with MbedTLS Support +# Provides a websockets implementation for query. # --build-boost Builds Boost libraries. # --build-zmq Builds ZeroMQ libraries. +# --build-mbedtls Builds MbedTLS libraries. # --build-dir= Location of downloaded and intermediate files. # --prefix= Library install location (defaults to /usr/local). # --disable-shared Disables shared library builds. @@ -37,6 +40,11 @@ BUILD_DIR="build-libbitcoin-server" ZMQ_URL="https://github.com/zeromq/libzmq/releases/download/v4.2.5/zeromq-4.2.5.tar.gz" ZMQ_ARCHIVE="zeromq-4.2.5.tar.gz" +# MBEDTLS archive. +#------------------------------------------------------------------------------ +MBEDTLS_URL="https://tls.mbed.org/download/mbedtls-2.12.0-apache.tgz" +MBEDTLS_ARCHIVE="mbedtls-2.12.0-apache.tgz" + # Boost archive. #------------------------------------------------------------------------------ BOOST_URL="http://downloads.sourceforge.net/project/boost/boost/1.62.0/boost_1_62_0.tar.bz2" @@ -169,8 +177,11 @@ display_help() display_message "Usage: ./install.sh [OPTION]..." display_message "Manage the installation of libbitcoin-server." display_message "Script options:" + display_message " --with-mbedtls Compile with MbedTLS Support" + display_message " Provides a websockets implementation for query." display_message " --build-boost Builds Boost libraries." display_message " --build-zmq Build ZeroMQ libraries." + display_message " --build-mbedtls Builds MbedTLS libraries." display_message " --build-dir= Location of downloaded and intermediate files." display_message " --prefix= Library install location (defaults to /usr/local)." display_message " --disable-shared Disables shared library builds." @@ -200,16 +211,10 @@ for OPTION in "$@"; do (--disable-static) DISABLE_STATIC="yes";; # Common project options. - (--with-icu) WITH_ICU="yes";; - (--with-png) WITH_PNG="yes";; - (--with-qrencode) WITH_QRENCODE="yes";; # Custom build options (in the form of --build-