127 lines
2.4 KiB
Go
127 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
|
||
|
}
|