沒有類型資訊的未知Proto 訊息解組
雖然protobuf 的proto.Unmarshal() 方法需要已知的訊息類型,但未知消息提出了挑戰。但是,我們可以使用 protowire 套件提取有限的資訊。
方法:
標識欄位類型,可以為:
數據模型:
type Field struct { Tag Tag Val Val } type Tag struct { Num int32 Type protowire.Type } type Val struct { Payload interface{} Length int }
解析器:
func parseUnknown(b []byte) []Field { // Iteratively consume and parse fields for len(b) > 0 { // Read field tag and length n, t, fieldlen := protowire.ConsumeField(b) if fieldlen < 1 { return nil } field := Field{Tag: Tag{Num: int32(n), Type: t}} // Read and process tag and value content _, _, taglen := protowire.ConsumeTag(b[:fieldlen]) if taglen < 1 { return nil } var v interface{} var vlen int switch t { case protowire.VarintType: v, vlen = protowire.ConsumeVarint(b[taglen:fieldlen]) case protowire.Fixed64Type: v, vlen = protowire.ConsumeFixed64(b[taglen:fieldlen]) case protowire.BytesType: v, vlen = protowire.ConsumeBytes(b[taglen:fieldlen]) sub := parseUnknown(v.([]byte)) if sub != nil { v = sub } case protowire.StartGroupType: v, vlen = protowire.ConsumeGroup(n, b[taglen:fieldlen]) sub := parseUnknown(v.([]byte)) if sub != nil { v = sub } case protowire.Fixed32Type: v, vlen = protowire.ConsumeFixed32(b[taglen:fieldlen]) } if vlen < 1 { return nil } field.Val = Val{Payload: v, Length: vlen - taglen} fields = append(fields, field) b = b[fieldlen:] } return fields }
示例(訊息結構):
message Foo { string a = 1; string b = 2; Bar bar = 3; } message Bar { string c = 1; }
範例(已解析輸出):
main.Field{Tag:main.Tag{Num:1, Type:2}, Val:main.Val{Payload:[]uint8{0x41}, Length:1}} main.Field{Tag:main.Tag{Num:2, Type:2}, Val:main.Val{Payload:[]uint8{0x42}, Length:1}} main.Field{Tag:main.Tag{Num:1, Type:2}, Val:main.Val{Payload:[]uint8{0x43}, Length:1}} main.Field{Tag:main.Tag{Num:3, Type:2}, Val:main.Val{Payload:[]main.Field{main.Field{Tag:main.Tag{Num:1, Type:2}, Val:main.Val{Payload:[]uint8{0x43}, Length:1}}}, Length:3}}
注意事項:
根據相同的欄位標籤編號進行處理。
Maps: 假設類似重複的 k/v 對。 Oneofs: Union類型資訊遺失,只有實際值雖然此程式碼沒有提供完整的生產級解決方案,但它提供了一種解析未知原始有效負載的方法,同時保留一些語意資訊。以上是如何在沒有類型資訊的情況下解析未知的 Protobuf 訊息?的詳細內容。更多資訊請關注PHP中文網其他相關文章!