sing-box/transport/v2raywebsocket/writer.go

75 lines
1.5 KiB
Go
Raw Normal View History

2022-09-23 09:21:24 +00:00
package v2raywebsocket
import (
"encoding/binary"
2023-11-09 08:59:44 +00:00
"io"
2022-09-23 09:21:24 +00:00
"math/rand"
"github.com/sagernet/sing/common/buf"
2022-09-30 03:27:18 +00:00
"github.com/sagernet/sing/common/bufio"
N "github.com/sagernet/sing/common/network"
2023-11-09 08:59:44 +00:00
"github.com/sagernet/ws"
2022-09-23 09:21:24 +00:00
)
type Writer struct {
2022-09-30 03:27:18 +00:00
writer N.ExtendedWriter
2022-09-23 09:21:24 +00:00
isServer bool
}
2023-11-09 08:59:44 +00:00
func NewWriter(writer io.Writer, state ws.State) *Writer {
2022-09-30 03:27:18 +00:00
return &Writer{
2023-11-09 08:59:44 +00:00
bufio.NewExtendedWriter(writer),
state == ws.StateServerSide,
2022-09-30 03:27:18 +00:00
}
}
2022-09-23 09:21:24 +00:00
func (w *Writer) WriteBuffer(buffer *buf.Buffer) error {
var payloadBitLength int
dataLen := buffer.Len()
data := buffer.Bytes()
if dataLen < 126 {
payloadBitLength = 1
} else if dataLen < 65536 {
payloadBitLength = 3
} else {
payloadBitLength = 9
}
var headerLen int
headerLen += 1 // FIN / RSV / OPCODE
headerLen += payloadBitLength
if !w.isServer {
headerLen += 4 // MASK KEY
}
header := buffer.ExtendHeader(headerLen)
2023-11-09 08:59:44 +00:00
header[0] = byte(ws.OpBinary) | 0x80
2022-09-23 09:21:24 +00:00
if w.isServer {
header[1] = 0
} else {
header[1] = 1 << 7
}
if dataLen < 126 {
header[1] |= byte(dataLen)
} else if dataLen < 65536 {
header[1] |= 126
binary.BigEndian.PutUint16(header[2:], uint16(dataLen))
} else {
header[1] |= 127
binary.BigEndian.PutUint64(header[2:], uint64(dataLen))
}
if !w.isServer {
maskKey := rand.Uint32()
binary.BigEndian.PutUint32(header[1+payloadBitLength:], maskKey)
2023-11-09 08:59:44 +00:00
ws.Cipher(data, *(*[4]byte)(header[1+payloadBitLength:]), 0)
2022-09-23 09:21:24 +00:00
}
2022-09-30 03:27:18 +00:00
return w.writer.WriteBuffer(buffer)
}
func (w *Writer) FrontHeadroom() int {
2022-10-07 12:18:50 +00:00
return 14
2022-09-23 09:21:24 +00:00
}