<?php
/**
*
* @author Benjamin Gillissen <hide@address.com>
*
* **************************************************************
Copyright (C) 2009 Benjamin Gillissen
This program 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.
This program 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 at:
http://www.gnu.org/copyleft/gpl.html
* **************************************************************
*/
if (!function_exists('_xmlrpcs_listmethods') ){
$p = CORE::getdeps(PATH_LIBS, 'xmlrpcs', NULL, 'inc', 'php');
if ( FALSE === $p ){
errors::raise('Missing XMLRpc librairies : not found in '.PATH_LIBS, CORE_LOG_ALERT, 'RPC');
}
include($p);
$p = CORE::getdeps(PATH_LIBS, 'xmlrpc', NULL, 'inc', 'php');
if ( FALSE === $p ){
errors::raise('Missing XMLRpc librairies : not found in '.PATH_LIBS, CORE_LOG_ALERT, 'RPC');
}
include($p);
}
class hellarpc_net {
private static $_RPC; //xml-rpc conn handler
private static $DFTO = 300; //default connection Timeout
private $lastreq; //last request stamp
private $RID = NULL; //rpcID
private $conf; //rpc conf
public function __construct($rid, $conf){
$this->conf = $this->validconf($conf);
if ( FALSE === $this->conf ){
errors::raise('Invalid Configuration for rpc "'.$rid.'"', CORE_LOG_ERROR, 'RPC');
return;
}
//errors::raise('HellaRPC loaded to connect to : '.$this->conf['host'].':'.$this->conf['port'], CORE_LOG_INFO, 'RPC');
$this->RID = $rid;
if ( !chrono::isinit('hellarpc_net') ){ chrono::init('hellarpc_net'); }
}
private function validconf($conf){
if( !isset($conf['host']) ){
//raise warning
$conf['host'] = '127.0.0.1';
} elseif (! isset($conf['port']) ){
//raise notice
$conf['port'] = '8760';
} elseif (! isset($conf['user']) ){
//raise warning
$conf['user'] = 'hellanzb';
} elseif (! isset($conf['conTO']) ){
//raise warning
$conf['conTO'] = self::$DFTO;
} elseif (! isset($conf['pass']) ){
return FALSE;
}
return $conf;
}
public function conn_need_revive(){
if ( !isset(self::$_RPC[$this->RID]) ){ return TRUE; }
$o = ( $this->lastreq <= bcsub(chrono::get_microtime(), $this->conf['conTO'], 4) );
if ( $o ){ errors::raise('RPC '.$this->RID.' connection is timedout, reconnecting.', CORE_LOG_DEBUG, 'RPC'); }
return $o;
}
public function connect(){
if ( $this->RID === NULL ){ return FALSE; }
if ( !isset(self::$_RPC[$this->RID]) ){
self::$_RPC[$this->RID] = new xmlrpc_client('', $this->conf['host'], $this->conf['port']);
self::$_RPC[$this->RID]->setCredentials($this->conf['user'], $this->conf['pass']);
self::$_RPC[$this->RID]->setDebug(0);
}
$q = new xmlrpcmsg("status", "");
$r = self::$_RPC[$this->RID]->send($q);
unset($q);
if ( !$r->faultCode() ){
errors::raise('Connection success to '.$this->RID, CORE_LOG_NOTICE, 'RPC');
$this->lastreq = chrono::get_microtime();
return TRUE;
}
errors::raise('Connection failure to '.$this->RID.': '.htmlspecialchars( $r->faultString() ), CORE_LOG_ERROR, 'RPC');
unset(self::$_RPC[$this->RID]);
return FALSE;
}
public function getstatus(){
$chr = chrono::start('hellarpc_net');
if ( $this->conn_need_revive() ){ if ( !$this->connect() ){ chrono::pause('hellarpc_net', $chr);return FALSE; } }
$q = new xmlrpcmsg("status", "");
$r = self::$_RPC[$this->RID]->send($q);
unset($q);
if ( !$r->faultCode() ){
$o = php_xmlrpc_decode( $r->value() );
} else {
errors::raise('RPC Request failure, Status : '.htmlspecialchars( $r->faultString() ), CORE_LOG_ERROR, 'RPC');
$o = FALSE;
}
$this->lastreq = chrono::get_microtime();
chrono::pause('hellarpc_net', $chr);
return $o;
}
private function rpcall($msg, $arg=NULL){
$chr = chrono::start('hellarpc_net');
if ( $this->conn_need_revive() ){ if ( !$this->connect() ){ chrono::pause('hellarpc_net', $chr);return FALSE; } }
if ( $arg === NULL ){
$q = new xmlrpcmsg($msg, "");
} else {
$q = new xmlrpcmsg($msg, $arg);
}
$r = self::$_RPC[$this->RID]->send($q);
unset($q);
if ( !$r->faultCode() ){ chrono::pause('hellarpc_net', $chr);return TRUE; }
errors::raise("RPC Call error, $msg : ".htmlspecialchars( $r->faultString() ), CORE_LOG_ERROR, 'RPC');
chrono::pause('hellarpc_net', $chr);
return FALSE;
}
public function cancel($id=NULL){
if ( $id===NULL ){
return $this->rpcall("cancel");
} else {
$buf[] = new xmlrpcval($id, "string");
$r = $this->rpcall("dequeue", $buf);
unset($buf);
return $r;
}
}
public function enqueue($did){
$buf[] = new xmlrpcval($did, "string");
$r = $this->rpcall("enqueuenewzbin", $buf);
unset($buf);
return $r;
}
public function pause(){ return $this->rpcall("pause"); }
public function resume(){ return $this->rpcall("continue"); }
public function setrate($rate){
$buf[] = new xmlrpcval($rate, "string");
$r = $this->rpcall("maxrate", $buf);
unset($buf);
return $r;
}
public function force($id){
$buf[] = new xmlrpcval($id, "string");
$r = $this->rpcall("force", $buf);
unset($buf);
return $r;
}
public function moveup($id){
$buf[] = new xmlrpcval($id, "string");
$r = $this->rpcall("up", $buf);
unset($buf);
return $r;
}
public function movedown($id){
$buf[] = new xmlrpcval($id, "string");
$r = $this->rpcall("down", $buf);
unset($buf);
return $r;
}
public function movetop($id){
$buf[] = new xmlrpcval($id, "string");
$r = $this->rpcall("next", $buf);
unset($buf);
return $r;
}
public function movebot($id){
$buf[] = new xmlrpcval($id, "string");
$r = $this->rpcall("last", $buf);
unset($buf);
return $r;
}
}