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 {
|
try {
|
||||||
$txid = $bitcoin->sendtoaddress($aData['coin_address'], $dBalance - $config['txfee_manual']);
|
$txid = $bitcoin->sendtoaddress($aData['coin_address'], $dBalance - $config['txfee_manual']);
|
||||||
} catch (Exception $e) {
|
} 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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -229,24 +229,7 @@ class Bitcoin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
require_once(INCLUDE_DIR . "/lib/jsonRPCClient.php");
|
||||||
* 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");
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bitcoin client class for access to a Bitcoin server via JSON-RPC-HTTP[S]
|
* Bitcoin client class for access to a Bitcoin server via JSON-RPC-HTTP[S]
|
||||||
@ -283,21 +266,18 @@ class BitcoinClient extends jsonRPCClient {
|
|||||||
* @access public
|
* @access public
|
||||||
* @throws BitcoinClientException
|
* @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);
|
$scheme = strtolower($scheme);
|
||||||
if ($scheme != "http" && $scheme != "https")
|
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))
|
if (empty($username))
|
||||||
throw new BitcoinClientException("Username must be non-blank");
|
throw new Exception("Username must be non-blank");
|
||||||
if (empty($password))
|
if (empty($password))
|
||||||
throw new BitcoinClientException("Password must be non-blank");
|
throw new Exception("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");
|
|
||||||
if (!empty($certificate_path) && !is_readable($certificate_path))
|
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 . "/";
|
$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
|
* some basic caching functionality and some debugging
|
||||||
**/
|
**/
|
||||||
class BitcoinWrapper extends BitcoinClient {
|
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->type = $type;
|
||||||
$this->username = $username;
|
$this->username = $username;
|
||||||
$this->password = $password;
|
$this->password = $password;
|
||||||
$this->host = $host;
|
$this->host = $host;
|
||||||
// $this->debug is already used
|
// $this->debug is already used
|
||||||
$this->oDebug = $debug;
|
$this->oDebug = $debug_object;
|
||||||
$this->memcache = $memcache;
|
$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
|
* Wrap variouns methods to add caching
|
||||||
@ -75,4 +76,4 @@ class BitcoinWrapper extends BitcoinClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load this wrapper
|
// 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
|
// Make sure we are called from index.php
|
||||||
if (!defined('SECURITY')) die('Hacking attempt');
|
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)) {
|
if (!$smarty->isCached('master.tpl', $smarty_cache_key)) {
|
||||||
$debug->append('No cached version available, fetching from backend', 3);
|
$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
|
// Top share contributors
|
||||||
$aContributorsShares = $statistics->getTopContributors('shares', 15);
|
$aContributorsShares = $statistics->getTopContributors('shares', 15);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user