github.com/xtls/xray-core@v1.8.12-0.20240518155711-3168d27b0bdb/infra/conf/transport_test.go (about)

     1  package conf_test
     2  
     3  import (
     4  	"encoding/json"
     5  	"testing"
     6  
     7  	"github.com/xtls/xray-core/common/protocol"
     8  	"github.com/xtls/xray-core/common/serial"
     9  	. "github.com/xtls/xray-core/infra/conf"
    10  	"github.com/xtls/xray-core/transport/global"
    11  	"github.com/xtls/xray-core/transport/internet"
    12  	"github.com/xtls/xray-core/transport/internet/grpc"
    13  	"github.com/xtls/xray-core/transport/internet/headers/http"
    14  	"github.com/xtls/xray-core/transport/internet/headers/noop"
    15  	"github.com/xtls/xray-core/transport/internet/headers/tls"
    16  	"github.com/xtls/xray-core/transport/internet/kcp"
    17  	"github.com/xtls/xray-core/transport/internet/quic"
    18  	"github.com/xtls/xray-core/transport/internet/tcp"
    19  	"github.com/xtls/xray-core/transport/internet/websocket"
    20  	"google.golang.org/protobuf/proto"
    21  )
    22  
    23  func TestSocketConfig(t *testing.T) {
    24  	createParser := func() func(string) (proto.Message, error) {
    25  		return func(s string) (proto.Message, error) {
    26  			config := new(SocketConfig)
    27  			if err := json.Unmarshal([]byte(s), config); err != nil {
    28  				return nil, err
    29  			}
    30  			return config.Build()
    31  		}
    32  	}
    33  
    34  	// test "tcpFastOpen": true, queue length 256 is expected. other parameters are tested here too
    35  	expectedOutput := &internet.SocketConfig{
    36  		Mark:           1,
    37  		Tfo:            256,
    38  		DomainStrategy: internet.DomainStrategy_USE_IP,
    39  		DialerProxy:    "tag",
    40  	}
    41  	runMultiTestCase(t, []TestCase{
    42  		{
    43  			Input: `{
    44  				"mark": 1,
    45  				"tcpFastOpen": true,
    46  				"domainStrategy": "UseIP",
    47  				"dialerProxy": "tag"
    48  			}`,
    49  			Parser: createParser(),
    50  			Output: expectedOutput,
    51  		},
    52  	})
    53  	if expectedOutput.ParseTFOValue() != 256 {
    54  		t.Fatalf("unexpected parsed TFO value, which should be 256")
    55  	}
    56  
    57  	// test "tcpFastOpen": false, disabled TFO is expected
    58  	expectedOutput = &internet.SocketConfig{
    59  		Mark: 0,
    60  		Tfo:  -1,
    61  	}
    62  	runMultiTestCase(t, []TestCase{
    63  		{
    64  			Input: `{
    65  				"tcpFastOpen": false
    66  			}`,
    67  			Parser: createParser(),
    68  			Output: expectedOutput,
    69  		},
    70  	})
    71  	if expectedOutput.ParseTFOValue() != 0 {
    72  		t.Fatalf("unexpected parsed TFO value, which should be 0")
    73  	}
    74  
    75  	// test "tcpFastOpen": 65535, queue length 65535 is expected
    76  	expectedOutput = &internet.SocketConfig{
    77  		Mark: 0,
    78  		Tfo:  65535,
    79  	}
    80  	runMultiTestCase(t, []TestCase{
    81  		{
    82  			Input: `{
    83  				"tcpFastOpen": 65535
    84  			}`,
    85  			Parser: createParser(),
    86  			Output: expectedOutput,
    87  		},
    88  	})
    89  	if expectedOutput.ParseTFOValue() != 65535 {
    90  		t.Fatalf("unexpected parsed TFO value, which should be 65535")
    91  	}
    92  
    93  	// test "tcpFastOpen": -65535, disable TFO is expected
    94  	expectedOutput = &internet.SocketConfig{
    95  		Mark: 0,
    96  		Tfo:  -65535,
    97  	}
    98  	runMultiTestCase(t, []TestCase{
    99  		{
   100  			Input: `{
   101  				"tcpFastOpen": -65535
   102  			}`,
   103  			Parser: createParser(),
   104  			Output: expectedOutput,
   105  		},
   106  	})
   107  	if expectedOutput.ParseTFOValue() != 0 {
   108  		t.Fatalf("unexpected parsed TFO value, which should be 0")
   109  	}
   110  
   111  	// test "tcpFastOpen": 0, no operation is expected
   112  	expectedOutput = &internet.SocketConfig{
   113  		Mark: 0,
   114  		Tfo:  0,
   115  	}
   116  	runMultiTestCase(t, []TestCase{
   117  		{
   118  			Input: `{
   119  				"tcpFastOpen": 0
   120  			}`,
   121  			Parser: createParser(),
   122  			Output: expectedOutput,
   123  		},
   124  	})
   125  	if expectedOutput.ParseTFOValue() != -1 {
   126  		t.Fatalf("unexpected parsed TFO value, which should be -1")
   127  	}
   128  
   129  	// test omit "tcpFastOpen", no operation is expected
   130  	expectedOutput = &internet.SocketConfig{
   131  		Mark: 0,
   132  		Tfo:  0,
   133  	}
   134  	runMultiTestCase(t, []TestCase{
   135  		{
   136  			Input:  `{}`,
   137  			Parser: createParser(),
   138  			Output: expectedOutput,
   139  		},
   140  	})
   141  	if expectedOutput.ParseTFOValue() != -1 {
   142  		t.Fatalf("unexpected parsed TFO value, which should be -1")
   143  	}
   144  
   145  	// test "tcpFastOpen": null, no operation is expected
   146  	expectedOutput = &internet.SocketConfig{
   147  		Mark: 0,
   148  		Tfo:  0,
   149  	}
   150  	runMultiTestCase(t, []TestCase{
   151  		{
   152  			Input: `{
   153  				"tcpFastOpen": null
   154  			}`,
   155  			Parser: createParser(),
   156  			Output: expectedOutput,
   157  		},
   158  	})
   159  	if expectedOutput.ParseTFOValue() != -1 {
   160  		t.Fatalf("unexpected parsed TFO value, which should be -1")
   161  	}
   162  }
   163  
   164  func TestTransportConfig(t *testing.T) {
   165  	createParser := func() func(string) (proto.Message, error) {
   166  		return func(s string) (proto.Message, error) {
   167  			config := new(TransportConfig)
   168  			if err := json.Unmarshal([]byte(s), config); err != nil {
   169  				return nil, err
   170  			}
   171  			return config.Build()
   172  		}
   173  	}
   174  
   175  	runMultiTestCase(t, []TestCase{
   176  		{
   177  			Input: `{
   178  				"tcpSettings": {
   179  					"header": {
   180  						"type": "http",
   181  						"request": {
   182  							"version": "1.1",
   183  							"method": "GET",
   184  							"path": "/b",
   185  							"headers": {
   186  								"a": "b",
   187  								"c": "d"
   188  							}
   189  						},
   190  						"response": {
   191  							"version": "1.0",
   192  							"status": "404",
   193  							"reason": "Not Found"
   194  						}
   195  					}
   196  				},
   197  				"kcpSettings": {
   198  					"mtu": 1200,
   199  					"header": {
   200  						"type": "none"
   201  					}
   202  				},
   203  				"wsSettings": {
   204  					"path": "/t"
   205  				},
   206  				"quicSettings": {
   207  					"key": "abcd",
   208  					"header": {
   209  						"type": "dtls"
   210  					}
   211  				},
   212  				"grpcSettings": {
   213  					"serviceName": "name",
   214  					"multiMode": true
   215  				}
   216  			}`,
   217  			Parser: createParser(),
   218  			Output: &global.Config{
   219  				TransportSettings: []*internet.TransportConfig{
   220  					{
   221  						ProtocolName: "tcp",
   222  						Settings: serial.ToTypedMessage(&tcp.Config{
   223  							HeaderSettings: serial.ToTypedMessage(&http.Config{
   224  								Request: &http.RequestConfig{
   225  									Version: &http.Version{Value: "1.1"},
   226  									Method:  &http.Method{Value: "GET"},
   227  									Uri:     []string{"/b"},
   228  									Header: []*http.Header{
   229  										{Name: "a", Value: []string{"b"}},
   230  										{Name: "c", Value: []string{"d"}},
   231  									},
   232  								},
   233  								Response: &http.ResponseConfig{
   234  									Version: &http.Version{Value: "1.0"},
   235  									Status:  &http.Status{Code: "404", Reason: "Not Found"},
   236  									Header: []*http.Header{
   237  										{
   238  											Name:  "Content-Type",
   239  											Value: []string{"application/octet-stream", "video/mpeg"},
   240  										},
   241  										{
   242  											Name:  "Transfer-Encoding",
   243  											Value: []string{"chunked"},
   244  										},
   245  										{
   246  											Name:  "Connection",
   247  											Value: []string{"keep-alive"},
   248  										},
   249  										{
   250  											Name:  "Pragma",
   251  											Value: []string{"no-cache"},
   252  										},
   253  										{
   254  											Name:  "Cache-Control",
   255  											Value: []string{"private", "no-cache"},
   256  										},
   257  									},
   258  								},
   259  							}),
   260  						}),
   261  					},
   262  					{
   263  						ProtocolName: "mkcp",
   264  						Settings: serial.ToTypedMessage(&kcp.Config{
   265  							Mtu:          &kcp.MTU{Value: 1200},
   266  							HeaderConfig: serial.ToTypedMessage(&noop.Config{}),
   267  						}),
   268  					},
   269  					{
   270  						ProtocolName: "websocket",
   271  						Settings: serial.ToTypedMessage(&websocket.Config{
   272  							Path: "/t",
   273  						}),
   274  					},
   275  					{
   276  						ProtocolName: "quic",
   277  						Settings: serial.ToTypedMessage(&quic.Config{
   278  							Key: "abcd",
   279  							Security: &protocol.SecurityConfig{
   280  								Type: protocol.SecurityType_NONE,
   281  							},
   282  							Header: serial.ToTypedMessage(&tls.PacketConfig{}),
   283  						}),
   284  					},
   285  					{
   286  						ProtocolName: "grpc",
   287  						Settings: serial.ToTypedMessage(&grpc.Config{
   288  							ServiceName: "name",
   289  							MultiMode:   true,
   290  						}),
   291  					},
   292  				},
   293  			},
   294  		},
   295  		{
   296  			Input: `{
   297  				"gunSettings": {
   298  					"serviceName": "name"
   299  				}
   300  			}`,
   301  			Parser: createParser(),
   302  			Output: &global.Config{
   303  				TransportSettings: []*internet.TransportConfig{
   304  					{
   305  						ProtocolName: "grpc",
   306  						Settings: serial.ToTypedMessage(&grpc.Config{
   307  							ServiceName: "name",
   308  						}),
   309  					},
   310  				},
   311  			},
   312  		},
   313  	})
   314  }