@ -12,86 +12,9 @@
# include <stdint.h>
# include <boost/algorithm/string.hpp>
# include <boost/asio.hpp>
# include <boost/asio/ssl.hpp>
# include <boost/bind.hpp>
# include <boost/filesystem.hpp>
# include <boost/foreach.hpp>
# include <boost/iostreams/concepts.hpp>
# include <boost/iostreams/stream.hpp>
# include <boost/shared_ptr.hpp>
# include "json/json_spirit_writer_template.h"
using namespace std ;
using namespace boost ;
using namespace boost : : asio ;
using namespace json_spirit ;
Object CallRPC ( const string & strMethod , const Array & params )
{
if ( mapArgs [ " -rpcuser " ] = = " " & & mapArgs [ " -rpcpassword " ] = = " " )
throw runtime_error ( strprintf (
_ ( " You must set rpcpassword=<password> in the configuration file: \n %s \n "
" If the file does not exist, create it with owner-readable-only file permissions. " ) ,
GetConfigFile ( ) . string ( ) . c_str ( ) ) ) ;
// Connect to localhost
bool fUseSSL = GetBoolArg ( " -rpcssl " , false ) ;
asio : : io_service io_service ;
ssl : : context context ( io_service , ssl : : context : : sslv23 ) ;
context . set_options ( ssl : : context : : no_sslv2 ) ;
asio : : ssl : : stream < asio : : ip : : tcp : : socket > sslStream ( io_service , context ) ;
SSLIOStreamDevice < asio : : ip : : tcp > d ( sslStream , fUseSSL ) ;
iostreams : : stream < SSLIOStreamDevice < asio : : ip : : tcp > > stream ( d ) ;
bool fWait = GetBoolArg ( " -rpcwait " , false ) ; // -rpcwait means try until server has started
do {
bool fConnected = d . connect ( GetArg ( " -rpcconnect " , " 127.0.0.1 " ) , GetArg ( " -rpcport " , itostr ( Params ( ) . RPCPort ( ) ) ) ) ;
if ( fConnected ) break ;
if ( fWait )
MilliSleep ( 1000 ) ;
else
throw runtime_error ( " couldn't connect to server " ) ;
} while ( fWait ) ;
// HTTP basic authentication
string strUserPass64 = EncodeBase64 ( mapArgs [ " -rpcuser " ] + " : " + mapArgs [ " -rpcpassword " ] ) ;
map < string , string > mapRequestHeaders ;
mapRequestHeaders [ " Authorization " ] = string ( " Basic " ) + strUserPass64 ;
// Send request
string strRequest = JSONRPCRequest ( strMethod , params , 1 ) ;
string strPost = HTTPPost ( strRequest , mapRequestHeaders ) ;
stream < < strPost < < std : : flush ;
// Receive HTTP reply status
int nProto = 0 ;
int nStatus = ReadHTTPStatus ( stream , nProto ) ;
// Receive HTTP reply message headers and body
map < string , string > mapHeaders ;
string strReply ;
ReadHTTPMessage ( stream , mapHeaders , strReply , nProto ) ;
if ( nStatus = = HTTP_UNAUTHORIZED )
throw runtime_error ( " incorrect rpcuser or rpcpassword (authorization failed) " ) ;
else if ( nStatus > = 400 & & nStatus ! = HTTP_BAD_REQUEST & & nStatus ! = HTTP_NOT_FOUND & & nStatus ! = HTTP_INTERNAL_SERVER_ERROR )
throw runtime_error ( strprintf ( " server returned HTTP error %d " , nStatus ) ) ;
else if ( strReply . empty ( ) )
throw runtime_error ( " no response from server " ) ;
// Parse reply
Value valReply ;
if ( ! read_string ( strReply , valReply ) )
throw runtime_error ( " couldn't parse reply from server " ) ;
const Object & reply = valReply . get_obj ( ) ;
if ( reply . empty ( ) )
throw runtime_error ( " expected reply to have result, error and id properties " ) ;
return reply ;
}
template < typename T >
void ConvertTo ( Value & value , bool fAllowNull = false )
{
@ -182,101 +105,3 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri
return params ;
}
int CommandLineRPC ( int argc , char * argv [ ] )
{
string strPrint ;
int nRet = 0 ;
try
{
// Skip switches
while ( argc > 1 & & IsSwitchChar ( argv [ 1 ] [ 0 ] ) )
{
argc - - ;
argv + + ;
}
// Method
if ( argc < 2 )
throw runtime_error ( " too few parameters " ) ;
string strMethod = argv [ 1 ] ;
// Parameters default to strings
std : : vector < std : : string > strParams ( & argv [ 2 ] , & argv [ argc ] ) ;
Array params = RPCConvertValues ( strMethod , strParams ) ;
// Execute
Object reply = CallRPC ( strMethod , params ) ;
// Parse reply
const Value & result = find_value ( reply , " result " ) ;
const Value & error = find_value ( reply , " error " ) ;
if ( error . type ( ) ! = null_type )
{
// Error
strPrint = " error: " + write_string ( error , false ) ;
int code = find_value ( error . get_obj ( ) , " code " ) . get_int ( ) ;
nRet = abs ( code ) ;
}
else
{
// Result
if ( result . type ( ) = = null_type )
strPrint = " " ;
else if ( result . type ( ) = = str_type )
strPrint = result . get_str ( ) ;
else
strPrint = write_string ( result , true ) ;
}
}
catch ( boost : : thread_interrupted ) {
throw ;
}
catch ( std : : exception & e ) {
strPrint = string ( " error: " ) + e . what ( ) ;
nRet = EXIT_FAILURE ;
}
catch ( . . . ) {
PrintExceptionContinue ( NULL , " CommandLineRPC() " ) ;
throw ;
}
if ( strPrint ! = " " )
{
fprintf ( ( nRet = = 0 ? stdout : stderr ) , " %s \n " , strPrint . c_str ( ) ) ;
}
return nRet ;
}
std : : string HelpMessageCli ( bool mainProgram )
{
string strUsage ;
if ( mainProgram )
{
strUsage + = _ ( " Options: " ) + " \n " ;
strUsage + = " -? " + _ ( " This help message " ) + " \n " ;
strUsage + = " -conf=<file> " + _ ( " Specify configuration file (default: bitcoin.conf) " ) + " \n " ;
strUsage + = " -datadir=<dir> " + _ ( " Specify data directory " ) + " \n " ;
strUsage + = " -testnet " + _ ( " Use the test network " ) + " \n " ;
strUsage + = " -regtest " + _ ( " Enter regression test mode, which uses a special chain in which blocks can be "
" solved instantly. This is intended for regression testing tools and app development. " ) + " \n " ;
} else {
strUsage + = _ ( " RPC client options: " ) + " \n " ;
}
strUsage + = " -rpcconnect=<ip> " + _ ( " Send commands to node running on <ip> (default: 127.0.0.1) " ) + " \n " ;
strUsage + = " -rpcport=<port> " + _ ( " Connect to JSON-RPC on <port> (default: 8332 or testnet: 18332) " ) + " \n " ;
strUsage + = " -rpcwait " + _ ( " Wait for RPC server to start " ) + " \n " ;
if ( mainProgram )
{
strUsage + = " -rpcuser=<user> " + _ ( " Username for JSON-RPC connections " ) + " \n " ;
strUsage + = " -rpcpassword=<pw> " + _ ( " Password for JSON-RPC connections " ) + " \n " ;
strUsage + = " \n " + _ ( " SSL options: (see the Bitcoin Wiki for SSL setup instructions) " ) + " \n " ;
strUsage + = " -rpcssl " + _ ( " Use OpenSSL (https) for JSON-RPC connections " ) + " \n " ;
}
return strUsage ;
}