raw_conn.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. //go:build go1.25 && badlinkname
  2. package badtls
  3. import (
  4. "bytes"
  5. "os"
  6. "reflect"
  7. "sync/atomic"
  8. "unsafe"
  9. E "github.com/sagernet/sing/common/exceptions"
  10. "github.com/sagernet/sing/common/tls"
  11. )
  12. type RawConn struct {
  13. pointer unsafe.Pointer
  14. methods *Methods
  15. IsClient *bool
  16. IsHandshakeComplete *atomic.Bool
  17. Vers *uint16
  18. CipherSuite *uint16
  19. RawInput *bytes.Buffer
  20. Input *bytes.Reader
  21. Hand *bytes.Buffer
  22. CloseNotifySent *bool
  23. CloseNotifyErr *error
  24. In *RawHalfConn
  25. Out *RawHalfConn
  26. BytesSent *int64
  27. PacketsSent *int64
  28. ActiveCall *atomic.Int32
  29. Tmp *[16]byte
  30. }
  31. func NewRawConn(rawTLSConn tls.Conn) (*RawConn, error) {
  32. var (
  33. pointer unsafe.Pointer
  34. methods *Methods
  35. loaded bool
  36. )
  37. for _, tlsCreator := range methodRegistry {
  38. pointer, methods, loaded = tlsCreator(rawTLSConn)
  39. if loaded {
  40. break
  41. }
  42. }
  43. if !loaded {
  44. return nil, os.ErrInvalid
  45. }
  46. conn := &RawConn{
  47. pointer: pointer,
  48. methods: methods,
  49. }
  50. rawConn := reflect.Indirect(reflect.ValueOf(rawTLSConn))
  51. rawIsClient := rawConn.FieldByName("isClient")
  52. if !rawIsClient.IsValid() || rawIsClient.Kind() != reflect.Bool {
  53. return nil, E.New("invalid Conn.isClient")
  54. }
  55. conn.IsClient = (*bool)(unsafe.Pointer(rawIsClient.UnsafeAddr()))
  56. rawIsHandshakeComplete := rawConn.FieldByName("isHandshakeComplete")
  57. if !rawIsHandshakeComplete.IsValid() || rawIsHandshakeComplete.Kind() != reflect.Struct {
  58. return nil, E.New("invalid Conn.isHandshakeComplete")
  59. }
  60. conn.IsHandshakeComplete = (*atomic.Bool)(unsafe.Pointer(rawIsHandshakeComplete.UnsafeAddr()))
  61. rawVers := rawConn.FieldByName("vers")
  62. if !rawVers.IsValid() || rawVers.Kind() != reflect.Uint16 {
  63. return nil, E.New("invalid Conn.vers")
  64. }
  65. conn.Vers = (*uint16)(unsafe.Pointer(rawVers.UnsafeAddr()))
  66. rawCipherSuite := rawConn.FieldByName("cipherSuite")
  67. if !rawCipherSuite.IsValid() || rawCipherSuite.Kind() != reflect.Uint16 {
  68. return nil, E.New("invalid Conn.cipherSuite")
  69. }
  70. conn.CipherSuite = (*uint16)(unsafe.Pointer(rawCipherSuite.UnsafeAddr()))
  71. rawRawInput := rawConn.FieldByName("rawInput")
  72. if !rawRawInput.IsValid() || rawRawInput.Kind() != reflect.Struct {
  73. return nil, E.New("invalid Conn.rawInput")
  74. }
  75. conn.RawInput = (*bytes.Buffer)(unsafe.Pointer(rawRawInput.UnsafeAddr()))
  76. rawInput := rawConn.FieldByName("input")
  77. if !rawInput.IsValid() || rawInput.Kind() != reflect.Struct {
  78. return nil, E.New("invalid Conn.input")
  79. }
  80. conn.Input = (*bytes.Reader)(unsafe.Pointer(rawInput.UnsafeAddr()))
  81. rawHand := rawConn.FieldByName("hand")
  82. if !rawHand.IsValid() || rawHand.Kind() != reflect.Struct {
  83. return nil, E.New("invalid Conn.hand")
  84. }
  85. conn.Hand = (*bytes.Buffer)(unsafe.Pointer(rawHand.UnsafeAddr()))
  86. rawCloseNotifySent := rawConn.FieldByName("closeNotifySent")
  87. if !rawCloseNotifySent.IsValid() || rawCloseNotifySent.Kind() != reflect.Bool {
  88. return nil, E.New("invalid Conn.closeNotifySent")
  89. }
  90. conn.CloseNotifySent = (*bool)(unsafe.Pointer(rawCloseNotifySent.UnsafeAddr()))
  91. rawCloseNotifyErr := rawConn.FieldByName("closeNotifyErr")
  92. if !rawCloseNotifyErr.IsValid() || rawCloseNotifyErr.Kind() != reflect.Interface {
  93. return nil, E.New("invalid Conn.closeNotifyErr")
  94. }
  95. conn.CloseNotifyErr = (*error)(unsafe.Pointer(rawCloseNotifyErr.UnsafeAddr()))
  96. rawIn := rawConn.FieldByName("in")
  97. if !rawIn.IsValid() || rawIn.Kind() != reflect.Struct {
  98. return nil, E.New("invalid Conn.in")
  99. }
  100. halfIn, err := NewRawHalfConn(rawIn, methods)
  101. if err != nil {
  102. return nil, E.Cause(err, "invalid Conn.in")
  103. }
  104. conn.In = halfIn
  105. rawOut := rawConn.FieldByName("out")
  106. if !rawOut.IsValid() || rawOut.Kind() != reflect.Struct {
  107. return nil, E.New("invalid Conn.out")
  108. }
  109. halfOut, err := NewRawHalfConn(rawOut, methods)
  110. if err != nil {
  111. return nil, E.Cause(err, "invalid Conn.out")
  112. }
  113. conn.Out = halfOut
  114. rawBytesSent := rawConn.FieldByName("bytesSent")
  115. if !rawBytesSent.IsValid() || rawBytesSent.Kind() != reflect.Int64 {
  116. return nil, E.New("invalid Conn.bytesSent")
  117. }
  118. conn.BytesSent = (*int64)(unsafe.Pointer(rawBytesSent.UnsafeAddr()))
  119. rawPacketsSent := rawConn.FieldByName("packetsSent")
  120. if !rawPacketsSent.IsValid() || rawPacketsSent.Kind() != reflect.Int64 {
  121. return nil, E.New("invalid Conn.packetsSent")
  122. }
  123. conn.PacketsSent = (*int64)(unsafe.Pointer(rawPacketsSent.UnsafeAddr()))
  124. rawActiveCall := rawConn.FieldByName("activeCall")
  125. if !rawActiveCall.IsValid() || rawActiveCall.Kind() != reflect.Struct {
  126. return nil, E.New("invalid Conn.activeCall")
  127. }
  128. conn.ActiveCall = (*atomic.Int32)(unsafe.Pointer(rawActiveCall.UnsafeAddr()))
  129. rawTmp := rawConn.FieldByName("tmp")
  130. if !rawTmp.IsValid() || rawTmp.Kind() != reflect.Array || rawTmp.Len() != 16 || rawTmp.Type().Elem().Kind() != reflect.Uint8 {
  131. return nil, E.New("invalid Conn.tmp")
  132. }
  133. conn.Tmp = (*[16]byte)(unsafe.Pointer(rawTmp.UnsafeAddr()))
  134. return conn, nil
  135. }
  136. func (c *RawConn) ReadRecord() error {
  137. return c.methods.readRecord(c.pointer)
  138. }
  139. func (c *RawConn) HandlePostHandshakeMessage() error {
  140. return c.methods.handlePostHandshakeMessage(c.pointer)
  141. }
  142. func (c *RawConn) WriteRecordLocked(typ uint16, data []byte) (int, error) {
  143. return c.methods.writeRecordLocked(c.pointer, typ, data)
  144. }