123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- package pomeloPacket
- import (
- "bytes"
- "fmt"
- "io"
- "net"
- cerr "github.com/mhaya/error"
- )
- type (
- Packet struct {
- typ Type
- len int
- data []byte
- }
- )
- func (p *Packet) Type() Type {
- return p.typ
- }
- func (p *Packet) Len() int {
- return p.len
- }
- func (p *Packet) Data() []byte {
- return p.data
- }
- func (p *Packet) SetData(data []byte) {
- p.data = data
- }
- // String represents the Packet's in text mode.
- func (p *Packet) String() string {
- return fmt.Sprintf("packet type: %s, length: %d, data: %s", TypeName(p.typ), p.len, string(p.data))
- }
- func Decode(data []byte) ([]*Packet, error) {
- buf := bytes.NewBuffer(data)
- var (
- packets []*Packet
- err error
- )
- // check length
- if buf.Len() < HeadLength {
- return nil, err
- }
- size, typ, err := forward(buf)
- if err != nil {
- return nil, err
- }
- for size <= buf.Len() {
- pkg := &Packet{
- typ: typ,
- len: size,
- data: buf.Next(size),
- }
- packets = append(packets, pkg)
- if buf.Len() < HeadLength {
- break
- }
- size, typ, err = forward(buf)
- if err != nil {
- return nil, err
- }
- }
- return packets, nil
- }
- // Encode create a packet.Packet from the raw bytes slice and then encode to network bytes slice
- // Protocol refs: https://github.com/NetEase/pomelo/wiki/Communication-Protocol
- //
- // -<type>-|--------<length>--------|-<data>-
- // --------|------------------------|--------
- // 1 byte packet type, 3 bytes packet data length(big end), and data segment
- func Encode(typ byte, data []byte) ([]byte, error) {
- if typ < Handshake || typ > Kick {
- return nil, cerr.PacketWrongType
- }
- if len(data) > MaxPacketSize {
- return nil, cerr.PacketSizeExceed
- }
- pkg := &Packet{
- typ: typ,
- len: len(data),
- }
- // header+body = 4 + len(body)
- buf := make([]byte, pkg.len+HeadLength)
- //第一个字节存放消息类型
- buf[0] = pkg.Type()
- //2~4 字节 存放消息长度
- copy(buf[1:HeadLength], IntToBytes(pkg.len))
- //4字节之后存放的内容是消息体
- copy(buf[HeadLength:], data)
- return buf, nil
- }
- func Read(conn net.Conn) ([]*Packet, bool, error) {
- header, err := io.ReadAll(io.LimitReader(conn, int64(HeadLength)))
- if err != nil {
- return nil, true, err
- }
- // if the header has no data, we can consider it as a closed connection
- if len(header) == 0 {
- return nil, true, cerr.PacketConnectClosed
- }
- msgSize, err := ParseHeader(header)
- if err != nil {
- return nil, true, err
- }
- msgData, err := io.ReadAll(io.LimitReader(conn, int64(msgSize)))
- if err != nil {
- return nil, true, err
- }
- if len(msgData) < msgSize {
- return nil, true, cerr.PacketMsgSmallerThanExpected
- }
- header = append(header, msgData...)
- packets, err := Decode(header)
- if err != nil {
- return nil, false, err
- }
- return packets, false, nil
- }
|