1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2013 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 #include "chainparamsbase.h"
7 #include "clientversion.h"
9 #include "rpcprotocol.h"
11 #include "utilstrencodings.h"
13 #include <boost/filesystem/operations.hpp>
15 #define _(x) std::string(x) /* Keep the _() around in case gettext or such will be used later to translate non-UI */
18 using namespace boost;
19 using namespace boost::asio;
20 using namespace json_spirit;
22 std::string HelpMessageCli()
25 strUsage += _("Options:") + "\n";
26 strUsage += " -? " + _("This help message") + "\n";
27 strUsage += " -conf=<file> " + strprintf(_("Specify configuration file (default: %s)"), "bitcoin.conf") + "\n";
28 strUsage += " -datadir=<dir> " + _("Specify data directory") + "\n";
29 strUsage += " -testnet " + _("Use the test network") + "\n";
30 strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be "
31 "solved instantly. This is intended for regression testing tools and app development.") + "\n";
32 strUsage += " -rpcconnect=<ip> " + strprintf(_("Send commands to node running on <ip> (default: %s)"), "127.0.0.1") + "\n";
33 strUsage += " -rpcport=<port> " + strprintf(_("Connect to JSON-RPC on <port> (default: %u or testnet: %u)"), 8332, 18332) + "\n";
34 strUsage += " -rpcwait " + _("Wait for RPC server to start") + "\n";
35 strUsage += " -rpcuser=<user> " + _("Username for JSON-RPC connections") + "\n";
36 strUsage += " -rpcpassword=<pw> " + _("Password for JSON-RPC connections") + "\n";
38 strUsage += "\n" + _("SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n";
39 strUsage += " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n";
44 //////////////////////////////////////////////////////////////////////////////
50 // Exception thrown on connection error. This error is used to determine
51 // when to wait if -rpcwait is given.
53 class CConnectionFailed : public std::runtime_error
57 explicit inline CConnectionFailed(const std::string& msg) :
58 std::runtime_error(msg)
63 static bool AppInitRPC(int argc, char* argv[])
68 ParseParameters(argc, argv);
69 if (!boost::filesystem::is_directory(GetDataDir(false))) {
70 fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str());
74 ReadConfigFile(mapArgs, mapMultiArgs);
75 } catch(std::exception &e) {
76 fprintf(stderr,"Error reading configuration file: %s\n", e.what());
79 // Check for -testnet or -regtest parameter (BaseParams() calls are only valid after this clause)
80 if (!SelectBaseParamsFromCommandLine()) {
81 fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n");
84 if (argc<2 || mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version")) {
85 std::string strUsage = _("Bitcoin Core RPC client version") + " " + FormatFullVersion() + "\n";
86 if (!mapArgs.count("-version")) {
87 strUsage += "\n" + _("Usage:") + "\n" +
88 " bitcoin-cli [options] <command> [params] " + _("Send command to Bitcoin Core") + "\n" +
89 " bitcoin-cli [options] help " + _("List commands") + "\n" +
90 " bitcoin-cli [options] help <command> " + _("Get help for a command") + "\n";
92 strUsage += "\n" + HelpMessageCli();
95 fprintf(stdout, "%s", strUsage.c_str());
101 Object CallRPC(const string& strMethod, const Array& params)
103 if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
104 throw runtime_error(strprintf(
105 _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
106 "If the file does not exist, create it with owner-readable-only file permissions."),
107 GetConfigFile().string().c_str()));
109 // Connect to localhost
110 bool fUseSSL = GetBoolArg("-rpcssl", false);
111 asio::io_service io_service;
112 ssl::context context(io_service, ssl::context::sslv23);
113 context.set_options(ssl::context::no_sslv2);
114 asio::ssl::stream<asio::ip::tcp::socket> sslStream(io_service, context);
115 SSLIOStreamDevice<asio::ip::tcp> d(sslStream, fUseSSL);
116 iostreams::stream< SSLIOStreamDevice<asio::ip::tcp> > stream(d);
118 const bool fConnected = d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(BaseParams().RPCPort())));
120 throw CConnectionFailed("couldn't connect to server");
122 // HTTP basic authentication
123 string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
124 map<string, string> mapRequestHeaders;
125 mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
128 string strRequest = JSONRPCRequest(strMethod, params, 1);
129 string strPost = HTTPPost(strRequest, mapRequestHeaders);
130 stream << strPost << std::flush;
132 // Receive HTTP reply status
134 int nStatus = ReadHTTPStatus(stream, nProto);
136 // Receive HTTP reply message headers and body
137 map<string, string> mapHeaders;
139 ReadHTTPMessage(stream, mapHeaders, strReply, nProto, std::numeric_limits<size_t>::max());
141 if (nStatus == HTTP_UNAUTHORIZED)
142 throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
143 else if (nStatus >= 400 && nStatus != HTTP_BAD_REQUEST && nStatus != HTTP_NOT_FOUND && nStatus != HTTP_INTERNAL_SERVER_ERROR)
144 throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
145 else if (strReply.empty())
146 throw runtime_error("no response from server");
150 if (!read_string(strReply, valReply))
151 throw runtime_error("couldn't parse reply from server");
152 const Object& reply = valReply.get_obj();
154 throw runtime_error("expected reply to have result, error and id properties");
159 int CommandLineRPC(int argc, char *argv[])
165 while (argc > 1 && IsSwitchChar(argv[1][0])) {
172 throw runtime_error("too few parameters");
173 string strMethod = argv[1];
175 // Parameters default to strings
176 std::vector<std::string> strParams(&argv[2], &argv[argc]);
177 Array params = RPCConvertValues(strMethod, strParams);
179 // Execute and handle connection failures with -rpcwait
180 const bool fWait = GetBoolArg("-rpcwait", false);
183 const Object reply = CallRPC(strMethod, params);
186 const Value& result = find_value(reply, "result");
187 const Value& error = find_value(reply, "error");
189 if (error.type() != null_type) {
191 const int code = find_value(error.get_obj(), "code").get_int();
192 if (fWait && code == RPC_IN_WARMUP)
193 throw CConnectionFailed("server in warmup");
194 strPrint = "error: " + write_string(error, false);
198 if (result.type() == null_type)
200 else if (result.type() == str_type)
201 strPrint = result.get_str();
203 strPrint = write_string(result, true);
206 // Connection succeeded, no need to retry.
209 catch (const CConnectionFailed& e) {
217 catch (boost::thread_interrupted) {
220 catch (std::exception& e) {
221 strPrint = string("error: ") + e.what();
225 PrintExceptionContinue(NULL, "CommandLineRPC()");
229 if (strPrint != "") {
230 fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
235 int main(int argc, char* argv[])
240 if(!AppInitRPC(argc, argv))
243 catch (std::exception& e) {
244 PrintExceptionContinue(&e, "AppInitRPC()");
247 PrintExceptionContinue(NULL, "AppInitRPC()");
251 int ret = EXIT_FAILURE;
253 ret = CommandLineRPC(argc, argv);
255 catch (std::exception& e) {
256 PrintExceptionContinue(&e, "CommandLineRPC()");
258 PrintExceptionContinue(NULL, "CommandLineRPC()");