diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/enum.go b/enum.go deleted file mode 100644 index 6fb25b8..0000000 --- a/enum.go +++ /dev/null @@ -1,10 +0,0 @@ -package packetflag - -type Flag = byte - -var ( - ChangeKey Flag = 1 - HeaderEncrypted Flag = 2 - DataEncrypted Flag = 4 - HasDummyBytes Flag = 8 -) diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..88c70dc --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module tpack + +go 1.17 diff --git a/proto/codec/decoder.go b/proto/codec/decoder.go new file mode 100644 index 0000000..b9a64fa --- /dev/null +++ b/proto/codec/decoder.go @@ -0,0 +1,50 @@ +package codec + +import ( + "bufio" + "io" + "net" + "tpack/proto/packet" +) + +type Decoder struct { + underlying io.Reader +} + +func NewDecoder(c net.Conn) *Decoder { + out := &Decoder{ + underlying: &fullReader{bufio.NewReader(c)}, + } + return out +} + +type fullReader struct{ io.Reader } + +func (fr *fullReader) Read(p []byte) (int, error) { return io.ReadFull(fr.Reader, p) } + +func (D *Decoder) ReadPacket() (*packet.Packet, error) { + pkt := &packet.Packet{} + pkt.Head = &packet.Header{} + err := pkt.Head.Decode(D.underlying) + if err != nil { + return pkt, err + } + if pkt.Head.Length < 9 { + return pkt, err + } + pkt.Data = make([]byte, pkt.Head.Length-9) + err = D.DecryptTo(pkt.Data) + if err != nil { + return nil, err + } + return pkt, err +} + +func (D *Decoder) DecryptTo(b []byte) error { + _, err := D.underlying.Read(b) + if err != nil { + return err + } + // you would decrypt the buffer here, since b now holds encrypted data + return err +} diff --git a/proto/codec/encoder.go b/proto/codec/encoder.go new file mode 100644 index 0000000..70a6de2 --- /dev/null +++ b/proto/codec/encoder.go @@ -0,0 +1,4 @@ +package codec + +type Encoder struct { +} diff --git a/proto/packet/header.go b/proto/packet/header.go new file mode 100644 index 0000000..282c7de --- /dev/null +++ b/proto/packet/header.go @@ -0,0 +1,62 @@ +package packet + +import ( + "io" + "tpack/proto/packet/packetflag" + "tpack/util" +) + +type HeaderFlag = byte + +type Header struct { + Length uint16 + Opcode uint16 + Sequence uint16 + Secret byte + Flag packetflag.Flag + Check byte +} + +func (H *Header) Decode(r io.Reader) (err error) { + if H.Length, err = util.ReadUint16(r); err != nil { + return err + } + if H.Opcode, err = util.ReadUint16(r); err != nil { + return err + } + if H.Sequence, err = util.ReadUint16(r); err != nil { + return err + } + if H.Secret, err = util.ReadByte(r); err != nil { + return err + } + if H.Flag, err = util.ReadByte(r); err != nil { + return err + } + if H.Check, err = util.ReadByte(r); err != nil { + return err + } + return nil +} + +func (H *Header) Encode(w io.Writer) (err error) { + if err = util.WriteUint16(w, H.Opcode); err != nil { + return err + } + if err = util.WriteUint16(w, H.Opcode); err != nil { + return err + } + if err = util.WriteUint16(w, H.Sequence); err != nil { + return err + } + if err = util.WriteByte(w, H.Secret); err != nil { + return err + } + if err = util.WriteByte(w, H.Flag); err != nil { + return err + } + if err = util.WriteByte(w, H.Check); err != nil { + return err + } + return nil +} diff --git a/proto/packet/packet.go b/proto/packet/packet.go new file mode 100644 index 0000000..8fe273e --- /dev/null +++ b/proto/packet/packet.go @@ -0,0 +1,6 @@ +package packet + +type Packet struct { + Head *Header + Data []byte +} diff --git a/util/reader.go b/util/reader.go new file mode 100644 index 0000000..6798ee4 --- /dev/null +++ b/util/reader.go @@ -0,0 +1,60 @@ +package util + +import ( + "encoding/binary" + "io" +) + +var EndianNess = binary.LittleEndian + +func ReadUint8(reader io.Reader) (val uint8, err error) { + if br, ok := reader.(io.ByteReader); ok { + return br.ReadByte() + } + var protocol [1]byte + _, err = reader.Read(protocol[:1]) + val = protocol[0] + return +} + +func ReadByte(reader io.Reader) (val byte, err error) { + return ReadUint8(reader) +} + +func ReadUint16(reader io.Reader) (val uint16, err error) { + var protocol [2]byte + _, err = reader.Read(protocol[:2]) + val = EndianNess.Uint16(protocol[:2]) + return +} + +func ReadInt16(reader io.Reader) (val int16, err error) { + uval, err := ReadUint16(reader) + val = int16(uval) + return +} +func ReadUint32(reader io.Reader) (val uint32, err error) { + var protocol [4]byte + _, err = reader.Read(protocol[:4]) + val = EndianNess.Uint32(protocol[:4]) + return +} + +func ReadInt32(reader io.Reader) (val int32, err error) { + uval, err := ReadUint32(reader) + val = int32(uval) + return +} + +func ReadUint64(reader io.Reader) (val uint64, err error) { + var protocol [8]byte + _, err = reader.Read(protocol[:8]) + val = EndianNess.Uint64(protocol[:8]) + return +} + +func ReadInt64(reader io.Reader) (val int64, err error) { + uval, err := ReadUint64(reader) + val = int64(uval) + return +} diff --git a/util/writer.go b/util/writer.go new file mode 100644 index 0000000..5d7b394 --- /dev/null +++ b/util/writer.go @@ -0,0 +1,60 @@ +package util + +import ( + "encoding/binary" + "io" +) + +func WriteUint8(writer io.Writer, val uint8) (err error) { + var protocol [1]byte + protocol[0] = val + _, err = writer.Write(protocol[:1]) + return +} + +func WriteInt8(writer io.Writer, val int8) (err error) { + return WriteUint8(writer, uint8(val)) +} + +func WriteByte(writer io.Writer, val byte) (err error) { + return WriteUint8(writer, val) +} + +func WriteInt16(writer io.Writer, val int16) (err error) { + err = WriteUint16(writer, uint16(val)) + return +} + +func WriteUint16(writer io.Writer, val uint16) (err error) { + var protocol [2]byte + binary.BigEndian.PutUint16(protocol[:2], val) + _, err = writer.Write(protocol[:2]) + return +} + +func WriteInt32(writer io.Writer, val int32) (err error) { + err = WriteUint32(writer, uint32(val)) + return +} + +func WriteInt(writer io.Writer, val int) (err error) { + return WriteInt32(writer, int32(val)) +} + +func WriteUint32(writer io.Writer, val uint32) (err error) { + var protocol [4]byte + binary.BigEndian.PutUint32(protocol[:4], val) + _, err = writer.Write(protocol[:4]) + return +} + +func WriteInt64(writer io.Writer, val int64) (err error) { + err = WriteUint64(writer, uint64(val)) + return +} +func WriteUint64(writer io.Writer, val uint64) (err error) { + var protocol [8]byte + binary.BigEndian.PutUint64(protocol[:8], val) + _, err = writer.Write(protocol[:8]) + return +}