Files
Archive/echo/internal/conn/ws_conn.go
2024-08-16 20:33:05 +02:00

86 lines
1.9 KiB
Go

package conn
import (
"fmt"
"io"
"net"
"time"
"github.com/Ehco1996/ehco/pkg/buffer"
"github.com/gobwas/ws"
"github.com/gobwas/ws/wsutil"
"go.uber.org/zap"
)
// wsConn represents a WebSocket connection to relay(io.Copy)
type wsConn struct {
conn net.Conn
isServer bool
buf []byte
}
func NewWSConn(conn net.Conn, isServer bool) *wsConn {
return &wsConn{conn: conn, isServer: isServer, buf: buffer.BufferPool.Get()}
}
func (c *wsConn) Read(b []byte) (n int, err error) {
header, err := ws.ReadHeader(c.conn)
if err != nil {
return 0, err
}
if header.Length > int64(cap(c.buf)) {
zap.S().Warnf("ws payload size:%d is larger than buffer size:%d", header.Length, cap(c.buf))
return 0, fmt.Errorf("buffer size:%d too small to transport ws payload size:%d", len(b), header.Length)
}
payload := c.buf[:header.Length]
_, err = io.ReadFull(c.conn, payload)
if err != nil {
return 0, err
}
if header.Masked {
ws.Cipher(payload, header.Mask, 0)
}
if len(payload) > len(b) {
return 0, fmt.Errorf("buffer size:%d too small to transport ws payload size:%d", len(b), len(payload))
}
copy(b, payload)
return len(payload), nil
}
func (c *wsConn) Write(b []byte) (n int, err error) {
if c.isServer {
err = wsutil.WriteServerBinary(c.conn, b)
} else {
err = wsutil.WriteClientBinary(c.conn, b)
}
if err != nil {
return 0, err
}
return len(b), nil
}
func (c *wsConn) Close() error {
defer buffer.BufferPool.Put(c.buf)
return c.conn.Close()
}
func (c *wsConn) LocalAddr() net.Addr {
return c.conn.LocalAddr()
}
func (c *wsConn) RemoteAddr() net.Addr {
return c.conn.RemoteAddr()
}
func (c *wsConn) SetDeadline(t time.Time) error {
return c.conn.SetDeadline(t)
}
func (c *wsConn) SetReadDeadline(t time.Time) error {
return c.conn.SetReadDeadline(t)
}
func (c *wsConn) SetWriteDeadline(t time.Time) error {
return c.conn.SetWriteDeadline(t)
}