private function processRequest($request)
    {
        if (!is_array($request)) {
            return self::requestError();
        }

        // The presence of the 'id' key indicates that a response is expected
        $isQuery = array_key_exists('id', $request);

        $id = &$request['id'];

        if (($id !== null) && !is_int($id) && !is_float($id) && !is_string($id)) {
            return self::requestError();
        }

        $version = &$request['jsonrpc'];

        if ($version !== self::VERSION) {
            return self::requestError($id);
        }

        $method = &$request['method'];

        if (!is_string($method)) {
            return self::requestError($id);
        }

        // The 'params' key is optional, but must be non-null when provided
        if (array_key_exists('params', $request)) {
            $arguments = $request['params'];

            if (!is_array($arguments)) {
                return self::requestError($id);
            }
        } else {
            $arguments = array();
        }

        if ($isQuery) {
            return $this->processQuery($id, $method, $arguments);
        }

        $this->processNotification($method, $arguments);
        return null;
    }