I am writing custom layer decoders with gopacket.
LayerA contains a field Type
that can be one of the following values:
- B-only, the next layer is LayerB, followed by a raw payload
- C-only, the next layer is LayerC, followed by a raw payload
- B-C, the next layer is LayerB, followed by LayerC then a raw payload
There is no field in LayerB that can be used to know if LayerC is the next or not. LayerB and LayerC decoding does not depend on whenever the other layer is present or not.
What would be the proper way to write the decode function of LayerA, since it's the one that knows what are the next layers?
There is not a lot of tutorials about custom layers with gopacket, and this case is not like the basic ones covered there.
It seems the logic should be put in LayerA decoding function, just before calling p.NextDecoder
.
I thought of two ways to achieve this:
1. Use a closure
Add a field nextDecoder Decoder
to the struct LayerB.
In the decoder of LayerA, when Type
is C-only, simply use the decoder of LayerC. Otherwise, create a struct LayerB and fill the field nextDecoder
accordingly. Then use this struct in a closure, that will be used as the next decoder.
Issues
The decoding logic of LayerB would be in the LayerA decoding function (see code in Palyground below).
Moreover, which decoding function to use when registering the LayerB with gopacket.RegisterLayer
?
2. Have two separate layers LayerB-C and LayerB-only
LayerB-C next decoder would be LayerC
's, LayerB-only's would be just the payload layer.
Issues
The decoding function of LayerB-only and LayerB-C is the same, expect the call the p.NextDecoder
.
Since there is no notion of 'inheritance' in go, I am not sure how to design this to avoid duplication. Maybe create a LayerB-base interface with a function nextDecoder() LayerType
, and make LayerB-C and LayerB-only implement it? Or embed a type LayerB-base that has a function Decode
? But neither of them doesn't feel right.
Code
Here is some code for each described way: https://play.golang.org/p/N9ZpYqFb16Q. The actual content of the layers are not relevant, except LayerA.Type
.
The result of this code is as expected but I would like to know if there is a better or more idiomatic to do it.