This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
from __future__ import annotations
|
||||
import struct
|
||||
MAGIC=b"CHM10DS1";FRAME=struct.Struct("<8sIIiiIIQ24s");NAMES=("app.pbm","app.json","app.xml","app.crc");MAX_FILE=4096;MAX_WIRE=16768
|
||||
class ProtocolError(ValueError):pass
|
||||
def frame(raw):
|
||||
if len(raw)!=64:raise ProtocolError("frame size")
|
||||
v=FRAME.unpack(raw)
|
||||
if v[0]!=MAGIC or v[1]!=1 or v[8]!=bytes(24):raise ProtocolError("frame identity")
|
||||
return v
|
||||
def parse_stream(raw:bytes)->dict[str,bytes]:
|
||||
if not isinstance(raw,bytes) or not 128<=len(raw)<=MAX_WIRE:raise ProtocolError("stream length")
|
||||
first=frame(raw[:64]);kind,status,saved,index,length,total=first[2:8]
|
||||
if kind==4:raise ProtocolError(f"target error {status}:{saved}")
|
||||
if (kind,status,saved,index,length,total)!=(1,0,0,4,0,0):raise ProtocolError("header invalid")
|
||||
offset=64;files={};transferred=0
|
||||
for expected,name in enumerate(NAMES):
|
||||
if offset+64>len(raw):raise ProtocolError("file frame truncated")
|
||||
value=frame(raw[offset:offset+64]);offset+=64;kind,status,saved,index,length,total=value[2:8]
|
||||
if kind==4:raise ProtocolError(f"target error {status}:{saved}")
|
||||
if kind!=2 or status or saved or index!=expected or length>MAX_FILE or total!=transferred:raise ProtocolError("file frame invalid")
|
||||
if offset+length>len(raw):raise ProtocolError("file truncated")
|
||||
files[name]=raw[offset:offset+length];offset+=length;transferred+=length
|
||||
if offset+64!=len(raw):raise ProtocolError("terminal position")
|
||||
value=frame(raw[offset:]);kind,status,saved,index,length,total=value[2:8]
|
||||
if (kind,status,saved,index,length,total)!=(3,0,0,4,0,transferred):raise ProtocolError("terminal invalid")
|
||||
return files
|
||||
Reference in New Issue
Block a user