ppforge/packet/packet.go

182 lines
3.5 KiB
Go

package packet
import (
"crypto/sha1"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"io/fs"
"os"
)
// FieldValue implements protocol.ProtocolFieldReferencer
type FieldValue struct {
Field string
FieldNum int
Value string
}
// GetProtocolField returns the protocol field
func (fv *FieldValue) GetProtocolField() (string, int) {
return fv.Field, fv.FieldNum
}
// SetProtocolField sets the protocl field
func (fv *FieldValue) SetProtocolField(f string, fn int) {
fv.Field = f
fv.FieldNum = fn
}
// SetValue sets the value
func (fv *FieldValue) SetValue(v string) {
fv.Value = v
}
// Layer implements protocol.ProtocolReferencer
type Layer struct {
ProtocolName string
Values []FieldValue
}
// Packet contains all layers of a packet and the data in different formats
type Packet struct {
MetaData Metadata
data []byte
Hex string
B64 string
Sha1 string
Layers []Layer
}
func NewPacketStructure() *Packet {
p := Packet{}
return &p
}
func UpdateMetaData(
pack *Packet,
) {
// still empty
}
func NewPacketLayer() *Layer {
p := Layer{}
return &p
}
func NewEmptyFieldValue() *FieldValue {
f := FieldValue{}
return &f
}
func NewFieldValue(
field string,
fieldnum int,
value string,
) *FieldValue {
f := FieldValue{
Value: value,
}
return &f
}
func (pack *Layer) AppendField(field *FieldValue) int {
i := len(pack.Values)
pack.Values = append(pack.Values, *field)
return i + 1
}
func (pack *Layer) AddField(index int, field *FieldValue) {
if len(pack.Values) == index {
pack.AppendField(field)
return
}
ret := make([]FieldValue, 0)
ret = append(ret, pack.Values[:index]...)
ret = append(ret, *field)
ret = append(ret, pack.Values[index:]...)
pack.Values = ret
}
func (pack *Packet) AppendLayer(layer *Layer) {
pack.Layers = append(pack.Layers, *layer)
}
func (pack *Packet) AddLayer(index int, layer *Layer) {
if len(pack.Layers) == index {
pack.AppendLayer(layer)
return
}
ret := make([]Layer, 0)
ret = append(ret, pack.Layers[:index]...)
ret = append(ret, *layer)
ret = append(ret, pack.Layers[index:]...)
pack.Layers = ret
}
func (pack *Layer) UpdateField(e int, field *FieldValue) {
pack.Values[e] = *field
}
func (pack *Packet) UpdateLayer(e int, layer *Layer) {
pack.Layers[e] = *layer
}
func (pack *Layer) RemoveField(e int) {
l := len(pack.Values) - 1
ret := make([]FieldValue, l)
ret = append(ret, pack.Values[:e]...)
ret = append(ret, pack.Values[e+1:]...)
pack.Values = ret
}
func (pack *Packet) RemoveLayer(e int) {
l := len(pack.Layers) - 1
ret := make([]Layer, l)
ret = append(ret, pack.Layers[:e]...)
ret = append(ret, pack.Layers[e+1:]...)
pack.Layers = ret
}
func (pack *Packet) Load(path string) error {
data, err := os.ReadFile(path)
if err != nil {
return err
}
err = json.Unmarshal(data, pack)
pack.data, err = base64.StdEncoding.DecodeString(pack.B64)
if err != nil {
return err
}
if pack.Sha1 != fmt.Sprintf("%x", sha1.Sum(pack.data)) {
return errors.New("sha1sum does not match")
}
return err
}
func (pack *Packet) UpdateData() {
pack.Hex = fmt.Sprintf("%x", pack.data)
pack.B64 = base64.RawStdEncoding.EncodeToString(pack.data)
pack.Sha1 = fmt.Sprintf("%x", sha1.Sum(pack.data))
}
func (pack *Packet) ToJSON() string {
pack.UpdateData()
data, err := json.MarshalIndent(*pack, "", " ")
if err != nil {
return ""
}
return string(data)
}
func (pack *Packet) Save(path string) error {
pack.UpdateData()
data, err := json.MarshalIndent(*pack, "", " ")
if err != nil {
return err
}
err = os.WriteFile(path, data, fs.ModeAppend)
return err
}