Highlights
⚡ construct replaced with stdlib parsing
Every binary protocol pymobiledevice3 speaks (DTX, RemoteXPC, usbmux, AFC, tunnel pairing, pcapd, kcdata stackshots, network monitor, syslog, baseband mbn/ftab) is now parsed with a small struct-based module (pymobiledevice3.binary) instead of construct. construct and construct-typing are no longer direct dependencies. Parsing and building are 4-22x faster (XPC parse+decode 826 → 63 µs, a 1.1 MB stackshot to JSON 183 → 27 ms). The CLI feels about the same, since startup and device round-trips dominate, except core-profile-session stackshot --json, which is ~0.16 s faster. Parsed values are typed dataclasses, and malformed data raises BinaryParseError with the record, field and offset.
🐛 Fixes that came with the port
- ftab: adding an entry (the Rose restore path that appends
rrko) overwrote the first payload of the image. - kcdata stackshots:
io_statisticscounters were read from the wrong layout;ts_pid,cputype/cpusubtype, donating pids and thread priorities were read unsigned; a name cut mid-UTF-8-character or a truncated stackshot no longer fails the whole parse. - pcap: pcapng blocks carry the device's capture time instead of the host's clock; a process name cut mid-UTF-8-character no longer ends
watch(). - syslog: an unknown log level no longer ends the stream.
- usbmux: a malformed device record no longer kills the tunneld monitor task.
- AFC/XPC: a string with an embedded NUL is rejected instead of silently becoming a different request.
- XPC: dates before 1970 decode correctly (also on Windows).
- netstat: an address without a decodable payload no longer crashes the CLI.
⚠️ Low-level API changes
The documented service APIs are unchanged. Internal protocol objects changed. The module-level construct structs (XpcWrapper, dtx_fragment_header, afc_*_t, usbmuxd_*, device_packet_struct, the kcdata structs, pymobiledevice3.construct_compat, ...) are replaced by dataclasses with parse()/build(). The full list is in #2031. If you use PcapdService.watch(), packets are now DevicePacket dataclasses: attribute access (packet.pid, packet.data, ...) works as before, but dict-style access (packet["pid"]) is gone.
What's Changed
- bce8898 treewide: Drop the construct and construct-typing dependencies (#2031) (@doronz88)
- 0aee41d mobilebackup2: Parse ManifestKey without pyiosbackup's construct struct (#2031) (@doronz88)
- 3e28831 utils: Read unsigned integers without construct (#2031) (@doronz88)
- bb07ea8 os_trace: Declare the syslog record header with BinaryStruct (#2031) (@doronz88)
- fa1831c network_monitor: Parse socket addresses without construct (#2031) (@doronz88)
- b00bf77 core_profile_session_tap: Parse kcdata stackshots without construct (#2031) (@doronz88)
- 7cb54a4 pcapd: Parse captured packets without construct (#2031) (@doronz88)
- a4fe4b2 restore: Parse baseband mbn and ftab images without construct (#2031) (@doronz88)
- 2b0bcf2 tunnel_service: Encode pairing TLV8 and tunnel packets without construct (#2031) (@doronz88)
- d351895 afc: Parse and build packets without construct (#2031) (@doronz88)
- ad5b975 usbmux: Parse the binary protocol without construct (#2031) (@doronz88)
- 804371c remotexpc: Parse and build XPC messages without construct (#2031) (@doronz88)
- 64fb2ef dtx: Parse fragments, primitives and aux data without construct (#2031) (@doronz88)
- 59537b9 binary: Add declarative fixed-size records and a byte reader (#2031) (@doronz88)
Full Changelog: v11.31.0...v11.32.0