@@ -116,17 +116,42 @@ static bool AppInitRPC(int argc, char* argv[])
116116/* * Reply structure for request_done to fill in */
117117struct HTTPReply
118118{
119+ HTTPReply (): status(0 ), error(-1 ) {}
120+
119121 int status;
122+ int error;
120123 std::string body;
121124};
122125
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+
123148static void http_request_done (struct evhttp_request *req, void *ctx)
124149{
125150 HTTPReply *reply = static_cast <HTTPReply*>(ctx);
126151
127152 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 .
130155 */
131156 reply->status = 0 ;
132157 return ;
@@ -145,6 +170,14 @@ static void http_request_done(struct evhttp_request *req, void *ctx)
145170 }
146171}
147172
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+
148181UniValue CallRPC (const string& strMethod, const UniValue& params)
149182{
150183 std::string host = GetArg (" -rpcconnect" , DEFAULT_RPCCONNECT);
@@ -165,6 +198,9 @@ UniValue CallRPC(const string& strMethod, const UniValue& params)
165198 struct evhttp_request *req = evhttp_request_new (http_request_done, (void *)&response); // TODO RAII
166199 if (req == NULL )
167200 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
168204
169205 // Get credentials
170206 std::string strRPCUserColonPass;
@@ -204,7 +240,7 @@ UniValue CallRPC(const string& strMethod, const UniValue& params)
204240 event_base_free (base);
205241
206242 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 )) );
208244 else if (response.status == HTTP_UNAUTHORIZED)
209245 throw runtime_error (" incorrect rpcuser or rpcpassword (authorization failed)" );
210246 else if (response.status >= 400 && response.status != HTTP_BAD_REQUEST && response.status != HTTP_NOT_FOUND && response.status != HTTP_INTERNAL_SERVER_ERROR)
0 commit comments