@@ -116,17 +116,42 @@ static bool AppInitRPC(int argc, char* argv[])
116
116
/* * Reply structure for request_done to fill in */
117
117
struct HTTPReply
118
118
{
119
+ HTTPReply (): status(0 ), error(-1 ) {}
120
+
119
121
int status;
122
+ int error;
120
123
std::string body;
121
124
};
122
125
126
+ const char *http_errorstring (int code)
127
+ {
128
+ switch (code) {
129
+ #if LIBEVENT_VERSION_NUMBER >= 0x02010300
130
+ case EVREQ_HTTP_TIMEOUT:
131
+ return " timeout reached" ;
132
+ case EVREQ_HTTP_EOF:
133
+ return " EOF reached" ;
134
+ case EVREQ_HTTP_INVALID_HEADER:
135
+ return " error while reading header, or invalid header" ;
136
+ case EVREQ_HTTP_BUFFER_ERROR:
137
+ return " error encountered while reading or writing" ;
138
+ case EVREQ_HTTP_REQUEST_CANCEL:
139
+ return " request was canceled" ;
140
+ case EVREQ_HTTP_DATA_TOO_LONG:
141
+ return " response body is larger than allowed" ;
142
+ #endif
143
+ default :
144
+ return " unknown" ;
145
+ }
146
+ }
147
+
123
148
static void http_request_done (struct evhttp_request *req, void *ctx)
124
149
{
125
150
HTTPReply *reply = static_cast <HTTPReply*>(ctx);
126
151
127
152
if (req == NULL ) {
128
- /* If req is NULL, it means an error occurred while connecting, but
129
- * I'm not sure how to find out which one. We also don't really care .
153
+ /* If req is NULL, it means an error occurred while connecting: the
154
+ * error code will have been passed to http_error_cb .
130
155
*/
131
156
reply->status = 0 ;
132
157
return ;
@@ -145,6 +170,14 @@ static void http_request_done(struct evhttp_request *req, void *ctx)
145
170
}
146
171
}
147
172
173
+ #if LIBEVENT_VERSION_NUMBER >= 0x02010300
174
+ static void http_error_cb (enum evhttp_request_error err, void *ctx)
175
+ {
176
+ HTTPReply *reply = static_cast <HTTPReply*>(ctx);
177
+ reply->error = err;
178
+ }
179
+ #endif
180
+
148
181
UniValue CallRPC (const string& strMethod, const UniValue& params)
149
182
{
150
183
std::string host = GetArg (" -rpcconnect" , DEFAULT_RPCCONNECT);
@@ -165,6 +198,9 @@ UniValue CallRPC(const string& strMethod, const UniValue& params)
165
198
struct evhttp_request *req = evhttp_request_new (http_request_done, (void *)&response); // TODO RAII
166
199
if (req == NULL )
167
200
throw runtime_error (" create http request failed" );
201
+ #if LIBEVENT_VERSION_NUMBER >= 0x02010300
202
+ evhttp_request_set_error_cb (req, http_error_cb);
203
+ #endif
168
204
169
205
// Get credentials
170
206
std::string strRPCUserColonPass;
@@ -204,7 +240,7 @@ UniValue CallRPC(const string& strMethod, const UniValue& params)
204
240
event_base_free (base);
205
241
206
242
if (response.status == 0 )
207
- throw CConnectionFailed (" couldn't connect to server" );
243
+ throw CConnectionFailed (strprintf ( " couldn't connect to server (%d %s) " , response. error , http_errorstring (response. error )) );
208
244
else if (response.status == HTTP_UNAUTHORIZED)
209
245
throw runtime_error (" incorrect rpcuser or rpcpassword (authorization failed)" );
210
246
else if (response.status >= 400 && response.status != HTTP_BAD_REQUEST && response.status != HTTP_NOT_FOUND && response.status != HTTP_INTERNAL_SERVER_ERROR)
0 commit comments