govmtools/proto.go
2021-11-10 09:06:53 +01:00

126 lines
2.4 KiB
Go

package govmtools
import (
"bytes"
"encoding/binary"
"fmt"
)
type Field struct {
Type FieldType
ID FieldID
Value interface{}
}
func (s *Socket) WritePacket(pkt []Field) error {
buf := bytes.NewBuffer(nil)
for _, field := range pkt {
err := binary.Write(buf, order, field.Type)
if err != nil {
return fmt.Errorf("write field type: %w", err)
}
if field.Type == FieldEmpty {
continue
}
err = binary.Write(buf, order, field.ID)
if err != nil {
return fmt.Errorf("write field ID: %w", err)
}
switch field.Type {
case FieldInt64:
err = binary.Write(buf, order, field.Value)
if err != nil {
return fmt.Errorf("write int64: %w", err)
}
case FieldString:
val := field.Value.(string)
err = binary.Write(buf, order, int32(len(val)))
if err != nil {
return fmt.Errorf("write string len: %w", err)
}
_, err = buf.WriteString(val)
if err != nil {
return fmt.Errorf("write string: %w", err)
}
}
}
res := make([]byte, buf.Len()+4)
order.PutUint32(res, uint32(buf.Len()))
copy(res[4:], buf.Bytes())
_, err := s.conn.Write(res)
if err != nil {
return fmt.Errorf("write: %w", err)
}
return nil
}
func (s *Socket) ReadPacket() ([]Field, error) {
length := make([]byte, 4)
_, err := s.conn.Read(length)
if err != nil {
return nil, fmt.Errorf("read len: %w", err)
}
response := make([]byte, order.Uint32(length))
_, err = s.conn.Read(response)
if err != nil {
return nil, fmt.Errorf("read: %w", err)
}
buf := bytes.NewBuffer(response)
var fields []Field
for buf.Len() > 0 {
field := Field{}
err = binary.Read(buf, order, &field.Type)
if err != nil {
return nil, fmt.Errorf("parse field type: %w", err)
}
if field.Type == FieldEmpty {
continue
}
err = binary.Read(buf, order, &field.ID)
if err != nil {
return nil, fmt.Errorf("parse field ID: %w", err)
}
switch field.Type {
case FieldInt64:
var val int64
err = binary.Read(buf, order, val)
if err != nil {
return nil, fmt.Errorf("parse int64: %w", err)
}
field.Value = val
case FieldString:
var length uint32
err = binary.Read(buf, order, &length)
if err != nil {
return nil, fmt.Errorf("parse string length: %w", err)
}
byt := make([]byte, length)
_, err := buf.Read(byt)
if err != nil {
return nil, fmt.Errorf("parse string: %w", err)
}
field.Value = string(byt)
}
fields = append(fields, field)
}
return fields, nil
}