Démarshalling de messages proto inconnus sans informations de type
Bien que la méthode proto.Unmarshal() de protobuf nécessite un type de message connu, les messages inconnus présentent un défi . Cependant, nous pouvons extraire des informations limitées à l'aide du package protowire.
Approche :
Identifier le type de champ, qui pourrait être :
Modèle de données :
type Field struct { Tag Tag Val Val } type Tag struct { Num int32 Type protowire.Type } type Val struct { Payload interface{} Length int }
Parseur :
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 }
Exemple (Structure du message) :
message Foo { string a = 1; string b = 2; Bar bar = 3; } message Bar { string c = 1; }
Exemple (sortie analysée) :
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}}
Considérations :
Bien que ce code ne fournisse pas une solution complète de niveau production, il offre une méthode pour analyser les charges utiles de proto inconnues tout en préservant certaines informations sémantiques.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!