package codec import ( "blazing/common/data/entity" "encoding/binary" "errors" "io" "log" "github.com/panjf2000/gnet/v2" ) // CROSS_DOMAIN 定义跨域策略文件内容 const CROSS_DOMAIN = "\x00" // TEXT 定义跨域请求的文本格式 const TEXT = "\x00" var ErrIncompletePacket = errors.New("incomplete packet") // TomeeSocketCodec 协议格式: // // * 0 4 // * +-----------+ // * | body len | // * +-----------+ // * | | // * + + // * | body bytes| // * + + // * | ... ... | // * +-----------+ type TomeeSocketCodec struct{} var _ SocketCodec = (*TomeeSocketCodec)(nil) func NewTomeeSocketCodec() *TomeeSocketCodec { return &TomeeSocketCodec{} } func handle(c gnet.Conn) { clientdata := c.Context().(*entity.ClientData) if clientdata.IsCrossDomain { return } // 读取数据并检查是否为跨域请求 data, err := c.Peek(len(TEXT)) if err != nil { log.Printf("Error reading cross-domain request: %v", err) return } if string(data) == TEXT { //判断是否是跨域请求 log.Printf("Received cross-domain request from %s", c.RemoteAddr()) // 处理跨域请求 c.Write([]byte(CROSS_DOMAIN)) c.Discard(len(TEXT)) clientdata.IsCrossDomain = true return } //return } func (codec TomeeSocketCodec) Encode(buf []byte) ([]byte, error) { bodyLen := len(buf) data := make([]byte, 4+bodyLen) // 写入4字节的包长度 binary.BigEndian.PutUint32(data[:4], uint32(bodyLen)) // 写入包体 copy(data[4:], buf) return data, nil } func (codec TomeeSocketCodec) Decode(c gnet.Conn) ([]byte, error) { handle(c) // 先读取4字节的包长度 lenBuf, err := c.Peek(4) if err != nil { if errors.Is(err, io.ErrShortBuffer) { return nil, ErrIncompletePacket } return nil, err } bodyLen := binary.BigEndian.Uint32(lenBuf) totalLen := 4 + int(bodyLen) // 检查整个包是否完整 buf, err := c.Peek(int(bodyLen)) if err != nil { if errors.Is(err, io.ErrShortBuffer) { return nil, ErrIncompletePacket } return nil, err } // 提取包体 body := make([]byte, bodyLen) copy(body, buf) // 从缓冲区中丢弃已读取的数据 _, _ = c.Discard(totalLen) return body, nil }