common.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. package scenarios
  2. import (
  3. "bytes"
  4. "crypto/rand"
  5. "fmt"
  6. "io"
  7. "os"
  8. "os/exec"
  9. "path/filepath"
  10. "runtime"
  11. "sync"
  12. "syscall"
  13. "time"
  14. "github.com/golang/protobuf/proto"
  15. "github.com/xtls/xray-core/app/dispatcher"
  16. "github.com/xtls/xray-core/app/proxyman"
  17. "github.com/xtls/xray-core/common"
  18. "github.com/xtls/xray-core/common/errors"
  19. "github.com/xtls/xray-core/common/log"
  20. "github.com/xtls/xray-core/common/net"
  21. "github.com/xtls/xray-core/common/retry"
  22. "github.com/xtls/xray-core/common/serial"
  23. "github.com/xtls/xray-core/common/units"
  24. core "github.com/xtls/xray-core/core"
  25. )
  26. func xor(b []byte) []byte {
  27. r := make([]byte, len(b))
  28. for i, v := range b {
  29. r[i] = v ^ 'c'
  30. }
  31. return r
  32. }
  33. func readFrom(conn net.Conn, timeout time.Duration, length int) []byte {
  34. b := make([]byte, length)
  35. deadline := time.Now().Add(timeout)
  36. conn.SetReadDeadline(deadline)
  37. n, err := io.ReadFull(conn, b[:length])
  38. if err != nil {
  39. fmt.Println("Unexpected error from readFrom:", err)
  40. }
  41. return b[:n]
  42. }
  43. func readFrom2(conn net.Conn, timeout time.Duration, length int) ([]byte, error) {
  44. b := make([]byte, length)
  45. deadline := time.Now().Add(timeout)
  46. conn.SetReadDeadline(deadline)
  47. n, err := io.ReadFull(conn, b[:length])
  48. if err != nil {
  49. return nil, err
  50. }
  51. return b[:n], nil
  52. }
  53. func InitializeServerConfigs(configs ...*core.Config) ([]*exec.Cmd, error) {
  54. servers := make([]*exec.Cmd, 0, 10)
  55. for _, config := range configs {
  56. server, err := InitializeServerConfig(config)
  57. if err != nil {
  58. CloseAllServers(servers)
  59. return nil, err
  60. }
  61. servers = append(servers, server)
  62. }
  63. time.Sleep(time.Second * 2)
  64. return servers, nil
  65. }
  66. func InitializeServerConfig(config *core.Config) (*exec.Cmd, error) {
  67. err := BuildXray()
  68. if err != nil {
  69. return nil, err
  70. }
  71. config = withDefaultApps(config)
  72. configBytes, err := proto.Marshal(config)
  73. if err != nil {
  74. return nil, err
  75. }
  76. proc := RunXrayProtobuf(configBytes)
  77. if err := proc.Start(); err != nil {
  78. return nil, err
  79. }
  80. return proc, nil
  81. }
  82. var (
  83. testBinaryPath string
  84. testBinaryPathGen sync.Once
  85. )
  86. func genTestBinaryPath() {
  87. testBinaryPathGen.Do(func() {
  88. var tempDir string
  89. common.Must(retry.Timed(5, 100).On(func() error {
  90. dir, err := os.MkdirTemp("", "xray")
  91. if err != nil {
  92. return err
  93. }
  94. tempDir = dir
  95. return nil
  96. }))
  97. file := filepath.Join(tempDir, "xray.test")
  98. if runtime.GOOS == "windows" {
  99. file += ".exe"
  100. }
  101. testBinaryPath = file
  102. fmt.Printf("Generated binary path: %s\n", file)
  103. })
  104. }
  105. func GetSourcePath() string {
  106. return filepath.Join("github.com", "xtls", "xray-core", "main")
  107. }
  108. func CloseAllServers(servers []*exec.Cmd) {
  109. log.Record(&log.GeneralMessage{
  110. Severity: log.Severity_Info,
  111. Content: "Closing all servers.",
  112. })
  113. for _, server := range servers {
  114. if runtime.GOOS == "windows" {
  115. server.Process.Kill()
  116. } else {
  117. server.Process.Signal(syscall.SIGTERM)
  118. }
  119. }
  120. for _, server := range servers {
  121. server.Process.Wait()
  122. }
  123. log.Record(&log.GeneralMessage{
  124. Severity: log.Severity_Info,
  125. Content: "All server closed.",
  126. })
  127. }
  128. func CloseServer(server *exec.Cmd) {
  129. log.Record(&log.GeneralMessage{
  130. Severity: log.Severity_Info,
  131. Content: "Closing server.",
  132. })
  133. if runtime.GOOS == "windows" {
  134. server.Process.Kill()
  135. } else {
  136. server.Process.Signal(syscall.SIGTERM)
  137. }
  138. server.Process.Wait()
  139. log.Record(&log.GeneralMessage{
  140. Severity: log.Severity_Info,
  141. Content: "Server closed.",
  142. })
  143. }
  144. func withDefaultApps(config *core.Config) *core.Config {
  145. config.App = append(config.App, serial.ToTypedMessage(&dispatcher.Config{}))
  146. config.App = append(config.App, serial.ToTypedMessage(&proxyman.InboundConfig{}))
  147. config.App = append(config.App, serial.ToTypedMessage(&proxyman.OutboundConfig{}))
  148. return config
  149. }
  150. func testTCPConn(port net.Port, payloadSize int, timeout time.Duration) func() error {
  151. return func() error {
  152. conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{
  153. IP: []byte{127, 0, 0, 1},
  154. Port: int(port),
  155. })
  156. if err != nil {
  157. return err
  158. }
  159. defer conn.Close()
  160. return testTCPConn2(conn, payloadSize, timeout)()
  161. }
  162. }
  163. func testUDPConn(port net.Port, payloadSize int, timeout time.Duration) func() error {
  164. return func() error {
  165. conn, err := net.DialUDP("udp", nil, &net.UDPAddr{
  166. IP: []byte{127, 0, 0, 1},
  167. Port: int(port),
  168. })
  169. if err != nil {
  170. return err
  171. }
  172. defer conn.Close()
  173. return testTCPConn2(conn, payloadSize, timeout)()
  174. }
  175. }
  176. func testTCPConn2(conn net.Conn, payloadSize int, timeout time.Duration) func() error {
  177. return func() (err1 error) {
  178. start := time.Now()
  179. defer func() {
  180. var m runtime.MemStats
  181. runtime.ReadMemStats(&m)
  182. // For info on each, see: https://golang.org/pkg/runtime/#MemStats
  183. fmt.Println("testConn finishes:", time.Since(start).Milliseconds(), "ms\t",
  184. err1, "\tAlloc =", units.ByteSize(m.Alloc).String(),
  185. "\tTotalAlloc =", units.ByteSize(m.TotalAlloc).String(),
  186. "\tSys =", units.ByteSize(m.Sys).String(),
  187. "\tNumGC =", m.NumGC)
  188. }()
  189. payload := make([]byte, payloadSize)
  190. common.Must2(rand.Read(payload))
  191. nBytes, err := conn.Write(payload)
  192. if err != nil {
  193. return err
  194. }
  195. if nBytes != len(payload) {
  196. return errors.New("expect ", len(payload), " written, but actually ", nBytes)
  197. }
  198. response, err := readFrom2(conn, timeout, payloadSize)
  199. if err != nil {
  200. return err
  201. }
  202. _ = response
  203. if r := bytes.Compare(response, xor(payload)); r != 0 {
  204. return errors.New(r)
  205. }
  206. return nil
  207. }
  208. }