Server : LiteSpeed
System : Linux server900.shared.spaceship.host 4.18.0-553.89.1.lve.el8.x86_64 #1 SMP Wed Dec 10 13:58:50 UTC 2025 x86_64
User : kvzyqrttyz ( 5084)
PHP Version : 8.1.34
Disable Function : NONE
Directory :  /opt/hc_php/unversioned/JsonRPC/

📁 Create New:
⬆️ Upload File:
Current Dir [ Not Writable ] Root [ Writable ]


OR Upload from URL:
URL: Save as:

📄 File: Client.php

Path: //opt/hc_php/unversioned/JsonRPC/Client.php

Size: 7.63 KB

Permissions: 0644

<?php

namespace JsonRPC;

use RuntimeException;
use BadFunctionCallException;
use InvalidArgumentException;

const TRANSPORT_TCP = 0;
const TRANSPORT_HTTP = 1;

// Retry config
const MAX_RETRIES = 5;
const RETRY_DELAY = 1; // seconds

class Client
{
    /**
     * RPC transport type
     * @var int
     */
    private $transport;

    /**
     * Path to the unix socket of the server
     * @var string
     */
    private $unix_socket_path;

    /**
     * HTTP client timeout
     * @var int
     */
    private $timeout;

    /**
     * Enable debug output to the php error log
     * @var bool
     */
    public $debug = false;

    /**
     * User that runs the script
     * @var string
     */
    private $user;

    /**
     * Default HTTP headers to send to the server
     * @var string
     */
    private $headers = "POST / HTTP/1.1\r\nHost: localhost\r\nContent-Type: application/json\r\nAccept: application/json\r\n";

    /**
     * Stream handle
     */
    private $ch;

    /**
     * Constructor
     *
     * @param  string  $unix_socket_path Path to the unix socket
     * @param  int     $timeout          Timeout
     * @param  int     $transport        Transport type
     */
    public function __construct($unix_socket_path, $timeout = 5, $transport = TRANSPORT_TCP)
    {
        $this->unix_socket_path = 'unix://'.$unix_socket_path;
        $this->timeout = $timeout;
        $this->transport = $transport;
        $this->connect();
    }

    /**
     * Destructor
     *
     * @access public
     */
    public function __destruct()
    {
        if (is_resource($this->ch)) {
            fclose($this->ch);
        }
    }

    /**
     * (Re)connect socket
     */
    private function connect()
    {
        if (is_resource($this->ch)) {
            @fclose($this->ch);
        }

        $this->ch = @stream_socket_client(
            $this->unix_socket_path,
            $errno,
            $errstr,
            $this->timeout
        );

        if (!$this->ch) {
            throw new RuntimeException("$errstr ($errno)");
        }

        // Make reads honor timeout
        stream_set_timeout($this->ch, $this->timeout);
    }

    /**
     * Automatic mapping of methods
     *
     * @access public
     * @param  string   $method   Method name
     * @param  array    $params   Method arguments
     * @return array
     */
    public function __call($method, array $params)
    {
        return $this->execute($method, $params);
    }

    /**
     * Execute a method
     */
    public function execute($method, array $params = array())
    {
        return $this->parseResponse(
            $this->doRequest($this->prepareRequest($method, $params))
        );
    }

    /**
     * Prepare the payload
     *
     * @access public
     * @param  string   $method   Method name
     * @param  array    $params      Method arguments
     * @return array
     */
    public function prepareRequest($method, array $params = array())
    {
        $payload = array(
            'jsonrpc' => '2.0',
            'method'  => $method,
            'id'      => mt_rand()
        );

        if (!empty($params)) {
            $payload['params'] = $params;
        }

        return $payload;
    }

    /**
     * Parse the response and return the method result
     *
     * @access public
     * @param  array     $payload
     * @return mixed
     */
    public function parseResponse(array $payload)
    {
        return $this->getResult($payload);
    }

    /**
     * Get a RPC call result
     */
    public function getResult(array $payload)
    {
        if (isset($payload['error']['code'])) {
            $this->handleRpcErrors($payload['error']);
        }

        return isset($payload['result']) ? $payload['result'] : null;
    }

    /**
     * Throw an exception according the RPC error
     */
    public function handleRpcErrors($error)
    {
        switch ($error['code']) {
            case -32601:
                throw new BadFunctionCallException('Method not found: '.$error['message']);
            case -32602:
                throw new InvalidArgumentException('Invalid arguments: '.$error['message']);
            default:
                throw new RuntimeException('Invalid request/response: '.$error['message'], $error['code']);
        }
    }

    /**
     * Prepare http message
     */
    private function prepareHttpMessage($headers, $body) {
        return $headers . "Content-Length: ".strlen($body)."\r\n\r\n".$body;
    }

    /**
     * Parse http message
     */
    private function parseHttpMessage($text) {
        $data = array();
        $response = explode("\r\n", $text);
        $header = preg_split("/\s+/", $response[0]);
        $data["code"] = $header[1];
        $data["body"] = "";
        $is_body = false;
        foreach (array_slice($response, 1) as $str) {
            if ($is_body) {
                $data["body"] .= $str;
                continue;
            }
            $header = preg_split("/:\s+/", $str);
            if ($header[0]) {
                $data[$header[0]] = $header[1];
                continue;
            }
            $is_body = true;
        }
        return $data;
    }

    /**
     * Do the HTTP/TCP request with retry
     *
     * Retries up to MAX_RETRIES with RETRY_DELAY seconds between attempts,
     * reconnecting the socket before each retry.
     */
    public function doRequest($payload)
    {
        $json_payload = json_encode($payload);
        $attempt = 1;

        while (true) {
            try {
                $body = ($this->transport == TRANSPORT_TCP)
                    ? $json_payload
                    : $this->prepareHttpMessage($this->headers, $json_payload);

                if (@fwrite($this->ch, $body) === false) {
                    throw new RuntimeException('Socket write error');
                }

                $response = '';
                while (($buffer = @fgets($this->ch)) !== false) {
                    $response .= $buffer;
                    if ($this->transport == TRANSPORT_TCP) {
                        // For raw TCP we expect a single JSON line
                        break;
                    }
                }

                // Check for timeout or empty read
                $meta = is_resource($this->ch) ? stream_get_meta_data($this->ch) : array();
                if (!$response || (!empty($meta['timed_out']) && $meta['timed_out'])) {
                    throw new RuntimeException('Socket read error');
                }

                $data = ($this->transport == TRANSPORT_TCP)
                    ? $response
                    : $this->parseHttpMessage($response)["body"];

                if ($this->debug) {
                    error_log('==> Request: '.PHP_EOL.json_encode($payload, JSON_PRETTY_PRINT));
                    error_log('==> Response: '.PHP_EOL.$response);
                }

                $result = json_decode($data, true);
                return is_array($result) ? $result : array();

            } catch (\Throwable $e) {
                if ($attempt >= MAX_RETRIES) {
                    throw new RuntimeException(
                        "Failed after ".MAX_RETRIES." attempts: ".$e->getMessage(),
                        $e->getCode()
                    );
                }

                if ($this->debug) {
                    error_log(sprintf(
                        '[Attempt %d/%d] Error: %s. Retrying in %ds...',
                        $attempt, MAX_RETRIES, $e->getMessage(), RETRY_DELAY
                    ));
                }

                // Wait then reconnect and retry
                sleep(RETRY_DELAY);
                $this->connect();
                $attempt++;
                continue;
            }
        }
    }
}
?>

← Back to Directory Edit File 🔒 Chmod

WP File Manager