예제 #1
0
    def __init__(self, config):
        try:
            (self.kv_helper, _) = connector.open(config)
        except Exception as err:
            logger.error(f"failed to open db: {err}")
            sys.exit(-1)

        # Worker registry handler needs to be instantiated before Work order handler. Otherwise, LMDB operations don't operate on updated values.
        # TODO: Needs further investigation on what is causing the above behavior.

        self.worker_registry_handler = TCSWorkerRegistryHandler(self.kv_helper)
        self.workorder_handler = TCSWorkOrderHandler(
            self.kv_helper, config["Listener"]["max_work_order_count"])
        self.workorder_receipt_handler = TCSWorkOrderReceiptHandler(
            self.kv_helper)
        self.worker_encryption_key_handler = WorkerEncryptionKeyHandler(
            self.kv_helper)

        self.dispatcher = Dispatcher()
        rpc_methods = [
            self.worker_encryption_key_handler.EncryptionKeyGet,
            self.worker_encryption_key_handler.EncryptionKeySet,
            self.worker_registry_handler.WorkerLookUp,
            self.worker_registry_handler.WorkerLookUpNext,
            self.worker_registry_handler.WorkerRegister,
            self.worker_registry_handler.WorkerSetStatus,
            self.worker_registry_handler.WorkerRetrieve,
            self.worker_registry_handler.WorkerUpdate,
            self.workorder_handler.WorkOrderSubmit,
            self.workorder_handler.WorkOrderGetResult,
        ]
        for m in rpc_methods:
            self.dispatcher.add_method(m)
예제 #2
0
class ArachnadoRPC(object):
    """ Base class for all Arachnado RPC resources.
    Use it as a mixin for tornado.web.RequestHandler subclasses.

    It provides :meth:`handle_request` method which handles
    Jobs, Sites and Pages RPC requests.
    """
    rpc_objects = tuple()

    def initialize(self, *args, **kwargs):
        jobs = Jobs(self, *args, **kwargs)
        sites = Sites(self, *args, **kwargs)
        pages = Pages(self, *args, **kwargs)
        self.rpc_objects = [jobs, sites, pages]

        self.dispatcher = Dispatcher()
        for obj in self.rpc_objects:
            self.dispatcher.add_object(obj)

    def handle_request(self, body):
        response = JSONRPCResponseManager.handle(body, self.dispatcher)
        if isinstance(response.result, Future):
            response.result.add_done_callback(
                partial(self.on_done, data=response.data))
        else:
            self.send_data(response.data)

    def on_done(self, future, data):
        data['result'] = future.result()
        self.send_data(data)

    def send_data(self, data):
        raise NotImplementedError
    def __init__(self, conn, *, name="RE QServer Comm"):
        self._conn = conn
        self._dispatcher = Dispatcher()  # json-rpc dispatcher
        self._thread_running = False  # Set True to exit the thread

        self._thread_name = name

        self._conn_polling_timeout = 0.1  # in sec.
예제 #4
0
    def initialize(self, *args, **kwargs):
        jobs = Jobs(self, *args, **kwargs)
        sites = Sites(self, *args, **kwargs)
        pages = Pages(self, *args, **kwargs)
        self.rpc_objects = [jobs, sites, pages]

        self.dispatcher = Dispatcher()
        for obj in self.rpc_objects:
            self.dispatcher.add_object(obj)
예제 #5
0
 def initialize(self, *args, **kwargs):
     self.stored_data = deque()
     self.storages = {}
     self.i_args = args
     self.i_kwargs = kwargs
     self.cp = kwargs.get("crawler_process", None)
     self.dispatcher = Dispatcher()
     self.dispatcher["cancel_subscription"] = self.cancel_subscription
     self.dispatcher["set_max_message_size"] = self.set_max_message_size
예제 #6
0
    def test_init_from_dictionary(self):

        dummy = {
            'one': lambda x: x,
            'two': lambda x: x,
        }

        d = Dispatcher(dummy)

        self.assertIn("one", d)
        self.assertIn("two", d)
예제 #7
0
 def __init__(self, rpc_socket, gpio_manager):
     self.rpc_socket = rpc_socket
     self.gpio_manager = gpio_manager
     self.dispatcher = Dispatcher()
     self.dispatcher.add_method(self.gpio_manager.add_input)
     self.dispatcher.add_method(self.gpio_manager.add_output)
     self.dispatcher.add_method(self.gpio_manager.pin_read)
     self.dispatcher.add_method(self.gpio_manager.pin_on)
     self.dispatcher.add_method(self.gpio_manager.pin_off)
     self.dispatcher.add_method(self.gpio_manager.enable_pub_when_activated)
     self.dispatcher.add_method(self.gpio_manager.disable_pub_when_activated)
     self.dispatcher.add_method(self.gpio_manager.enable_pub_when_deactivated)
     self.dispatcher.add_method(self.gpio_manager.disable_pub_when_deactivated)
예제 #8
0
    def __init__(self, config):
        try:
            self.kv_helper = \
                    connector.open(config['KvStorage']['remote_storage_url'])
        except Exception as err:
            logger.error(f"failed to open db: {err}")
            sys.exit(-1)

        self.worker_registry_handler = TCSWorkerRegistryHandler(self.kv_helper)
        self.workorder_handler = TCSWorkOrderHandler(
            self.kv_helper, config["Listener"]["max_work_order_count"])
        self.workorder_receipt_handler = TCSWorkOrderReceiptHandler(
            self.kv_helper)
        self.worker_encryption_key_handler = WorkerEncryptionKeyHandler(
            self.kv_helper)

        self.dispatcher = Dispatcher()
        rpc_methods = [
            self.worker_encryption_key_handler.EncryptionKeyGet,
            self.worker_encryption_key_handler.EncryptionKeySet,
            self.worker_registry_handler.WorkerLookUp,
            self.worker_registry_handler.WorkerLookUpNext,
            self.worker_registry_handler.WorkerRegister,
            self.worker_registry_handler.WorkerSetStatus,
            self.worker_registry_handler.WorkerRetrieve,
            self.worker_registry_handler.WorkerUpdate,
            self.workorder_handler.WorkOrderSubmit,
            self.workorder_handler.WorkOrderGetResult,
            self.workorder_receipt_handler.WorkOrderReceiptCreate,
            self.workorder_receipt_handler.WorkOrderReceiptUpdate,
            self.workorder_receipt_handler.WorkOrderReceiptRetrieve,
            self.workorder_receipt_handler.WorkOrderReceiptUpdateRetrieve,
            self.workorder_receipt_handler.WorkOrderReceiptLookUp,
            self.workorder_receipt_handler.WorkOrderReceiptLookUpNext
        ]
        for m in rpc_methods:
            self.dispatcher.add_method(m)
예제 #9
0
    def test_init_from_object_instance(self):
        class Dummy():
            def one(self):
                pass

            def two(self):
                pass

        dummy = Dummy()

        d = Dispatcher(dummy)

        self.assertIn("one", d)
        self.assertIn("two", d)
        self.assertNotIn("__class__", d)
예제 #10
0
    def __getitem__(self, key):
        """Override __getitem__ to support transparent translation.

        Translate function arguments, return value, and exceptions.
        """
        old_value = Dispatcher.__getitem__(self, key)
        @wraps(old_value)
        def wrapped(*args, **kwargs):
            """Wrap a function in JSON formatting."""
            try:
                return to_json(old_value(*from_json(args),
                                         **from_json(kwargs)))
            except Exception as exception:
                convert_exception(exception)
                raise
        return wrapped
예제 #11
0
class TCSListener(resource.Resource):
    """
    TCSListener Class  is comprised of HTTP interface which listens for the end user requests, 
    Worker Registry Handler, Work Order Handler and Work Order Receipts Handler .
    """
    # The isLeaf instance variable describes whether or not a resource will have children and only leaf resources get rendered.
    # TCSListener is the most derived class hence isLeaf is required.

    isLeaf = True

    # -----------------------------------------------------------------
    def __init__(self, config):
        try:
            (self.kv_helper, _) = connector.open(config)
        except Exception as err:
            logger.error(f"failed to open db: {err}")
            sys.exit(-1)

        # Worker registry handler needs to be instantiated before Work order handler. Otherwise, LMDB operations don't operate on updated values.
        # TODO: Needs further investigation on what is causing the above behavior.

        self.worker_registry_handler = TCSWorkerRegistryHandler(self.kv_helper)
        self.workorder_handler = TCSWorkOrderHandler(
            self.kv_helper, config["Listener"]["max_work_order_count"])
        self.workorder_receipt_handler = TCSWorkOrderReceiptHandler(
            self.kv_helper)
        self.worker_encryption_key_handler = WorkerEncryptionKeyHandler(
            self.kv_helper)

        self.dispatcher = Dispatcher()
        rpc_methods = [
            self.worker_encryption_key_handler.EncryptionKeyGet,
            self.worker_encryption_key_handler.EncryptionKeySet,
            self.worker_registry_handler.WorkerLookUp,
            self.worker_registry_handler.WorkerLookUpNext,
            self.worker_registry_handler.WorkerRegister,
            self.worker_registry_handler.WorkerSetStatus,
            self.worker_registry_handler.WorkerRetrieve,
            self.worker_registry_handler.WorkerUpdate,
            self.workorder_handler.WorkOrderSubmit,
            self.workorder_handler.WorkOrderGetResult,
        ]
        for m in rpc_methods:
            self.dispatcher.add_method(m)

    def _process_request(self, input_json_str):
        response = {}
        response['error'] = {}
        response['error'][
            'code'] = WorkOrderStatus.INVALID_PARAMETER_FORMAT_OR_VALUE

        try:
            input_json = json.loads(input_json_str)
        except:
            response['error'][
                'message'] = 'Error: Improper Json. Unable to load'
            return response

        if ('jsonrpc' not in input_json or 'id' not in input_json
                or 'method' not in input_json or 'params' not in input_json):
            response['error'][
                'message'] = 'Error: Json does not have the required field'
            return response

        if not isinstance(input_json['id'], int):
            response['error'][
                'message'] = 'Error: Id should be of type integer'
            return response

        response['jsonrpc'] = input_json['jsonrpc']
        response['id'] = input_json['id']

        if not isinstance(input_json['method'], str):
            response['error'][
                'message'] = 'Error: Method has to be of type string'
            return response

        if ("WorkOrderReceipt" in input_json['method']):
            return self.workorder_receipt_handler.workorder_receipt_handler(
                input_json_str)

        logger.info("Received request: %s", input_json['method'])
        # save the full json for WorkOrderSubmit
        input_json["params"]["raw"] = input_json_str

        data = json.dumps(input_json).encode('utf-8')
        response = JSONRPCResponseManager.handle(data, self.dispatcher)
        return response.data

    def render_GET(self, request):
        # JRPC response with id 0 is returned because id parameter
        # will not be found in GET request
        response = utility.create_error_response(
            WorkOrderStatus.INVALID_PARAMETER_FORMAT_OR_VALUE, "0",
            "Only POST request is supported")
        logger.error(
            "GET request is not supported. Only POST request is supported")

        return response

    def render_POST(self, request):
        response = {}

        logger.info('Received a new request from the client')
        try:
            # process the message encoding
            encoding = request.getHeader('Content-Type')
            data = request.content.read()
            if encoding == 'application/json':

                try:
                    input_json_str = data.decode('utf-8')
                    input_json = json.loads(input_json_str)
                    jrpc_id = input_json["id"]
                    response = self._process_request(input_json_str)

                except AttributeError:
                    logger.error("Error while loading input json")
                    response = utility.create_error_response(
                        WorkOrderStatus.UNKNOWN_ERROR, jrpc_id,
                        "UNKNOWN_ERROR: Error while loading the input JSON file"
                    )
                    return response

            else:
                # JRPC response with 0 as id is returned because id can't be fecthed
                # from a request with unknown encoding
                response = utility.create_error_response(
                    WorkOrderStatus.UNKNOWN_ERROR, 0,
                    "UNKNOWN_ERROR: unknown message encoding")
                return response

        except:
            logger.exception('exception while decoding http request %s',
                             request.path)
            # JRPC response with 0 as id is returned because id can't be
            # fetched from improper request
            response = utility.create_error_response(
                WorkOrderStatus.UNKNOWN_ERROR, 0,
                "UNKNOWN_ERROR: unable to decode incoming request")
            return response

        # send back the results
        try:
            if encoding == 'application/json':
                response = json.dumps(response)
            logger.info('response[%s]: %s', encoding, response)
            request.setHeader('content-type', encoding)
            request.setResponseCode(http.OK)
            return response.encode('utf8')

        except:
            logger.exception('unknown exception while processing request %s',
                             request.path)
            response = utility.create_error_response(
                WorkOrderStatus.UNKNOWN_ERROR, jrpc_id,
                "UNKNOWN_ERROR: unknown exception processing http \
                    request {0}".format(request.path))
            return response
class PipeJsonRpcReceive:
    """
    The class contains functions for receiving and processing JSON RPC messages received on
    communication pipe.

    Parameters
    ----------
    conn: multiprocessing.Connection
        Reference to bidirectional end of a pipe (multiprocessing.Pipe)
    name: str
        Name of the receiving thread (it is better to assign meaningful unique names to threads.

    Examples
    --------

    .. code-block:: python

        conn1, conn2 = multiprocessing.Pipe()
        pc = PipeJsonRPC(conn=conn1, name="RE QServer Receive")

        def func():
            print("Testing")

        pc.add_handler(func, "some_method")
        pc.start()   # Wait and process commands
        # The function 'func' is called when the message with method=="some_method" is received
        pc.stop()  # Stop before exit to stop the thread.
    """
    def __init__(self, conn, *, name="RE QServer Comm"):
        self._conn = conn
        self._dispatcher = Dispatcher()  # json-rpc dispatcher
        self._thread_running = False  # Set True to exit the thread

        self._thread_name = name

        self._conn_polling_timeout = 0.1  # in sec.

    def start(self):
        """
        Start processing of the pipe messages
        """
        self._start_conn_thread()

    def stop(self):
        """
        Stop processing of the pipe messages (and exit the tread)
        """
        self._thread_running = False

    def __del__(self):
        self.stop()

    def add_method(self, handler, name=None):
        """
        Add method to json-rpc dispatcher.

        Parameters
        ----------
        handler: callable
            Reference to a handler
        name: str, optional
            Name to register (default is the handler name)
        """
        # Add method to json-rpc dispatcher
        self._dispatcher.add_method(handler, name)

    def _start_conn_thread(self):
        if not self._thread_running:

            # Clear the pipe from outdated unprocessed messages.
            while self._conn.poll():
                self._conn.recv()

            self._thread_running = True
            self._thread_conn = threading.Thread(
                target=self._receive_conn_thread,
                name=self._thread_name,
                daemon=True)
            self._thread_conn.start()

    def _receive_conn_thread(self):
        while True:
            if self._conn.poll(self._conn_polling_timeout):
                try:
                    msg = self._conn.recv()
                    # Messages should be handled in the event loop
                    self._conn_received(msg)
                except Exception as ex:
                    logger.exception(
                        "Exception occurred while waiting for RE Manager-> Watchdog message: %s",
                        str(ex))
                    break
            if not self._thread_running:  # Exit thread
                break

    def _conn_received(self, msg):

        # if logger.level < 11:  # Print output only if logging level is DEBUG (10) or less
        #     msg_json = json.loads(msg)
        #     We don't want to print 'heartbeat' messages
        #     if not isinstance(msg_json, dict) or (msg_json["method"] != "heartbeat"):
        #         logger.debug("Command received RE Manager->Watchdog: %s", pprint.pformat(msg_json))

        response = JSONRPCResponseManager.handle(msg, self._dispatcher)
        if response:
            response = response.json
            self._conn.send(response)
 def __init__(self, rpc_methods):
     self.dispatcher = Dispatcher()
     for m in rpc_methods:
         self.dispatcher.add_method(m)
class BaseJRPCListener(resource.Resource):
    """
    BaseJRPCListener Class is comprised of HTTP interface which listens for the
    end user requests using JRPC.
    """
    # The isLeaf instance variable describes whether or not a resource will
    # have children and only leaf resources get rendered.
    # BaseListener is the supposed to be one but last class in the derivation
    # tree. So, isLeaf is set to False.

    isLeaf = False

    # -----------------------------------------------------------------
    def __init__(self, rpc_methods):
        self.dispatcher = Dispatcher()
        for m in rpc_methods:
            self.dispatcher.add_method(m)

    def _process_request(self, input_json_str):
        """
        Handles incoming requests or rather dispatches to appropriate
        rpc method

        Parameters :
            input_json_str - JSON formatted str of the request
        Returns :
            response - data field from the response received which is a dict
        """
        response = {}
        response['error'] = {}
        response['error']['code'] = \
            JRPCErrorCodes.INVALID_PARAMETER_FORMAT_OR_VALUE

        try:
            input_json = json.loads(input_json_str)
            logger.info("Received request: %s", input_json['method'])
        except Exception as err:
            logger.error("exception loading Json: %s", str(err))
            response["error"]["message"] = "Improper Json request"
            return response

        # save the full json for WorkOrderSubmit
        input_json["params"]["raw"] = input_json_str
        data = json.dumps(input_json).encode('utf-8')
        response = JSONRPCResponseManager.handle(data, self.dispatcher)
        return response.data

    def render_GET(self, request):
        """
        Handle a GET request to the listener. Not supported. So only
        error is expected to be returned as response.

        Parameters :
            request - Request coming in from a client
        Returns :
            response - A dict type response which always contains error
        """
        # JRPC response with id 0 is returned because id parameter
        # will not be found in GET request
        response = jrpc_utility.create_error_response(
            JRPCErrorCodes.INVALID_PARAMETER_FORMAT_OR_VALUE, "0",
            "Only POST request is supported")
        logger.error(
            "GET request is not supported. Only POST request is supported")

        return response

    def render_POST(self, request):
        """
        Handle a POST request to the listener. Decode and delegate to
        _process_request for handling.

        Parameters :
            request - Request coming in from a client
        Returns :
            response - A dict type response
        """
        response = {}

        logger.info('Received a new request from the client')
        try:
            # process the message encoding
            encoding = request.getHeader('Content-Type')
            data = request.content.read()
            if encoding == 'application/json':

                try:
                    input_json_str = data.decode('utf-8')
                    input_json = json.loads(input_json_str)
                    jrpc_id = input_json["id"]
                    response = self._process_request(input_json_str)

                except AttributeError:
                    logger.error("Error while loading input json")
                    response = jrpc_utility.create_error_response(
                        JRPCErrorCodes.UNKNOWN_ERROR, jrpc_id,
                        "UNKNOWN_ERROR: Error while loading input JSON file")
                    return response

            else:
                # JRPC response with 0 as id is returned because id can't be
                # fetched from a request with unknown encoding.
                response = jrpc_utility.create_error_response(
                    JRPCErrorCodes.UNKNOWN_ERROR, 0,
                    "UNKNOWN_ERROR: unknown message encoding")
                return response

        except Exception as err:
            logger.exception('exception while decoding http request %s: %s',
                             request.path, str(err))
            # JRPC response with 0 as id is returned because id can't be
            # fetched from improper request
            response = jrpc_utility.create_error_response(
                JRPCErrorCodes.UNKNOWN_ERROR, 0,
                "UNKNOWN_ERROR: unable to decode incoming request")
            return response

        # send back the results
        try:
            if encoding == 'application/json':
                response = json.dumps(response)
            logger.info('response[%s]: %s', encoding, response)
            request.setHeader('content-type', encoding)
            request.setResponseCode(http.OK)
            return response.encode('utf8')

        except Exception as err:
            logger.exception(
                'unknown exception while processing request %s: %s',
                request.path, str(err))
            response = jrpc_utility.create_error_response(
                JRPCErrorCodes.UNKNOWN_ERROR, jrpc_id,
                "UNKNOWN_ERROR: unknown exception processing http " +
                "request {0}: {1}".format(request.path, str(err)))
            return response

    def start(self, host_name, port):
        """
        Start the listener instance on specified socket.

        Parameters :
            host_name - The hostname where this listener is reachable
            port - The port at which this listener needs to listen
        """
        root = self
        site = server.Site(root)
        reactor.listenTCP(port, site, interface=host_name)

        logger.info('%s started on port %s', type(self).__name__, port)

        try:
            reactor.run()
        except reactor_error.ReactorNotRunning:
            logger.error('shutdown')
        except Exception as err:
            logger.error('shutdown: %s', str(err))

        exit(0)
예제 #15
0
 def __init__(self, conn):
     self._conn = conn
     self._dispatcher = Dispatcher()  # json-rpc dispatcher
     self._stop_thread = False  # Set True to exit the thread
예제 #16
0
 def setUp(self):
     self.d = Dispatcher()
예제 #17
0
    def dispatcher(self):  # TODO: make decorator or something
        d = Dispatcher()

        d.add_method(self.request_player_state, name="request_state")
        d.add_method(self.player_change_state, name="state")
        d.add_method(self.register_player, name="register")
        d.add_method(self.register_controller, name="subscribe")
        d.add_method(self.player_command, name="command")

        return d
예제 #18
0
class GpioCoreServer:

    def __init__(self, rpc_socket, gpio_manager):
        self.rpc_socket = rpc_socket
        self.gpio_manager = gpio_manager
        self.dispatcher = Dispatcher()
        self.dispatcher.add_method(self.gpio_manager.add_input)
        self.dispatcher.add_method(self.gpio_manager.add_output)
        self.dispatcher.add_method(self.gpio_manager.pin_read)
        self.dispatcher.add_method(self.gpio_manager.pin_on)
        self.dispatcher.add_method(self.gpio_manager.pin_off)
        self.dispatcher.add_method(self.gpio_manager.enable_pub_when_activated)
        self.dispatcher.add_method(self.gpio_manager.disable_pub_when_activated)
        self.dispatcher.add_method(self.gpio_manager.enable_pub_when_deactivated)
        self.dispatcher.add_method(self.gpio_manager.disable_pub_when_deactivated)

    def run(self):
        try:
            while True:
                message = self.rpc_socket.recv_string()
                response = JSONRPCResponseManager.handle(message, self.dispatcher)
                self.rpc_socket.send_string(response.json)
        finally:
            self.gpio_manager.clean_up()
예제 #19
0
class TCSListener(resource.Resource):
    """
    TCSListener Class is comprised of HTTP interface which listens for the
    end user requests, Worker Registry Handler, Work Order Handler and
    Work Order Receipts Handler .
    """
    # The isLeaf instance variable describes whether or not a resource will
    # have children and only leaf resources get rendered.
    # TCSListener is the most derived class hence isLeaf is required.

    isLeaf = True

    # -----------------------------------------------------------------
    def __init__(self, config):
        try:
            self.kv_helper = connector.open(config['KvStorage']['remote_url'])
        except Exception as err:
            logger.error(f"failed to open db: {err}")
            sys.exit(-1)

        self.worker_registry_handler = TCSWorkerRegistryHandler(self.kv_helper)
        self.workorder_handler = TCSWorkOrderHandler(
            self.kv_helper, config["Listener"]["max_work_order_count"])
        self.workorder_receipt_handler = TCSWorkOrderReceiptHandler(
            self.kv_helper)
        self.worker_encryption_key_handler = WorkerEncryptionKeyHandler(
            self.kv_helper)

        self.dispatcher = Dispatcher()
        rpc_methods = [
            self.worker_encryption_key_handler.EncryptionKeyGet,
            self.worker_encryption_key_handler.EncryptionKeySet,
            self.worker_registry_handler.WorkerLookUp,
            self.worker_registry_handler.WorkerLookUpNext,
            self.worker_registry_handler.WorkerRegister,
            self.worker_registry_handler.WorkerSetStatus,
            self.worker_registry_handler.WorkerRetrieve,
            self.worker_registry_handler.WorkerUpdate,
            self.workorder_handler.WorkOrderSubmit,
            self.workorder_handler.WorkOrderGetResult,
            self.workorder_receipt_handler.WorkOrderReceiptCreate,
            self.workorder_receipt_handler.WorkOrderReceiptUpdate,
            self.workorder_receipt_handler.WorkOrderReceiptRetrieve,
            self.workorder_receipt_handler.WorkOrderReceiptUpdateRetrieve,
            self.workorder_receipt_handler.WorkOrderReceiptLookUp,
            self.workorder_receipt_handler.WorkOrderReceiptLookUpNext
        ]
        for m in rpc_methods:
            self.dispatcher.add_method(m)

    def _process_request(self, input_json_str):
        response = {}
        response['error'] = {}
        response['error']['code'] = \
            WorkOrderStatus.INVALID_PARAMETER_FORMAT_OR_VALUE

        try:
            input_json = json.loads(input_json_str)
        except Exception as err:
            logger.exception("exception loading Json: %s", str(err))
            response = {
                "error": {
                    "code": WorkOrderStatus.INVALID_PARAMETER_FORMAT_OR_VALUE,
                    "message": "Error: Improper Json. Unable to load",
                },
            }
            return response

        logger.info("Received request: %s", input_json['method'])
        # save the full json for WorkOrderSubmit
        input_json["params"]["raw"] = input_json_str

        data = json.dumps(input_json).encode('utf-8')
        response = JSONRPCResponseManager.handle(data, self.dispatcher)
        return response.data

    def render_GET(self, request):
        # JRPC response with id 0 is returned because id parameter
        # will not be found in GET request
        response = jrpc_utility.create_error_response(
            WorkOrderStatus.INVALID_PARAMETER_FORMAT_OR_VALUE, "0",
            "Only POST request is supported")
        logger.error(
            "GET request is not supported. Only POST request is supported")

        return response

    def render_POST(self, request):
        response = {}

        logger.info('Received a new request from the client')
        try:
            # process the message encoding
            encoding = request.getHeader('Content-Type')
            data = request.content.read()
            if encoding == 'application/json':

                try:
                    input_json_str = data.decode('utf-8')
                    input_json = json.loads(input_json_str)
                    jrpc_id = input_json["id"]
                    response = self._process_request(input_json_str)

                except AttributeError:
                    logger.error("Error while loading input json")
                    response = jrpc_utility.create_error_response(
                        WorkOrderStatus.UNKNOWN_ERROR, jrpc_id,
                        "UNKNOWN_ERROR: Error while loading input JSON file")
                    return response

            else:
                # JRPC response with 0 as id is returned because id can't be
                # fetched from a request with unknown encoding.
                response = jrpc_utility.create_error_response(
                    WorkOrderStatus.UNKNOWN_ERROR, 0,
                    "UNKNOWN_ERROR: unknown message encoding")
                return response

        except Exception as err:
            logger.exception('exception while decoding http request %s: %s',
                             request.path, str(err))
            # JRPC response with 0 as id is returned because id can't be
            # fetched from improper request
            response = jrpc_utility.create_error_response(
                WorkOrderStatus.UNKNOWN_ERROR, 0,
                "UNKNOWN_ERROR: unable to decode incoming request")
            return response

        # send back the results
        try:
            if encoding == 'application/json':
                response = json.dumps(response)
            logger.info('response[%s]: %s', encoding, response)
            request.setHeader('content-type', encoding)
            request.setResponseCode(http.OK)
            return response.encode('utf8')

        except Exception as err:
            logger.exception(
                'unknown exception while processing request %s: %s',
                request.path, str(err))
            response = jrpc_utility.create_error_response(
                WorkOrderStatus.UNKNOWN_ERROR, jrpc_id,
                "UNKNOWN_ERROR: unknown exception processing http " +
                "request {0}: {1}".format(request.path, str(err)))
            return response
예제 #20
0
# coding:utf-8
from uuid import uuid4

from flask import Blueprint
from jsonrpc.backend.flask import JSONRPCAPI
from jsonrpc.dispatcher import Dispatcher


class MyJsonRpcApi(JSONRPCAPI):

    def as_blueprint(self, name=None, url='/'):
        blueprint = Blueprint(name if name else str(uuid4()), __name__)
        blueprint.add_url_rule(
            url, view_func=self.jsonrpc, methods=['POST'])
        blueprint.add_url_rule(
            '/map', view_func=self.jsonrpc_map, methods=['GET'])
        return blueprint


dispatcher = Dispatcher()
api = MyJsonRpcApi(dispatcher)
api_add = api.dispatcher.add_method
api_class = api.dispatcher.add_class
예제 #21
0
def create_dispatcher(node: ecdkg.ECDKGNode, address: int = None):
    # TODO: make loop use uniform
    loop = asyncio.get_event_loop()

    dispatcher = Dispatcher()

    dispatcher['echo'] = lambda value: value

    def dispatcher_add_async_method(corofunc):
        @functools.wraps(corofunc)
        def wrapper(*args, **kwargs):
            return loop.create_task(corofunc(*args, **kwargs))
        return dispatcher.add_method(wrapper)

    @dispatcher_add_async_method
    async def get_ecdkg_state(decryption_condition: str, phase: ecdkg.ECDKGPhase = ecdkg.ECDKGPhase.uninitialized):
        ecdkg_obj = node.get_protocol_instance_by_decryption_condition(decryption_condition)
        return ecdkg_obj.to_state_message()

    @dispatcher_add_async_method
    async def get_encryption_key(decryption_condition, notify_others=True):
        ecdkg_obj = node.get_protocol_instance_by_decryption_condition(decryption_condition)
        await ecdkg_obj.run_until_phase(ecdkg.ECDKGPhase.key_publication)
        return '{0[0]:064x}{0[1]:064x}'.format(ecdkg_obj.encryption_key)

    @dispatcher_add_async_method
    async def get_signed_decryption_key_part(decryption_condition):
        # TODO: Is running the get enc key even necessary now?
        await get_encryption_key(decryption_condition)
        await util.decryption_condition_satisfied(decryption_condition)
        ecdkg_obj = node.get_protocol_instance_by_decryption_condition(decryption_condition)
        return ecdkg_obj.get_signed_decryption_key_part()

    @dispatcher_add_async_method
    async def get_decryption_key(decryption_condition):
        ecdkg_obj = node.get_protocol_instance_by_decryption_condition(decryption_condition)
        await ecdkg_obj.run_until_phase(ecdkg.ECDKGPhase.complete)
        return '{:064x}'.format(ecdkg_obj.decryption_key)

    @dispatcher_add_async_method
    async def get_signed_verification_points(decryption_condition):
        logging.info('sending vpoints to {:040x}'.format(address))
        ecdkg_obj = node.get_protocol_instance_by_decryption_condition(decryption_condition)
        await ecdkg_obj.run_until_phase(ecdkg.ECDKGPhase.key_distribution)
        return ecdkg_obj.get_signed_verification_points()

    @dispatcher_add_async_method
    async def get_signed_encryption_key_vector(decryption_condition):
        ecdkg_obj = node.get_protocol_instance_by_decryption_condition(decryption_condition)
        # await ecdkg_obj.run_until_phase(ecdkg.ECDKGPhase.key_generation)
        await ecdkg_obj.run_until_phase(ecdkg.ECDKGPhase.key_distribution)
        return ecdkg_obj.get_signed_encryption_key_vector()

    @dispatcher_add_async_method
    async def get_complaints(decryption_condition):
        ecdkg_obj = node.get_protocol_instance_by_decryption_condition(decryption_condition)
        # await ecdkg_obj.run_until_phase(ecdkg.ECDKGPhase.key_check)
        await ecdkg_obj.run_until_phase(ecdkg.ECDKGPhase.key_distribution)
        complaints = ecdkg_obj.get_complaints_by(node.address)
        logging.info('sending complaints: {}'.format(complaints))
        return complaints

    if address is not None:
        @dispatcher_add_async_method
        async def get_signed_secret_shares(decryption_condition):
            logging.info('sending shares to {:040x}'.format(address))
            ecdkg_obj = node.get_protocol_instance_by_decryption_condition(decryption_condition)
            await ecdkg_obj.run_until_phase(ecdkg.ECDKGPhase.key_distribution)
            return ecdkg_obj.get_signed_secret_shares(address)

    return dispatcher