#!/usr/bin/env python #coding=utf8 import select import socket import logging from sjrpc.core import RpcConnection, ConnectionManager class SimpleRpcClient(ConnectionManager): ''' Create a new simple RPC client. :param connect: the :class:`RpcConnection` object to bind the client manager :param default_handler: the default handler to bind to the client connection :param on_disconnect: method on the handler to call when the client disconnects. ''' def __init__(self, connection, default_handler=None, on_disconnect=None): super(SimpleRpcClient, self).__init__() self._on_disconnect = on_disconnect self._connection = connection self._connection.set_handler(default_handler) self.register(self._connection) @classmethod def from_addr(cls, addr, port, enable_ssl=False, cert=None, timeout=None, conn_timeout=30.0, default_handler=None, on_disconnect=None): ''' Construct the instance of :class:`SimpleRpcClient` without providing the :class:`RpcConnection` object. The :class:`RpcConnection` is automatically created and passed to the standard constructor before to return the new instance. :param addr: the target ip address :param port: the target port :param ssl: enable SSL :param timeout: the global call timeout setting :param conn_timeout: the connection operation timeout :param cert: is SSL is enabled, profile the filename of certificate to check. If None, don't check certificate. :param default_handler: the default handler to bind to the client connection :param on_disconnect: method on the handler to call when the client disconnects. ''' connection = RpcConnection.from_addr(addr, port, None, timeout=timeout, conn_timeout=conn_timeout, enable_ssl=enable_ssl, cert=cert) client = cls(connection, default_handler=default_handler, on_disconnect=on_disconnect) connection._manager = client return client @classmethod def from_sock(cls, sock, default_handler=None, on_disconnect=None): ''' Construct the instance of :class:`SimpleRpcClient` without providing the :class:`RpcConnection` object. The :class:`RpcConnection` is automatically created and passed to the standard constructor before to return the new instance :param sock: the socket object to wrap with :class:`RpcConnection` object. :param default_handler: the default handler to bind to the client connection :param on_disconnect: method on the handler to call when the client disconnects. ''' connection = RpcConnection(sock, None) client = cls(connection, default_handler, on_disconnect) connection._manager = client return client def shutdown(self): super(SimpleRpcClient, self).shutdown() self._connection.shutdown(self._on_disconnect) def handle_event(self, fd, event): if event & select.EPOLLIN: # Data are ready to be readed on socket try: self._connection.receive() except socket.error as err: logging.debug('Socket error while receiving from the client ' 'fd/%s: %s', fd, err) self.shutdown() if event & select.EPOLLOUT: # Data are ready to be written on socket try: self._connection.send() except socket.error as err: logging.debug('Socket error while sending to the client ' 'fd/%s: %s', fd, err) self.shutdown() if event & select.EPOLLHUP: logging.debug('Socket HUP fd/%s', fd) self.shutdown() def all_connections(self): return set((self._connection,)) def call(self, *args, **kwargs): return self._connection.call(*args, **kwargs)