Merge pull request #1420 from TheSerapher/issue-1343
[IMPROVED] jsonRPC Error Handling with CURL
This commit is contained in:
commit
1dfbeea5f7
@ -68,7 +68,7 @@ if ($setting->getValue('disable_manual_payouts') != 1) {
|
||||
try {
|
||||
$txid = $bitcoin->sendtoaddress($aData['coin_address'], $dBalance - $config['txfee_manual']);
|
||||
} catch (Exception $e) {
|
||||
$log->logError('Failed to send requested balance to coin address, please check payout process. Does the wallet cover the amount?');
|
||||
$log->logError('Failed to send requested balance to coin address, please check payout process. Does the wallet cover the amount? Error:' . $e->getMessage());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@ -229,24 +229,7 @@ class Bitcoin {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception class for BitcoinClient
|
||||
*
|
||||
* @author Mike Gogulski
|
||||
* http://www.gogulski.com/ http://www.nostate.com/
|
||||
*/
|
||||
class BitcoinClientException extends ErrorException {
|
||||
// Redefine the exception so message isn't optional
|
||||
public function __construct($message, $code = 0, $severity = E_USER_NOTICE, Exception $previous = null) {
|
||||
parent::__construct($message, $code, $severity, $previous);
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
|
||||
}
|
||||
}
|
||||
|
||||
require_once(INCLUDE_DIR . "/jsonRPCClient.php");
|
||||
require_once(INCLUDE_DIR . "/lib/jsonRPCClient.php");
|
||||
|
||||
/**
|
||||
* Bitcoin client class for access to a Bitcoin server via JSON-RPC-HTTP[S]
|
||||
@ -283,21 +266,18 @@ class BitcoinClient extends jsonRPCClient {
|
||||
* @access public
|
||||
* @throws BitcoinClientException
|
||||
*/
|
||||
public function __construct($scheme, $username, $password, $address = "localhost", $port = 8332, $certificate_path = '', $debug_level = 0) {
|
||||
public function __construct($scheme, $username, $password, $address = "localhost", $certificate_path = '', $debug = false) {
|
||||
$scheme = strtolower($scheme);
|
||||
if ($scheme != "http" && $scheme != "https")
|
||||
throw new BitcoinClientException("Scheme must be http or https");
|
||||
throw new Exception("Scheme must be http or https");
|
||||
if (empty($username))
|
||||
throw new BitcoinClientException("Username must be non-blank");
|
||||
throw new Exception("Username must be non-blank");
|
||||
if (empty($password))
|
||||
throw new BitcoinClientException("Password must be non-blank");
|
||||
$port = (string) $port;
|
||||
if (!$port || empty($port) || !is_numeric($port) || $port < 1 || $port > 65535 || floatval($port) != intval($port))
|
||||
throw new BitcoinClientException("Port must be an integer and between 1 and 65535");
|
||||
throw new Exception("Password must be non-blank");
|
||||
if (!empty($certificate_path) && !is_readable($certificate_path))
|
||||
throw new BitcoinClientException("Certificate file " . $certificate_path . " is not readable");
|
||||
throw new Exception("Certificate file " . $certificate_path . " is not readable");
|
||||
$uri = $scheme . "://" . $username . ":" . $password . "@" . $address . "/";
|
||||
parent::__construct($uri);
|
||||
parent::__construct($uri, $debug);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -9,15 +9,16 @@ if (!defined('SECURITY'))
|
||||
* some basic caching functionality and some debugging
|
||||
**/
|
||||
class BitcoinWrapper extends BitcoinClient {
|
||||
public function __construct($type, $username, $password, $host, $debug, $memcache) {
|
||||
public function __construct($type, $username, $password, $host, $debug_level, $debug_object, $memcache) {
|
||||
$this->type = $type;
|
||||
$this->username = $username;
|
||||
$this->password = $password;
|
||||
$this->host = $host;
|
||||
// $this->debug is already used
|
||||
$this->oDebug = $debug;
|
||||
$this->oDebug = $debug_object;
|
||||
$this->memcache = $memcache;
|
||||
return parent::__construct($this->type, $this->username, $this->password, $this->host);
|
||||
$debug_level > 0 ? $debug_level = true : $debug_level = false;
|
||||
return parent::__construct($this->type, $this->username, $this->password, $this->host, '', $debug_level);
|
||||
}
|
||||
/**
|
||||
* Wrap variouns methods to add caching
|
||||
@ -75,4 +76,4 @@ class BitcoinWrapper extends BitcoinClient {
|
||||
}
|
||||
|
||||
// Load this wrapper
|
||||
$bitcoin = new BitcoinWrapper($config['wallet']['type'], $config['wallet']['username'], $config['wallet']['password'], $config['wallet']['host'], $debug, $memcache);
|
||||
$bitcoin = new BitcoinWrapper($config['wallet']['type'], $config['wallet']['username'], $config['wallet']['password'], $config['wallet']['host'], DEBUG, $debug, $memcache);
|
||||
|
||||
@ -1,167 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
COPYRIGHT
|
||||
|
||||
Copyright 2007 Sergio Vaccaro <sergio@inservibile.org>
|
||||
|
||||
This file is part of JSON-RPC PHP.
|
||||
|
||||
JSON-RPC PHP is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
JSON-RPC PHP is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with JSON-RPC PHP; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* The object of this class are generic jsonRPC 1.0 clients
|
||||
* http://json-rpc.org/wiki/specification
|
||||
*
|
||||
* @author sergio <jsonrpcphp@inservibile.org>
|
||||
*/
|
||||
class jsonRPCClient {
|
||||
|
||||
/**
|
||||
* Debug state
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
private $debug;
|
||||
|
||||
/**
|
||||
* The server URL
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $url;
|
||||
/**
|
||||
* The request id
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $id;
|
||||
/**
|
||||
* If true, notifications are performed instead of requests
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
private $notification = false;
|
||||
|
||||
/**
|
||||
* Takes the connection parameters
|
||||
*
|
||||
* @param string $url
|
||||
* @param boolean $debug
|
||||
*/
|
||||
public function __construct($url,$debug = false) {
|
||||
// server URL
|
||||
$this->url = $url;
|
||||
// proxy
|
||||
empty($proxy) ? $this->proxy = '' : $this->proxy = $proxy;
|
||||
// debug state
|
||||
empty($debug) ? $this->debug = false : $this->debug = true;
|
||||
// message id
|
||||
$this->id = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the notification state of the object. In this state, notifications are performed, instead of requests.
|
||||
*
|
||||
* @param boolean $notification
|
||||
*/
|
||||
public function setRPCNotification($notification) {
|
||||
empty($notification) ?
|
||||
$this->notification = false
|
||||
:
|
||||
$this->notification = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a jsonRCP request and gets the results as an array
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $params
|
||||
* @return array
|
||||
*/
|
||||
public function __call($method,$params) {
|
||||
|
||||
// check
|
||||
if (!is_scalar($method)) {
|
||||
throw new Exception('Method name has no scalar value');
|
||||
}
|
||||
|
||||
// check
|
||||
if (is_array($params)) {
|
||||
// no keys
|
||||
$params = array_values($params);
|
||||
} else {
|
||||
throw new Exception('Params must be given as array');
|
||||
}
|
||||
|
||||
// sets notification or request task
|
||||
if ($this->notification) {
|
||||
$currentId = NULL;
|
||||
} else {
|
||||
$currentId = $this->id;
|
||||
}
|
||||
|
||||
// prepares the request
|
||||
$request = array(
|
||||
'method' => $method,
|
||||
'params' => $params,
|
||||
'id' => $currentId
|
||||
);
|
||||
$request = json_encode($request);
|
||||
$this->debug && $this->debug.='***** Request *****'."\n".$request."\n".'***** End Of request *****'."\n\n";
|
||||
|
||||
// performs the HTTP POST
|
||||
$opts = array ('http' => array (
|
||||
'method' => 'POST',
|
||||
'header' => 'Content-type: application/json',
|
||||
'content' => $request
|
||||
));
|
||||
$context = stream_context_create($opts);
|
||||
if ($fp = @fopen($this->url, 'r', false, $context)) {
|
||||
$response = '';
|
||||
while($row = fgets($fp)) {
|
||||
$response.= trim($row)."\n";
|
||||
}
|
||||
$this->debug && $this->debug.='***** Server response *****'."\n".$response.'***** End of server response *****'."\n";
|
||||
$response = json_decode($response,true);
|
||||
} else {
|
||||
$error = error_get_last();
|
||||
$error = explode(']: ', $error['message']);
|
||||
throw new Exception('Unable to connect: ' . $error[1]);
|
||||
}
|
||||
|
||||
// debug output
|
||||
if ($this->debug) {
|
||||
echo nl2br($debug);
|
||||
}
|
||||
|
||||
// final checks and return
|
||||
if (!$this->notification) {
|
||||
// check
|
||||
if ($response['id'] != $currentId) {
|
||||
throw new Exception('Incorrect response id (request id: '.$currentId.', response id: '.$response['id'].')');
|
||||
}
|
||||
if (!is_null($response['error'])) {
|
||||
throw new Exception('Request error: '.$response['error']);
|
||||
}
|
||||
|
||||
return $response['result'];
|
||||
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
127
public/include/lib/jsonRPCClient.php
Normal file
127
public/include/lib/jsonRPCClient.php
Normal file
@ -0,0 +1,127 @@
|
||||
<?php
|
||||
/*
|
||||
COPYRIGHT
|
||||
|
||||
Copyright 2007 Sergio Vaccaro <sergio@inservibile.org>
|
||||
|
||||
This file is part of JSON-RPC PHP.
|
||||
|
||||
JSON-RPC PHP is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
JSON-RPC PHP is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with JSON-RPC PHP; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* The object of this class are generic jsonRPC 1.0 clients
|
||||
* http://json-rpc.org/wiki/specification
|
||||
*
|
||||
* @author sergio <jsonrpcphp@inservibile.org>
|
||||
*/
|
||||
class jsonRPCClient {
|
||||
|
||||
/**
|
||||
* Debug state
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
private $debug;
|
||||
private $debug_output = NULL;
|
||||
|
||||
/**
|
||||
* The server URL
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $url;
|
||||
/**
|
||||
* The request id
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* Takes the connection parameters
|
||||
*
|
||||
* @param string $url
|
||||
* @param boolean $debug
|
||||
*/
|
||||
public function __construct($url, $debug = false) {
|
||||
$this->url = $url;
|
||||
$this->debug = $debug;
|
||||
$this->debug_output = '';
|
||||
$this->id = rand(1, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch debug information
|
||||
* @param none
|
||||
* @return array Debug data
|
||||
**/
|
||||
public function getDebugData() {
|
||||
if ($this->debug) return $this->debug_output;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a jsonRCP request and gets the results as an array
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $params
|
||||
* @return array
|
||||
*/
|
||||
public function __call($method, $params) {
|
||||
if (!is_scalar($method)) throw new Exception('Method name has no scalar value');
|
||||
|
||||
if (is_array($params)) {
|
||||
// no keys
|
||||
$params = array_values($params);
|
||||
} else {
|
||||
throw new Exception('Params must be given as array');
|
||||
}
|
||||
|
||||
// prepares the request
|
||||
$request = array(
|
||||
'method' => $method,
|
||||
'params' => $params,
|
||||
'id' => $this->id
|
||||
);
|
||||
$request = json_encode($request);
|
||||
if ($this->debug) $this->debug_output[] = 'Request: '.$request;
|
||||
|
||||
// performs the HTTP POST
|
||||
// extract information from URL for proper authentication
|
||||
$url = parse_url($this->url);
|
||||
$ch = curl_init($url['scheme'].'://'.$url['host'].':'.$url['port'].$url['path']);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/json'));
|
||||
curl_setopt($ch, CURLOPT_USERPWD, $url['user'] . ":" . $url['pass']);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
|
||||
$response = curl_exec($ch);
|
||||
if ($this->debug) $this->debug_output[] = 'Response: ' . $response;
|
||||
$response = json_decode($response, true);
|
||||
$resultStatus = curl_getinfo($ch);
|
||||
if ($resultStatus['http_code'] != '200') {
|
||||
if ($resultStatus['http_code'] == '401') throw new Exception('RPC call did not return 200: Authentication failed');
|
||||
throw new Exception('RPC call did not return 200: HTTP error: ' . $resultStatus['http_code']);
|
||||
}
|
||||
if (curl_errno($ch)) throw new Exception('RPC call failed: ' . curl_error($ch));
|
||||
curl_close($ch);
|
||||
|
||||
// final checks and return
|
||||
if (!is_null($response['error']) || is_null($response)) throw new Exception('Response error or empty: ' . @$response['error']);
|
||||
if ($response['id'] != $this->id) throw new Exception('Incorrect response id (request id: ' . $this->id . ', response id: ' . $response['id'] . ')');
|
||||
return $response['result'];
|
||||
}
|
||||
}
|
||||
@ -3,20 +3,21 @@
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
|
||||
// Fetch data from wallet, always run this check
|
||||
if ($bitcoin->can_connect() === true){
|
||||
$dDifficulty = $bitcoin->getdifficulty();
|
||||
$dNetworkHashrate = $bitcoin->getnetworkhashps();
|
||||
$iBlock = $bitcoin->getblockcount();
|
||||
is_int($iBlock) && $iBlock > 0 ? $sBlockHash = $bitcoin->getblockhash($iBlock) : $sBlockHash = '';
|
||||
} else {
|
||||
$dDifficulty = 1;
|
||||
$dNetworkHashrate = 1;
|
||||
$iBlock = 0;
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to wallet RPC service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg');
|
||||
}
|
||||
|
||||
if (!$smarty->isCached('master.tpl', $smarty_cache_key)) {
|
||||
$debug->append('No cached version available, fetching from backend', 3);
|
||||
// Fetch data from wallet
|
||||
if ($bitcoin->can_connect() === true){
|
||||
$dDifficulty = $bitcoin->getdifficulty();
|
||||
$dNetworkHashrate = $bitcoin->getnetworkhashps();
|
||||
$iBlock = $bitcoin->getblockcount();
|
||||
is_int($iBlock) && $iBlock > 0 ? $sBlockHash = $bitcoin->getblockhash($iBlock) : $sBlockHash = '';
|
||||
} else {
|
||||
$dDifficulty = 1;
|
||||
$dNetworkHashrate = 1;
|
||||
$iBlock = 0;
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to wallet RPC service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg');
|
||||
}
|
||||
|
||||
// Top share contributors
|
||||
$aContributorsShares = $statistics->getTopContributors('shares', 15);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user