writer.go 1.5 KB

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