Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SplitHTTP: More range options, change defaults, enforce maxUploadSize, fix querystring behavior #3603

Merged
merged 3 commits into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions infra/conf/transport_internet.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,8 @@ type SplitHTTPConfig struct {
Host string `json:"host"`
Path string `json:"path"`
Headers map[string]string `json:"headers"`
MaxConcurrentUploads int32 `json:"maxConcurrentUploads"`
MaxUploadSize int32 `json:"maxUploadSize"`
MaxConcurrentUploads Int32Range `json:"maxConcurrentUploads"`
MaxUploadSize Int32Range `json:"maxUploadSize"`
MinUploadIntervalMs Int32Range `json:"minUploadIntervalMs"`
}

Expand All @@ -245,11 +245,17 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
c.Host = c.Headers["Host"]
}
config := &splithttp.Config{
Path: c.Path,
Host: c.Host,
Header: c.Headers,
MaxConcurrentUploads: c.MaxConcurrentUploads,
MaxUploadSize: c.MaxUploadSize,
Path: c.Path,
Host: c.Host,
Header: c.Headers,
MaxConcurrentUploads: &splithttp.RandRangeConfig{
From: c.MaxConcurrentUploads.From,
To: c.MaxConcurrentUploads.To,
},
MaxUploadSize: &splithttp.RandRangeConfig{
From: c.MaxUploadSize.From,
To: c.MaxUploadSize.To,
},
MinUploadIntervalMs: &splithttp.RandRangeConfig{
From: c.MinUploadIntervalMs.From,
To: c.MinUploadIntervalMs.To,
Expand Down
61 changes: 42 additions & 19 deletions transport/internet/splithttp/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,28 @@ import (
"crypto/rand"
"math/big"
"net/http"
"strings"

"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/transport/internet"
)

func (c *Config) GetNormalizedPath() string {
path := c.Path
if path == "" {
path = "/"
func (c *Config) GetNormalizedPath(addPath string, addQuery bool) string {
pathAndQuery := strings.SplitN(c.Path, "?", 2)
path := pathAndQuery[0]
query := ""
if len(pathAndQuery) > 1 && addQuery {
query = "?" + pathAndQuery[1]
}
if path[0] != '/' {

if path == "" || path[0] != '/' {
path = "/" + path
}
if path[len(path)-1] != '/' {
path = path + "/"
}
return path

return path + addPath + query
}

func (c *Config) GetRequestHeader() http.Header {
Expand All @@ -31,33 +36,51 @@ func (c *Config) GetRequestHeader() http.Header {
return header
}

func (c *Config) GetNormalizedMaxConcurrentUploads() int32 {
if c.MaxConcurrentUploads == 0 {
return 10
func (c *Config) GetNormalizedMaxConcurrentUploads(isServer bool) RandRangeConfig {
if c.MaxConcurrentUploads == nil {
if isServer {
return RandRangeConfig{
From: 200,
To: 200,
}
} else {
return RandRangeConfig{
From: 100,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default value is changed from 10 to 100, really?

Copy link
Collaborator Author

@mmmray mmmray Jul 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the justification for this is that minUploadInterval=30 should prevent this from being reached in practice. #3592 (comment) I also don't see this limit being reached at all in my tests (number of connections/streams is lower than 20 at all times), so I am also not convinced it needed to be raised by that much (or at all)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

你要这么想,本来我是想删掉这个选项的,不过它确实对服务端还有些用

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also don't see this limit being reached at all in my tests (number of connections/streams is lower than 20 at all times), so I am also not convinced it needed to be raised by that much (or at all)

如果为了打游戏调成了 minUploadInterval=10,number of concurrent streams 应该会变多,I guess

To: 100,
}
}
}

return c.MaxConcurrentUploads
return *c.MaxConcurrentUploads
}

func (c *Config) GetNormalizedMaxUploadSize() int32 {
if c.MaxUploadSize == 0 {
return 1000000
func (c *Config) GetNormalizedMaxUploadSize(isServer bool) RandRangeConfig {
if c.MaxUploadSize == nil {
if isServer {
return RandRangeConfig{
From: 2000000,
To: 2000000,
}
} else {
return RandRangeConfig{
From: 1000000,
To: 1000000,
}
}
}

return c.MaxUploadSize
return *c.MaxUploadSize
}

func (c *Config) GetNormalizedMinUploadInterval() RandRangeConfig {
r := c.MinUploadIntervalMs

if r == nil {
r = &RandRangeConfig{
if c.MinUploadIntervalMs == nil {
return RandRangeConfig{
From: 30,
To: 30,
}
}

return *r
return *c.MinUploadIntervalMs
}

func init() {
Expand Down
94 changes: 51 additions & 43 deletions transport/internet/splithttp/config.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions transport/internet/splithttp/config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ message Config {
string host = 1;
string path = 2;
map<string, string> header = 3;
int32 maxConcurrentUploads = 4;
int32 maxUploadSize = 5;
RandRangeConfig maxConcurrentUploads = 4;
RandRangeConfig maxUploadSize = 5;
RandRangeConfig minUploadIntervalMs = 6;
}

Expand Down
51 changes: 51 additions & 0 deletions transport/internet/splithttp/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package splithttp_test

import (
"testing"

. "github.com/xtls/xray-core/transport/internet/splithttp"
)

func Test_GetNormalizedPath(t *testing.T) {
c := Config{
Path: "/?world",
}

path := c.GetNormalizedPath("hello", true)
if path != "/hello?world" {
t.Error("Unexpected: ", path)
}
}

func Test_GetNormalizedPath2(t *testing.T) {
c := Config{
Path: "?world",
}

path := c.GetNormalizedPath("hello", true)
if path != "/hello?world" {
t.Error("Unexpected: ", path)
}
}

func Test_GetNormalizedPath3(t *testing.T) {
c := Config{
Path: "hello?world",
}

path := c.GetNormalizedPath("", true)
if path != "/hello/?world" {
t.Error("Unexpected: ", path)
}
}

func Test_GetNormalizedPath4(t *testing.T) {
c := Config{
Path: "hello?world",
}

path := c.GetNormalizedPath("", false)
if path != "/hello/" {
t.Error("Unexpected: ", path)
}
}
17 changes: 8 additions & 9 deletions transport/internet/splithttp/dialer.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
transportConfiguration := streamSettings.ProtocolSettings.(*Config)
tlsConfig := tls.ConfigFromStreamSettings(streamSettings)

maxConcurrentUploads := transportConfiguration.GetNormalizedMaxConcurrentUploads()
maxUploadSize := transportConfiguration.GetNormalizedMaxUploadSize()
maxConcurrentUploads := transportConfiguration.GetNormalizedMaxConcurrentUploads(false)
maxUploadSize := transportConfiguration.GetNormalizedMaxUploadSize(false)
minUploadInterval := transportConfiguration.GetNormalizedMinUploadInterval()

if tlsConfig != nil {
Expand All @@ -194,18 +194,17 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
if requestURL.Host == "" {
requestURL.Host = dest.NetAddr()
}
requestURL.Path = transportConfiguration.GetNormalizedPath()

httpClient := getHTTPClient(ctx, dest, streamSettings)

sessionIdUuid := uuid.New()
sessionId := sessionIdUuid.String()
baseURL := requestURL.String() + sessionId
requestURL.Path = transportConfiguration.GetNormalizedPath(sessionIdUuid.String(), true)
baseURL := requestURL.String()

httpClient := getHTTPClient(ctx, dest, streamSettings)

uploadPipeReader, uploadPipeWriter := pipe.New(pipe.WithSizeLimit(maxUploadSize))
uploadPipeReader, uploadPipeWriter := pipe.New(pipe.WithSizeLimit(maxUploadSize.roll()))

go func() {
requestsLimiter := semaphore.New(int(maxConcurrentUploads))
requestsLimiter := semaphore.New(int(maxConcurrentUploads.roll()))
var requestCounter int64

lastWrite := time.Now()
Expand Down
Loading