예제 #1
0
def PrefixedOffset(sizetype, type, offs=0):
    return C.FocusedSeq(
        "content", "_data" / C.Rebuild(
            C.Struct("size" / C.Rebuild(sizetype,
                                        C.len_(this.data) - offs),
                     "data" / C.Bytes(this.size + offs)), lambda obj:
            {"data": type.build(obj.content, **{
                **obj._params,
                **obj
            })}), "content" / C.RestreamData(this._data.data, type))
def LifeScanPacket(include_link_control: bool, ) -> construct.Struct:  # pylint: disable=invalid-name
    if include_link_control:
        link_control_construct = _LINK_CONTROL
    else:
        link_control_construct = construct.Const(b"\x00")

    return construct.Struct(
        "data" / construct.RawCopy(
            construct.Struct(
                construct.Const(b"\x02"),  # stx
                "length" / construct.Rebuild(
                    construct.Byte, lambda this: len(this.message) + 6),
                "link_control" / link_control_construct,
                "message" / construct.Bytes(lambda this: this.length - 6),
                construct.Const(b"\x03"),  # etx
            ), ),
        "checksum" / construct.Checksum(construct.Int16ul, lifescan.crc_ccitt,
                                        construct.this.data.data),
    )
예제 #3
0
def LifeScanPacket(include_link_control):  # pylint: disable=invalid-name
    # type: (bool) -> construct.Struct
    if include_link_control:
        link_control_construct = _LINK_CONTROL
    else:
        link_control_construct = construct.Const(b'\x00')

    return construct.Struct(
        'data' / construct.RawCopy(
            construct.Struct(
                construct.Const(b'\x02'),  # stx
                'length' / construct.Rebuild(
                    construct.Byte, lambda this: len(this.message) + 6),
                'link_control' / link_control_construct,
                'message' / construct.Bytes(lambda this: this.length - 6),
                construct.Const(b'\x03'),  # etx
            ), ),
        'checksum' / construct.Checksum(construct.Int16ul, lifescan.crc_ccitt,
                                        construct.this.data.data),
    )
예제 #4
0
def LifeScanPacket(command_prefix, include_link_control):
    if include_link_control:
        link_control_construct = _LINK_CONTROL
    else:
        link_control_construct = construct.Const(b'\x00')

    command_prefix_construct = construct.Const(command_prefix, construct.Byte)

    return construct.Struct(
        'data' / construct.RawCopy(
            construct.Struct(
                construct.Const(b'\x02'),  # stx
                'length' / construct.Rebuild(
                    construct.Byte, lambda this: len(this.message) + 7),
                'link_control' / link_control_construct,
                'command_prefix' / command_prefix_construct,
                'message' / construct.Bytes(lambda this: this.length - 7),
                construct.Const(b'\x03'),  # etx
            ), ),
        'checksum' / construct.Checksum(construct.Int16ul, lifescan.crc_ccitt,
                                        construct.this.data.data),
    )
예제 #5
0
def DataEntry(type):
    return C.FocusedSeq(
        "values",
        "_count" / C.Rebuild(Int32ul, C.len_(this.values)),
        "values" / C.Switch(
            type,
            {
                0: Pass,
                1: ClassEntry(),
                2: ClassEntry(),
                3: Byte,  #boolean
                4: Int8ul,
                5: Int16ul,
                6: Int32ul,
                7: Int64ul,
                8: Int8sl,
                9: Int16sl,
                10: Int32sl,
                11: Int64sl,
                12: Float32l,
                13: Float64l,
                14: CString("utf8"),
                15: RGBA(),
                16: Int64ul,  #pointer
                #17: Int32ul #size, potentially not a uint but that's probably the best option of it
                20: Vector3(),
                21: Vector4(),
                22: Quat4(),
                32: CString(
                    'utf8'
                ),  #specifically a CString, while 14 is probably something like std::string
                46: Capsule(),
                64: Vector2()
            },
            default=C.StopFieldError)[this._count],
    )
예제 #6
0
        "require_user_click" / c.Flag,
        "red_background" / c.Flag,
        "delay" / c.BitsInteger(4),
    ), _transform_vendor_trust, 2, _transform_vendor_trust, 2)

VendorHeader = c.Struct(
    "_start_offset" / c.Tell,
    "magic" / c.Const(b"TRZV"),
    "_header_len" / c.Padding(4),
    "expiry" / c.Int32ul,
    "version" / c.Struct(
        "major" / c.Int8ul,
        "minor" / c.Int8ul,
    ),
    "vendor_sigs_required" / c.Int8ul,
    "vendor_sigs_n" / c.Rebuild(c.Int8ul, c.len_(c.this.pubkeys)),
    "vendor_trust" / VendorTrust,
    "reserved" / c.Padding(14),
    "pubkeys" / c.Bytes(32)[c.this.vendor_sigs_n],
    "vendor_string" / c.Aligned(4, c.PascalString(c.Int8ul, "utf-8")),
    "vendor_image" / Toif,
    "_data_end_offset" / c.Tell,
    c.Padding(-(c.this._data_end_offset + 65) % 512),
    "sigmask" / c.Byte,
    "signature" / c.Bytes(64),
    "_end_offset" / c.Tell,
    "header_len" /
    c.Pointer(c.this._start_offset + 4,
              c.Rebuild(c.Int32ul, c.this._end_offset - c.this._start_offset)),
)
예제 #7
0
def create_rotator(inverse: bool):
    return lambda obj, ctx: bytes(
        rotate_bytes(obj, ctx.header.bytes_rotation, ctx.header.bytes_rotation,
                     inverse))


PermalinkBinary = construct.FocusedSeq(
    "fields",
    schema_version=construct.Const(_CURRENT_SCHEMA_VERSION, construct.Byte),
    fields=construct.RawCopy(
        construct.Aligned(
            3,
            construct.Struct(
                header=construct.BitStruct(
                    has_seed_hash=construct.Rebuild(
                        construct.Flag, construct.this._.seed_hash != None),
                    bytes_rotation=construct.Rebuild(
                        construct.BitsInteger(7),
                        lambda ctx: single_byte_hash(ctx._.generator_params) >>
                        1,
                    )),
                seed_hash=construct.If(construct.this.header.has_seed_hash,
                                       construct.Bytes(5)),
                randovania_version=construct.Bytes(4),  # short git hash
                generator_params=construct.ExprAdapter(
                    construct.Prefixed(construct.VarInt,
                                       construct.GreedyBytes),
                    # parsing
                    decoder=create_rotator(inverse=True),
                    # building
                    encoder=create_rotator(inverse=False),
예제 #8
0
    @classmethod
    def _get_type_for_name(cls, name):
        """ Returns the type that's appropriate for a given descriptor field name. """

        try:
            return cls.USB_TYPES[cls._get_prefix(name)]
        except KeyError:
            raise ValueError(
                "field names must be formatted per the USB standard!")

    def __init__(self, description="", default=None):
        self.description = description
        self.default = default

    def __rtruediv__(self, field_name):
        field_type = self._get_type_for_name(field_name)

        if self.default is not None:
            field_type = construct.Default(field_type, self.default)

        # Build our subconstruct. Construct makes this look super weird,
        # but this is actually "we have a field with <field_name> of type <field_type>".
        # In long form, we'll call it "description".
        return (field_name / field_type) * self.description


# Convenience type that gets a descriptor's own length.
DescriptorLength = \
     construct.Rebuild(construct.Int8ul, construct.len_(construct.this)) \
     * "Descriptor Length"
예제 #9
0
ClassMemberDefinition = Struct(
    "name" / DataPointer(Int64ul, CString("utf8"), "names"),
    "type" / Byte,
    "unkn" / Byte,
    "size" / Byte,
    "_unknData" / C.Default(Byte[69], [0 for _ in range(69)]),
)

ClassDefinition = DataPointer(
    Int64ul,
    Struct("hash" / Int64ul,
           "members" / C.PrefixedArray(Int64ul, ClassMemberDefinition)),
    "definitionData")

ClassDefinitionList = C.FocusedSeq(
    "definitions", "_count" / C.Rebuild(Int32ul, C.len_(this.definitions)),
    "definitions" / C.Prefixed(
        Int32ul,
        C.Aligned(
            8,
            C.FocusedSeq(
                "definitions",
                "definitions" / ClassDefinition[this._._count],
                DataEntries("definitionData"),
                DataEntries("names"),
            ))))

# Hierarchy handling
varcount = 0

예제 #10
0
    heading_radians=c.Float32l,
    # 132
    flags=ValidFlags,
    # 134
    _pad3=c.Padding(140 - 134),
    # 140
    time_offset=c.Int32ul,
    sounded_data=c.Array(count=c.this.packet_size, subcon=c.Int8ul))

sl3_frame = c.Struct(
    # 0
    frame_offset=c.Int32ul,
    # 4
    _pad4=c.Padding(4),
    # 8
    frame_size=c.Rebuild(c.Int16ul, c.this.packet_size + 168),
    previous_frame_size=c.Int16ul,
    channel_type=ChannelType,
    # 14
    _pad14=c.Padding(2),
    # 16
    frame_index=c.Int32ul,
    upper_limit_feet=c.Float32l,
    lower_limit_feet=c.Float32l,
    # 28
    _pad28=c.Padding(40 - 28),
    # 40
    creation_date_time=c.Default(c.Int32sl, -1),
    packet_size=c.Int16ul,
    # 44
    _pad46=c.Padding(2),
예제 #11
0
def xor_checksum(msg: bytes) -> int:
    return functools.reduce(operator.xor, msg)


class Direction(enum.Enum):
    In = 0x20
    Out = 0x10


_PACKET = construct.Struct(
    stx=construct.Const(0x53, construct.Byte),
    direction=construct.Mapping(construct.Byte,
                                {e: e.value
                                 for e in Direction}),
    length=construct.Rebuild(construct.Byte,
                             lambda this: len(this.message) + 2),
    message=construct.Bytes(lambda this: this.length - 2),
    checksum=construct.Checksum(construct.Byte, xor_checksum,
                                construct.this.message),
    etx=construct.Const(0xAA, construct.Byte),
)

_FIRST_MESSAGE = construct.Struct(
    const_1=construct.Const(0x30, construct.Byte),
    count=construct.Int16ub,
    const_2=construct.Const(0xAA, construct.Byte)[19],
)

_CHALLENGE_PACKET_FULL = b"\x53\x20\x04\x10\x30\x20\xAA"
_RESPONSE_MESSAGE = b"\x10\x40"
예제 #12
0
def profile_base(is_v1, recipe_name_encoding="GBK"):
    """Build a Construct for IHCooker recipes based on version and name encoding."""
    return c.Struct(
        c.Const(3, c.Int8un),
        "device_version" / c.Default(c.Enum(c.Int8ub, **DEVICE_ID), 1 if is_v1 else 2),
        "menu_location"
        / c.Default(c.ExprValidator(c.Int8ub, lambda o, _: 0 <= o < 10), 9),
        "recipe_name"
        / c.Default(
            c.ExprAdapter(
                c.StringEncoded(  # PaddedString wrapper does not support GBK encoding.
                    c.FixedSized(
                        RECIPE_NAME_MAX_LEN_V1 if is_v1 else RECIPE_NAME_MAX_LEN_V2,
                        c.NullStripped(c.GreedyBytes),
                    ),
                    recipe_name_encoding,
                ),
                lambda x, _: x.replace("\n", " "),
                lambda x, _: x.replace(" ", "\n"),
            ),
            "Unnamed",
        ),
        c.Padding(1) if is_v1 else c.Padding(2),
        "recipe_id" / c.Default(c.Int32ub, lambda _: random.randint(0, 2 ** 32 - 1)),
        "menu_settings"
        / c.Default(
            c.BitStruct(  # byte 37
                "save_recipe" / c.Default(c.Flag, 0),
                "confirm_start" / c.Default(c.Flag, 0),
                "menu_unknown3" / c.Default(c.Flag, 0),
                "menu_unknown4" / c.Default(c.Flag, 0),
                "menu_unknown5" / c.Default(c.Flag, 0),
                "menu_unknown6" / c.Default(c.Flag, 0),
                "menu_unknown7" / c.Default(c.Flag, 0),
                "menu_unknown8" / c.Default(c.Flag, 0),
            ),
            {},
        ),
        "duration_hours"
        / c.Rebuild(
            c.Int8ub, lambda ctx: ctx.get("duration_minutes", 0) // 60
        ),  # byte 38
        "duration_minutes"
        / c.Default(
            c.ExprAdapter(
                c.Int8ub, lambda obj, ctx: obj + ctx.duration_hours * 60, c.obj_ % 60
            ),
            60,
        ),  # byte 39
        "duration_max_hours"
        / c.Rebuild(
            c.Int8ub, lambda ctx: ctx.get("duration_max_minutes", 0) // 60
        ),  # byte 40
        "duration_max_minutes"
        / c.Default(
            c.ExprAdapter(
                c.Int8ub,
                lambda obj, ctx: obj + ctx.duration_max_hours * 60,
                c.obj_ % 60,
            ),
            0,
        ),  # byte 41
        "duration_min_hours"
        / c.Rebuild(
            c.Int8ub, lambda ctx: ctx.get("duration_min_minutes", 0) // 60
        ),  # byte 42
        "duration_min_minutes"
        / c.Default(
            c.ExprAdapter(
                c.Int8ub,
                lambda obj, ctx: obj + ctx.duration_min_hours * 60,
                c.obj_ % 60,
            ),
            0,
        ),  # byte 43
        c.Padding(2),  # byte 44, 45
        "unknown_46" / c.Default(c.Byte, 1),  # byte 46, should be set to 1
        c.Padding(7) if is_v1 else c.Padding(1),
        "stages"
        / c.Default(
            ArrayDefault(
                15,
                c.Struct(  # byte 48-168
                    "mode" / c.Default(c.Enum(c.Byte, StageMode), StageMode.FireMode),
                    "hours"
                    / c.Rebuild(
                        c.Int8ub, lambda ctx: (ctx.get("minutes", 0) // 60) + 128
                    ),
                    "minutes"
                    / c.Default(
                        c.ExprAdapter(
                            c.Int8ub,
                            decoder=lambda obj, ctx: obj + (ctx.hours - 128) * 60,
                            encoder=c.obj_ % 60,
                        ),
                        DEFAULT_PHASE_MINUTES,
                    ),
                    "temp_threshold" / c.Default(c.Int8ub, DEFAULT_THRESHOLD_CELCIUS),
                    "temp_target" / c.Default(c.Int8ub, DEFAULT_TEMP_TARGET_CELCIUS),
                    "power" / c.Default(c.Int8ub, DEFAULT_FIRE_LEVEL),
                    "fire_off" / c.Default(c.Int8ub, DEFAULT_FIRE_ON_OFF),
                    "fire_on" / c.Default(c.Int8ub, DEFAULT_FIRE_ON_OFF),
                ),
                default=dict(
                    mode=StageMode.FireMode,
                    minutes=DEFAULT_PHASE_MINUTES,
                    temp_threshold=DEFAULT_THRESHOLD_CELCIUS,
                    temp_target=DEFAULT_TEMP_TARGET_CELCIUS,
                    power=DEFAULT_FIRE_LEVEL,
                    fire_off=DEFAULT_FIRE_ON_OFF,
                    fire_on=DEFAULT_FIRE_ON_OFF,
                ),
            ),
            [],
        ),
        c.Padding(16) if is_v1 else c.Padding(6),  # byte 169-174
        "unknown175" / c.Default(c.Int8ub, 0),
        "unknown176" / c.Default(c.Int8ub, 0),
        "unknown177" / c.Default(c.Int8ub, 0),
        "crc"  # byte 178-179
        / RebuildStream(
            c.Bytes(2), crc16
        ),  # Default profiles have invalid crc, c.Checksum() raises undesired error when parsed.
    )
예제 #13
0
파일: message.py 프로젝트: DrPyser/plumber
def decode_attrs(raw: str) -> dict:
    import shlex
    pairs = shlex.split(raw)
    attrs = dict(p.split("=", maxsplit=1) for p in pairs)
    return attrs


def encode_attrs(attrs: dict) -> str:
    return " ".join(f"{k}=\"{str(v)}\"" for k, v in attrs.items())


PlumbMessageFormat = construct.Struct(
    "src" / header_line, "dst" / header_line, "type" / header_line,
    "attrs" / header_line,
    "ndata" / construct.Rebuild(header_line, lambda this: str(len(this.data))),
    "data" / construct.Byte[lambda this: int(this.ndata)])


class PlumbMsg(typing.NamedTuple):
    src: str
    dst: str
    type: str
    attrs: dict
    ndata: int
    data: bytes


class ParseError(ValueError):
    pass
예제 #14
0
    ),
)

MSC_TRANSPORT_SUSPEND_RESPONSE_PACKET = construct.Padded(
    BLOCK_SIZE,
    construct.Struct(HEADER_CON, RANDOM_TOKEN_CON, construct.Const(bytes([0x00]))),
)

MSC_TRANSPORT_COMMAND_PACKET = construct.Padded(
    BLOCK_SIZE,
    construct.Struct(
        HEADER_CON,
        TOKEN_CON,
        "command_data_length"
        / construct.Rebuild(
            construct.Int16ub, construct.len_(construct.this.command_data)
        ),
        construct.Const(bytes([0x00, 0x00])),
        "command_data" / construct.Byte[construct.this.command_data_length],
    ),
)

MSC_TRANSPORT_RESPONSE_PACKET = construct.Padded(
    BLOCK_SIZE,
    construct.Struct(
        HEADER_CON,
        RANDOM_TOKEN_CON,
        "response_data" / construct.Prefixed(construct.Int16ub, construct.GreedyBytes),
    ),
)
예제 #15
0
ConfigurationDescriptor = DescriptorFormat(
    "bLength" / construct.Const(9, construct.Int8ul),
    "bDescriptorType" /
    DescriptorNumber(StandardDescriptorNumbers.CONFIGURATION),
    "wTotalLength" / DescriptorField("Length including subordinates"),
    "bNumInterfaces" / DescriptorField("Interface count"),
    "bConfigurationValue" / DescriptorField("Configuration number", default=1),
    "iConfiguration" / DescriptorField("Description string", default=0),
    "bmAttributes" / DescriptorField("Attributes", default=0x80),
    "bMaxPower" / DescriptorField("Max power consumption", default=250),
)

# Field that automatically reflects a string descriptor's length.
StringDescriptorLength = construct.Rebuild(
    construct.Int8ul,
    construct.len_(this.bString) * 2 + 2)

StringDescriptor = DescriptorFormat(
    "bLength" / StringDescriptorLength,
    "bDescriptorType" / DescriptorNumber(StandardDescriptorNumbers.STRING),
    "bString" / construct.GreedyString("utf_16_le"))


StringLanguageDescriptorLength = \
     construct.Rebuild(construct.Int8ul, construct.len_(this.wLANGID) * 2 + 2)

StringLanguageDescriptor = DescriptorFormat(
    "bLength" / StringLanguageDescriptorLength,
    "bDescriptorType" / DescriptorNumber(StandardDescriptorNumbers.STRING),
    "wLANGID" / construct.GreedyRange(construct.Int16ul))
예제 #16
0
TRANSPORT_COMMAND_PACKET = construct.Struct(
    construct.Const(bytes([0x5C, 0x54])),
    "command" / construct.Int16ub,
    "command_data" / construct.Prefixed(
        construct.Int16ub, construct.GreedyRange(TRANSPORT_DATA_PARAMETER)),
)

TRANSPORT_COMMAND_CONTINUE_FRAGMENTED_READ = bytes([0xC5])
TRANSPORT_COMMAND_ABORT_FRAGMENTED_READ = bytes([0xC4])

TRANSPORT_ERROR_RESPONSE_PACKET = construct.Struct("error_code" /
                                                   construct.Int16ub)

TRANSPORT_EXPORT_DATA_RESPONSE_PACKET = construct.Struct(
    construct.Const(bytes([0x90, 0x00])),
    "response_data_length" / construct.Rebuild(
        construct.Int64ub, construct.len_(construct.this.response_data)),
    "response_data" / construct.GreedyBytes,
)

TRANSPORT_RESPONSE_PACKET = construct.Struct(
    "response_data_length" / construct.Rebuild(
        construct.Int16ub, construct.len_(construct.this.response_data)),
    "response_data" / construct.GreedyBytes,
)

TRANSPORT_RESULT = construct.GreedyRange(TRANSPORT_DATA_PARAMETER)


class Transport:
    def __init__(self, tse_path):
        self._transport = msc_transport.MscTransport(tse_path)