]> Git Repo - VerusCoin.git/blob - src/bitcoin-cli.cpp
Auto merge of #1027 - ThisIsNotOfficialCodeItsJustForks:t862-trivial-mock-test-exampl...
[VerusCoin.git] / src / bitcoin-cli.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2013 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #include "chainparamsbase.h"
7 #include "clientversion.h"
8 #include "rpcclient.h"
9 #include "rpcprotocol.h"
10 #include "util.h"
11 #include "utilstrencodings.h"
12
13 #include <boost/filesystem/operations.hpp>
14
15 using namespace std;
16 using namespace json_spirit;
17
18 std::string HelpMessageCli()
19 {
20     string strUsage;
21     strUsage += HelpMessageGroup(_("Options:"));
22     strUsage += HelpMessageOpt("-?", _("This help message"));
23     strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file (default: %s)"), "zcash.conf"));
24     strUsage += HelpMessageOpt("-datadir=<dir>", _("Specify data directory"));
25     strUsage += HelpMessageOpt("-testnet", _("Use the test network"));
26     strUsage += HelpMessageOpt("-regtest", _("Enter regression test mode, which uses a special chain in which blocks can be "
27                                              "solved instantly. This is intended for regression testing tools and app development."));
28     strUsage += HelpMessageOpt("-rpcconnect=<ip>", strprintf(_("Send commands to node running on <ip> (default: %s)"), "127.0.0.1"));
29     strUsage += HelpMessageOpt("-rpcport=<port>", strprintf(_("Connect to JSON-RPC on <port> (default: %u or testnet: %u)"), 8232, 18232));
30     strUsage += HelpMessageOpt("-rpcwait", _("Wait for RPC server to start"));
31     strUsage += HelpMessageOpt("-rpcuser=<user>", _("Username for JSON-RPC connections"));
32     strUsage += HelpMessageOpt("-rpcpassword=<pw>", _("Password for JSON-RPC connections"));
33
34     strUsage += HelpMessageGroup(_("SSL options: (see the Bitcoin Wiki for SSL setup instructions)"));
35     strUsage += HelpMessageOpt("-rpcssl", _("Use OpenSSL (https) for JSON-RPC connections"));
36
37     return strUsage;
38 }
39
40 //////////////////////////////////////////////////////////////////////////////
41 //
42 // Start
43 //
44
45 //
46 // Exception thrown on connection error.  This error is used to determine
47 // when to wait if -rpcwait is given.
48 //
49 class CConnectionFailed : public std::runtime_error
50 {
51 public:
52
53     explicit inline CConnectionFailed(const std::string& msg) :
54         std::runtime_error(msg)
55     {}
56
57 };
58
59 static bool AppInitRPC(int argc, char* argv[])
60 {
61     //
62     // Parameters
63     //
64     ParseParameters(argc, argv);
65     if (argc<2 || mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help") || mapArgs.count("-version")) {
66         std::string strUsage = _("Zcash RPC client version") + " " + FormatFullVersion() + "\n";
67         if (!mapArgs.count("-version")) {
68             strUsage += "\n" + _("Usage:") + "\n" +
69                   "  zcash-cli [options] <command> [params]  " + _("Send command to Zcash") + "\n" +
70                   "  zcash-cli [options] help                " + _("List commands") + "\n" +
71                   "  zcash-cli [options] help <command>      " + _("Get help for a command") + "\n";
72
73             strUsage += "\n" + HelpMessageCli();
74         }
75
76         fprintf(stdout, "%s", strUsage.c_str());
77         return false;
78     }
79     if (!boost::filesystem::is_directory(GetDataDir(false))) {
80         fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str());
81         return false;
82     }
83     try {
84         ReadConfigFile(mapArgs, mapMultiArgs);
85     } catch (const std::exception& e) {
86         fprintf(stderr,"Error reading configuration file: %s\n", e.what());
87         return false;
88     }
89     // Check for -testnet or -regtest parameter (BaseParams() calls are only valid after this clause)
90     if (!SelectBaseParamsFromCommandLine()) {
91         fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n");
92         return false;
93     }
94     return true;
95 }
96
97 Object CallRPC(const string& strMethod, const Array& params)
98 {
99     if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
100         throw runtime_error(strprintf(
101             _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
102               "If the file does not exist, create it with owner-readable-only file permissions."),
103                 GetConfigFile().string().c_str()));
104
105     // Connect to localhost
106     bool fUseSSL = GetBoolArg("-rpcssl", false);
107     boost::asio::io_service io_service;
108     boost::asio::ssl::context context(io_service, boost::asio::ssl::context::sslv23);
109     context.set_options(boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::no_sslv3);
110     boost::asio::ssl::stream<boost::asio::ip::tcp::socket> sslStream(io_service, context);
111     SSLIOStreamDevice<boost::asio::ip::tcp> d(sslStream, fUseSSL);
112     boost::iostreams::stream< SSLIOStreamDevice<boost::asio::ip::tcp> > stream(d);
113
114     const bool fConnected = d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(BaseParams().RPCPort())));
115     if (!fConnected)
116         throw CConnectionFailed("couldn't connect to server");
117
118     // HTTP basic authentication
119     string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
120     map<string, string> mapRequestHeaders;
121     mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
122
123     // Send request
124     string strRequest = JSONRPCRequest(strMethod, params, 1);
125     string strPost = HTTPPost(strRequest, mapRequestHeaders);
126     stream << strPost << std::flush;
127
128     // Receive HTTP reply status
129     int nProto = 0;
130     int nStatus = ReadHTTPStatus(stream, nProto);
131
132     // Receive HTTP reply message headers and body
133     map<string, string> mapHeaders;
134     string strReply;
135     ReadHTTPMessage(stream, mapHeaders, strReply, nProto, std::numeric_limits<size_t>::max());
136
137     if (nStatus == HTTP_UNAUTHORIZED)
138         throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
139     else if (nStatus >= 400 && nStatus != HTTP_BAD_REQUEST && nStatus != HTTP_NOT_FOUND && nStatus != HTTP_INTERNAL_SERVER_ERROR)
140         throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
141     else if (strReply.empty())
142         throw runtime_error("no response from server");
143
144     // Parse reply
145     Value valReply;
146     if (!read_string(strReply, valReply))
147         throw runtime_error("couldn't parse reply from server");
148     const Object& reply = valReply.get_obj();
149     if (reply.empty())
150         throw runtime_error("expected reply to have result, error and id properties");
151
152     return reply;
153 }
154
155 int CommandLineRPC(int argc, char *argv[])
156 {
157     string strPrint;
158     int nRet = 0;
159     try {
160         // Skip switches
161         while (argc > 1 && IsSwitchChar(argv[1][0])) {
162             argc--;
163             argv++;
164         }
165
166         // Method
167         if (argc < 2)
168             throw runtime_error("too few parameters");
169         string strMethod = argv[1];
170
171         // Parameters default to strings
172         std::vector<std::string> strParams(&argv[2], &argv[argc]);
173         Array params = RPCConvertValues(strMethod, strParams);
174
175         // Execute and handle connection failures with -rpcwait
176         const bool fWait = GetBoolArg("-rpcwait", false);
177         do {
178             try {
179                 const Object reply = CallRPC(strMethod, params);
180
181                 // Parse reply
182                 const Value& result = find_value(reply, "result");
183                 const Value& error  = find_value(reply, "error");
184
185                 if (error.type() != null_type) {
186                     // Error
187                     const int code = find_value(error.get_obj(), "code").get_int();
188                     if (fWait && code == RPC_IN_WARMUP)
189                         throw CConnectionFailed("server in warmup");
190                     strPrint = "error: " + write_string(error, false);
191                     nRet = abs(code);
192                 } else {
193                     // Result
194                     if (result.type() == null_type)
195                         strPrint = "";
196                     else if (result.type() == str_type)
197                         strPrint = result.get_str();
198                     else
199                         strPrint = write_string(result, true);
200                 }
201
202                 // Connection succeeded, no need to retry.
203                 break;
204             }
205             catch (const CConnectionFailed&) {
206                 if (fWait)
207                     MilliSleep(1000);
208                 else
209                     throw;
210             }
211         } while (fWait);
212     }
213     catch (const boost::thread_interrupted&) {
214         throw;
215     }
216     catch (const std::exception& e) {
217         strPrint = string("error: ") + e.what();
218         nRet = EXIT_FAILURE;
219     }
220     catch (...) {
221         PrintExceptionContinue(NULL, "CommandLineRPC()");
222         throw;
223     }
224
225     if (strPrint != "") {
226         fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
227     }
228     return nRet;
229 }
230
231 int main(int argc, char* argv[])
232 {
233     SetupEnvironment();
234
235     try {
236         if(!AppInitRPC(argc, argv))
237             return EXIT_FAILURE;
238     }
239     catch (const std::exception& e) {
240         PrintExceptionContinue(&e, "AppInitRPC()");
241         return EXIT_FAILURE;
242     } catch (...) {
243         PrintExceptionContinue(NULL, "AppInitRPC()");
244         return EXIT_FAILURE;
245     }
246
247     int ret = EXIT_FAILURE;
248     try {
249         ret = CommandLineRPC(argc, argv);
250     }
251     catch (const std::exception& e) {
252         PrintExceptionContinue(&e, "CommandLineRPC()");
253     } catch (...) {
254         PrintExceptionContinue(NULL, "CommandLineRPC()");
255     }
256     return ret;
257 }
This page took 0.037749 seconds and 4 git commands to generate.