def from_bytes(cls, bitstream):
        '''
        Parse the given packet and update properties accordingly
        '''
        packet = cls()

        # Convert to ConstBitStream (if not already provided)
        if not isinstance(bitstream, ConstBitStream):
            if isinstance(bitstream, Bits):
                bitstream = ConstBitStream(auto=bitstream)
            else:
                bitstream = ConstBitStream(bytes=bitstream)

        # Read the type
        type_nr = bitstream.read('uint:4')
        if type_nr != packet.message_type:
            msg = 'Invalid bitstream for a {0} packet'
            class_name = packet.__class__.__name__
            raise ValueError(msg.format(class_name))

        # Read the flags
        packet.proxy_map_reply = bitstream.read('bool')

        # Skip reserved bits
        packet._reserved1 = bitstream.read(1)

        # NATT bits
        has_xtr_site_id = bitstream.read('bool')
        packet.for_rtr = bitstream.read('bool')

        # Skip reserved bits
        packet._reserved2 = bitstream.read(15)

        # Read the rest of the flags
        packet.want_map_notify = bitstream.read('bool')

        # Store the record count until we need it
        record_count = bitstream.read('uint:8')

        # Read the nonce
        packet.nonce = bitstream.read('bytes:8')

        # Read the key id
        packet.key_id = bitstream.read('uint:16')

        # Read the authentication data
        data_length = bitstream.read('uint:16')
        packet.authentication_data = bitstream.read('bytes:%d' % data_length)

        # Read the records
        for dummy in range(record_count):
            record = MapRegisterRecord.from_bytes(bitstream)
            packet.records.append(record)

        # Read the xtr-id and site-id
        if has_xtr_site_id:
            packet.xtr_id = bitstream.read('uint:128')
            packet.site_id = bitstream.read('uint:64')

        # Verify that the properties make sense
        packet.sanitize()

        return packet