diff options
author | Micah Anderson <micah@riseup.net> | 2013-08-13 14:25:57 -0400 |
---|---|---|
committer | Micah Anderson <micah@riseup.net> | 2013-08-13 14:27:01 -0400 |
commit | ddff9c2dda51fd28dcdc8e2db998d7254f69a41b (patch) | |
tree | b000723d9c7e54f0ac163e54f8d0d6fcd829209a /src/leap/common/events | |
parent | cc8dd1e7f3d64ae6d7d69ed08a4346bfabfe7b22 (diff) | |
parent | 0e721b1b47c3b94f6d4d6709e34b6b816f9fd810 (diff) |
Merge tag '0.3.0' into debian
Tag leap.common version 0.3.0
Diffstat (limited to 'src/leap/common/events')
-rw-r--r-- | src/leap/common/events/README.rst | 12 | ||||
-rw-r--r-- | src/leap/common/events/__init__.py | 128 | ||||
-rw-r--r-- | src/leap/common/events/client.py (renamed from src/leap/common/events/component.py) | 155 | ||||
-rw-r--r-- | src/leap/common/events/daemon.py | 2 | ||||
-rw-r--r-- | src/leap/common/events/events.proto | 44 | ||||
-rw-r--r-- | src/leap/common/events/events_pb2.py | 550 | ||||
-rw-r--r-- | src/leap/common/events/server.py | 132 |
7 files changed, 731 insertions, 292 deletions
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 9fc93ee..6eaf3d4 100644 --- a/src/leap/common/events/__init__.py +++ b/src/leap/common/events/__init__.py @@ -16,7 +16,58 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. """ -An events mechanism that allows for signaling of events between components. +This is an events mechanism that uses a server to allow for signaling of +events between clients. + +Application components should use the interface available in this file to +register callbacks to be executed upon receiving specific signals, and to send +signals to other components. + +To register a callback to be executed when a specific event is signaled, use +leap.common.events.register(): + +>>> from leap.common.events import register +>>> from leap.common.events.proto import CLIENT_UID +>>> register(CLIENT_UID, lambda req: do_something(req)) + +To signal an event, use leap.common.events.signal(): + +>>> from leap.common.events import signal +>>> from leap.common.events.proto import CLIENT_UID +>>> signal(CLIENT_UID) + + +NOTE ABOUT SYNC/ASYNC REQUESTS: + +Clients always communicate with the server, and never between themselves. +When a client registers a callback for an event, the callback is saved locally +in the client and the server stores the client socket port in a list +associated with that event. When a client signals an event, the server +forwards the signal to all registered client ports, and then each client +executes its callbacks associated with that event locally. + +Each RPC call from a client to the server is followed by a response from the +server to the client. Calls to register() and signal() (and all other RPC +calls) can be synchronous or asynchronous meaning if they will or not wait for +the server's response before returning. + +This mechanism was built on top of protobuf.socketrpc, and because of this RPC +calls are made synchronous or asynchronous in the following way: + + * If RPC calls receive a parameter called `reqcbk`, then the call is made + asynchronous. That means that: + + - an eventual `timeout` parameter is not used, + - the call returns immediatelly with value None, and + - the `reqcbk` callback is executed asynchronously upon the arrival of + a response from the server. + + * Otherwise, if the `reqcbk` parameter is None, then the call is made in a + synchronous manner: + + - if a response from server arrives within `timeout` milliseconds, the + RPC call returns it; + - otherwise, the call returns None. """ import logging @@ -24,9 +75,9 @@ import socket from leap.common.events import ( - events_pb2, + events_pb2 as proto, server, - component, + client, daemon, ) @@ -54,17 +105,40 @@ def register(signal, callback, uid=None, replace=False, reqcbk=None, :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) + received + :type reqcbk: function(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 + """ + return client.register(signal, callback, uid, replace, reqcbk, 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 registered for C{signal}. + + :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(proto.UnregisterRequest, proto.EventResponse) :param timeout: the timeout for synch calls :type timeout: int :return: the response from server for synch calls or nothing for asynch - calls + calls. :rtype: leap.common.events.events_pb2.EventsResponse or None """ - return component.register(signal, callback, uid, replace, reqcbk, timeout) + return client.unregister(signal, uid, reqcbk, timeout) def signal(signal, content="", mac_method="", mac="", reqcbk=None, @@ -87,14 +161,42 @@ def signal(signal, content="", mac_method="", mac="", reqcbk=None, :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) + received + :type reqcbk: function(proto.SignalRequest, proto.EventResponse) :param timeout: the timeout for synch calls :type timeout: int :return: the response from server for synch calls or nothing for asynch - calls + 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) + +def ping_client(port, reqcbk=None, timeout=1000): + """ + Ping a client running in C{port}. + + :param port: the port in which the client should be listening + :type port: int + :param reqcbk: a callback to be called when a response from client is + received + :type reqcbk: function(proto.PingRequest, proto.EventResponse) + :param timeout: the timeout for synch calls + :type timeout: int + """ + return client.ping(port, reqcbk=reqcbk, timeout=timeout) + + +def ping_server(port=server.SERVER_PORT, reqcbk=None, timeout=1000): + """ + Ping the server. + + :param port: the port in which server should be listening + :type port: int + :param reqcbk: a callback to be called when a response from server is + received + :type reqcbk: function(proto.PingRequest, proto.EventResponse) + :param timeout: the timeout for synch calls + :type timeout: int + """ + return server.ping(port, reqcbk=reqcbk, timeout=timeout) diff --git a/src/leap/common/events/component.py b/src/leap/common/events/client.py index 9932190..4ae9bff 100644 --- a/src/leap/common/events/component.py +++ b/src/leap/common/events/client.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# component.py +# client.py # Copyright (C) 2013 LEAP # # This program is free software: you can redistribute it and/or modify @@ -16,15 +16,15 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. """ -The component end point of the events mechanism. +The client end point of the events mechanism. -Components are the communicating parties of the events mechanism. They +Clients are the communicating parties of the events mechanism. They communicate by sending messages to a server, which in turn redistributes -messages to other components. +messages to other clients. -When a component registers a callback for a given signal, it also tells the +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 component. +some other client. """ @@ -56,25 +56,26 @@ class CallbackAlreadyRegistered(Exception): """ Raised when trying to register an already registered callback. """ + pass -def ensure_component_daemon(): +def ensure_client_daemon(): """ - Ensure the component daemon is running and listening for incoming + Ensure the client daemon is running and listening for incoming messages. :return: the daemon instance - :rtype: EventsComponentDaemon + :rtype: EventsClientDaemon """ import time - daemon = EventsComponentDaemon.ensure(0) - logger.debug('ensure component daemon') + 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 component daemon. + # local client daemon. - while not (EventsComponentDaemon.get_instance() and - EventsComponentDaemon.get_instance().get_port()): + while not (EventsClientDaemon.get_instance() and + EventsClientDaemon.get_instance().get_port()): time.sleep(0.1) return daemon @@ -94,16 +95,14 @@ def register(signal, callback, uid=None, replace=False, reqcbk=None, :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) + :type callback: function(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) + received + :type reqcbk: function(proto.RegisterRequest, proto.EventResponse) :param timeout: the timeout for synch calls :type timeout: int @@ -111,10 +110,10 @@ def register(signal, callback, uid=None, replace=False, reqcbk=None, callback identified by the given uid and replace is False. :return: the response from server for synch calls or nothing for asynch - calls + calls. :rtype: leap.common.events.events_pb2.EventsResponse or None """ - ensure_component_daemon() # so we can receive registered signals + ensure_client_daemon() # so we can receive registered signals # register callback locally if signal not in registered_callbacks: registered_callbacks[signal] = [] @@ -129,7 +128,7 @@ def register(signal, callback, uid=None, replace=False, reqcbk=None, # register callback on server request = proto.RegisterRequest() request.event = signal - request.port = EventsComponentDaemon.get_instance().get_port() + request.port = EventsClientDaemon.get_instance().get_port() request.mac_method = mac_auth.MacMethod.MAC_NONE request.mac = "" service = RpcService(proto.EventsServerService_Stub, @@ -140,6 +139,56 @@ def register(signal, callback, uid=None, replace=False, reqcbk=None, 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(proto.UnregisterRequest, proto.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): @@ -161,14 +210,13 @@ def signal(signal, content="", mac_method="", mac="", reqcbk=None, :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) + received + :type reqcbk: function(proto.SignalRequest, proto.EventResponse) :param timeout: the timeout for synch calls :type timeout: int :return: the response from server for synch calls or nothing for asynch - calls + calls. :rtype: leap.common.events.events_pb2.EventsResponse or None """ request = proto.SignalRequest() @@ -182,13 +230,38 @@ def signal(signal, content="", mac_method="", mac="", reqcbk=None, return service.signal(request, callback=reqcbk, timeout=timeout) -class EventsComponentService(proto.EventsComponentService): +def ping(port, reqcbk=None, timeout=1000): """ - Service for receiving signal events in components. + Ping a client running in C{port}. + + :param port: the port in which the client should be listening + :type port: int + :param reqcbk: a callback to be called when a response from client is + received + :type reqcbk: function(proto.PingRequest, proto.EventResponse) + :param timeout: the timeout for synch calls + :type timeout: int + + :return: the response from client for synch calls or nothing for asynch + calls. + :rtype: leap.common.events.events_pb2.EventsResponse or None + """ + request = proto.PingRequest() + service = RpcService( + proto.EventsClientService_Stub, + port, + 'localhost') + logger.info("Pinging a client in port %d..." % port) + return service.ping(request, callback=reqcbk, timeout=timeout) + + +class EventsClientService(proto.EventsClientService): + """ + Service for receiving signal events in clients. """ def __init__(self): - proto.EventsComponentService.__init__(self) + proto.EventsClientService.__init__(self) def signal(self, controller, request, done): """ @@ -199,7 +272,7 @@ class EventsComponentService(proto.EventsComponentService): :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 @@ -219,8 +292,24 @@ class EventsComponentService(proto.EventsComponentService): response.status = proto.EventResponse.OK done.run(response) + def ping(self, controller, request, done): + """ + Reply to a ping request. + + :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.RegisterRequest + :param done: callback to be called when done + :type done: protobuf.socketrpc.server.Callback + """ + logger.info("Received ping request, sending response.") + response = proto.EventResponse() + response.status = proto.EventResponse.OK + done.run(response) + -class EventsComponentDaemon(daemon.EventsSingletonDaemon): +class EventsClientDaemon(daemon.EventsSingletonDaemon): """ A daemon that listens for incoming events from server. """ @@ -234,6 +323,6 @@ class EventsComponentDaemon(daemon.EventsSingletonDaemon): :type port: int :return: a daemon instance - :rtype: EventsComponentDaemon + :rtype: EventsClientDaemon """ - return cls.ensure_service(port, EventsComponentService()) + return cls.ensure_service(port, EventsClientService()) 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 447b038..b844f42 100644 --- a/src/leap/common/events/events.proto +++ b/src/leap/common/events/events.proto @@ -17,6 +17,9 @@ package leap.common.events; option py_generic_services = true; + +// These are the events that can be signaled using the events mechanism. + enum Event { CLIENT_SESSION_ID = 1; CLIENT_UID = 2; @@ -33,6 +36,10 @@ enum Event { RAISE_WINDOW = 13; } + +// A SignalRequest is the type of the message sent from one component to request +// that a signal be sent to every registered component. + message SignalRequest { required Event event = 1; required string content = 2; @@ -42,6 +49,10 @@ message SignalRequest { optional bool error_occurred = 6; } + +// A RegisterRequest message tells the server that a component wants to +// be signaled whenever a specific event occurs. + message RegisterRequest { required Event event = 1; required int32 port = 2; @@ -49,6 +60,28 @@ message RegisterRequest { required bytes mac = 4; } + +// An UnregisterRequest message tells the server that a component does not +// want to be signaled when a specific event occurs. + +message UnregisterRequest { + required Event event = 1; + required int32 port = 2; + required string mac_method = 3; + required bytes mac = 4; +} + + +// A PingRequest message is used to find out if a server or component is +// alive. + +message PingRequest { +} + + +// The EventResponse is the message sent back by server and components after +// they receive other kinds of requests. + message EventResponse { enum Status { @@ -61,11 +94,20 @@ message EventResponse { optional string result = 2; } + +// The EventsServerService is the service provided by the server. + service EventsServerService { + rpc ping(PingRequest) returns (EventResponse); rpc register(RegisterRequest) returns (EventResponse); + rpc unregister(UnregisterRequest) returns (EventResponse); rpc signal(SignalRequest) returns (EventResponse); } -service EventsComponentService { + +// EventsComponentService is the service provided by components (clients). + +service EventsClientService { + rpc ping(PingRequest) returns (EventResponse); rpc signal(SignalRequest) returns (EventResponse); } diff --git a/src/leap/common/events/events_pb2.py b/src/leap/common/events/events_pb2.py index a4f1df4..274514c 100644 --- a/src/leap/common/events/events_pb2.py +++ b/src/leap/common/events/events_pb2.py @@ -1,85 +1,87 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! +# source: events.proto -from google.protobuf import descriptor -from google.protobuf import message -from google.protobuf import reflection -from google.protobuf import service +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import service as _service from google.protobuf import service_reflection from google.protobuf import descriptor_pb2 # @@protoc_insertion_point(imports) -DESCRIPTOR = descriptor.FileDescriptor( +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\"\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\xb9\x01\n\x13\x45ventsServerService\x12R\n\x08register\x12#.leap.common.events.RegisterRequest\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\"\r\n\x0bPingRequest\"\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\xdd\x02\n\x13\x45ventsServerService\x12J\n\x04ping\x12\x1f.leap.common.events.PingRequest\x1a!.leap.common.events.EventResponse\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.EventResponse2\xb1\x01\n\x13\x45ventsClientService\x12J\n\x04ping\x12\x1f.leap.common.events.PingRequest\x1a!.leap.common.events.EventResponse\x12N\n\x06signal\x12!.leap.common.events.SignalRequest\x1a!.leap.common.events.EventResponseB\x03\x90\x01\x01') -_EVENT = descriptor.EnumDescriptor( +_EVENT = _descriptor.EnumDescriptor( name='Event', full_name='leap.common.events.Event', filename=None, file=DESCRIPTOR, values=[ - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CLIENT_SESSION_ID', index=0, number=1, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='CLIENT_UID', index=1, number=2, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='SOLEDAD_CREATING_KEYS', index=2, number=3, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='SOLEDAD_DONE_CREATING_KEYS', index=3, number=4, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='SOLEDAD_UPLOADING_KEYS', index=4, number=5, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='SOLEDAD_DONE_UPLOADING_KEYS', index=5, number=6, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='SOLEDAD_DOWNLOADING_KEYS', index=6, number=7, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='SOLEDAD_DONE_DOWNLOADING_KEYS', index=7, number=8, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='SOLEDAD_NEW_DATA_TO_SYNC', index=8, number=9, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='SOLEDAD_DONE_DATA_SYNC', index=9, number=10, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='UPDATER_NEW_UPDATES', index=10, number=11, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='UPDATER_DONE_UPDATING', index=11, number=12, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='RAISE_WINDOW', index=12, number=13, options=None, type=None), ], containing_type=None, options=None, - serialized_start=432, - serialized_end=791, + serialized_start=557, + serialized_end=916, ) - +Event = enum_type_wrapper.EnumTypeWrapper(_EVENT) CLIENT_SESSION_ID = 1 CLIENT_UID = 2 SOLEDAD_CREATING_KEYS = 3 @@ -95,240 +97,349 @@ UPDATER_DONE_UPDATING = 12 RAISE_WINDOW = 13 -_EVENTRESPONSE_STATUS = descriptor.EnumDescriptor( +_EVENTRESPONSE_STATUS = _descriptor.EnumDescriptor( name='Status', full_name='leap.common.events.EventResponse.Status', filename=None, file=DESCRIPTOR, values=[ - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='OK', index=0, number=1, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='UNAUTH', index=1, number=2, options=None, type=None), - descriptor.EnumValueDescriptor( + _descriptor.EnumValueDescriptor( name='ERROR', index=2, number=3, options=None, type=None), ], containing_type=None, options=None, - serialized_start=390, - serialized_end=429, + serialized_start=515, + serialized_end=554, ) -_SIGNALREQUEST = descriptor.Descriptor( +_SIGNALREQUEST = _descriptor.Descriptor( name='SignalRequest', full_name='leap.common.events.SignalRequest', filename=None, file=DESCRIPTOR, containing_type=None, fields=[ - descriptor.FieldDescriptor( + _descriptor.FieldDescriptor( name='event', full_name='leap.common.events.SignalRequest.event', index=0, number=1, type=14, cpp_type=8, label=2, has_default_value=False, default_value=1, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None), - descriptor.FieldDescriptor( - name='content', full_name='leap.common.events.SignalRequest.content', index=1, - number=2, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None), - descriptor.FieldDescriptor( - name='mac_method', full_name='leap.common.events.SignalRequest.mac_method', index=2, - number=3, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None), - descriptor.FieldDescriptor( - name='mac', full_name='leap.common.events.SignalRequest.mac', index=3, - number=4, type=12, cpp_type=9, label=2, - has_default_value=False, default_value="", - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None), - descriptor.FieldDescriptor( - name='enc_method', full_name='leap.common.events.SignalRequest.enc_method', index=4, - number=5, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None), - descriptor.FieldDescriptor( - name='error_occurred', full_name='leap.common.events.SignalRequest.error_occurred', index=5, - number=6, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - options=None, - is_extendable=False, - extension_ranges=[], - serialized_start=37, - serialized_end=188, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='content', full_name='leap.common.events.SignalRequest.content', index=1, + number=2, type=9, cpp_type=9, label=2, + has_default_value=False, default_value=unicode("", "utf-8"), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='mac_method', full_name='leap.common.events.SignalRequest.mac_method', index=2, + number=3, type=9, cpp_type=9, label=2, + has_default_value=False, default_value=unicode("", "utf-8"), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='mac', full_name='leap.common.events.SignalRequest.mac', index=3, + number=4, type=12, cpp_type=9, label=2, + has_default_value=False, default_value="", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='enc_method', full_name='leap.common.events.SignalRequest.enc_method', index=4, + number=5, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=unicode("", "utf-8"), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='error_occurred', full_name='leap.common.events.SignalRequest.error_occurred', index=5, + number=6, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + extension_ranges=[], + serialized_start=37, + serialized_end=188, +) + + +_REGISTERREQUEST = _descriptor.Descriptor( + name='RegisterRequest', + full_name='leap.common.events.RegisterRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='event', full_name='leap.common.events.RegisterRequest.event', index=0, + number=1, type=14, cpp_type=8, label=2, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='port', full_name='leap.common.events.RegisterRequest.port', index=1, + number=2, type=5, cpp_type=1, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='mac_method', full_name='leap.common.events.RegisterRequest.mac_method', index=2, + number=3, type=9, cpp_type=9, label=2, + has_default_value=False, default_value=unicode("", "utf-8"), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='mac', full_name='leap.common.events.RegisterRequest.mac', index=3, + number=4, type=12, cpp_type=9, label=2, + has_default_value=False, default_value="", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + extension_ranges=[], + serialized_start=190, + serialized_end=296, +) + + +_UNREGISTERREQUEST = _descriptor.Descriptor( + name='UnregisterRequest', + full_name='leap.common.events.UnregisterRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='event', full_name='leap.common.events.UnregisterRequest.event', index=0, + number=1, type=14, cpp_type=8, label=2, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='port', full_name='leap.common.events.UnregisterRequest.port', index=1, + number=2, type=5, cpp_type=1, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='mac_method', full_name='leap.common.events.UnregisterRequest.mac_method', index=2, + number=3, type=9, cpp_type=9, label=2, + has_default_value=False, default_value=unicode("", "utf-8"), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='mac', full_name='leap.common.events.UnregisterRequest.mac', index=3, + number=4, type=12, cpp_type=9, label=2, + has_default_value=False, default_value="", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + extension_ranges=[], + serialized_start=298, + serialized_end=406, ) -_REGISTERREQUEST = descriptor.Descriptor( - name='RegisterRequest', - full_name='leap.common.events.RegisterRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - descriptor.FieldDescriptor( - name='event', full_name='leap.common.events.RegisterRequest.event', index=0, - number=1, type=14, cpp_type=8, label=2, - has_default_value=False, default_value=1, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None), - descriptor.FieldDescriptor( - name='port', full_name='leap.common.events.RegisterRequest.port', index=1, - number=2, type=5, cpp_type=1, label=2, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None), - descriptor.FieldDescriptor( - name='mac_method', full_name='leap.common.events.RegisterRequest.mac_method', index=2, - number=3, type=9, cpp_type=9, label=2, - has_default_value=False, default_value=unicode("", "utf-8"), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None), - descriptor.FieldDescriptor( - name='mac', full_name='leap.common.events.RegisterRequest.mac', index=3, - number=4, type=12, cpp_type=9, label=2, - has_default_value=False, default_value="", - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - options=None, - is_extendable=False, - extension_ranges=[], - serialized_start=190, - serialized_end=296, +_PINGREQUEST = _descriptor.Descriptor( + name='PingRequest', + full_name='leap.common.events.PingRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + extension_ranges=[], + serialized_start=408, + serialized_end=421, ) -_EVENTRESPONSE = descriptor.Descriptor( - name='EventResponse', - full_name='leap.common.events.EventResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - descriptor.FieldDescriptor( - name='status', full_name='leap.common.events.EventResponse.status', index=0, - number=1, type=14, cpp_type=8, label=2, - has_default_value=False, default_value=1, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None), - descriptor.FieldDescriptor( - name='result', full_name='leap.common.events.EventResponse.result', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=unicode("", "utf-8"), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - _EVENTRESPONSE_STATUS, - ], - options=None, - is_extendable=False, - extension_ranges=[], - serialized_start=299, - serialized_end=429, +_EVENTRESPONSE = _descriptor.Descriptor( + name='EventResponse', + full_name='leap.common.events.EventResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='status', full_name='leap.common.events.EventResponse.status', index=0, + number=1, type=14, cpp_type=8, label=2, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + _descriptor.FieldDescriptor( + name='result', full_name='leap.common.events.EventResponse.result', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=unicode("", "utf-8"), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _EVENTRESPONSE_STATUS, + ], + options=None, + is_extendable=False, + extension_ranges=[], + serialized_start=424, + serialized_end=554, ) _SIGNALREQUEST.fields_by_name['event'].enum_type = _EVENT _REGISTERREQUEST.fields_by_name['event'].enum_type = _EVENT +_UNREGISTERREQUEST.fields_by_name['event'].enum_type = _EVENT _EVENTRESPONSE.fields_by_name['status'].enum_type = _EVENTRESPONSE_STATUS -_EVENTRESPONSE_STATUS.containing_type = _EVENTRESPONSE; +_EVENTRESPONSE_STATUS.containing_type = _EVENTRESPONSE DESCRIPTOR.message_types_by_name['SignalRequest'] = _SIGNALREQUEST DESCRIPTOR.message_types_by_name['RegisterRequest'] = _REGISTERREQUEST +DESCRIPTOR.message_types_by_name['UnregisterRequest'] = _UNREGISTERREQUEST +DESCRIPTOR.message_types_by_name['PingRequest'] = _PINGREQUEST DESCRIPTOR.message_types_by_name['EventResponse'] = _EVENTRESPONSE -class SignalRequest(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType +class SignalRequest(_message.Message): + __metaclass__ = _reflection.GeneratedProtocolMessageType DESCRIPTOR = _SIGNALREQUEST # @@protoc_insertion_point(class_scope:leap.common.events.SignalRequest) -class RegisterRequest(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType +class RegisterRequest(_message.Message): + __metaclass__ = _reflection.GeneratedProtocolMessageType DESCRIPTOR = _REGISTERREQUEST # @@protoc_insertion_point(class_scope:leap.common.events.RegisterRequest) -class EventResponse(message.Message): - __metaclass__ = reflection.GeneratedProtocolMessageType +class UnregisterRequest(_message.Message): + __metaclass__ = _reflection.GeneratedProtocolMessageType + DESCRIPTOR = _UNREGISTERREQUEST + + # @@protoc_insertion_point(class_scope:leap.common.events.UnregisterRequest) + + +class PingRequest(_message.Message): + __metaclass__ = _reflection.GeneratedProtocolMessageType + DESCRIPTOR = _PINGREQUEST + + # @@protoc_insertion_point(class_scope:leap.common.events.PingRequest) + + +class EventResponse(_message.Message): + __metaclass__ = _reflection.GeneratedProtocolMessageType DESCRIPTOR = _EVENTRESPONSE # @@protoc_insertion_point(class_scope:leap.common.events.EventResponse) -_EVENTSSERVERSERVICE = descriptor.ServiceDescriptor( - name='EventsServerService', - full_name='leap.common.events.EventsServerService', - file=DESCRIPTOR, - index=0, - options=None, - serialized_start=794, - serialized_end=979, - methods=[ - descriptor.MethodDescriptor( - name='register', - full_name='leap.common.events.EventsServerService.register', +DESCRIPTOR.has_options = True +DESCRIPTOR._options = _descriptor._ParseOptions( + descriptor_pb2.FileOptions(), '\220\001\001') + +_EVENTSSERVERSERVICE = _descriptor.ServiceDescriptor( + name='EventsServerService', + full_name='leap.common.events.EventsServerService', + file=DESCRIPTOR, index=0, - containing_service=None, - input_type=_REGISTERREQUEST, - output_type=_EVENTRESPONSE, - options=None, - ), - descriptor.MethodDescriptor( - name='signal', - full_name='leap.common.events.EventsServerService.signal', - index=1, - containing_service=None, - input_type=_SIGNALREQUEST, - output_type=_EVENTRESPONSE, options=None, - ), -]) + serialized_start=919, + serialized_end=1268, + methods=[ + _descriptor.MethodDescriptor( + name='ping', + full_name='leap.common.events.EventsServerService.ping', + index=0, + containing_service=None, + input_type=_PINGREQUEST, + output_type=_EVENTRESPONSE, + options=None, + ), + _descriptor.MethodDescriptor( + name='register', + full_name='leap.common.events.EventsServerService.register', + index=1, + containing_service=None, + input_type=_REGISTERREQUEST, + output_type=_EVENTRESPONSE, + options=None, + ), + _descriptor.MethodDescriptor( + name='unregister', + full_name='leap.common.events.EventsServerService.unregister', + index=2, + containing_service=None, + input_type=_UNREGISTERREQUEST, + output_type=_EVENTRESPONSE, + options=None, + ), + _descriptor.MethodDescriptor( + name='signal', + full_name='leap.common.events.EventsServerService.signal', + index=3, + containing_service=None, + input_type=_SIGNALREQUEST, + output_type=_EVENTRESPONSE, + options=None, + ), + ]) -class EventsServerService(service.Service): +class EventsServerService(_service.Service): __metaclass__ = service_reflection.GeneratedServiceType DESCRIPTOR = _EVENTSSERVERSERVICE @@ -338,34 +449,43 @@ class EventsServerService_Stub(EventsServerService): DESCRIPTOR = _EVENTSSERVERSERVICE -_EVENTSCOMPONENTSERVICE = descriptor.ServiceDescriptor( - name='EventsComponentService', - full_name='leap.common.events.EventsComponentService', - file=DESCRIPTOR, - index=1, - options=None, - serialized_start=981, - serialized_end=1085, - methods=[ - descriptor.MethodDescriptor( - name='signal', - full_name='leap.common.events.EventsComponentService.signal', - index=0, - containing_service=None, - input_type=_SIGNALREQUEST, - output_type=_EVENTRESPONSE, +_EVENTSCLIENTSERVICE = _descriptor.ServiceDescriptor( + name='EventsClientService', + full_name='leap.common.events.EventsClientService', + file=DESCRIPTOR, + index=1, options=None, - ), -]) + serialized_start=1271, + serialized_end=1448, + methods=[ + _descriptor.MethodDescriptor( + name='ping', + full_name='leap.common.events.EventsClientService.ping', + index=0, + containing_service=None, + input_type=_PINGREQUEST, + output_type=_EVENTRESPONSE, + options=None, + ), + _descriptor.MethodDescriptor( + name='signal', + full_name='leap.common.events.EventsClientService.signal', + index=1, + containing_service=None, + input_type=_SIGNALREQUEST, + output_type=_EVENTRESPONSE, + options=None, + ), + ]) -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 1f3a874..59f3454 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,19 @@ 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 = {} + + +class PortAlreadyTaken(Exception): + """ + Raised when trying to open a server in a port that is already taken. + """ + pass def ensure_server(port=SERVER_PORT): @@ -60,71 +67,150 @@ def ensure_server(port=SERVER_PORT): :return: the daemon instance or nothing :rtype: EventsServerDaemon or None + + :raise PortAlreadyTaken: Raised if C{port} is already taken by something + that is not an events server. """ try: + # check if port is available s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('localhost', port)) s.close() - logger.info('Server is already running on port %d.', port) - return None + # port is taken, check if there's a server running there + response = ping(port) + if response is not None and response.status == proto.EventResponse.OK: + logger.info('A server is already running on port %d.', port) + return None + # port is taken, and not by an events server + logger.info('Port %d is taken by something not an events server.', port) + raise PortAlreadyTaken(port) except socket.error: + # port is available, run a server logger.info('Launching server on port %d.', port) return EventsServerDaemon.ensure(port) +def ping(port=SERVER_PORT, reqcbk=None, timeout=1000): + """ + Ping the server. + + :param port: the port in which server should be listening + :type port: int + :param reqcbk: a callback to be called when a response from server is + received + :type reqcbk: function(proto.PingRequest, proto.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.PingRequest() + service = RpcService( + proto.EventsServerService_Stub, + port, + 'localhost') + logger.info("Pinging server in port %d..." % port) + return service.ping(request, callback=reqcbk, timeout=timeout) + + 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() response.status = proto.EventResponse.OK done.run(response) + def unregister(self, controller, request, done): + """ + 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 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 client port from signal list + response = proto.EventResponse() + if request.event in registered_clients: + try: + 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 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) + + def ping(self, controller, request, done): + """ + Reply to a ping request. + + :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.RegisterRequest + :param done: callback to be called when done + :type done: protobuf.socketrpc.server.Callback + """ + logger.info("Received ping request, sending response.") response = proto.EventResponse() response.status = proto.EventResponse.OK done.run(response) |