我正在尝试用Kaitai语言(.ksy 文件)描述SSH协议。一开始有如下格式的协议版本交换:
SSH-protoversion-softwareversion SP comments CR LF
哪里SP comments
是可选的。AFAIK,没有办法将属性描述为完全可选的,只能通过if
条件。有谁知道如何在 Kaitai 中描述这种关系,以便解析器也接受这种格式:SSH-protoversion-softwareversion CR LF
?
谢谢
我正在尝试用Kaitai语言(.ksy 文件)描述SSH协议。一开始有如下格式的协议版本交换:
SSH-protoversion-softwareversion SP comments CR LF
哪里SP comments
是可选的。AFAIK,没有办法将属性描述为完全可选的,只能通过if
条件。有谁知道如何在 Kaitai 中描述这种关系,以便解析器也接受这种格式:SSH-protoversion-softwareversion CR LF
?
谢谢
Kaitai Struct 并非设计为传统意义上的语法(即映射到常规语言、上下文无关语法、BNF或类似的东西)。传统语法有“这个元素是可选的”或“这个元素可以重复多次”的概念,但 KS 则相反:它甚至不是试图解决歧义问题,而是建立在一个事实之上,即所有二进制格式被设计为明确的。
因此,每当您遇到诸如“可选元素”或“重复元素”之类的内容而没有任何进一步的上下文时,请暂停一下并考虑 Kaitai Struct 是否是完成任务的正确工具,它真的是二进制格式吗?试图解析。例如,使用 KS 解析 JSON、XML 或 YAML 之类的东西在理论上可能是可行的,但结果并没有多大用处。
也就是说,在这种特殊情况下,完全可以使用 Kaitai Struct,您只需要考虑现实生活中的二进制解析器将如何处理它。据我了解,现实生活中的解析器将读取整行,直到 CR 字节,然后再尝试解释该行的内容。您可以使用以下方法在 KS 中对其进行建模:
seq:
- id: line
terminator: 0xd # CR
type: version_line
# ^^^ this creates a substream with all bytes up to CR byte
- id: reserved_lf
contents: [0xa]
types:
version_line:
seq:
- id: magic
contents: 'SSH-'
- id: proto_version
type: str
terminator: 0x2d # '-'
- id: software_version
type: str
terminator: 0x20 # ' '
eos-error: false
# ^^^ if we don't find that space and will just hit end of stream, that's fine
- id: comments
type: str
size-eos: true
# ^^^ if we still have some data in the stream, that's all comment
如果您想null
在不包含注释时获取注释而不是空字符串,只需if: not _io.eof
为comments
属性添加额外内容。