2

我正在尝试用Kaitai语言(.ksy 文件)描述SSH协议。一开始有如下格式的协议版本交换:

SSH-protoversion-softwareversion SP comments CR LF

哪里SP comments是可选的。AFAIK,没有办法将属性描述为完全可选的,只能通过if条件。有谁知道如何在 Kaitai 中描述这种关系,以便解析器也接受这种格式:SSH-protoversion-softwareversion CR LF

谢谢

4

1 回答 1

4

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.eofcomments属性添加额外内容。

于 2020-02-15T18:49:46.843 回答