def test_emit_return(): ee = EventEmitter() # make sure emission without callback retruns False nt.assert_false(ee.emit('data')) # add a callback ee.on('data')(lambda: None) # should return true now nt.assert_true(ee.emit('data'))
class InterceptEmitter(object): """ This class intercepts and allows emitting events between the skill_tester and the skill being tested. When a test is running emitted communication is intercepted for analysis """ def __init__(self): self.emitter = EventEmitter() self.q = None def on(self, event, f): # run all events print("Event: ", event) self.emitter.on(event, f) def emit(self, event, *args, **kwargs): event_name = event.type if self.q: self.q.put(event) self.emitter.emit(event_name, event, *args, **kwargs) def once(self, event, f): self.emitter.once(event, f) def remove(self, event_name, func): pass def remove_all_listeners(self, event_name): pass
class DummyEmitter(object): """Dummy emitter for testing.""" __emitter = None def __init__(self): """ctor.""" self.__emitter = EventEmitter() def on(self, evt, callback): """Register event handler.""" self.__emitter.on(evt, callback) def emit(self, evt, args): """Fire event.""" self.__emitter.emit(evt, args) def on_pin_state_change(self, psce): """Fire the pin state change event.""" self.emit("gpioStateChanged", psce) def trigger_event(self): """Trigger the state change event.""" pin_address = gpio_pins.Gpio01.value old_state = pin_state.LOW new_state = pin_state.HIGH evt = PinStateChangeEvent(old_state, new_state, pin_address) self.on_pin_state_change(evt)
class Camera() running = True def __init__(self,fps=24): self.emitter = EventEmitter() self.fps = fps self.cap = cv2.VideoCapture(0) self.thread = threading.Thread(target=self.run) self.thread.daemon = True self.thread.start() def run(self): capturePeriodSecs = 1.0 / self.fps while self.Running == True: try: self.cap_frame() except Exception as error: print ("error with capturing frames: ", error) time.sleep(capturePeriodSecs) def onNewFrame(self,callback): self.emitter.on('frame', callback) def removeOnNewFrameListener(self,callback): self.emitter.remove_emitter_listener('frame', callback) def stop(self): self.running = False def cap_frame(self): f,img = self.cap.read() self.latest_frame = img self.emitter.emit('frame', img)
class PendingPacket(): def __init__(self, packet, packet_sender): print 'Init PendingPacket' self.ee = EventEmitter() self._packet_sender = packet_sender self._packet = packet def send(self): def packet_send(): self._packetSender.send(self._packet) self._intervalID = helpers.set_interval( packet_send, constants.TIMEOUT ) self._packet_sender.send(self._packet) def get_sequence_number(self): return self._packet.get_sequence_number() def acknowledge(self): self._intervalID.cancel() self.ee.emit('acknowledge')
class Runner(object): def __init__(self, client, make_request): self.client = client self.make_request = make_request self._pending = [] self.events = EventEmitter() def _on_request_finished(self, _): """ Start the next waiting request if possible. """ if len(self.client.active) < self.client.max_clients: self._start_request() def _start_request(self): """ Start a request and add callbacks to its future. Most notably, the completion of the requests's future will also trigger the completion of a future we had prepared earlier. """ request = self.make_request(streaming_callback=lambda c: None) future = concurrent.Future() self.events.emit("request_ready", future, request) self.client.fetch(request, callback=future.set_result) self.events.emit("request_started", future) self._pending.append(future) future.add_done_callback(lambda f: self.events.emit("request_finished", f)) future.add_done_callback(self._pending.remove) future.add_done_callback(self._on_request_finished)
def test_listener_removal_on_emit(): """Test that a listener removed during an emit is called inside the current emit cycle. """ call_me = Mock() ee = EventEmitter() def should_remove(): ee.remove_listener('remove', call_me) ee.on('remove', should_remove) ee.on('remove', call_me) ee.emit('remove') call_me.assert_called_once() call_me.reset_mock() # Also test with the listeners added in the opposite order ee = EventEmitter() ee.on('remove', call_me) ee.on('remove', should_remove) ee.emit('remove') call_me.assert_called_once()
async def test_asyncio_error(event_loop): """Test that event_emitters can handle errors when wrapping coroutines as used with asyncio. """ ee = EventEmitter(loop=event_loop) should_call = Future(loop=event_loop) @ee.on('event') async def event_handler(): raise PyeeTestError() @ee.on('error') def handle_error(exc): assert isinstance(exc, PyeeTestError) should_call.set_result(exc) async def create_timeout(loop=event_loop): await sleep(0.1, loop=event_loop) if not should_call.done(): raise Exception('should_call timed out!') return should_call.cancel() timeout = create_timeout(loop=event_loop) ee.emit('event') result = await should_call assert isinstance(result, PyeeTestError)
class DummyEmitter(object): """Dummy emitter for testing.""" __emitter = None __evt = None __pollThread = None def __init__(self): """ctor.""" self.__emitter = EventEmitter() def on(self, evt, callback): """Register event handler.""" self.__emitter.on(evt, callback) def emit(self, evt, args): """Fire event.""" self.__emitter.emit(evt, args) def on_poll_fail(self): """Fire pin poll faiure event.""" self.emit("pinPollFailed", self.__evt) def poll(self): """Execute pin polling on background thread.""" ioEx = IOException("Poll failed.") self.__evt = PinPollFailEvent(ioEx) self.__pollThread = threading.Thread(target=self.on_poll_fail) self.__pollThread.name = "DummyEmitterThread" self.__pollThread.daemon = True self.__pollThread.start()
def test_asyncio_error(): """Test that event_emitters can handle errors when wrapping coroutines as used with asyncio. """ loop = new_event_loop() ee = EventEmitter(loop=loop) should_call = Future(loop=loop) @ee.on('event') async def event_handler(): raise PyeeTestError() @ee.on('error') def handle_error(exc): should_call.set_result(exc) async def create_timeout(loop=loop): await sleep(0.1, loop=loop) if not should_call.done(): raise Exception('should_call timed out!') return should_call.cancel() timeout = create_timeout(loop=loop) @should_call.add_done_callback def _done(result): assert isinstance(result, PyeeTestError) ee.emit('event') loop.run_until_complete(gather(should_call, timeout, loop=loop)) loop.close()
class Connection(object): def __init__(self, packet_sender): self.log = logging.getLogger('%s' % self.__class__.__name__) self.log.info('Init Connection') self.event_emitter = EventEmitter() self._sender = Sender(packet_sender) self._receiver = Receiver(packet_sender) # pylint: disable=unused-variable @self._receiver.event_emitter.on('data') def on_data(data): self.log.debug('Received IncomingMessage: %s', data) self.event_emitter.emit('data', data) # pylint: disable=unused-variable @self._receiver.event_emitter.on('_reset') def on_reset(data): self.log.debug('Received reset message') #self._sender = Sender(packet_sender) def send(self, data): self._sender.send(data) count_outgoing_packet(data) def receive(self, packet): if packet._acknowledgement: self._sender.verify_acknowledgement(packet._sequence_number) else: self._receiver.receive(packet) count_incoming_packet(packet)
class RegistrationOnlyEmitter(object): def __init__(self): self.emitter = EventEmitter() def on(self, event, f): allow_events_to_execute = True if allow_events_to_execute: # don't filter events, just run them all print "Event: "+str(event) self.emitter.on(event, f) else: # filter to just the registration events, # preventing them from actually executing if event in [ 'register_intent', 'register_vocab', 'recognizer_loop:utterance' ]: print "Event: " + str(event) self.emitter.on(event, f) def emit(self, event, *args, **kwargs): event_name = event.type self.emitter.emit(event_name, event, *args, **kwargs) def once(self, event, f): self.emitter.once(event, f) def remove(self, event_name, func): pass
def test_asyncio_error(): """Test that event_emitters can handle errors when wrapping coroutines as used with asyncio. """ loop = new_event_loop() ee = EventEmitter(loop=loop) should_call = Future(loop=loop) @ee.on('event') async def event_handler(): raise PyeeTestException() @ee.on('error') def handle_error(exc): should_call.set_result(exc) async def create_timeout(loop=loop): await sleep(0.1, loop=loop) if not should_call.done(): raise Exception('should_call timed out!') return should_call.cancel() timeout = create_timeout(loop=loop) @should_call.add_done_callback def _done(result): assert isinstance(result, PyeeTestError) ee.emit('event') loop.run_until_complete(gather(should_call, timeout, loop=loop)) loop.close()
def test_listeners(): """`listeners()` returns a copied list of listeners.""" call_me = Mock() ee = EventEmitter() @ee.on('event') def event_handler(): pass @ee.once('event') def once_handler(): pass listeners = ee.listeners('event') assert listeners[0] == event_handler assert listeners[1] == once_handler # listeners is a copy, you can't mutate the innards this way listeners[0] = call_me ee.emit('event') call_me.assert_not_called()
def test_properties_preserved(): """Test that the properties of decorated functions are preserved.""" call_me = Mock() call_me_also = Mock() ee = EventEmitter() @ee.on('always') def always_event_handler(): """An event handler.""" call_me() @ee.once('once') def once_event_handler(): """Another event handler.""" call_me_also() assert always_event_handler.__doc__ == 'An event handler.' assert once_event_handler.__doc__ == 'Another event handler.' always_event_handler() call_me.assert_called_once() once_event_handler() call_me_also.assert_called_once() call_me_also.reset_mock() # Calling the event handler directly doesn't clear the handler ee.emit('once') call_me_also.assert_called_once()
async def test_asyncio_emit(event_loop): """Test that event_emitters can handle wrapping coroutines as used with asyncio. """ ee = EventEmitter(loop=event_loop) should_call = Future(loop=event_loop) @ee.on('event') async def event_handler(): should_call.set_result(True) async def create_timeout(loop=event_loop): await sleep(0.1, loop=event_loop) if not should_call.done(): raise Exception('should_call timed out!') return should_call.cancel() timeout = create_timeout(loop=event_loop) ee.emit('event') result = await should_call assert result == True
class RegistrationOnlyEmitter(object): def __init__(self): self.emitter = EventEmitter() def on(self, event, f): allow_events_to_execute = True if allow_events_to_execute: # don't filter events, just run them all print "Event: " + str(event) self.emitter.on(event, f) else: # filter to just the registration events, # preventing them from actually executing if event in [ 'register_intent', 'register_vocab', 'recognizer_loop:utterance' ]: print "Event: " + str(event) self.emitter.on(event, f) def emit(self, event, *args, **kwargs): event_name = event.type self.emitter.emit(event_name, event, *args, **kwargs) def once(self, event, f): self.emitter.once(event, f) def remove(self, event_name, func): pass
class PendingPacket(object): def __init__(self, packet, packet_sender): self.ee = EventEmitter() self._packet_sender = packet_sender self._packet = packet self._intervalID = None self._sending = False self._sending_count = 0 self.log = logging.getLogger('%s' % self.__class__.__name__) self.log.info('Init PendingPacket') def send(self): self._sending = True def packet_send(counter): def packet_lost(): if self._sending: self.log.info('Packet %s Lost', self._packet.get_sequence_number()) if self._sending and counter < 2: self.log.debug('Sending Packet #%s: %s', self._packet.get_sequence_number(), self._sending) self._packet_sender.send(self._packet) packet_send(counter + 1) else: ioloop.IOLoop.instance().call_later(5, packet_lost) packet_send(0) # self._intervalID = rudp.helpers.set_interval( # packet_send, # rudp.constants.TIMEOUT # ) # self.log.debug('Packet %s sent %d times', self._packet.get_sequence_number(), self._sending_count) def get_sequence_number(self): return self._packet.get_sequence_number() def acknowledge(self): self.log.debug('Pending Packet Acknowledged: %s', self._packet.get_sequence_number()) self._sending = None if self._intervalID: self._intervalID.cancel() self._intervalID = None self.ee.emit('acknowledge')
class IncomingMessage(object): def __init__(self, im_id, size): self.log = logging.getLogger( '%s' % self.__class__.__name__ ) self.log.debug('New IncomingMessage Created') self.im_id = im_id self.size = size self.ee = EventEmitter() self.synced = False self._next_sequence_number = 0 self._sync_sequence_number = None self._packets = SortedList() self.body = '' self.waiting = False def add_to_body(self, payload): if payload in self.body: self.log.debug('This content is already in the body.') return else: self.body += payload def reset(self): self.log.debug('IncomingMessage Reset') self.log.debug('Self Packets: %s', self._packets) self._packets.clear() self.synced = False self._next_sequence_number = 0 self._sync_sequence_number = None try: self.log.debug('Downloaded (%s) | Total Size (%s)', len(self.body), self.size) if len(self.body) >= int(self.size): self.log.debug('Download Complete') if len(self.body) > int(self.size): self.log.debug('Oversized Message') self.ee.emit('complete', {'body': self.body}) return else: # print self._message, self._message_size self.log.debug('Still downloading...') self.waiting = True except Exception as e: self.log.debug('Problem with resetting IncomingMessage: %s', e)
class RegistrationOnlyEmitter(object): def __init__(self): self.emitter = EventEmitter() def on(self, event, f): if event in ['register_intent', 'register_vocab', 'recognizer_loop:utterance']: self.emitter.on(event, f) def emit(self, event, *args, **kwargs): event_name = event.message_type self.emitter.emit(event_name, event, *args, **kwargs)
def test_emit_return(): ee = EventEmitter() # make sure emitting without a callback returns False nt.assert_false(ee.emit('data')) # add a callback ee.on('data')(lambda: None) # should return True now nt.assert_true(ee.emit('data'))
def test_emit_error(): ee = EventEmitter() with nt.assert_raises(Exception): ee.emit('error') @ee.on('error') def onError(): pass # No longer raises and error instead return True indicating handled nt.assert_true(ee.emit('error'))
class IncomingMessage(object): def __init__(self, im_id, size): self.log = logging.getLogger('%s' % self.__class__.__name__) self.log.debug('New IncomingMessage Created') self.im_id = im_id self.size = size self.ee = EventEmitter() self.synced = False self._next_sequence_number = 0 self._sync_sequence_number = None self._packets = SortedList() self.body = '' self.waiting = False def add_to_body(self, payload): if payload in self.body: self.log.debug('This content is already in the body.') return else: self.body += payload def reset(self): self.log.debug('IncomingMessage Reset') self.log.debug('Self Packets: %s', self._packets) self._packets.clear() self.synced = False self._next_sequence_number = 0 self._sync_sequence_number = None try: self.log.debug('Downloaded (%s) | Total Size (%s)', len(self.body), self.size) if len(self.body) >= int(self.size): self.log.debug('Download Complete') if len(self.body) > int(self.size): self.log.debug('Oversized Message') self.ee.emit('complete', {'body': self.body}) return else: # print self._message, self._message_size self.log.debug('Still downloading...') self.waiting = True except Exception as e: self.log.debug('Problem with resetting IncomingMessage: %s', e)
class RegistrationOnlyEmitter(object): def __init__(self): self.emitter = EventEmitter() def on(self, event, f): if event in [ 'register_intent', 'register_vocab', 'recognizer_loop:utterance' ]: self.emitter.on(event, f) def emit(self, event, *args, **kwargs): event_name = event.message_type self.emitter.emit(event_name, event, *args, **kwargs)
def test_shorter_pattern(): """Tests correct behaviour with shorter patterns""" ee = EventEmitter() @ee.on('#') def event_handler(ev): raise ItWorkedException with nt.assert_raises(ItWorkedException) as it_worked: ee.emit('a/b/c') with nt.assert_raises(ItWorkedException) as it_worked: ee.emit('cool')
def test_twisted_emit(): """Test that event_emitters can handle wrapping coroutines when using twisted and ensureDeferred. """ ee = EventEmitter(scheduler=ensureDeferred) should_call = Mock() @ee.on('event') async def event_handler(): should_call(True) ee.emit('event') should_call.assert_called_once()
def test_emit_sync(): """Basic synchronous emission works""" call_me = Mock() ee = EventEmitter() @ee.on('event') def event_handler(data, **kwargs): call_me() assert data == 'emitter is emitted!' # Making sure data is passed propers ee.emit('event', 'emitter is emitted!', error=False) call_me.assert_called_once()
def test_emit_return(): """Emit returns True when handlers are registered on an event, and false otherwise. """ call_me = Mock() ee = EventEmitter() # make sure emitting without a callback returns False assert not ee.emit('data') # add a callback ee.on('data')(call_me) # should return True now assert ee.emit('data')
def test_twisted_once(): """Test that event_emitters also wrap coroutines for once when using twisted and ensureDeferred. """ ee = EventEmitter(scheduler=ensureDeferred) should_call = Mock() @ee.once('event') async def event_handler(): _ = await succeed('yes!') should_call(True) ee.emit('event') should_call.assert_called_once()
def test_longer_pattern(): """Tests correct behaviour with longer patterns""" ee = EventEmitter() @ee.on('a/b/#') def event_handler(ev): raise ItWorkedException ee.emit('c') @ee.on('+/a/b') def event_handler(ev): raise ItWorkedException('c and #/a/b') ee.emit('c')
async def test_asyncio_once_emit(event_loop): """Test that event_emitters also wrap coroutines when using once """ ee = EventEmitter(loop=event_loop) should_call = Future(loop=event_loop) @ee.once('event') async def event_handler(): should_call.set_result(True) ee.emit('event') result = await wait_for(should_call, 0.1) assert result == True
class Server: def __init__(self, ctx, **kwargs): self.ctx = ctx self.is_running = False # Provide an interface for event subscribers self.emitter = EventEmitter() # Prepare OSC message dispatcher and UDP server self.address = kwargs.get('osc_address', OSC_ADDRESS) self.port = kwargs.get('osc_port', OSC_PORT) bind = (self.address, self.port) disp = dispatcher.Dispatcher() disp.map('/leasebot/*', self._on_param) self._server = osc_server.ThreadingOSCUDPServer(bind, disp) def start(self): thread = threading.Thread(target=self._start_server) thread.daemon = True thread.start() self.is_running = True def stop(self): self._server.shutdown() self.is_running = False def _start_server(self): self.ctx.log('OSC server @ {}:{}'.format(self.address, self.port)) self._server.serve_forever() def _on_param(self, address, *args): param = address.replace('/leasebot/', '') # Commands with no arguments if param == 'reset': self.emitter.emit('reset') return # We expect one float argument from now on if not len(args) == 1 or type(args[0]) is not float: return if param in ['temperature'] and 0 <= args[0] <= 1: self.emitter.emit('param', param, args[0]) if param in ['interval'] and 0 <= args[0] <= 5: self.emitter.emit('param', param, args[0]) if param in ['volume']: self.emitter.emit('param', param, args[0])
async def test_asyncio_emit(event_loop): """Test that event_emitters can handle wrapping coroutines as used with asyncio. """ ee = EventEmitter(loop=event_loop) should_call = Future(loop=event_loop) @ee.on('event') async def event_handler(): should_call.set_result(True) ee.emit('event') result = await wait_for(should_call, 0.1) assert result == True
def test_emit_error(): """Errors raise with no event handler, otherwise emit on handler""" call_me = Mock() ee = EventEmitter() test_exception = PyeeTestException('lololol') with raises(PyeeTestException) as exc_info: ee.emit('error', test_exception) @ee.on('error') def on_error(exc): call_me() # No longer raises and error instead return True indicating handled assert ee.emit('error', test_exception) call_me.assert_called_once()
class PendingPacket(object): def __init__(self, packet, packet_sender): self.loop = ioloop.IOLoop.current() self.event_emitter = EventEmitter() self._packet_sender = packet_sender self._packet = packet self._interval_id = None self._sending = False self._sending_count = 0 self.log = logging.getLogger( '%s' % self.__class__.__name__ ) self.log.info('Init PendingPacket') def send(self): self._sending = True self.log.debug('Sending Packet #%s: %s', self._packet.get_sequence_number(), self._sending) self._packet_sender.send(self._packet) # self._interval_id = rudp.helpers.set_interval( # packet_send, # rudp.constants.TIMEOUT # ) # self.log.debug('Packet %s sent %d times', self._packet.get_sequence_number(), self._sending_count) def get_sequence_number(self): return self._packet.get_sequence_number() def acknowledge(self): self.log.debug('Pending Packet Acknowledged: %s', self._packet.get_sequence_number()) self._sending = None if self._interval_id: self._interval_id.cancel() self._interval_id = None self.event_emitter.emit('acknowledge')
class PendingPacket(object): def __init__(self, packet, packet_sender): self.loop = ioloop.IOLoop.current() self.event_emitter = EventEmitter() self._packet_sender = packet_sender self._packet = packet self._interval_id = None self._sending = False self._sending_count = 0 self.log = logging.getLogger('%s' % self.__class__.__name__) self.log.info('Init PendingPacket') def send(self): self._sending = True self.log.debug('Sending Packet #%s: %s', self._packet.get_sequence_number(), self._sending) self._packet_sender.send(self._packet) # self._interval_id = rudp.helpers.set_interval( # packet_send, # rudp.constants.TIMEOUT # ) # self.log.debug('Packet %s sent %d times', self._packet.get_sequence_number(), self._sending_count) def get_sequence_number(self): return self._packet.get_sequence_number() def acknowledge(self): self.log.debug('Pending Packet Acknowledged: %s', self._packet.get_sequence_number()) self._sending = None if self._interval_id: self._interval_id.cancel() self._interval_id = None self.event_emitter.emit('acknowledge')
class Tracker(object): def __init__(self, runner=None): self.events = EventEmitter() self.started = None self.finished = None self.requests = 0 self._pending = {} self._records = [] if runner: self._attach_to(runner) def _attach_to(self, runner): runner.events.on("tests_started", self.tests_started) runner.events.on("tests_finished", self.tests_finished) runner.events.on("request_ready", self.request_ready) runner.events.on("request_started", self.request_started) runner.events.on("request_finished", self.request_finished) def get_records(self): return self._records def tests_started(self): self.started = time.time() def tests_finished(self): self.finished = time.time() self.events.emit("tests_finished", self) def request_ready(self, future, request): record = Record() request.streaming_callback = record.on_received self._pending[future] = record self._records.append(record) def request_started(self, future): self._pending[future].start() def request_finished(self, future): record = self._pending.pop(future) record.complete(future) self.events.emit("request_finished", record)
class MessageBusEventHandler(WebSocketHandler): def __init__(self, application, request, **kwargs): super().__init__(application, request, **kwargs) self.emitter = EventEmitter() def on(self, event_name, handler): self.emitter.on(event_name, handler) def on_message(self, message): LOG.debug(message) try: deserialized_message = Message.deserialize(message) except Exception: return try: self.emitter.emit(deserialized_message.msg_type, deserialized_message) except Exception as e: LOG.exception(e) traceback.print_exc(file=sys.stdout) pass for client in client_connections: client.write_message(message) def open(self): self.write_message(Message("connected").serialize()) client_connections.append(self) def on_close(self): client_connections.remove(self) def emit(self, channel_message): if (hasattr(channel_message, 'serialize') and callable(getattr(channel_message, 'serialize'))): self.write_message(channel_message.serialize()) else: self.write_message(json.dumps(channel_message)) def check_origin(self, origin): return True
class InterceptEmitter(object): """ This class intercepts and allows emitting events between the skill_tester and the skill being tested. When a test is running emitted communication is intercepted for analysis """ def __init__(self): self.emitter = EventEmitter() self.q = None def on(self, event, f): # run all events print("Event: ", event) self.emitter.on(event, f) def emit(self, event, *args, **kwargs): event_name = event.msg_type if self.q: self.q.put(event) self.emitter.emit(event_name, event, *args, **kwargs) def wait_for_response(self, event, reply_type=None, *args, **kwargs): """Simple single thread implementation of wait_for_response.""" message_type = reply_type or event.msg_type + '.response' response = None def response_handler(msg): nonlocal response response = msg self.emitter.once(message_type, response_handler) self.emitter.emit(event.msg_type, event) return response def once(self, event, f): self.emitter.once(event, f) def remove(self, event_name, func): pass def remove_all_listeners(self, event_name): pass
def test_listeners(): """`listeners()` gives you access to the listeners array.""" call_me = Mock() ee = EventEmitter() @ee.on('event') def event_handler(): pass listeners = ee.listeners('event') assert listeners[0] == event_handler # Overwrite listener listeners[0] = call_me ee.emit('event') call_me.assert_called_once()
def test_emit_single_listener_return(): """Get return value if single and flag set""" ee = EventEmitter() retvalue = "123456" @ee.on("return_something") def return_something(whattoreturn): return whattoreturn ret = ee.emit("return_something", retvalue, capture_return_value=True) assert ret == retvalue
class AckTimeoutRegister: def __init__(self, client, topic, timeout_duration): self._client = client self._topic = topic self._timeout_duration = timeout_duration self._register = {} self._emitter = EventEmitter() def add(self, name, action): """ Adds an action to the registry with a timeout. If the timeout happens the register emits an error. :param name: Name of the occurrence to add to the registry :param action: Type of action it is (event etc) """ ''' unique_name = action + "-" + name if action is not None else name ''' unique_name = name if unique_name in self._register: self.clear({"data": [unique_name]}) self._register[unique_name] = Timer(self._timeout_duration, self._on_timeout, args=(unique_name,)) self._register[unique_name].start() def clear(self, event_data): name = event_data['data'][1] timeout = self._register[name] if timeout is not None: timeout.cancel() else: self._client._on_error(self._topic, C.EVENT_UNSOLICITED_MESSAGE, event_data) def _on_timeout(self, event_name): self._register.pop(event_name) msg = 'No ACK message received in time for ' + event_name self._client._on_error(self._topic, C.EVENT_ACK_TIMEOUT, msg) self._emitter.emit('timeout', event_name)
class Connection: def __init__(self, packet_sender): print 'Init Connection' self.ee = EventEmitter() self._sender = Sender(packet_sender) self._receiver = Receiver(packet_sender) @self._receiver.ee.on('data') def on_data(data): self.ee.emit('data', data) def send(self, data): self._sender.send(data) def receive(self, packet): if packet.getIsAcknowledgement(): self._sender.verifyAcknowledgement(packet.getSequenceNumber()) else: self._receiver.receive(packet)
class WebsocketClient(object): def __init__(self, host=client_config.get("host"), port=client_config.get("port"), path=client_config.get("route"), ssl=str2bool(client_config.get("ssl"))): validate_param(host, "host") validate_param(port, "port") validate_param(path, "route") # validate_param(ssl, "ssl") # ssl = str2bool(ssl) self.emitter = EventEmitter() self.scheme = "wss" if ssl else "ws" self.host = host self.port = port self.path = path self.exp_backoff_counter = 1 self.client = self._create_new_connection() self.pool = ThreadPool(10) def _create_new_connection(self): return WebSocketApp( self.scheme + "://" + self.host + ":" + str(self.port) + self.path, on_open=self.on_open, on_close=self.on_close, on_error=self.on_error, on_message=self.on_message) def on_open(self, ws): logger.info("Connected") self.emitter.emit("open") def on_close(self, ws): self.emitter.emit("close") def on_error(self, ws, error): try: self.emitter.emit('error', error) self.client.close() except Exception, e: logger.error(repr(e)) sleep_time = self.exp_backoff_counter logger.warn( "Disconnecting on error, reconnecting in %d seconds." % sleep_time) self.exp_backoff_counter = min(self.exp_backoff_counter * 2, 60) time.sleep(sleep_time) self.client = self._create_new_connection() self.run_forever()
class WebsocketClient(object): def __init__(self, host=None, port=None, route=None, ssl=None): config = Configuration.get().get("websocket") host = host or config.get("host") port = port or config.get("port") route = route or config.get("route") ssl = ssl or config.get("ssl") validate_param(host, "websocket.host") validate_param(port, "websocket.port") validate_param(route, "websocket.route") self.url = WebsocketClient.build_url(host, port, route, ssl) self.emitter = EventEmitter() self.client = self.create_client() self.pool = ThreadPool(10) self.retry = 5 @staticmethod def build_url(host, port, route, ssl): scheme = "wss" if ssl else "ws" return scheme + "://" + host + ":" + str(port) + route def create_client(self): return WebSocketApp(self.url, on_open=self.on_open, on_close=self.on_close, on_error=self.on_error, on_message=self.on_message) def on_open(self, ws): LOG.info("Connected") self.emitter.emit("open") # Restore reconnect timer to 5 seconds on sucessful connect self.retry = 5 def on_close(self, ws): self.emitter.emit("close") def on_error(self, ws, error): try: self.emitter.emit('error', error) self.client.close() except Exception, e: LOG.error(repr(e)) LOG.warning("WS Client will reconnect in %d seconds." % self.retry) time.sleep(self.retry) self.retry = min(self.retry * 2, 60) self.client = self.create_client() self.run_forever()
class WebsocketClient(object): def __init__(self, host=config.get("host"), port=config.get("port"), route=config.get("route"), ssl=config.get("ssl")): validate_param(host, "websocket.host") validate_param(port, "websocket.port") validate_param(route, "websocket.route") self.build_url(host, port, route, ssl) self.emitter = EventEmitter() self.client = self.create_client() self.pool = ThreadPool(10) self.retry = 5 def build_url(self, host, port, route, ssl): scheme = "wss" if ssl else "ws" self.url = scheme + "://" + host + ":" + str(port) + route def create_client(self): return WebSocketApp(self.url, on_open=self.on_open, on_close=self.on_close, on_error=self.on_error, on_message=self.on_message) def on_open(self, ws): LOG.info("Connected") self.emitter.emit("open") def on_close(self, ws): self.emitter.emit("close") def on_error(self, ws, error): try: self.emitter.emit('error', error) self.client.close() except Exception, e: LOG.error(repr(e)) LOG.warn("WS Client will reconnect in %d seconds." % self.retry) time.sleep(self.retry) self.retry = min(self.retry * 2, 60) self.client = self.create_client() self.run_forever()
class WebsocketClient(object): def __init__(self, host=config.get("Websocket", "host"), port=int(config.get("Websocket", "port")), route=config.get("Websocket", "route"), ssl=config.getboolean("Websocket", "ssl")): validate_param(host, "websocket.host") validate_param(port, "websocket.port") validate_param(route, "websocket.route") self.build_url(host, port, route, ssl) self.emitter = EventEmitter() self.client = self.create_client() self.pool = ThreadPool(10) self.retry = 5 def build_url(self, host, port, route, ssl): scheme = "wss" if ssl else "ws" self.url = scheme + "://" + host + ":" + str(port) + route def create_client(self): return WebSocketApp(self.url, on_open=self.on_open, on_close=self.on_close, on_error=self.on_error, on_message=self.on_message) def on_open(self, ws): LOG.info("Connected") self.emitter.emit("open") def on_close(self, ws): self.emitter.emit("close") def on_error(self, ws, error): try: self.emitter.emit('error', error) self.client.close() except Exception as e: LOG.error(repr(e)) LOG.warn("WS Client will reconnect in %d seconds." % self.retry) time.sleep(self.retry) self.retry = min(self.retry * 2, 60) self.client = self.create_client() self.run_forever() def on_message(self, ws, message): self.emitter.emit('message', message) parsed_message = Message.deserialize(message) self.pool.apply_async( self.emitter.emit, (parsed_message.type, parsed_message)) def emit(self, message): if (not self.client or not self.client.sock or not self.client.sock.connected): return if hasattr(message, 'serialize'): self.client.send(message.serialize()) else: self.client.send(json.dumps(message.__dict__)) def on(self, event_name, func): self.emitter.on(event_name, func) def once(self, event_name, func): self.emitter.once(event_name, func) def remove(self, event_name, func): self.emitter.remove_listener(event_name, func) def run_forever(self): self.client.run_forever() def close(self): self.client.close()
class Receiver(object): def __init__(self, packet_sender): # TODO: have this be a DuplexStream instead of an EventEmitter. # TODO: the Receiver should never send raw packets to the end host. It should # only be acknowledgement packets. Please see [1] self.ee = EventEmitter() self.incoming_messages = {} self._synced = False self._next_sequence_number = 0 self._sync_sequence_number = None self._packets = SortedList() self._packet_sender = packet_sender self._closed = False self._message = '' self._message_id = None self._fullmessage = '' self._message_size = 0 self._waiting = False self.log = logging.getLogger( '%s' % self.__class__.__name__ ) self.log.debug('Init Receiver') def reset(self): self.log.debug('Reset') self.log.debug('Self Packets: %s', self._packets) self._packets.clear() self._synced = False self._next_sequence_number = 0 self._sync_sequence_number = None self._message_id = None # try: # message = self._message # except Exception as e: try: self.log.debug('%s %s', len(self._message), self._message_size) if len(self._message) == int(self._message_size): self.log.debug('Matched up') self.ee.emit('data', {'payload': self._message, 'size': self._message_size}) self._waiting = False self._message = '' self._message_size = 0 return else: # print self._message, self._message_size self.log.debug('Not equal') self._waiting = True except Exception as e: self.log.debug('Not full yet: %s', e) def receive(self, packet): self.log.debug('Receive Packet #%s', packet.get_sequence_number()) try: packet_data = packet._payload.split('|') message_id = packet_data[0] message_size = packet_data[1] payload = packet_data[2] if message_id not in self.incoming_messages: message = IncomingMessage(message_id, message_size) self.incoming_messages[message_id] = message # pylint: disable=unused-variable @message.ee.on('complete') def on_complete(body): self.log.debug('IncomingMessage Complete') self.ee.emit('data', {'payload': message.body, 'size': message.size}) else: message = self.incoming_messages[message_id] # Process Packet Contents if packet._synchronize: if not message.synced: self.log.debug('Receive Sync Packet') if packet._sequenceNumber == message._sync_sequence_number: return self.log.debug('Inserting Packet #%s', packet._sequenceNumber) message._packets.insertSorted(packet) if not message.waiting: message.body = payload else: self.log.debug('Appending to Waiting Message: %s', self._message) message.add_to_body(payload) message._next_sequence_number = packet._sequenceNumber + 1 message.synced = True message._sync_sequence_number = packet._sequenceNumber if packet._reset: message.reset() self._packet_sender.send(Packet.createAcknowledgementPacket( packet._sequenceNumber, self._packet_sender._transport.guid, self._packet_sender._transport.pubkey )) return elif packet._reset: self.log.debug('Receive Reset Packet') if message._next_sequence_number == packet.get_sequence_number(): if payload in message.body: self.log.debug('This content is already in here.') return else: message.body += payload self.log.debug('Message Updated: %s', message.body) message.reset() self._packet_sender.send(Packet.createAcknowledgementPacket( packet._sequenceNumber, self._packet_sender._transport.guid, self._packet_sender._transport.pubkey )) return else: self.log.debug('Receive Inside Packet') if message._packets.count(packet) == 0: message._packets.insertSorted(packet) if packet.get_sequence_number() == message._next_sequence_number: if payload in message.body: self.log.debug('This content is already in here.') return else: message.body += payload message._next_sequence_number += 1 # message._packets.seek() # if message._packets.hasNext(): # self._push_if_expected_sequence(self._packets.nextValue()) self._packet_sender.send(Packet.createAcknowledgementPacket( packet._sequenceNumber, self._packet_sender._transport.guid, self._packet_sender._transport.pubkey )) else: self.log.debug('Already have this packet') # Ignores packets that have a sequence number less than the next sequence # number # if not packet._synchronize and packet._sequenceNumber < self._sync_sequence_number: # self.log.debug('Just ignoring this packet') # return # if packet._synchronize and not self._synced: # # # This is the beginning of the stream. # self.log.debug('Beginning of stream %s %s', packet._sequenceNumber, self._sync_sequence_number) # # data = packet._payload.split('|', 2) # # if len(data) > 1: # self._message_id = data[0] # self._message_size = data[1] # packet._payload = data[2] # self.log.debug('Message #%s (%s bytes): %s', self._message_id, # self._message_size, packet._payload) # # self._packet_sender.send(Packet.createAcknowledgementPacket( # packet._sequenceNumber, # self._packet_sender._transport.guid, # self._packet_sender._transport.pubkey # )) # # if packet._sequenceNumber == self._sync_sequence_number: # return # # # Send the packet upstream, send acknowledgement packet to end host, and # # increment the next expected packet. # self._packets.clear() # # self.log.debug('Inserting Packet #%s', packet._sequenceNumber) # # self.log.debug('Before Packets: %s', self._packets) # self._packets.insertSorted(packet) # # if not self._waiting: # self._message = packet._payload # else: # self.log.debug('Appending to Waiting Message: %s', self._message) # self._message += packet._payload # # self.log.debug('Updated Message: %s', self._message) # # self._next_sequence_number = packet._sequenceNumber + 1 # self._synced = True # self._sync_sequence_number = packet._sequenceNumber # # if packet._reset: # self.reset() # # return # # elif not self._synced: # # If we are not synchronized with sender, then this means that we should # # wait for the end host to send a synchronization packet. # # # We are done. # self.log.debug('Got an out of order packet.') # return # # elif packet._sequenceNumber < self._sync_sequence_number: # # This is a troll packet. Ignore it. # self.log.debug('Ignoring packet out of the current window.') # return # # elif packet._sequenceNumber >= (self._packets.currentValue()._sequenceNumber # + rudp.constants.WINDOW_SIZE): # # This means that the next packet received is not within the window size. # self.ee.emit('_window_size_exceeded') # self.log.debug('Ignoring packet out of the current window.') # # return # # elif packet._reset: # # data = packet._payload.split('|') # payload = data[1] # # self.log.debug(data) # if self._message != '' and data[0] == self._message_id: # self.log.debug('Message Before Appending: %s', self._message) # self._message += payload # self.log.debug('After Updated Message: %s', self._message) # self._packet_sender.send(Packet.createAcknowledgementPacket( # packet._sequenceNumber, # self._packet_sender._transport.guid, # self._packet_sender._transport.pubkey # )) # self.reset() # return except Exception as e: self.log.error(e) # This means that we should simply insert the packet. If the packet's # sequence number is the one that we were expecting, then send it upstream, # acknowledge the packet, and increment the next expected sequence number. # # Once acknowledged, check to see if there aren't any more pending packets # after the current packet. If there are, then check to see if the next # packet is the expected packet number. If it is, then start the # acknowledgement process anew. def _push_if_expected_sequence(self, packet): if packet.get_sequence_number() == self._next_sequence_number: data = packet._payload.split('|') payload = data[1] self.log.debug('Before Updated 2 Message: %s', self._message) if payload in self._message: self.log.debug('This content is already in here.') else: self._message += payload self.log.debug('After Updated Message: %s', self._message) # [1] Never send packets directly! self._packet_sender.send(Packet.createAcknowledgementPacket(packet.get_sequence_number(), self._packet_sender._transport.guid, self._packet_sender._transport.pubkey)) self._next_sequence_number += 1 self._packets.seek() if self._packets.hasNext(): self._push_if_expected_sequence(self._packets.nextValue()) def end(self): self._closed = True self.ee.emit('end')
class Machine(object): def __init__(self, universe, id): self.logger = universe.logger.getChild('machines.{}'.format(id)) self.universe = universe self.id = id self.secret = idlist.generate_random_id(length=40) self.processes = idlist.IdList(idlist.integer_id_generator(1000)) self.services = weakref.WeakValueDictionary() self.register_tick = universe.register_tick self.unregister_tick = universe.unregister_tick self.events = EventEmitter() def create_process(self, ppid=None, factory=process.EmuProcess): pid = self.processes.add_fn(lambda id: factory(self, id, ppid)) proc = self.processes[pid] self.events.emit('process_created', proc) return proc def start_process(self, program): parent = self.create_process(factory=machine_services.InterfaceService) try: proc = self.create_process(ppid=parent.pid) proc.run_program(program) return (proc, parent) finally: self.kill_process(parent.pid) def kill_process(self, pid): proc = self.processes.get(pid) if proc is None: return del self.processes[pid] self.events.emit('process_killed', proc) proc.kill() async def interface_send(self, target, values): parent = self.create_process(factory=machine_services.InterfaceService) try: return await self.send_ipc(str(parent.pid), target, values) finally: self.kill_process(parent.pid) def register_service(self, proc, service): self.services[service] = proc def start_builtin_service(self, svc): factory = machine_services.FACTORIES.get(svc) if factory is None: self.logger.error('tried to start non-existant service: {}'.format(svc)) return proc = self.create_process(factory=factory) self.register_service(proc, svc) return proc async def send_ipc(self, sender, target, values): addr = maybe_remote_address(target) if addr is not None: dest = self.universe.machines.get(addr[0]) if dest is None: raise Exception('destination machine {} not found'.format(addr[0])) return await dest.send_ipc('{}:{}'.format(self.id, sender), addr[1], values) if (len(target) > 0) and (target[0] in string.digits): target = int(target) if target in self.processes: return await self.processes[target].send_ipc(sender, values) if target in self.services: svc = self.services[target] if svc is not None: return await svc.send_ipc(sender, values) raise Exception('no receiver {}'.format(target))
class PeerListener(GUIDMixin): def __init__(self, hostname, port, guid, data_cb): super(PeerListener, self).__init__(guid) self.hostname = hostname self.port = port self._data_cb = data_cb self.is_listening = False self.socket = None self._ok_msg = None self._connections = {} self.log = logging.getLogger(self.__class__.__name__) self.event_emitter = EventEmitter() def set_ip_address(self, new_ip): self.hostname = new_ip if not self.is_listening: return try: self.listen() except Exception as exc: self.log.error('[Requests] error: %s', exc) def set_ok_msg(self, ok_msg): self._ok_msg = ok_msg def listen(self): self.log.info("Listening at: %s:%s", self.hostname, self.port) if network_util.is_loopback_addr(self.hostname): # we are in local test mode so bind that socket on the # specified IP self.log.info("PeerListener.socket.bind('%s') LOOPBACK", self.hostname) self._prepare_datagram_socket() elif '[' in self.hostname: self.log.info("PeerListener.socket.bind('tcp://[*]:%s') IPV6", self.port) self.socket.ipv6 = True self._prepare_datagram_socket(socket.AF_INET6) else: self.log.info("PeerListener.socket.bind('tcp://*:%s') IPV4", self.port) # Temporary while I fix things self.hostname = '0.0.0.0' self._prepare_datagram_socket() self.is_listening = True def start_listening(): while self.is_listening: try: data, addr = self.socket.recvfrom(PEERLISTENER_RECV_FROM_BUFFER_SIZE) self.log.debug('Got data from %s:%d: %s', addr[0], addr[1], data[:50]) count_incoming_packet(data) if data[:MSG_PING_ID_SIZE] == MSG_PING_ID: self.socket.sendto('pong', (addr[0], addr[1])) count_outgoing_packet('pong') elif data[:MSG_PONG_ID_SIZE] == MSG_PONG_ID: self.event_emitter.emit('on_pong_message', (data, addr)) elif data[:MSG_SEND_RELAY_PING_ID_SIZE] == MSG_SEND_RELAY_PING_ID: self.event_emitter.emit('on_send_relay_ping', (data, addr)) elif data[:MSG_RELAY_PING_ID_SIZE] == MSG_RELAY_PING_ID: data = data.split(' ') sender = self.guid recipient = data[1] self.socket.sendto('send_relay_pong %s %s' % (sender, recipient), (addr[0], addr[1])) count_outgoing_packet('send_relay_pong %s %s' % (sender, recipient)) elif data[:MSG_SEND_RELAY_PONG_ID_SIZE] == MSG_SEND_RELAY_PONG_ID: self.event_emitter.emit('on_send_relay_pong', (data, addr)) elif data[:MSG_HEARTBEAT_ID_SIZE] == MSG_HEARTBEAT_ID: self.log.debug('We just received a heartbeat.') elif data[:MSG_RELAYTO_ID_SIZE] == MSG_RELAYTO_ID: self.log.debug('Relay To Packet') self.event_emitter.emit('on_relayto', data) elif data[:MSG_RELAY_ID_SIZE] == MSG_RELAY_ID: self.log.debug('Relay Packet') self.event_emitter.emit('on_message', (data, addr)) else: self.event_emitter.emit('on_message', (data, addr)) except socket.timeout as exc: err = exc.args[0] if err == 'timed out': time.sleep(0.5) continue else: sys.exit(1) except socket.error: # No data. This is normal. pass # except AttributeError as err: # print 'Packet was jacked up: %s', err Thread(target=start_listening).start() def on_raw_message(self, serialized): self.log.info("connected %d", len(serialized)) try: msg = json.loads(serialized[0]) except ValueError: self.log.info("incorrect msg! %s", serialized) return self._data_cb(msg) def _prepare_datagram_socket(self, family=socket.AF_INET): self.socket = socket.socket(family, socket.SOCK_DGRAM) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # self.socket.setblocking(0) self.socket.bind((self.hostname, self.port))
class WebsocketClient: def __init__(self, host=None, port=None, route=None, ssl=None): config = Configuration.get().get("websocket") host = host or config.get("host") port = port or config.get("port") route = route or config.get("route") ssl = ssl or config.get("ssl") validate_param(host, "websocket.host") validate_param(port, "websocket.port") validate_param(route, "websocket.route") self.url = WebsocketClient.build_url(host, port, route, ssl) self.emitter = EventEmitter() self.client = self.create_client() self.pool = ThreadPool(10) self.retry = 5 self.connected_event = Event() self.started_running = False @staticmethod def build_url(host, port, route, ssl): scheme = "wss" if ssl else "ws" return scheme + "://" + host + ":" + str(port) + route def create_client(self): return WebSocketApp(self.url, on_open=self.on_open, on_close=self.on_close, on_error=self.on_error, on_message=self.on_message) def on_open(self, ws): LOG.info("Connected") self.connected_event.set() self.emitter.emit("open") # Restore reconnect timer to 5 seconds on sucessful connect self.retry = 5 def on_close(self, ws): self.emitter.emit("close") def on_error(self, ws, error): """ On error start trying to reconnect to the websocket. """ if isinstance(error, WebSocketConnectionClosedException): LOG.warning('Could not send message because connection has closed') else: LOG.exception('=== ' + repr(error) + ' ===') try: self.emitter.emit('error', error) if self.client.keep_running: self.client.close() except Exception as e: LOG.error('Exception closing websocket: ' + repr(e)) LOG.warning("WS Client will reconnect in %d seconds." % self.retry) time.sleep(self.retry) self.retry = min(self.retry * 2, 60) try: self.emitter.emit('reconnecting') self.client = self.create_client() self.run_forever() except WebSocketException: pass def on_message(self, ws, message): self.emitter.emit('message', message) parsed_message = Message.deserialize(message) self.pool.apply_async( self.emitter.emit, (parsed_message.type, parsed_message)) def emit(self, message): if not self.connected_event.wait(10): if not self.started_running: raise ValueError('You must execute run_forever() ' 'before emitting messages') self.connected_event.wait() try: if hasattr(message, 'serialize'): self.client.send(message.serialize()) else: self.client.send(json.dumps(message.__dict__)) except WebSocketConnectionClosedException: LOG.warning('Could not send {} message because connection ' 'has been closed'.format(message.type)) def wait_for_response(self, message, reply_type=None, timeout=None): """Send a message and wait for a response. Args: message (Message): message to send reply_type (str): the message type of the expected reply. Defaults to "<message.type>.response". timeout: seconds to wait before timeout, defaults to 3 Returns: The received message or None if the response timed out """ response = [] def handler(message): """Receive response data.""" response.append(message) # Setup response handler self.once(reply_type or message.type + '.response', handler) # Send request self.emit(message) # Wait for response start_time = time.monotonic() while len(response) == 0: time.sleep(0.2) if time.monotonic() - start_time > (timeout or 3.0): try: self.remove(reply_type, handler) except (ValueError, KeyError): # ValueError occurs on pyee 1.0.1 removing handlers # registered with once. # KeyError may theoretically occur if the event occurs as # the handler is removed pass return None return response[0] def on(self, event_name, func): self.emitter.on(event_name, func) def once(self, event_name, func): self.emitter.once(event_name, func) def remove(self, event_name, func): try: if event_name in self.emitter._events: LOG.debug("Removing found '"+str(event_name)+"'") else: LOG.debug("Not able to find '"+str(event_name)+"'") self.emitter.remove_listener(event_name, func) except ValueError as e: LOG.warning('Failed to remove event {}: {}'.format(event_name, str(func))) for line in traceback.format_stack(): LOG.warning(line.strip()) if event_name in self.emitter._events: LOG.debug("Removing found '"+str(event_name)+"'") else: LOG.debug("Not able to find '"+str(event_name)+"'") LOG.warning("Existing events: " + str(self.emitter._events)) for evt in self.emitter._events: LOG.warning(" "+str(evt)) LOG.warning(" "+str(self.emitter._events[evt])) if event_name in self.emitter._events: LOG.debug("Removing found '"+str(event_name)+"'") else: LOG.debug("Not able to find '"+str(event_name)+"'") LOG.warning('----- End dump -----') def remove_all_listeners(self, event_name): ''' Remove all listeners connected to event_name. Args: event_name: event from which to remove listeners ''' if event_name is None: raise ValueError self.emitter.remove_all_listeners(event_name) def run_forever(self): self.started_running = True self.client.run_forever() def close(self): self.client.close() self.connected_event.clear()
class Window(object): def __init__(self, packets): self.log = logging.getLogger("%s" % self.__class__.__name__) self.log.info("Init Window") self.event_emitter = EventEmitter() self._packets = packets self._acknowledged = [] def send(self): # Our packets to send. pkts = list(self._packets) if len(pkts) < 1: self.event_emitter.emit("done") return # The initial synchronization packet. Always send this first. self.synchronization_packet = pkts.pop(0) # The final reset packet. It can be equal to the synchronization packet. self._reset_packet = pkts.pop() if len(pkts) else self.synchronization_packet # This means that the reset packet's acknowledge event thrown will be # different from that of the synchronization packet. if self._reset_packet is not self.synchronization_packet: # pylint: disable=unused-variable @self._reset_packet.event_emitter.on("acknowledge") def on_acknowledge(): self.log.debug("ACKNOWLEDGED PACKETS: %s", self._acknowledged) self.log.debug("done for real") self.event_emitter.emit("done") # Will be used to handle the case when all non sync or reset packets have # been acknowledged. @self.synchronization_packet.event_emitter.on("acknowledge") def on_sync_knowledge(): # pylint: disable=unused-variable self.log.debug("ACK SYNC: #%s", self.synchronization_packet.get_sequence_number()) # We will either notify the owning class that this window has finished # sending all of its packets (that is, if this window only had one packet # in it), or keep looping through each each non sync-reset packets until # they have been acknowledged. if self._reset_packet is self.synchronization_packet: self.log.debug("SYNC is RESET. DONE") self.event_emitter.emit("done") return elif not len(pkts): # This means that this window only had two packets, and the second one # was a reset packet. self.log.debug("RESET SENT: #%s", self.synchronization_packet.get_sequence_number()) self._reset_packet.send() return # pylint: disable=unused-variable @self.event_emitter.on("acknowledge") def on_sender_acknowledge(): # This means that it is now time to send the reset packet. self.log.debug("RESET SENT: #%s", self.synchronization_packet.get_sequence_number()) self._reset_packet.send() for packet in pkts: # pylint: disable=unused-variable @packet.event_emitter.on("acknowledge") def on_packet_acknowledge(): if len(self._acknowledged) == len(self._packets) - 1: self.log.debug("ALL PACKETS ACKD") self.event_emitter.emit("acknowledge") packet.send() self.log.debug("SYNC SENT: #%s", self.synchronization_packet.get_sequence_number()) self.synchronization_packet.send() def verify_acknowledgement(self, sequence_number): self.log.debug("ACK #%s of %s packets", sequence_number, len(self._packets)) for i in range(0, len(self._packets)): if self._packets[i].get_sequence_number() == sequence_number: self.log.debug("%s seq %s", sequence_number, self._acknowledged) if not sequence_number in self._acknowledged: self._acknowledged.append(sequence_number) self.log.debug("ACKD PACKETS: %s", self._acknowledged) self._packets[i].acknowledge() return
class Window(): def __init__(self, packets): print 'Init Window' self.ee = EventEmitter() self._packets = packets def send(self): # Our packets to send. pkts = self._packets # The initial synchronization packet. Always send this first. self._synchronization_packet = pkts.pop(0) # The final reset packet. It can be equal to the synchronization packet. self._reset_packet = pkts.pop() if len(pkts) else self._synchronization_packet # This means that the reset packet's acknowledge event thrown will be # different from that of the synchronization packet. if self._reset_packet is not self._synchronization_packet: @self._reset_packet.ee.on('acknowledge') def on_acknowledge(): self.ee.emit('done') # Will be used to handle the case when all non sync or reset packets have # been acknowledged. @self._synchronization_packet.ee.on('acknowledge') def on_sync_knowledge(): # We will either notify the owning class that this window has finished # sending all of its packets (that is, if this window only had one packet # in it), or keep looping through each each non sync-reset packets until # they have been acknowledged. if self._reset_packet is self._synchronization_packet: self.ee.emit('done') return elif len(pkts) is 0: # This means that this window only had two packets, and the second one # was a reset packet. self._reset_packet.send() return @self.ee.on('acknowledge') def on_sender_acknowledge(): # This means that it is now time to send the reset packet. self._reset_packet.send() # And if there are more than two packets in this window, then send all # other packets. self.acknowledged = 0 for packet in pkts: @packet.ee.on('acknowledge') def on_packet_acknowledge(): self.acknowledged += 1 if self.acknowledged is len(pkts): self.ee.emit('acknowledge') packet.send() self._synchronization_packet.send() def verify_acknowledgement(self, sequence_number): for i in range(0, len(self._packets)): if self._packets[i].get_sequence_number() is sequence_number: self._packets[i].acknowledge()
class Receiver(): def __init__(self, packet_sender): print 'Init Receiver' # TODO: have this be a DuplexStream instead of an EventEmitter. # TODO: the Receiver should never send raw packets to the end host. It should # only be acknowledgement packets. Please see [1] self.ee = EventEmitter() self._synced = False self._next_sequence_number = 0 def sort_by_sequence(packet_a, packet_b): return packet_a.get_sequence_number() - packet_b.get_sequence_number() self._packets = LinkedList(sort_by_sequence) self._packet_sender = packet_sender self._closed = False def receive(self, packet): if self._closed: # Since this is closed, don't do anything. return # Ignores packets that have a sequence number less than the next sequence # number if not packet.getIsSynchronize() and packet.getSequenceNumber() < self._sync_sequence_number: return if packet.getIsSynchronize() and not self._synced: # This is the beginning of the stream. if packet.getSequenceNumber() is self._sync_sequence_number: self._packet_sender.send(Packet.createAcknowledgementPacket(packet.getSequenceNumber())) return # Send the packet upstream, send acknowledgement packet to end host, and # increment the next expected packet. self._packets.clear() self.ee.emit('data', packet.getPayload()) self._packet_sender.send(Packet.createAcknowledgementPacket(packet.getSequenceNumber())) self._packets.insert(packet) self._next_sequence_number = packet.getSequenceNumber() + 1 self._synced = True self._sync_sequence_number = packet.getSequenceNumber() if packet.getIsReset(): self.ee.emit('_reset') self._synced = False # We're done. return elif (packet.getIsReset()): self.ee.emit('_reset') self.ee._synced = False elif not self._synced: # If we are not synchronized with sender, then this means that we should # wait for the end host to send a synchronization packet. # We are done. return elif packet.getSequenceNumber() < self._syncSequenceNumber: # This is a troll packet. Ignore it. return elif packet.getSequenceNumber() >= (self._packets.currentValue().getSequenceNumber() + constants.WINDOW_SIZE): # This means that the next packet received is not within the window size. self.ee.emit('_window_size_exceeded') return # This means that we should simply insert the packet. If the packet's # sequence number is the one that we were expecting, then send it upstream, # acknowledge the packet, and increment the next expected sequence number. # # Once acknowledged, check to see if there aren't any more pending packets # after the current packet. If there are, then check to see if the next # packet is the expected packet number. If it is, then start the # acknowledgement process anew. result = self._packets.insert(packet) if result is LinkedList.InsertionResult.INSERTED: self._pushIfExpectedSequence(packet) elif result is LinkedList.InsertionResult.EXISTS: self._packet_sender.send(Packet.createAcknowledgementPacket(packet.getSequenceNumber())) def _pushIfExpectedSequence(self, packet): if packet.get_sequence_number() is self._next_sequence_number: self.ee.emit('data', packet.getPayload()) # [1] Never send packets directly! self._packet_sender.send(Packet.createAcknowledgementPacket(packet.getSequenceNumber())) self._nextSequenceNumber += 1 self._packets.seek() if self._packets.hasNext(): self._pushIfExpectedSequence(self._packets.nextValue()) def end(self): self._closed = True self.ee.emit('end')
class WebsocketClient(object): def __init__(self, host=None, port=None, route=None, ssl=None): config = Configuration.get().get("websocket") host = host or config.get("host") port = port or config.get("port") route = route or config.get("route") ssl = ssl or config.get("ssl") validate_param(host, "websocket.host") validate_param(port, "websocket.port") validate_param(route, "websocket.route") self.url = WebsocketClient.build_url(host, port, route, ssl) self.emitter = EventEmitter() self.client = self.create_client() self.pool = ThreadPool(10) self.retry = 5 @staticmethod def build_url(host, port, route, ssl): scheme = "wss" if ssl else "ws" return scheme + "://" + host + ":" + str(port) + route def create_client(self): return WebSocketApp(self.url, on_open=self.on_open, on_close=self.on_close, on_error=self.on_error, on_message=self.on_message) def on_open(self, ws): LOG.info("Connected") self.emitter.emit("open") # Restore reconnect timer to 5 seconds on sucessful connect self.retry = 5 def on_close(self, ws): self.emitter.emit("close") def on_error(self, ws, error): try: self.emitter.emit('error', error) self.client.close() except Exception as e: LOG.error(repr(e)) LOG.warning("WS Client will reconnect in %d seconds." % self.retry) time.sleep(self.retry) self.retry = min(self.retry * 2, 60) self.client = self.create_client() self.run_forever() def on_message(self, ws, message): self.emitter.emit('message', message) parsed_message = Message.deserialize(message) self.pool.apply_async( self.emitter.emit, (parsed_message.type, parsed_message)) def emit(self, message): if (not self.client or not self.client.sock or not self.client.sock.connected): return if hasattr(message, 'serialize'): self.client.send(message.serialize()) else: self.client.send(json.dumps(message.__dict__)) def on(self, event_name, func): self.emitter.on(event_name, func) def once(self, event_name, func): self.emitter.once(event_name, func) def remove(self, event_name, func): self.emitter.remove_listener(event_name, func) def remove_all_listeners(self, event_name): ''' Remove all listeners connected to event_name. Args: event_name: event from which to remove listeners ''' if event_name is None: raise ValueError self.emitter.remove_all_listeners(event_name) def run_forever(self): self.client.run_forever() def close(self): self.client.close()