@ -26,7 +26,6 @@
# include <boost/thread.hpp>
# include <boost/thread.hpp>
# include "json/json_spirit_writer_template.h"
# include "json/json_spirit_writer_template.h"
using namespace boost ;
using namespace boost : : asio ;
using namespace boost : : asio ;
using namespace json_spirit ;
using namespace json_spirit ;
using namespace std ;
using namespace std ;
@ -39,7 +38,7 @@ static std::string rpcWarmupStatus("RPC server started");
static CCriticalSection cs_rpcWarmup ;
static CCriticalSection cs_rpcWarmup ;
//! These are created by StartRPCThreads, destroyed in StopRPCThreads
//! These are created by StartRPCThreads, destroyed in StopRPCThreads
static asio : : io_service * rpc_io_service = NULL ;
static boost : : asio : : io_service * rpc_io_service = NULL ;
static map < string , boost : : shared_ptr < deadline_timer > > deadlineTimers ;
static map < string , boost : : shared_ptr < deadline_timer > > deadlineTimers ;
static ssl : : context * rpc_ssl_context = NULL ;
static ssl : : context * rpc_ssl_context = NULL ;
static boost : : thread_group * rpc_worker_group = NULL ;
static boost : : thread_group * rpc_worker_group = NULL ;
@ -428,7 +427,7 @@ class AcceptedConnectionImpl : public AcceptedConnection
{
{
public :
public :
AcceptedConnectionImpl (
AcceptedConnectionImpl (
asio : : io_service & io_service ,
boost : : asio : : io_service & io_service ,
ssl : : context & context ,
ssl : : context & context ,
bool fUseSSL ) :
bool fUseSSL ) :
sslStream ( io_service , context ) ,
sslStream ( io_service , context ) ,
@ -453,11 +452,11 @@ public:
}
}
typename Protocol : : endpoint peer ;
typename Protocol : : endpoint peer ;
asio : : ssl : : stream < typename Protocol : : socket > sslStream ;
boost : : asio : : ssl : : stream < typename Protocol : : socket > sslStream ;
private :
private :
SSLIOStreamDevice < Protocol > _d ;
SSLIOStreamDevice < Protocol > _d ;
iostreams : : stream < SSLIOStreamDevice < Protocol > > _stream ;
boost : : iostreams : : stream < SSLIOStreamDevice < Protocol > > _stream ;
} ;
} ;
void ServiceConnection ( AcceptedConnection * conn ) ;
void ServiceConnection ( AcceptedConnection * conn ) ;
@ -504,7 +503,7 @@ static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor<Protocol,
const boost : : system : : error_code & error )
const boost : : system : : error_code & error )
{
{
// Immediately start accepting new connections, except when we're cancelled or our socket is closed.
// Immediately start accepting new connections, except when we're cancelled or our socket is closed.
if ( error ! = asio : : error : : operation_aborted & & acceptor - > is_open ( ) )
if ( error ! = boost : : asio : : error : : operation_aborted & & acceptor - > is_open ( ) )
RPCListen ( acceptor , context , fUseSSL ) ;
RPCListen ( acceptor , context , fUseSSL ) ;
AcceptedConnectionImpl < ip : : tcp > * tcp_conn = dynamic_cast < AcceptedConnectionImpl < ip : : tcp > * > ( conn . get ( ) ) ;
AcceptedConnectionImpl < ip : : tcp > * tcp_conn = dynamic_cast < AcceptedConnectionImpl < ip : : tcp > * > ( conn . get ( ) ) ;
@ -535,7 +534,7 @@ static ip::tcp::endpoint ParseEndpoint(const std::string &strEndpoint, int defau
std : : string addr ;
std : : string addr ;
int port = defaultPort ;
int port = defaultPort ;
SplitHostPort ( strEndpoint , port , addr ) ;
SplitHostPort ( strEndpoint , port , addr ) ;
return ip : : tcp : : endpoint ( asio : : ip : : address : : from_string ( addr ) , port ) ;
return ip : : tcp : : endpoint ( boost : : asio : : ip : : address : : from_string ( addr ) , port ) ;
}
}
void StartRPCThreads ( )
void StartRPCThreads ( )
@ -590,7 +589,7 @@ void StartRPCThreads()
}
}
assert ( rpc_io_service = = NULL ) ;
assert ( rpc_io_service = = NULL ) ;
rpc_io_service = new asio : : io_service ( ) ;
rpc_io_service = new boost : : asio : : io_service ( ) ;
rpc_ssl_context = new ssl : : context ( * rpc_io_service , ssl : : context : : sslv23 ) ;
rpc_ssl_context = new ssl : : context ( * rpc_io_service , ssl : : context : : sslv23 ) ;
const bool fUseSSL = GetBoolArg ( " -rpcssl " , false ) ;
const bool fUseSSL = GetBoolArg ( " -rpcssl " , false ) ;
@ -599,14 +598,14 @@ void StartRPCThreads()
{
{
rpc_ssl_context - > set_options ( ssl : : context : : no_sslv2 | ssl : : context : : no_sslv3 ) ;
rpc_ssl_context - > set_options ( ssl : : context : : no_sslv2 | ssl : : context : : no_sslv3 ) ;
filesystem : : path pathCertFile ( GetArg ( " -rpcsslcertificatechainfile " , " server.cert " ) ) ;
boost : : filesystem : : path pathCertFile ( GetArg ( " -rpcsslcertificatechainfile " , " server.cert " ) ) ;
if ( ! pathCertFile . is_complete ( ) ) pathCertFile = filesystem : : path ( GetDataDir ( ) ) / pathCertFile ;
if ( ! pathCertFile . is_complete ( ) ) pathCertFile = boost : : filesystem : : path ( GetDataDir ( ) ) / pathCertFile ;
if ( filesystem : : exists ( pathCertFile ) ) rpc_ssl_context - > use_certificate_chain_file ( pathCertFile . string ( ) ) ;
if ( boost : : filesystem : : exists ( pathCertFile ) ) rpc_ssl_context - > use_certificate_chain_file ( pathCertFile . string ( ) ) ;
else LogPrintf ( " ThreadRPCServer ERROR: missing server certificate file %s \n " , pathCertFile . string ( ) ) ;
else LogPrintf ( " ThreadRPCServer ERROR: missing server certificate file %s \n " , pathCertFile . string ( ) ) ;
filesystem : : path pathPKFile ( GetArg ( " -rpcsslprivatekeyfile " , " server.pem " ) ) ;
boost : : filesystem : : path pathPKFile ( GetArg ( " -rpcsslprivatekeyfile " , " server.pem " ) ) ;
if ( ! pathPKFile . is_complete ( ) ) pathPKFile = filesystem : : path ( GetDataDir ( ) ) / pathPKFile ;
if ( ! pathPKFile . is_complete ( ) ) pathPKFile = boost : : filesystem : : path ( GetDataDir ( ) ) / pathPKFile ;
if ( filesystem : : exists ( pathPKFile ) ) rpc_ssl_context - > use_private_key_file ( pathPKFile . string ( ) , ssl : : context : : pem ) ;
if ( boost : : filesystem : : exists ( pathPKFile ) ) rpc_ssl_context - > use_private_key_file ( pathPKFile . string ( ) , ssl : : context : : pem ) ;
else LogPrintf ( " ThreadRPCServer ERROR: missing server private key file %s \n " , pathPKFile . string ( ) ) ;
else LogPrintf ( " ThreadRPCServer ERROR: missing server private key file %s \n " , pathPKFile . string ( ) ) ;
string strCiphers = GetArg ( " -rpcsslciphers " , " TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH " ) ;
string strCiphers = GetArg ( " -rpcsslciphers " , " TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH " ) ;
@ -618,8 +617,8 @@ void StartRPCThreads()
int defaultPort = GetArg ( " -rpcport " , BaseParams ( ) . RPCPort ( ) ) ;
int defaultPort = GetArg ( " -rpcport " , BaseParams ( ) . RPCPort ( ) ) ;
if ( ! mapArgs . count ( " -rpcallowip " ) ) // Default to loopback if not allowing external IPs
if ( ! mapArgs . count ( " -rpcallowip " ) ) // Default to loopback if not allowing external IPs
{
{
vEndpoints . push_back ( ip : : tcp : : endpoint ( asio : : ip : : address_v6 : : loopback ( ) , defaultPort ) ) ;
vEndpoints . push_back ( ip : : tcp : : endpoint ( boost : : asio : : ip : : address_v6 : : loopback ( ) , defaultPort ) ) ;
vEndpoints . push_back ( ip : : tcp : : endpoint ( asio : : ip : : address_v4 : : loopback ( ) , defaultPort ) ) ;
vEndpoints . push_back ( ip : : tcp : : endpoint ( boost : : asio : : ip : : address_v4 : : loopback ( ) , defaultPort ) ) ;
if ( mapArgs . count ( " -rpcbind " ) )
if ( mapArgs . count ( " -rpcbind " ) )
{
{
LogPrintf ( " WARNING: option -rpcbind was ignored because -rpcallowip was not specified, refusing to allow everyone to connect \n " ) ;
LogPrintf ( " WARNING: option -rpcbind was ignored because -rpcallowip was not specified, refusing to allow everyone to connect \n " ) ;
@ -641,8 +640,8 @@ void StartRPCThreads()
}
}
}
}
} else { // No specific bind address specified, bind to any
} else { // No specific bind address specified, bind to any
vEndpoints . push_back ( ip : : tcp : : endpoint ( asio : : ip : : address_v6 : : any ( ) , defaultPort ) ) ;
vEndpoints . push_back ( ip : : tcp : : endpoint ( boost : : asio : : ip : : address_v6 : : any ( ) , defaultPort ) ) ;
vEndpoints . push_back ( ip : : tcp : : endpoint ( asio : : ip : : address_v4 : : any ( ) , defaultPort ) ) ;
vEndpoints . push_back ( ip : : tcp : : endpoint ( boost : : asio : : ip : : address_v4 : : any ( ) , defaultPort ) ) ;
// Prefer making the socket dual IPv6/IPv4 instead of binding
// Prefer making the socket dual IPv6/IPv4 instead of binding
// to both addresses seperately.
// to both addresses seperately.
bBindAny = true ;
bBindAny = true ;
@ -654,7 +653,7 @@ void StartRPCThreads()
BOOST_FOREACH ( const ip : : tcp : : endpoint & endpoint , vEndpoints )
BOOST_FOREACH ( const ip : : tcp : : endpoint & endpoint , vEndpoints )
{
{
try {
try {
asio : : ip : : address bindAddress = endpoint . address ( ) ;
boost : : asio : : ip : : address bindAddress = endpoint . address ( ) ;
straddress = bindAddress . to_string ( ) ;
straddress = bindAddress . to_string ( ) ;
LogPrintf ( " Binding RPC on address %s port %i (IPv4+IPv6 bind any: %i) \n " , straddress , endpoint . port ( ) , bBindAny ) ;
LogPrintf ( " Binding RPC on address %s port %i (IPv4+IPv6 bind any: %i) \n " , straddress , endpoint . port ( ) , bBindAny ) ;
boost : : system : : error_code v6_only_error ;
boost : : system : : error_code v6_only_error ;
@ -665,7 +664,7 @@ void StartRPCThreads()
// Try making the socket dual IPv6/IPv4 when listening on the IPv6 "any" address
// Try making the socket dual IPv6/IPv4 when listening on the IPv6 "any" address
acceptor - > set_option ( boost : : asio : : ip : : v6_only (
acceptor - > set_option ( boost : : asio : : ip : : v6_only (
! bBindAny | | bindAddress ! = asio : : ip : : address_v6 : : any ( ) ) , v6_only_error ) ;
! bBindAny | | bindAddress ! = boost : : asio : : ip : : address_v6 : : any ( ) ) , v6_only_error ) ;
acceptor - > bind ( endpoint ) ;
acceptor - > bind ( endpoint ) ;
acceptor - > listen ( socket_base : : max_connections ) ;
acceptor - > listen ( socket_base : : max_connections ) ;
@ -675,7 +674,7 @@ void StartRPCThreads()
fListening = true ;
fListening = true ;
rpc_acceptors . push_back ( acceptor ) ;
rpc_acceptors . push_back ( acceptor ) ;
// If dual IPv6/IPv4 bind successful, skip binding to IPv4 separately
// If dual IPv6/IPv4 bind successful, skip binding to IPv4 separately
if ( bBindAny & & bindAddress = = asio : : ip : : address_v6 : : any ( ) & & ! v6_only_error )
if ( bBindAny & & bindAddress = = boost : : asio : : ip : : address_v6 : : any ( ) & & ! v6_only_error )
break ;
break ;
}
}
catch ( const boost : : system : : system_error & e )
catch ( const boost : : system : : system_error & e )
@ -693,7 +692,7 @@ void StartRPCThreads()
rpc_worker_group = new boost : : thread_group ( ) ;
rpc_worker_group = new boost : : thread_group ( ) ;
for ( int i = 0 ; i < GetArg ( " -rpcthreads " , 4 ) ; i + + )
for ( int i = 0 ; i < GetArg ( " -rpcthreads " , 4 ) ; i + + )
rpc_worker_group - > create_thread ( boost : : bind ( & asio : : io_service : : run , rpc_io_service ) ) ;
rpc_worker_group - > create_thread ( boost : : bind ( & boost : : asio : : io_service : : run , rpc_io_service ) ) ;
fRPCRunning = true ;
fRPCRunning = true ;
}
}
@ -701,12 +700,12 @@ void StartDummyRPCThread()
{
{
if ( rpc_io_service = = NULL )
if ( rpc_io_service = = NULL )
{
{
rpc_io_service = new asio : : io_service ( ) ;
rpc_io_service = new boost : : asio : : io_service ( ) ;
/* Create dummy "work" to keep the thread from exiting when no timeouts active,
/* Create dummy "work" to keep the thread from exiting when no timeouts active,
* see http : //www.boost.org/doc/libs/1_51_0/doc/html/boost_asio/reference/io_service.html#boost_asio.reference.io_service.stopping_the_io_service_from_running_out_of_work */
* see http : //www.boost.org/doc/libs/1_51_0/doc/html/boost_asio/reference/io_service.html#boost_asio.reference.io_service.stopping_the_io_service_from_running_out_of_work */
rpc_dummy_work = new asio : : io_service : : work ( * rpc_io_service ) ;
rpc_dummy_work = new boost : : asio : : io_service : : work ( * rpc_io_service ) ;
rpc_worker_group = new boost : : thread_group ( ) ;
rpc_worker_group = new boost : : thread_group ( ) ;
rpc_worker_group - > create_thread ( boost : : bind ( & asio : : io_service : : run , rpc_io_service ) ) ;
rpc_worker_group - > create_thread ( boost : : bind ( & boost : : asio : : io_service : : run , rpc_io_service ) ) ;
fRPCRunning = true ;
fRPCRunning = true ;
}
}
}
}
@ -719,7 +718,7 @@ void StopRPCThreads()
// First, cancel all timers and acceptors
// First, cancel all timers and acceptors
// This is not done automatically by ->stop(), and in some cases the destructor of
// This is not done automatically by ->stop(), and in some cases the destructor of
// asio::io_service can hang if this is skipped.
// boost:: asio::io_service can hang if this is skipped.
boost : : system : : error_code ec ;
boost : : system : : error_code ec ;
BOOST_FOREACH ( const boost : : shared_ptr < ip : : tcp : : acceptor > & acceptor , rpc_acceptors )
BOOST_FOREACH ( const boost : : shared_ptr < ip : : tcp : : acceptor > & acceptor , rpc_acceptors )
{
{
@ -787,7 +786,7 @@ void RPCRunLater(const std::string& name, boost::function<void(void)> func, int6
deadlineTimers . insert ( make_pair ( name ,
deadlineTimers . insert ( make_pair ( name ,
boost : : shared_ptr < deadline_timer > ( new deadline_timer ( * rpc_io_service ) ) ) ) ;
boost : : shared_ptr < deadline_timer > ( new deadline_timer ( * rpc_io_service ) ) ) ) ;
}
}
deadlineTimers [ name ] - > expires_from_now ( posix_time : : seconds ( nSeconds ) ) ;
deadlineTimers [ name ] - > expires_from_now ( boost : : posix_time : : seconds ( nSeconds ) ) ;
deadlineTimers [ name ] - > async_wait ( boost : : bind ( RPCRunHandler , _1 , func ) ) ;
deadlineTimers [ name ] - > async_wait ( boost : : bind ( RPCRunHandler , _1 , func ) ) ;
}
}