Maison >développement back-end >Golang >Comment puis-je analyser les messages Protobuf inconnus sans informations de type ?

Comment puis-je analyser les messages Protobuf inconnus sans informations de type ?

Patricia Arquette
Patricia Arquetteoriginal
2024-11-28 01:36:10715parcourir

How Can I Parse Unknown Protobuf Messages Without Type Information?

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 :

  1. Utilisez protowire.ConsumeField() pour parcourir la charge utile du message inconnu.
  2. Identifier le type de champ, qui pourrait être :

    • Varint
    • Fixed64
    • Bytes
    • StartGroup
    • Fixed32
  3. Analyser la charge utile du champ en fonction de son tapez.
  4. Gérez les sous-messages en analysant de manière récursive leurs charges utiles.

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 :

  • Sous-messages : Analyse récursive de charges utiles d'octets identifiées comme messages.
  • Champs répétés : Gérés en fonction de numéros de balise de champ identiques.
  • Cartes : Supposées être similaires aux k répétés /v paires.
  • Oneofs : Les informations sur le type d'union sont perdues, seule la valeur réelle la valeur est analysée.

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn