def testParser(self): p = FrameParser() self.assertEqual(p.decode(b''), None) frame = Frame('Hello', final=True) self.assertRaises(ProtocolError, p.decode, frame.msg) frame = Frame('Hello', masking_key='ciao', final=True) pframe = p.decode(frame.msg) self.assertTrue(pframe) self.assertEqual(pframe.body, 'Hello') self.assertEqual(pframe.payload_length, 5) self.assertEqual(pframe.masking_key, b'ciao')
def testPartialParsing(self): p = FrameParser() frame = Frame(self.large_bdata, opcode=0x2, final=True, masking_key='ciao') self.assertEqual(p.decode(frame.msg[:1]), None) self.assertEqual(p.decode(frame.msg[1:5]), None) self.assertEqual(p.decode(frame.msg[5:50]), None) pframe = p.decode(frame.msg[50:]) self.assertTrue(pframe) self.assertEqual(pframe.payload_length, len(self.large_bdata)) self.assertEqual(pframe.body, self.large_bdata)
def testParserBinary(self): p = FrameParser() frame = Frame(self.bdata, opcode=0x2, final=True, masking_key='ciao') pframe = p.decode(frame.msg) self.assertTrue(pframe) self.assertEqual(pframe.payload_length, 256) self.assertEqual(pframe.body, self.bdata) frame = Frame(self.large_bdata, opcode=0x2, final=True, masking_key='ciao') pframe = p.decode(frame.msg) self.assertTrue(pframe) self.assertEqual(pframe.payload_length, len(self.large_bdata)) self.assertEqual(pframe.body, self.large_bdata)
class MailboxConsumer(ProtocolConsumer): '''The :class:`pulsar.ProtocolConsumer` for internal message passing between actors. Encoding and decoding uses the unmasked websocket protocol.''' def connection_made(self, connection): self._pending_responses = {} self._parser = FrameParser(kind=2) actor = get_actor() if actor.is_arbiter(): self.connection.bind_event('connection_lost', None, self._connection_lost) def request(self, command, sender, target, args, kwargs): '''Used by the server to send messages to the client.''' req = Message.command(command, sender, target, args, kwargs) self.start_request(req) return req.future ####################################################################### ## PROTOCOL CONSUMER IMPLEMENTATION def data_received(self, data): # Feed data into the parser msg = self._parser.decode(data) while msg: try: message = pickle.loads(msg.body) except Exception as e: raise ProtocolError('Could not decode message body: %s' % e) maybe_async(self._responde(message), event_loop=self.event_loop) msg = self._parser.decode() def start_request(self, req=None): if req: if req.future and 'ack' in req.data: self._pending_responses[req.data['ack']] = req.future try: self._write(req) except Exception as e: req.future.callback(e) else: self._write(req) start = start_request ######################################################################## ## INTERNALS def _connection_lost(self, failure): actor = get_actor() if actor.is_running(): failure.log(msg='Connection lost with actor.', level='warning') else: failure.mute() return failure def _responde(self, message): actor = get_actor() command = message.get('command') #actor.logger.debug('handling %s', command) if command == 'callback': # this is a callback self._callback(message.get('ack'), message.get('result')) else: try: target = actor.get_actor(message['target']) if target is None: raise CommandError('Cannot execute "%s" in %s. Unknown ' 'actor %s' % (command, actor, message['target'])) # Get the caller proxy without throwing caller = get_proxy(actor.get_actor(message['sender']), safe=True) if isinstance(target, ActorProxy): # route the message to the actor proxy if caller is None: raise CommandError( "'%s' got message from unknown '%s'" % (actor, message['sender'])) result = yield actor.send(target, command, *message['args'], **message['kwargs']) else: actor = target command = get_command(command) req = CommandRequest(target, caller, self.connection) result = yield command(req, message['args'], message['kwargs']) except Exception: result = Failure(sys.exc_info()) if message.get('ack'): req = Message.callback(result, message['ack']) self.start_request(req) def _callback(self, ack, result): if not ack: raise ProtocolError('A callback without id') try: pending = self._pending_responses.pop(ack) except KeyError: raise KeyError('Callback %s not in pending callbacks' % ack) pending.callback(result) def _write(self, req): obj = pickle.dumps(req.data, protocol=2) data = self._parser.encode(obj, opcode=0x2).msg try: self.transport.write(data) except IOError: actor = get_actor() if actor.is_running(): raise