def process(self, value: COMMANDS) -> None: if isinstance(value, commands.Connection.Start): self._set_state(STATE_START_RECEIVED) self._process_start(value) elif isinstance(value, commands.Connection.Tune): self._set_state(STATE_TUNE_RECEIVED) self._process_tune(value) elif isinstance(value, commands.Connection.OpenOk): self._set_state(STATE_OPENOK_RECEIVED) elif isinstance(value, commands.Connection.Blocked): self._set_state(STATE_BLOCKED_RECEIVED) self.blocked.set() elif isinstance(value, commands.Connection.Unblocked): self._set_state(STATE_UNBLOCKED_RECEIVED) self.blocked.clear() elif isinstance(value, commands.Connection.Close): self._set_state(STATE_CLOSE_RECEIVED) self._transport.write( frame.marshal(commands.Connection.CloseOk(), 0)) self._set_state(STATE_CLOSEOK_SENT) self._on_remote_close(value.reply_code, value.reply_text) elif isinstance(value, commands.Connection.CloseOk): self._set_state(STATE_CLOSEOK_RECEIVED) elif isinstance(value, heartbeat.Heartbeat): self._set_state(STATE_HEARTBEAT_RECEIVED) self._last_heartbeat = self._loop.time() self._transport.write(frame.marshal(heartbeat.Heartbeat(), 0)) self._set_state(STATE_HEARTBEAT_SENT) else: self._set_state( state.STATE_EXCEPTION, exceptions.AIORabbitException( 'Unsupported Frame Passed to Channel0'))
def _poll(self): # Poll select with the materialized lists if not self._data.running: LOGGER.debug('Exiting poll') # Build the outbound write buffer of marshalled frames while not self._data.write_queue.empty(): data = self._data.write_queue.get(False) self._data.write_buffer.append(frame.marshal(data[1], data[0])) # Poll the poller, passing in a bool if there is data to write rlist, wlist, xlist = self._poller.poll(bool(self._data.write_buffer)) if xlist: LOGGER.debug('Poll errors: %r', xlist) self._data.events.set(events.SOCKET_CLOSE) self._data.error_callback('Connection reset') return # Clear out the trigger socket if self._data.write_trigger.fileno() in rlist: self._data.write_trigger.recv(1024) # Read if the data socket is in the read list if self._data.fd.fileno() in rlist: self._read() # Write if the data socket is writable if wlist and self._data.write_buffer: self._write()
def test_basic_cancelok(self): expectation = (b'\x01\x00\x01\x00\x00\x00\x0c\x00<\x00\x1f\x07' b'ctag1.0\xce') frame_obj = commands.Basic.CancelOk(consumer_tag='ctag1.0') response = frame.marshal(frame_obj, 1) self.assertEqual(response, expectation, 'Basic.Cancel did not match expectation')
def basic_ack_test(self): expectation = encode('\x01\x00\x01\x00\x00\x00\r\x00<\x00P\x00\x00\x00' '\x00\x00\x00\x00\x01\x00\xce') frame_obj = specification.Basic.Ack(1, False) response = frame.marshal(frame_obj, 1) self.assertEqual(response, expectation, "Basic.Ack did not match expectation")
def test_basic_cancel(self): expectation = (b'\x01\x00\x01\x00\x00\x00\r\x00<\x00\x1e\x07' b'ctag1.0\x00\xce') frame_obj = specification.Basic.Cancel(consumer_tag='ctag1.0') response = frame.marshal(frame_obj, 1) self.assertEqual(response, expectation, "Basic.Cancel did not match expectation")
def basic_cancelok_test(self): expectation = encode('\x01\x00\x01\x00\x00\x00\x0c\x00<\x00\x1f\x07' 'ctag1.0\xce') frame_obj = specification.Basic.CancelOk(consumer_tag='ctag1.0') response = frame.marshal(frame_obj, 1) self.assertEqual(response, expectation, "Basic.Cancel did not match expectation")
def test_basic_ack(self): expectation = (b'\x01\x00\x01\x00\x00\x00\r\x00<\x00P\x00\x00\x00' b'\x00\x00\x00\x00\x01\x00\xce') frame_obj = commands.Basic.Ack(1, False) response = frame.marshal(frame_obj, 1) self.assertEqual(response, expectation, 'Basic.Ack did not match expectation')
def test_basic_cancel(self): expectation = (b'\x01\x00\x01\x00\x00\x00\r\x00<\x00\x1e\x07' b'ctag1.0\x00\xce') frame_obj = commands.Basic.Cancel('ctag1.0', False) response = frame.marshal(frame_obj, 1) self.assertEqual(response, expectation, 'Basic.Cancel did not match expectation')
def test_basic_cancelok(self): expectation = (b'\x01\x00\x01\x00\x00\x00\x0c\x00<\x00\x1f\x07' b'ctag1.0\xce') frame_obj = specification.Basic.CancelOk(consumer_tag='ctag1.0') response = frame.marshal(frame_obj, 1) self.assertEqual(response, expectation, 'Basic.Cancel did not match expectation')
def test_basic_ack(self): expectation = (b'\x01\x00\x01\x00\x00\x00\r\x00<\x00P\x00\x00\x00' b'\x00\x00\x00\x00\x01\x00\xce') frame_obj = specification.Basic.Ack(1, False) response = frame.marshal(frame_obj, 1) self.assertEqual(response, expectation, 'Basic.Ack did not match expectation')
def basic_consume_test(self): expectation = encode('\x01\x00\x01\x00\x00\x00\x15\x00<\x00\x14\x00' '\x00\x03bar\x05ctag0\x00\x00\x00\x00\x00\xce') frame_obj = specification.Basic.Consume(0, 'bar', 'ctag0', False, False, False, False) response = frame.marshal(frame_obj, 1) self.assertEqual(response, expectation, "Basic.Consume did not match expectation")
def test_basic_consume(self): expectation = (b'\x01\x00\x01\x00\x00\x00\x15\x00<\x00\x14\x00' b'\x00\x03bar\x05ctag0\x00\x00\x00\x00\x00\xce') frame_obj = commands.Basic.Consume(0, 'bar', 'ctag0', False, False, False, False) response = frame.marshal(frame_obj, 1) self.assertEqual(response, expectation, 'Basic.Consume did not match expectation')
async def close(self, code=200) -> None: self._heartbeat_timer.cancel() self._heartbeat_timer = None self._transport.write( frame.marshal( commands.Connection.Close(code, 'Client Requested', 0, 0), 0)) self._set_state(STATE_CLOSE_SENT) await self._wait_on_state(STATE_CLOSEOK_RECEIVED)
def write_frame(self, channel_id, frame_out): """Marshal and write an outgoing pamqp frame to the socket. :param int channel_id: :param pamqp_spec.Frame frame_out: Amqp frame. :return: """ frame_data = pamqp_frame.marshal(frame_out, channel_id) self._write_to_socket(frame_data)
def _process_tune(self, value: commands.Connection.Tune) -> None: self.max_channels = self._negotiate(self.max_channels, value.channel_max) self.max_frame_size = self._negotiate(self.max_frame_size, value.frame_max) if self._heartbeat_interval is None: self._heartbeat_interval = value.heartbeat elif not self._heartbeat_interval and not value.heartbeat: self._heartbeat_interval = 0 self._transport.write( frame.marshal( commands.Connection.TuneOk(self.max_channels, self.max_frame_size, self._heartbeat_interval), 0)) self._set_state(STATE_TUNEOK_SENT) self._transport.write( frame.marshal(commands.Connection.Open(self._virtual_host), 0)) self._set_state(STATE_OPEN_SENT)
def write_frame(self, channel_id, frame_out): """Marshal and write an outgoing pamqp frame to the socket. :param int channel_id: :param pamqp_spec.Frame frame_out: Amqp frame. :return: """ frame_data = pamqp_frame.marshal(frame_out, channel_id) self._io.write_to_socket(frame_data)
def write_frame(self, channel_id, frame_out): """Marshal and write an outgoing pamqp frame to the Socket. :param int channel_id: Channel ID. :param specification.Frame frame_out: Amqp frame. :return: """ frame_data = pamqp_frame.marshal(frame_out, channel_id) self.heartbeat.register_write() self._io.write_to_socket(frame_data)
def write_frames(self, channel_id, frames_out): """Marshal and write any outgoing pamqp frames to the socket. :param int channel_id: :param list frames_out: Amqp frames. :return: """ frame_data = EMPTY_BUFFER for single_frame in frames_out: frame_data += pamqp_frame.marshal(single_frame, channel_id) self._write_to_socket(frame_data)
def write_frame(self, channel_id, frame_out): """Marshal and write an outgoing pamqp frame to the Socket. :param int channel_id: Channel ID. :param pamqp_spec.Frame frame_out: Amqp frame. :return: """ frame_data = pamqp_frame.marshal(frame_out, channel_id) self.heartbeat.register_write() self._io.write_to_socket(frame_data)
def write_frames(self, channel_id, multiple_frames): """Marshal and write multiple outgoing pamqp frames to the socket. :param int channel_id: :param list multiple_frames: Amqp frames. :return: """ frame_data = EMPTY_BUFFER for single_frame in multiple_frames: frame_data += pamqp_frame.marshal(single_frame, channel_id) self._io.write_to_socket(frame_data)
def write_frames(self, channel_id, multiple_frames): """Marshal and write multiple outgoing pamqp frames to the socket. :param int channel_id: :param list multiple_frames: Amqp frames. :return: """ frame_data = EMPTY_BUFFER for single_frame in multiple_frames: frame_data += pamqp_frame.marshal(single_frame, channel_id) self.io.write_to_socket(frame_data)
async def open(self, transport: asyncio.Transport) -> bool: self._transport = transport self._transport.write(frame.marshal(header.ProtocolHeader(), 0)) self._set_state(STATE_PROTOCOL_HEADER_SENT) result = await self._wait_on_state(STATE_OPENOK_RECEIVED, STATE_CLOSEOK_SENT) if self._heartbeat_interval: self._logger.debug('Checking for heartbeats every %2f seconds', self._heartbeat_interval) self._heartbeat_timer = self._loop.call_later( self._heartbeat_interval, self._heartbeat_check) return result == STATE_OPENOK_RECEIVED
def write_frames(self, channel_id, frames_out): """Marshal and write multiple outgoing pamqp frames to the Socket. :param int channel_id: Channel ID/ :param list frames_out: Amqp frames. :return: """ data_out = EMPTY_BUFFER for single_frame in frames_out: data_out += pamqp_frame.marshal(single_frame, channel_id) self.heartbeat.register_write() self._io.write_to_socket(data_out)
def _write_frame(self, channel, value): if not self._data.running: LOGGER.debug('Skipping write frame, not running') return frame_data = frame.marshal(value, channel) try: self._data.fd.sendall(frame_data) except socket.timeout: self._data.failed_write = channel, value except socket.error as exception: self._data.running = False self._data.error_callback(exception)
def _process_start(self, value: commands.Connection.Start) -> None: if (value.version_major, value.version_minor) != ( constants.VERSION[0], constants.VERSION[1]): self._logger.warning( 'AMQP version error (received %i.%i, expected %r)', value.version_major, value.version_minor, constants.VERSION) self._transport.close() return self._set_state( state.STATE_EXCEPTION, exceptions.ClientNegotiationException( 'AMQP version error (received {}.{}, expected {})'.format( value.version_major, value.version_minor, constants.VERSION))) self.properties = dict(value.server_properties) for key in self.properties: if key == 'capabilities': for capability in self.properties[key]: self._logger.debug('Server supports %s: %r', capability, self.properties[key][capability]) else: self._logger.debug('Server %s: %r', key, self.properties[key]) self._transport.write( frame.marshal( commands.Connection.StartOk(client_properties={ 'product': self._product, 'platform': 'Python {}'.format(platform.python_version()), 'capabilities': { 'authentication_failure_close': True, 'basic.nack': True, 'connection.blocked': True, 'consumer_cancel_notify': True, 'consumer_priorities': True, 'direct_reply_to': True, 'per_consumer_qos': True, 'publisher_confirms': True }, 'information': 'See https://aiorabbit.readthedocs.io', 'version': version }, response='\0{}\0{}'.format( self._username, self._password), locale=self._locale), 0)) self._set_state(STATE_STARTOK_SENT)
def test_content_header_with_basic_properties(self): props = commands.Basic.Properties( app_id='unittest', content_type='application/json', content_encoding='bzip2', correlation_id='d146482a-42dd-4b8b-a620-63d62ef686f3', delivery_mode=2, expiration='100', headers={'foo': 'Test ✈'}, message_id='4b5baed7-66e3-49da-bfe4-20a9651e0db4', message_type='foo', priority=10, reply_to='q1', timestamp=datetime.datetime(2019, 12, 19, 23, 29, 00)) expectation = (b'\x02\x00\x01\x00\x00\x00\xa2\x00<\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\n\xff\xe8\x10application/json\x05' b'bzip2\x00\x00\x00\x11\x03fooS\x00\x00\x00\x08Test ' b'\xe2\x9c\x88\x02\n$d146482a-42dd-4b8b-a620-63d62ef68' b'6f3\x02q1\x03100$4b5baed7-66e3-49da-bfe4-20a9651e0db4' b'\x00\x00\x00\x00]\xfc\x07\xbc\x03foo\x08unittest\xce') self.assertEqual(frame.marshal(header.ContentHeader(0, 10, props), 1), expectation)
def test_protocol_header(self): expectation = b'AMQP\x00\x00\t\x01' response = frame.marshal(header.ProtocolHeader(), 0) self.assertEqual(response, expectation, 'ProtocolHeader did not match expectation')
def test_unknown_frame_type(self): with self.assertRaises(ValueError): frame.marshal(self, 1)
def test_content_body(self): value = str(uuid.uuid4()).encode('utf-8') expectation = b'\x03\x00\x01\x00\x00\x00$' + value + b'\xce' self.assertEqual(frame.marshal(body.ContentBody(value), 1), expectation)
def test_content_header(self): expectation = (b'\x02\x00\x01\x00\x00\x00\x0e\x00<\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\n\x00\x00\xce') self.assertEqual(frame.marshal(header.ContentHeader(body_size=10), 1), expectation)
def test_heartbeat(self): expectation = b'\x08\x00\x00\x00\x00\x00\x00\xce' response = frame.marshal(heartbeat.Heartbeat(), 0) self.assertEqual(response, expectation, 'Heartbeat did not match expectation')
def test_content_header(self): expectation = (b'\x02\x00\x01\x00\x00\x00\x0e\x00<\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\n\x00\x00\xce') self.assertEqual(frame.marshal(header.ContentHeader(body_size=10), 1), expectation)
async def _send_frame(self, channel_id: int, frame: AnyFrame) -> None: _logger.debug(f"-> {frame.name}") self._stream_writer.write(bytes(marshal(frame, channel_id))) await self._stream_writer.drain()
def heartbeat_test(self): expectation = encode('\x08\x00\x00\x00\x00\x00\x00\xce') response = frame.marshal(heartbeat.Heartbeat(), 0) self.assertEqual(response, expectation, "Heartbeat did not match expectation")