From 1f1412f3c31dfba10135ceae4641313ee48318c8 Mon Sep 17 00:00:00 2001 From: drebs Date: Wed, 24 Jul 2013 14:01:30 -0300 Subject: Refactor events so components become clients. --- src/leap/common/events/README.rst | 12 +- src/leap/common/events/__init__.py | 10 +- src/leap/common/events/client.py | 290 +++++++++++++++++++++++++++++++++++ src/leap/common/events/component.py | 290 ----------------------------------- src/leap/common/events/daemon.py | 2 +- src/leap/common/events/events.proto | 2 +- src/leap/common/events/events_pb2.py | 20 +-- src/leap/common/events/server.py | 54 +++---- src/leap/common/tests/test_events.py | 66 ++++---- 9 files changed, 373 insertions(+), 373 deletions(-) create mode 100644 src/leap/common/events/client.py delete mode 100644 src/leap/common/events/component.py (limited to 'src/leap') diff --git a/src/leap/common/events/README.rst b/src/leap/common/events/README.rst index 813be8b..2e7f254 100644 --- a/src/leap/common/events/README.rst +++ b/src/leap/common/events/README.rst @@ -1,19 +1,19 @@ Events mechanism ================ -The events mechanism allows for "components" to send signal events to each -other by means of a centralized server. Components can register with the +The events mechanism allows for clients to send signal events to each +other by means of a centralized server. Clients can register with the server to receive signals of certain types, and they can also send signals to -the server that will then redistribute these signals to registered components. +the server that will then redistribute these signals to registered clients. Listening daemons ----------------- -Both components and the server listen for incoming messages by using a +Both clients and the server listen for incoming messages by using a listening daemon that runs in its own thread. The server daemon has to be -started explicitly, while components daemon will be started whenever a -component registers with the server to receive messages. +started explicitly, while clients daemon will be started whenever a +client registers with the server to receive messages. How to use it diff --git a/src/leap/common/events/__init__.py b/src/leap/common/events/__init__.py index 12416e4..d498340 100644 --- a/src/leap/common/events/__init__.py +++ b/src/leap/common/events/__init__.py @@ -16,7 +16,7 @@ # along with this program. If not, see . """ -An events mechanism that allows for signaling of events between components. +An events mechanism that allows for signaling of events between clients. """ import logging @@ -26,7 +26,7 @@ import socket from leap.common.events import ( events_pb2 as proto, server, - component, + client, daemon, ) @@ -64,7 +64,7 @@ def register(signal, callback, uid=None, replace=False, reqcbk=None, calls. :rtype: leap.common.events.events_pb2.EventsResponse or None """ - return component.register(signal, callback, uid, replace, reqcbk, timeout) + return client.register(signal, callback, uid, replace, reqcbk, timeout) def unregister(signal, uid=None, reqcbk=None, timeout=1000): @@ -89,7 +89,7 @@ def unregister(signal, uid=None, reqcbk=None, timeout=1000): calls. :rtype: leap.common.events.events_pb2.EventsResponse or None """ - return component.unregister(signal, uid, reqcbk, timeout) + return client.unregister(signal, uid, reqcbk, timeout) def signal(signal, content="", mac_method="", mac="", reqcbk=None, @@ -122,4 +122,4 @@ def signal(signal, content="", mac_method="", mac="", reqcbk=None, calls. :rtype: leap.common.events.events_pb2.EventsResponse or None """ - return component.signal(signal, content, mac_method, mac, reqcbk, timeout) + return client.signal(signal, content, mac_method, mac, reqcbk, timeout) diff --git a/src/leap/common/events/client.py b/src/leap/common/events/client.py new file mode 100644 index 0000000..17fc326 --- /dev/null +++ b/src/leap/common/events/client.py @@ -0,0 +1,290 @@ +# -*- coding: utf-8 -*- +# client.py +# Copyright (C) 2013 LEAP +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +The client end point of the events mechanism. + +Clients are the communicating parties of the events mechanism. They +communicate by sending messages to a server, which in turn redistributes +messages to other clients. + +When a client registers a callback for a given signal, it also tells the +server that it wants to be notified whenever signals of that type are sent by +some other client. +""" + + +import logging +import threading + + +from protobuf.socketrpc import RpcService +from leap.common.events import ( + events_pb2 as proto, + server, + daemon, + mac_auth, +) + + +logger = logging.getLogger(__name__) + + +# the `registered_callbacks` dictionary below should have the following +# format: +# +# { event_signal: [ (uid, callback), ... ], ... } +# +registered_callbacks = {} + + +class CallbackAlreadyRegistered(Exception): + """ + Raised when trying to register an already registered callback. + """ + pass + + +def ensure_client_daemon(): + """ + Ensure the client daemon is running and listening for incoming + messages. + + :return: the daemon instance + :rtype: EventsClientDaemon + """ + import time + daemon = EventsClientDaemon.ensure(0) + logger.debug('ensure client daemon') + + # Because we use a random port we want to wait until a port is assigned to + # local client daemon. + + while not (EventsClientDaemon.get_instance() and + EventsClientDaemon.get_instance().get_port()): + time.sleep(0.1) + return daemon + + +def register(signal, callback, uid=None, replace=False, reqcbk=None, + timeout=1000): + """ + Registers a callback to be called when a specific signal event is + received. + + Will timeout after timeout ms if response has not been received. The + timeout arg is only used for asynch requests. If a reqcbk callback has + been supplied the timeout arg is not used. The response value will be + returned for a synch request but nothing will be returned for an asynch + request. + + :param signal: the signal that causes the callback to be launched + :type signal: int (see the `events.proto` file) + :param callback: the callback to be called when the signal is received + :type callback: function + callback(leap.common.events.events_pb2.SignalRequest) + :param uid: a unique id for the callback + :type uid: int + :param replace: should an existent callback with same uid be replaced? + :type replace: bool + :param reqcbk: a callback to be called when a response from server is + received + :type reqcbk: function + callback(leap.common.events.events_pb2.EventResponse) + :param timeout: the timeout for synch calls + :type timeout: int + + Might raise a CallbackAlreadyRegistered exception if there's already a + callback identified by the given uid and replace is False. + + :return: the response from server for synch calls or nothing for asynch + calls. + :rtype: leap.common.events.events_pb2.EventsResponse or None + """ + ensure_client_daemon() # so we can receive registered signals + # register callback locally + if signal not in registered_callbacks: + registered_callbacks[signal] = [] + cbklist = registered_callbacks[signal] + if uid and filter(lambda (x, y): x == uid, cbklist): + if not replace: + raise CallbackAlreadyRegisteredException() + else: + registered_callbacks[signal] = filter(lambda(x, y): x != uid, + cbklist) + registered_callbacks[signal].append((uid, callback)) + # register callback on server + request = proto.RegisterRequest() + request.event = signal + request.port = EventsClientDaemon.get_instance().get_port() + request.mac_method = mac_auth.MacMethod.MAC_NONE + request.mac = "" + service = RpcService(proto.EventsServerService_Stub, + server.SERVER_PORT, 'localhost') + logger.info( + "Sending registration request to server on port %s: %s", + server.SERVER_PORT, + str(request)[:40]) + return service.register(request, callback=reqcbk, timeout=timeout) + +def unregister(signal, uid=None, reqcbk=None, timeout=1000): + """ + Unregister a callback. + + If C{uid} is specified, unregisters only the callback identified by that + unique id. Otherwise, unregisters all callbacks + + :param signal: the signal that causes the callback to be launched + :type signal: int (see the `events.proto` file) + :param uid: a unique id for the callback + :type uid: int + :param reqcbk: a callback to be called when a response from server is + received + :type reqcbk: function + callback(leap.common.events.events_pb2.EventResponse) + :param timeout: the timeout for synch calls + :type timeout: int + + :return: the response from server for synch calls or nothing for asynch + calls or None if no callback is registered for that signal or uid. + :rtype: leap.common.events.events_pb2.EventsResponse or None + """ + if signal not in registered_callbacks or not registered_callbacks[signal]: + logger.warning("No callback registered for signal %d." % signal) + return None + # unregister callback locally + cbklist = registered_callbacks[signal] + if uid is not None: + if filter(lambda (cbkuid, _): cbkuid == uid, cbklist) == []: + logger.warning("No callback registered for uid %d." % st) + return None + registered_callbacks[signal] = filter(lambda(x, y): x != uid, cbklist) + else: + # exclude all callbacks for given signal + registered_callbacks[signal] = [] + # unregister port in server if there are no more callbacks for this signal + if not registered_callbacks[signal]: + request = proto.UnregisterRequest() + request.event = signal + request.port = EventsClientDaemon.get_instance().get_port() + request.mac_method = mac_auth.MacMethod.MAC_NONE + request.mac = "" + service = RpcService(proto.EventsServerService_Stub, + server.SERVER_PORT, 'localhost') + logger.info( + "Sending unregistration request to server on port %s: %s", + server.SERVER_PORT, + str(request)[:40]) + return service.unregister(request, callback=reqcbk, timeout=timeout) + + +def signal(signal, content="", mac_method="", mac="", reqcbk=None, + timeout=1000): + """ + Send `signal` event to events server. + + Will timeout after timeout ms if response has not been received. The + timeout arg is only used for asynch requests. If a reqcbk callback has + been supplied the timeout arg is not used. The response value will be + returned for a synch request but nothing will be returned for an asynch + request. + + :param signal: the signal that causes the callback to be launched + :type signal: int (see the `events.proto` file) + :param content: the contents of the event signal + :type content: str + :param mac_method: the method used for auth mac + :type mac_method: str + :param mac: the content of the auth mac + :type mac: str + :param reqcbk: a callback to be called when a response from server is + received + :type reqcbk: function + callback(leap.common.events.events_pb2.EventResponse) + :param timeout: the timeout for synch calls + :type timeout: int + + :return: the response from server for synch calls or nothing for asynch + calls. + :rtype: leap.common.events.events_pb2.EventsResponse or None + """ + request = proto.SignalRequest() + request.event = signal + request.content = content + request.mac_method = mac_method + request.mac = mac + service = RpcService(proto.EventsServerService_Stub, server.SERVER_PORT, + 'localhost') + logger.info("Sending signal to server: %s", str(request)[:40]) + return service.signal(request, callback=reqcbk, timeout=timeout) + + +class EventsClientService(proto.EventsClientService): + """ + Service for receiving signal events in clients. + """ + + def __init__(self): + proto.EventsClientService.__init__(self) + + def signal(self, controller, request, done): + """ + Receive a signal and run callbacks registered for that signal. + + This method is called whenever a signal request is received from + server. + + :param controller: used to mediate a single method call + :type controller: protobuf.socketrpc.controller.SocketRpcController + :param request: the request received from the client + :type request: leap.common.events.events_pb2.SignalRequest + :param done: callback to be called when done + :type done: protobuf.socketrpc.server.Callback + """ + logger.info('Received signal from server: %s...' % str(request)[:40]) + + # run registered callbacks + # TODO: verify authentication using mac in incoming message + if request.event in registered_callbacks: + for (_, cbk) in registered_callbacks[request.event]: + # callbacks should be prepared to receive a + # events_pb2.SignalRequest. + cbk(request) + + # send response back to server + response = proto.EventResponse() + response.status = proto.EventResponse.OK + done.run(response) + + +class EventsClientDaemon(daemon.EventsSingletonDaemon): + """ + A daemon that listens for incoming events from server. + """ + + @classmethod + def ensure(cls, port): + """ + Make sure the daemon is running on the given port. + + :param port: the port in which the daemon should listen + :type port: int + + :return: a daemon instance + :rtype: EventsClientDaemon + """ + return cls.ensure_service(port, EventsClientService()) diff --git a/src/leap/common/events/component.py b/src/leap/common/events/component.py deleted file mode 100644 index 029d1ac..0000000 --- a/src/leap/common/events/component.py +++ /dev/null @@ -1,290 +0,0 @@ -# -*- coding: utf-8 -*- -# component.py -# Copyright (C) 2013 LEAP -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -""" -The component end point of the events mechanism. - -Components are the communicating parties of the events mechanism. They -communicate by sending messages to a server, which in turn redistributes -messages to other components. - -When a component registers a callback for a given signal, it also tells the -server that it wants to be notified whenever signals of that type are sent by -some other component. -""" - - -import logging -import threading - - -from protobuf.socketrpc import RpcService -from leap.common.events import ( - events_pb2 as proto, - server, - daemon, - mac_auth, -) - - -logger = logging.getLogger(__name__) - - -# the `registered_callbacks` dictionary below should have the following -# format: -# -# { event_signal: [ (uid, callback), ... ], ... } -# -registered_callbacks = {} - - -class CallbackAlreadyRegistered(Exception): - """ - Raised when trying to register an already registered callback. - """ - pass - - -def ensure_component_daemon(): - """ - Ensure the component daemon is running and listening for incoming - messages. - - :return: the daemon instance - :rtype: EventsComponentDaemon - """ - import time - daemon = EventsComponentDaemon.ensure(0) - logger.debug('ensure component daemon') - - # Because we use a random port we want to wait until a port is assigned to - # local component daemon. - - while not (EventsComponentDaemon.get_instance() and - EventsComponentDaemon.get_instance().get_port()): - time.sleep(0.1) - return daemon - - -def register(signal, callback, uid=None, replace=False, reqcbk=None, - timeout=1000): - """ - Registers a callback to be called when a specific signal event is - received. - - Will timeout after timeout ms if response has not been received. The - timeout arg is only used for asynch requests. If a reqcbk callback has - been supplied the timeout arg is not used. The response value will be - returned for a synch request but nothing will be returned for an asynch - request. - - :param signal: the signal that causes the callback to be launched - :type signal: int (see the `events.proto` file) - :param callback: the callback to be called when the signal is received - :type callback: function - callback(leap.common.events.events_pb2.SignalRequest) - :param uid: a unique id for the callback - :type uid: int - :param replace: should an existent callback with same uid be replaced? - :type replace: bool - :param reqcbk: a callback to be called when a response from server is - received - :type reqcbk: function - callback(leap.common.events.events_pb2.EventResponse) - :param timeout: the timeout for synch calls - :type timeout: int - - Might raise a CallbackAlreadyRegistered exception if there's already a - callback identified by the given uid and replace is False. - - :return: the response from server for synch calls or nothing for asynch - calls. - :rtype: leap.common.events.events_pb2.EventsResponse or None - """ - ensure_component_daemon() # so we can receive registered signals - # register callback locally - if signal not in registered_callbacks: - registered_callbacks[signal] = [] - cbklist = registered_callbacks[signal] - if uid and filter(lambda (x, y): x == uid, cbklist): - if not replace: - raise CallbackAlreadyRegisteredException() - else: - registered_callbacks[signal] = filter(lambda(x, y): x != uid, - cbklist) - registered_callbacks[signal].append((uid, callback)) - # register callback on server - request = proto.RegisterRequest() - request.event = signal - request.port = EventsComponentDaemon.get_instance().get_port() - request.mac_method = mac_auth.MacMethod.MAC_NONE - request.mac = "" - service = RpcService(proto.EventsServerService_Stub, - server.SERVER_PORT, 'localhost') - logger.info( - "Sending registration request to server on port %s: %s", - server.SERVER_PORT, - str(request)[:40]) - return service.register(request, callback=reqcbk, timeout=timeout) - -def unregister(signal, uid=None, reqcbk=None, timeout=1000): - """ - Unregister a callback. - - If C{uid} is specified, unregisters only the callback identified by that - unique id. Otherwise, unregisters all callbacks - - :param signal: the signal that causes the callback to be launched - :type signal: int (see the `events.proto` file) - :param uid: a unique id for the callback - :type uid: int - :param reqcbk: a callback to be called when a response from server is - received - :type reqcbk: function - callback(leap.common.events.events_pb2.EventResponse) - :param timeout: the timeout for synch calls - :type timeout: int - - :return: the response from server for synch calls or nothing for asynch - calls or None if no callback is registered for that signal or uid. - :rtype: leap.common.events.events_pb2.EventsResponse or None - """ - if signal not in registered_callbacks or not registered_callbacks[signal]: - logger.warning("No callback registered for signal %d." % signal) - return None - # unregister callback locally - cbklist = registered_callbacks[signal] - if uid is not None: - if filter(lambda (cbkuid, _): cbkuid == uid, cbklist) == []: - logger.warning("No callback registered for uid %d." % st) - return None - registered_callbacks[signal] = filter(lambda(x, y): x != uid, cbklist) - else: - # exclude all callbacks for given signal - registered_callbacks[signal] = [] - # unregister port in server if there are no more callbacks for this signal - if not registered_callbacks[signal]: - request = proto.UnregisterRequest() - request.event = signal - request.port = EventsComponentDaemon.get_instance().get_port() - request.mac_method = mac_auth.MacMethod.MAC_NONE - request.mac = "" - service = RpcService(proto.EventsServerService_Stub, - server.SERVER_PORT, 'localhost') - logger.info( - "Sending unregistration request to server on port %s: %s", - server.SERVER_PORT, - str(request)[:40]) - return service.unregister(request, callback=reqcbk, timeout=timeout) - - -def signal(signal, content="", mac_method="", mac="", reqcbk=None, - timeout=1000): - """ - Send `signal` event to events server. - - Will timeout after timeout ms if response has not been received. The - timeout arg is only used for asynch requests. If a reqcbk callback has - been supplied the timeout arg is not used. The response value will be - returned for a synch request but nothing will be returned for an asynch - request. - - :param signal: the signal that causes the callback to be launched - :type signal: int (see the `events.proto` file) - :param content: the contents of the event signal - :type content: str - :param mac_method: the method used for auth mac - :type mac_method: str - :param mac: the content of the auth mac - :type mac: str - :param reqcbk: a callback to be called when a response from server is - received - :type reqcbk: function - callback(leap.common.events.events_pb2.EventResponse) - :param timeout: the timeout for synch calls - :type timeout: int - - :return: the response from server for synch calls or nothing for asynch - calls. - :rtype: leap.common.events.events_pb2.EventsResponse or None - """ - request = proto.SignalRequest() - request.event = signal - request.content = content - request.mac_method = mac_method - request.mac = mac - service = RpcService(proto.EventsServerService_Stub, server.SERVER_PORT, - 'localhost') - logger.info("Sending signal to server: %s", str(request)[:40]) - return service.signal(request, callback=reqcbk, timeout=timeout) - - -class EventsComponentService(proto.EventsComponentService): - """ - Service for receiving signal events in components. - """ - - def __init__(self): - proto.EventsComponentService.__init__(self) - - def signal(self, controller, request, done): - """ - Receive a signal and run callbacks registered for that signal. - - This method is called whenever a signal request is received from - server. - - :param controller: used to mediate a single method call - :type controller: protobuf.socketrpc.controller.SocketRpcController - :param request: the request received from the component - :type request: leap.common.events.events_pb2.SignalRequest - :param done: callback to be called when done - :type done: protobuf.socketrpc.server.Callback - """ - logger.info('Received signal from server: %s...' % str(request)[:40]) - - # run registered callbacks - # TODO: verify authentication using mac in incoming message - if request.event in registered_callbacks: - for (_, cbk) in registered_callbacks[request.event]: - # callbacks should be prepared to receive a - # events_pb2.SignalRequest. - cbk(request) - - # send response back to server - response = proto.EventResponse() - response.status = proto.EventResponse.OK - done.run(response) - - -class EventsComponentDaemon(daemon.EventsSingletonDaemon): - """ - A daemon that listens for incoming events from server. - """ - - @classmethod - def ensure(cls, port): - """ - Make sure the daemon is running on the given port. - - :param port: the port in which the daemon should listen - :type port: int - - :return: a daemon instance - :rtype: EventsComponentDaemon - """ - return cls.ensure_service(port, EventsComponentService()) diff --git a/src/leap/common/events/daemon.py b/src/leap/common/events/daemon.py index c253948..c4a4189 100644 --- a/src/leap/common/events/daemon.py +++ b/src/leap/common/events/daemon.py @@ -43,7 +43,7 @@ class ServiceAlreadyRunningException(Exception): class EventsRpcServer(SocketRpcServer): """ - RPC server used in server and component interfaces to receive messages. + RPC server used in server and client interfaces to receive messages. """ def __init__(self, port, host='localhost'): diff --git a/src/leap/common/events/events.proto b/src/leap/common/events/events.proto index a813ed1..79a5564 100644 --- a/src/leap/common/events/events.proto +++ b/src/leap/common/events/events.proto @@ -74,6 +74,6 @@ service EventsServerService { rpc signal(SignalRequest) returns (EventResponse); } -service EventsComponentService { +service EventsClientService { rpc signal(SignalRequest) returns (EventResponse); } diff --git a/src/leap/common/events/events_pb2.py b/src/leap/common/events/events_pb2.py index 5b1c118..3b39950 100644 --- a/src/leap/common/events/events_pb2.py +++ b/src/leap/common/events/events_pb2.py @@ -14,7 +14,7 @@ from google.protobuf import descriptor_pb2 DESCRIPTOR = _descriptor.FileDescriptor( name='events.proto', package='leap.common.events', - serialized_pb='\n\x0c\x65vents.proto\x12\x12leap.common.events\"\x97\x01\n\rSignalRequest\x12(\n\x05\x65vent\x18\x01 \x02(\x0e\x32\x19.leap.common.events.Event\x12\x0f\n\x07\x63ontent\x18\x02 \x02(\t\x12\x12\n\nmac_method\x18\x03 \x02(\t\x12\x0b\n\x03mac\x18\x04 \x02(\x0c\x12\x12\n\nenc_method\x18\x05 \x01(\t\x12\x16\n\x0e\x65rror_occurred\x18\x06 \x01(\x08\"j\n\x0fRegisterRequest\x12(\n\x05\x65vent\x18\x01 \x02(\x0e\x32\x19.leap.common.events.Event\x12\x0c\n\x04port\x18\x02 \x02(\x05\x12\x12\n\nmac_method\x18\x03 \x02(\t\x12\x0b\n\x03mac\x18\x04 \x02(\x0c\"l\n\x11UnregisterRequest\x12(\n\x05\x65vent\x18\x01 \x02(\x0e\x32\x19.leap.common.events.Event\x12\x0c\n\x04port\x18\x02 \x02(\x05\x12\x12\n\nmac_method\x18\x03 \x02(\t\x12\x0b\n\x03mac\x18\x04 \x02(\x0c\"\x82\x01\n\rEventResponse\x12\x38\n\x06status\x18\x01 \x02(\x0e\x32(.leap.common.events.EventResponse.Status\x12\x0e\n\x06result\x18\x02 \x01(\t\"\'\n\x06Status\x12\x06\n\x02OK\x10\x01\x12\n\n\x06UNAUTH\x10\x02\x12\t\n\x05\x45RROR\x10\x03*\xe7\x02\n\x05\x45vent\x12\x15\n\x11\x43LIENT_SESSION_ID\x10\x01\x12\x0e\n\nCLIENT_UID\x10\x02\x12\x19\n\x15SOLEDAD_CREATING_KEYS\x10\x03\x12\x1e\n\x1aSOLEDAD_DONE_CREATING_KEYS\x10\x04\x12\x1a\n\x16SOLEDAD_UPLOADING_KEYS\x10\x05\x12\x1f\n\x1bSOLEDAD_DONE_UPLOADING_KEYS\x10\x06\x12\x1c\n\x18SOLEDAD_DOWNLOADING_KEYS\x10\x07\x12!\n\x1dSOLEDAD_DONE_DOWNLOADING_KEYS\x10\x08\x12\x1c\n\x18SOLEDAD_NEW_DATA_TO_SYNC\x10\t\x12\x1a\n\x16SOLEDAD_DONE_DATA_SYNC\x10\n\x12\x17\n\x13UPDATER_NEW_UPDATES\x10\x0b\x12\x19\n\x15UPDATER_DONE_UPDATING\x10\x0c\x12\x10\n\x0cRAISE_WINDOW\x10\r2\x91\x02\n\x13\x45ventsServerService\x12R\n\x08register\x12#.leap.common.events.RegisterRequest\x1a!.leap.common.events.EventResponse\x12V\n\nunregister\x12%.leap.common.events.UnregisterRequest\x1a!.leap.common.events.EventResponse\x12N\n\x06signal\x12!.leap.common.events.SignalRequest\x1a!.leap.common.events.EventResponse2h\n\x16\x45ventsComponentService\x12N\n\x06signal\x12!.leap.common.events.SignalRequest\x1a!.leap.common.events.EventResponseB\x03\x90\x01\x01') + serialized_pb='\n\x0c\x65vents.proto\x12\x12leap.common.events\"\x97\x01\n\rSignalRequest\x12(\n\x05\x65vent\x18\x01 \x02(\x0e\x32\x19.leap.common.events.Event\x12\x0f\n\x07\x63ontent\x18\x02 \x02(\t\x12\x12\n\nmac_method\x18\x03 \x02(\t\x12\x0b\n\x03mac\x18\x04 \x02(\x0c\x12\x12\n\nenc_method\x18\x05 \x01(\t\x12\x16\n\x0e\x65rror_occurred\x18\x06 \x01(\x08\"j\n\x0fRegisterRequest\x12(\n\x05\x65vent\x18\x01 \x02(\x0e\x32\x19.leap.common.events.Event\x12\x0c\n\x04port\x18\x02 \x02(\x05\x12\x12\n\nmac_method\x18\x03 \x02(\t\x12\x0b\n\x03mac\x18\x04 \x02(\x0c\"l\n\x11UnregisterRequest\x12(\n\x05\x65vent\x18\x01 \x02(\x0e\x32\x19.leap.common.events.Event\x12\x0c\n\x04port\x18\x02 \x02(\x05\x12\x12\n\nmac_method\x18\x03 \x02(\t\x12\x0b\n\x03mac\x18\x04 \x02(\x0c\"\x82\x01\n\rEventResponse\x12\x38\n\x06status\x18\x01 \x02(\x0e\x32(.leap.common.events.EventResponse.Status\x12\x0e\n\x06result\x18\x02 \x01(\t\"\'\n\x06Status\x12\x06\n\x02OK\x10\x01\x12\n\n\x06UNAUTH\x10\x02\x12\t\n\x05\x45RROR\x10\x03*\xe7\x02\n\x05\x45vent\x12\x15\n\x11\x43LIENT_SESSION_ID\x10\x01\x12\x0e\n\nCLIENT_UID\x10\x02\x12\x19\n\x15SOLEDAD_CREATING_KEYS\x10\x03\x12\x1e\n\x1aSOLEDAD_DONE_CREATING_KEYS\x10\x04\x12\x1a\n\x16SOLEDAD_UPLOADING_KEYS\x10\x05\x12\x1f\n\x1bSOLEDAD_DONE_UPLOADING_KEYS\x10\x06\x12\x1c\n\x18SOLEDAD_DOWNLOADING_KEYS\x10\x07\x12!\n\x1dSOLEDAD_DONE_DOWNLOADING_KEYS\x10\x08\x12\x1c\n\x18SOLEDAD_NEW_DATA_TO_SYNC\x10\t\x12\x1a\n\x16SOLEDAD_DONE_DATA_SYNC\x10\n\x12\x17\n\x13UPDATER_NEW_UPDATES\x10\x0b\x12\x19\n\x15UPDATER_DONE_UPDATING\x10\x0c\x12\x10\n\x0cRAISE_WINDOW\x10\r2\x91\x02\n\x13\x45ventsServerService\x12R\n\x08register\x12#.leap.common.events.RegisterRequest\x1a!.leap.common.events.EventResponse\x12V\n\nunregister\x12%.leap.common.events.UnregisterRequest\x1a!.leap.common.events.EventResponse\x12N\n\x06signal\x12!.leap.common.events.SignalRequest\x1a!.leap.common.events.EventResponse2e\n\x13\x45ventsClientService\x12N\n\x06signal\x12!.leap.common.events.SignalRequest\x1a!.leap.common.events.EventResponseB\x03\x90\x01\x01') _EVENT = _descriptor.EnumDescriptor( name='Event', @@ -411,18 +411,18 @@ class EventsServerService_Stub(EventsServerService): DESCRIPTOR = _EVENTSSERVERSERVICE -_EVENTSCOMPONENTSERVICE = _descriptor.ServiceDescriptor( - name='EventsComponentService', - full_name='leap.common.events.EventsComponentService', +_EVENTSCLIENTSERVICE = _descriptor.ServiceDescriptor( + name='EventsClientService', + full_name='leap.common.events.EventsClientService', file=DESCRIPTOR, index=1, options=None, serialized_start=1179, - serialized_end=1283, + serialized_end=1280, methods=[ _descriptor.MethodDescriptor( name='signal', - full_name='leap.common.events.EventsComponentService.signal', + full_name='leap.common.events.EventsClientService.signal', index=0, containing_service=None, input_type=_SIGNALREQUEST, @@ -432,13 +432,13 @@ _EVENTSCOMPONENTSERVICE = _descriptor.ServiceDescriptor( ]) -class EventsComponentService(_service.Service): +class EventsClientService(_service.Service): __metaclass__ = service_reflection.GeneratedServiceType - DESCRIPTOR = _EVENTSCOMPONENTSERVICE + DESCRIPTOR = _EVENTSCLIENTSERVICE -class EventsComponentService_Stub(EventsComponentService): +class EventsClientService_Stub(EventsClientService): __metaclass__ = service_reflection.GeneratedServiceStubType - DESCRIPTOR = _EVENTSCOMPONENTSERVICE + DESCRIPTOR = _EVENTSCLIENTSERVICE # @@protoc_insertion_point(module_scope) diff --git a/src/leap/common/events/server.py b/src/leap/common/events/server.py index d53c218..8a0d4e5 100644 --- a/src/leap/common/events/server.py +++ b/src/leap/common/events/server.py @@ -17,12 +17,12 @@ """ A server for the events mechanism. -A server can receive different kinds of requests from components: +A server can receive different kinds of requests from clients: - 1. Registration request: store component port number to be notified when + 1. Registration request: store client port number to be notified when a specific signal arrives. - 2. Signal request: redistribute the signal to registered components. + 2. Signal request: redistribute the signal to registered clients. """ import logging import socket @@ -40,12 +40,12 @@ logger = logging.getLogger(__name__) SERVER_PORT = 8090 -# the `registered_components` dictionary below should have the following +# the `registered_clients` dictionary below should have the following # format: # # { event_signal: [ port, ... ], ... } # -registered_components = {} +registered_clients = {} def ensure_server(port=SERVER_PORT): @@ -74,26 +74,26 @@ def ensure_server(port=SERVER_PORT): class EventsServerService(proto.EventsServerService): """ - Service for receiving events in components. + Service for receiving events in clients. """ def register(self, controller, request, done): """ - Register a component port to be signaled when specific events come in. + Register a client port to be signaled when specific events come in. :param controller: used to mediate a single method call :type controller: protobuf.socketrpc.controller.SocketRpcController - :param request: the request received from the component + :param request: the request received from the client :type request: leap.common.events.events_pb2.RegisterRequest :param done: callback to be called when done :type done: protobuf.socketrpc.server.Callback """ logger.info("Received registration request: %s..." % str(request)[:40]) - # add component port to signal list - if request.event not in registered_components: - registered_components[request.event] = set([]) - registered_components[request.event].add(request.port) - # send response back to component + # add client port to signal list + if request.event not in registered_clients: + registered_clients[request.event] = set([]) + registered_clients[request.event].add(request.port) + # send response back to client logger.debug('sending response back') response = proto.EventResponse() @@ -102,56 +102,56 @@ class EventsServerService(proto.EventsServerService): def unregister(self, controller, request, done): """ - Unregister a component port so it will not be signaled when specific + Unregister a client port so it will not be signaled when specific events come in. :param controller: used to mediate a single method call :type controller: protobuf.socketrpc.controller.SocketRpcController - :param request: the request received from the component + :param request: the request received from the client :type request: leap.common.events.events_pb2.RegisterRequest :param done: callback to be called when done :type done: protobuf.socketrpc.server.Callback """ logger.info( "Received unregistration request: %s..." % str(request)[:40]) - # remove component port from signal list + # remove client port from signal list response = proto.EventResponse() - if request.event in registered_components: + if request.event in registered_clients: try: - registered_components[request.event].remove(request.port) + registered_clients[request.event].remove(request.port) response.status = proto.EventResponse.OK except KeyError: response.status = proto.EventsResponse.ERROR response.result = 'Port %d not registered.' % request.port - # send response back to component + # send response back to client logger.debug('sending response back') done.run(response) def signal(self, controller, request, done): """ - Perform an RPC call to signal all components registered to receive a + Perform an RPC call to signal all clients registered to receive a specific signal. :param controller: used to mediate a single method call :type controller: protobuf.socketrpc.controller.SocketRpcController - :param request: the request received from the component + :param request: the request received from the client :type request: leap.common.events.events_pb2.SignalRequest :param done: callback to be called when done :type done: protobuf.socketrpc.server.Callback """ - logger.info('Received signal from component: %s...', str(request)[:40]) - # send signal to all registered components + logger.info('Received signal from client: %s...', str(request)[:40]) + # send signal to all registered clients # TODO: verify signal auth - if request.event in registered_components: - for port in registered_components[request.event]: + if request.event in registered_clients: + for port in registered_clients[request.event]: def callback(req, resp): logger.info("Signal received by " + str(port)) - service = RpcService(proto.EventsComponentService_Stub, + service = RpcService(proto.EventsClientService_Stub, port, 'localhost') service.signal(request, callback=callback) - # send response back to component + # send response back to client response = proto.EventResponse() response.status = proto.EventResponse.OK done.run(response) diff --git a/src/leap/common/tests/test_events.py b/src/leap/common/tests/test_events.py index 7286bdc..687195f 100644 --- a/src/leap/common/tests/test_events.py +++ b/src/leap/common/tests/test_events.py @@ -22,7 +22,7 @@ from protobuf.socketrpc import RpcService from leap.common import events from leap.common.events import ( server, - component, + client, mac_auth, ) from leap.common.events.events_pb2 import ( @@ -51,7 +51,7 @@ class EventsTestCase(unittest.TestCase): @classmethod def setUpClass(cls): server.EventsServerDaemon.ensure(8090) - cls.callbacks = events.component.registered_callbacks + cls.callbacks = events.client.registered_callbacks @classmethod def tearDownClass(cls): @@ -62,8 +62,8 @@ class EventsTestCase(unittest.TestCase): super(EventsTestCase, self).setUp() def tearDown(self): - #events.component.registered_callbacks = {} - server.registered_components = {} + #events.client.registered_callbacks = {} + server.registered_clients = {} super(EventsTestCase, self).tearDown() def test_service_singleton(self): @@ -76,24 +76,24 @@ class EventsTestCase(unittest.TestCase): self.assertEqual(service1, service2, "Can't get singleton class for service.") - def test_component_register(self): + def test_client_register(self): """ - Ensure components can register callbacks. + Ensure clients can register callbacks. """ self.assertTrue(1 not in self.callbacks, 'There should should be no callback for this signal.') events.register(1, lambda x: True) self.assertTrue(1 in self.callbacks, - 'Could not register signal in local component.') + 'Could not register signal in local client.') events.register(2, lambda x: True) self.assertTrue(1 in self.callbacks, - 'Could not register signal in local component.') + 'Could not register signal in local client.') self.assertTrue(2 in self.callbacks, - 'Could not register signal in local component.') + 'Could not register signal in local client.') def test_register_signal_replace(self): """ - Make sure components can replace already registered callbacks. + Make sure clients can replace already registered callbacks. """ sig = 3 cbk = lambda x: True @@ -134,7 +134,7 @@ class EventsTestCase(unittest.TestCase): def test_events_server_service_register(self): """ - Ensure the server can register components to be signaled. + Ensure the server can register clients to be signaled. """ sig = 5 request = RegisterRequest() @@ -143,34 +143,34 @@ class EventsTestCase(unittest.TestCase): request.mac_method = mac_auth.MacMethod.MAC_NONE request.mac = "" service = RpcService(EventsServerService_Stub, port, 'localhost') - complist = server.registered_components + complist = server.registered_clients self.assertEqual({}, complist, 'There should be no registered_ports when ' 'server has just been created.') response = service.register(request, timeout=1000) self.assertTrue(sig in complist, "Signal not registered succesfully.") self.assertTrue(8091 in complist[sig], - 'Failed registering component port.') + 'Failed registering client port.') - def test_component_request_register(self): + def test_client_request_register(self): """ - Ensure components can register themselves with server. + Ensure clients can register themselves with server. """ sig = 6 - complist = server.registered_components + complist = server.registered_clients self.assertTrue(sig not in complist, - 'There should be no registered components for this ' + 'There should be no registered clients for this ' 'signal.') events.register(sig, lambda x: True) time.sleep(0.1) - port = component.EventsComponentDaemon.get_instance().get_port() - self.assertTrue(sig in complist, 'Failed registering component.') + port = client.EventsClientDaemon.get_instance().get_port() + self.assertTrue(sig in complist, 'Failed registering client.') self.assertTrue(port in complist[sig], - 'Failed registering component port.') + 'Failed registering client port.') - def test_component_receives_signal(self): + def test_client_receives_signal(self): """ - Ensure components can receive signals. + Ensure clients can receive signals. """ sig = 7 @@ -190,44 +190,44 @@ class EventsTestCase(unittest.TestCase): time.sleep(0.5) self.assertTrue(received, 'Did not receive signal back.') - def test_component_send_signal(self): + def test_client_send_signal(self): """ - Ensure components can send signals. + Ensure clients can send signals. """ sig = 8 response = events.signal(sig) self.assertTrue(response.status == response.OK, 'Received wrong response status when signaling.') - def test_component_unregister_all(self): + def test_client_unregister_all(self): """ - Test that the component can unregister all events for one signal. + Test that the client can unregister all events for one signal. """ sig = CLIENT_UID - complist = server.registered_components + complist = server.registered_clients events.register(sig, lambda x: True) events.register(sig, lambda x: True) time.sleep(0.1) events.unregister(sig) time.sleep(0.1) - port = component.EventsComponentDaemon.get_instance().get_port() + port = client.EventsClientDaemon.get_instance().get_port() self.assertFalse(bool(complist[sig])) self.assertTrue(port not in complist[sig]) - def test_component_unregister_by_uid(self): + def test_client_unregister_by_uid(self): """ - Test that the component can unregister an event by uid. + Test that the client can unregister an event by uid. """ sig = CLIENT_UID - complist = server.registered_components + complist = server.registered_clients events.register(sig, lambda x: True, uid='cbkuid') events.register(sig, lambda x: True, uid='cbkuid2') time.sleep(0.1) events.unregister(sig, uid='cbkuid') time.sleep(0.1) - port = component.EventsComponentDaemon.get_instance().get_port() + port = client.EventsClientDaemon.get_instance().get_port() self.assertTrue(sig in complist) self.assertTrue(len(complist[sig]) == 1) self.assertTrue( - component.registered_callbacks[sig].pop()[0] == 'cbkuid2') + client.registered_callbacks[sig].pop()[0] == 'cbkuid2') self.assertTrue(port in complist[sig]) -- cgit v1.2.3