Ejemplo n.º 1
0
    def _process_buffer(self):
        while self.buffer:
            length, raw = variant.read_variant(self.buffer)
            if len(raw) < length:
                break

            data = raw[:length]
            self.buffer = raw[length:]
            if self.chacha:
                log_binary(_LOGGER, "ENC Phone->ATV", Encrypted=data)
                data = self.chacha.decrypt(data)

            message = protobuf.ProtocolMessage()
            message.ParseFromString(data)
            _LOGGER.info("(DEC Phone->ATV): %s", message)

            try:
                if message.type == protobuf.DEVICE_INFO_MESSAGE:
                    self.handle_device_info(message, message.inner())
                elif message.type == protobuf.CRYPTO_PAIRING_MESSAGE:
                    self.handle_crypto_pairing(message, message.inner())
                else:
                    self.connection.send_raw(data)
            except Exception:  # pylint: disable=broad-except
                _LOGGER.exception("Error while dispatching message")
Ejemplo n.º 2
0
    def data_received(self, data):
        """Message received from iOS app/client."""
        self.buffer += data

        while self.buffer:
            length, raw = variant.read_variant(self.buffer)
            if len(raw) < length:
                break

            data = raw[:length]
            self.buffer = raw[length:]
            if self.chacha:
                log_binary(_LOGGER, 'ENC Phone->ATV', Encrypted=data)
                data = self.chacha.decrypt(data)

            parsed = protobuf.ProtocolMessage()
            parsed.ParseFromString(data)
            _LOGGER.info('(DEC Phone->ATV): %s', parsed)

            try:

                def unhandled_message(_, raw):
                    self.connection.send_raw(raw)

                self.mapping.get(parsed.type, unhandled_message)(parsed, data)
            except Exception:  # pylint: disable=broad-except
                _LOGGER.exception('Error while dispatching message')
Ejemplo n.º 3
0
    def data_received(self, data):
        self.buffer += data

        while self.buffer:
            length, raw = variant.read_variant(self.buffer)
            if len(raw) < length:
                return

            data = raw[:length]
            self.buffer = raw[length:]
            if self.chacha:
                data = self.chacha.decrypt(data)

            parsed = protobuf.ProtocolMessage()
            parsed.ParseFromString(data)
            _LOGGER.info('Incoming message: %s', parsed)

            try:
                name = parsed.Type.Name(
                    parsed.type).lower().replace('_message', '')

                _LOGGER.debug('Received %s message', name)
                getattr(self, 'handle_' + name)(parsed, parsed.inner())
            except AttributeError:
                _LOGGER.exception('No message handler for ' + str(parsed))
            except Exception:
                _LOGGER.exception('Error while dispatching message')
Ejemplo n.º 4
0
    def data_received(self, data):
        self.buffer += data

        while self.buffer:
            length, raw = variant.read_variant(self.buffer)
            if len(raw) < length:
                return

            data = raw[:length]
            self.buffer = raw[length:]
            if self.chacha:
                data = self.chacha.decrypt(data)

            parsed = protobuf.ProtocolMessage()
            parsed.ParseFromString(data)
            log_protobuf(_LOGGER, "<< Receive: Protobuf", parsed)

            try:
                name = parsed.Type.Name(parsed.type).lower().replace("_message", "")

                _LOGGER.debug("Received %s message", name)
                getattr(self, "handle_" + name)(parsed, parsed.inner())
            except AttributeError:
                _LOGGER.exception("No message handler for " + str(parsed))
            except Exception:
                _LOGGER.exception("Error while dispatching message")
Ejemplo n.º 5
0
    def data_received(self, data):
        """Message was received from device."""
        # A message might be split over several reads, so we store a buffer and
        # try to decode messages from that buffer
        self._buffer += data
        log_binary(_LOGGER, self._log_str + "<< Receive", Data=data)

        while self._buffer:
            # The variant tells us how much data must follow
            length, raw = read_variant(self._buffer)
            if len(raw) < length:
                _LOGGER.debug(
                    self._log_str + "Require %d bytes but only %d in buffer",
                    length,
                    len(raw),
                )
                break

            data = raw[:length]  # Incoming message (might be encrypted)
            self._buffer = raw[length:]  # Buffer, might contain more messages

            try:
                self._handle_message(data)
            except Exception:  # pylint: disable=broad-except
                _LOGGER.exception(self._log_str + "Failed to handle message")
Ejemplo n.º 6
0
def decode_and_print_message(args):
    """Decode and print protobuf messages."""
    buf = binascii.unhexlify(args.message)
    if not args.stream:
        buf = variant.write_variant(len(buf)) + buf

    while buf:
        length, raw = variant.read_variant(buf)
        data = raw[:length]
        buf = raw[length:]
        _print_single_message(data, args.unknown_fields)

    return 0
Ejemplo n.º 7
0
def decode_and_print_message(args):
    """Decode and print protobuf messages."""
    # Import here to allow other parts of script, e.g. message generation to run
    # without having pyatv installed
    from pyatv.mrp import variant  # pylint: disable=import-outside-toplevel

    buf = binascii.unhexlify(args.message)
    if not args.stream:
        buf = variant.write_variant(len(buf)) + buf

    while buf:
        length, raw = variant.read_variant(buf)
        data = raw[:length]
        buf = raw[length:]
        _print_single_message(data, args.unknown_fields)

    return 0
Ejemplo n.º 8
0
    def data_received(self, data):
        self.buffer += data

        length, raw = variant.read_variant(self.buffer)
        if len(raw) < length:
            return

        data = raw[:length]
        self.buffer = raw[length:]
        parsed = protobuf.ProtocolMessage()
        parsed.ParseFromString(data)
        _LOGGER.info('Incoming message: %s', parsed)

        try:

            def unhandled_message(message):
                _LOGGER.warning('No message handler for %s', message)

            self.mapping.get(parsed.type, unhandled_message)(parsed)
        except Exception:
            _LOGGER.exception('Error while dispatching message')
Ejemplo n.º 9
0
 def test_read_multiple_bytes(self):
     self.assertEqual(read_variant(b"\xb5\x44")[0], 8757)
     self.assertEqual(read_variant(b"\xc5\x92\x01")[0], 18757)
Ejemplo n.º 10
0
#!/usr/bin/env python3
"""Raw decode sequence of messages with protoc.

Pass hex string (including variant length). Multiple messages
are supported.
"""

import os
import sys
import binascii

from pyatv.mrp import variant

if __name__ == '__main__':
    buf = binascii.unhexlify(sys.argv[1])
    while buf:
        length, raw = variant.read_variant(buf)
        data = raw[:length]
        buf = raw[length:]

        hexdata = binascii.hexlify(data).decode('ascii')
        print('Raw:', hexdata, '\n')
        print('Decoded')
        os.system('echo ' + hexdata + ' | xxd -r -p | protoc --decode_raw')
        print(40 * '-')
Ejemplo n.º 11
0
 def test_read_single_byte(self):
     self.assertEqual(read_variant(b"\x00")[0], 0x00)
     self.assertEqual(read_variant(b"\x35")[0], 0x35)
Ejemplo n.º 12
0
 def test_read_invalid_variant(self):
     with self.assertRaises(Exception):
         read_variant(b"\x80")
Ejemplo n.º 13
0
 def test_read_and_return_remaining_data(self):
     value, remaining = read_variant(b"\xb5\x44\xca\xfe")
     self.assertEqual(value, 8757)
     self.assertEqual(remaining, b"\xca\xfe")
Ejemplo n.º 14
0
def test_read_single_byte():
    assert read_variant(b"\x00")[0] == 0x00
    assert read_variant(b"\x35")[0] == 0x35
Ejemplo n.º 15
0
def test_read_invalid_variant():
    with pytest.raises(Exception):
        read_variant(b"\x80")
Ejemplo n.º 16
0
def test_read_and_return_remaining_data():
    value, remaining = read_variant(b"\xb5\x44\xca\xfe")
    assert value == 8757
    assert remaining == b"\xca\xfe"
Ejemplo n.º 17
0
def test_read_multiple_bytes():
    assert read_variant(b"\xb5\x44")[0] == 8757
    assert read_variant(b"\xc5\x92\x01")[0] == 18757