writer.go 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package v2raywebsocket
  2. import (
  3. "encoding/binary"
  4. "math/rand"
  5. "github.com/sagernet/sing/common/buf"
  6. "github.com/sagernet/sing/common/bufio"
  7. N "github.com/sagernet/sing/common/network"
  8. "github.com/sagernet/websocket"
  9. )
  10. type Writer struct {
  11. *websocket.Conn
  12. writer N.ExtendedWriter
  13. isServer bool
  14. }
  15. func NewWriter(conn *websocket.Conn, isServer bool) *Writer {
  16. return &Writer{
  17. conn,
  18. bufio.NewExtendedWriter(conn.NetConn()),
  19. isServer,
  20. }
  21. }
  22. func (w *Writer) Write(p []byte) (n int, err error) {
  23. err = w.Conn.WriteMessage(websocket.BinaryMessage, p)
  24. if err != nil {
  25. return
  26. }
  27. return len(p), nil
  28. }
  29. func (w *Writer) WriteBuffer(buffer *buf.Buffer) error {
  30. var payloadBitLength int
  31. dataLen := buffer.Len()
  32. data := buffer.Bytes()
  33. if dataLen < 126 {
  34. payloadBitLength = 1
  35. } else if dataLen < 65536 {
  36. payloadBitLength = 3
  37. } else {
  38. payloadBitLength = 9
  39. }
  40. var headerLen int
  41. headerLen += 1 // FIN / RSV / OPCODE
  42. headerLen += payloadBitLength
  43. if !w.isServer {
  44. headerLen += 4 // MASK KEY
  45. }
  46. header := buffer.ExtendHeader(headerLen)
  47. header[0] = websocket.BinaryMessage | 1<<7
  48. if w.isServer {
  49. header[1] = 0
  50. } else {
  51. header[1] = 1 << 7
  52. }
  53. if dataLen < 126 {
  54. header[1] |= byte(dataLen)
  55. } else if dataLen < 65536 {
  56. header[1] |= 126
  57. binary.BigEndian.PutUint16(header[2:], uint16(dataLen))
  58. } else {
  59. header[1] |= 127
  60. binary.BigEndian.PutUint64(header[2:], uint64(dataLen))
  61. }
  62. if !w.isServer {
  63. maskKey := rand.Uint32()
  64. binary.BigEndian.PutUint32(header[1+payloadBitLength:], maskKey)
  65. maskBytes(*(*[4]byte)(header[1+payloadBitLength:]), 0, data)
  66. }
  67. return w.writer.WriteBuffer(buffer)
  68. }
  69. func (w *Writer) Upstream() any {
  70. return w.Conn.NetConn()
  71. }
  72. func (w *Writer) FrontHeadroom() int {
  73. return 14
  74. }