def call(self, method_name: str, *args, rpc_timeout: float = None, **kwargs):
        request = utils.rpc_request(method_name, *args, **kwargs)
        _log.debug("Sending request: %s", request)
        self._socket.send_multipart([to_msgpack(request)])
        if rpc_timeout is None:
            rpc_timeout = self.rpc_timeout
        start_time = time.time()
        while True:
            timeout = max((start_time + rpc_timeout - time.time()) * 1000, 0) if rpc_timeout is not None else None
            if self._socket.poll(timeout) == 0:
                raise TimeoutError(f"Timeout on client {self.endpoint}, method name {method_name}, class info: {self}")
            raw_reply, = self._socket.recv_multipart()
            reply = from_msgpack(raw_reply)
            _log.debug("Received reply: %s", reply)
            if reply.id == request.id:
                break
            else:
                _log.debug('Discarding reply: %s', reply)
        for warning in reply.warnings:
            warn(f"{warning.kind}: {warning.body}")
        if isinstance(reply, RPCError):
            raise utils.RPCError(reply.error)
        else:
            return reply.result