mirror of https://github.com/XTLS/Xray-core
				
				
				
			Add shadowsocks-2022 inbound/outbound (#1061)
							parent
							
								
									3f64f3206c
								
							
						
					
					
						commit
						087f0d1240
					
				| 
						 | 
				
			
			@ -1,6 +1,10 @@
 | 
			
		|||
package session
 | 
			
		||||
 | 
			
		||||
import "context"
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
 | 
			
		||||
	"github.com/xtls/xray-core/features/routing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type sessionKey int
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -12,6 +16,7 @@ const (
 | 
			
		|||
	muxPreferedSessionKey
 | 
			
		||||
	sockoptSessionKey
 | 
			
		||||
	trackedConnectionErrorKey
 | 
			
		||||
	dispatcherKey
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ContextWithID returns a new context with the given ID.
 | 
			
		||||
| 
						 | 
				
			
			@ -115,3 +120,14 @@ func SubmitOutboundErrorToOriginator(ctx context.Context, err error) {
 | 
			
		|||
func TrackedConnectionError(ctx context.Context, tracker TrackedRequestErrorFeedback) context.Context {
 | 
			
		||||
	return context.WithValue(ctx, trackedConnectionErrorKey, tracker)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ContextWithDispatcher(ctx context.Context, dispatcher routing.Dispatcher) context.Context {
 | 
			
		||||
	return context.WithValue(ctx, dispatcherKey, dispatcher)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func DispatcherFromContext(ctx context.Context) routing.Dispatcher {
 | 
			
		||||
	if dispatcher, ok := ctx.Value(dispatcherKey).(routing.Dispatcher); ok {
 | 
			
		||||
		return dispatcher
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										18
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										18
									
								
								go.mod
								
								
								
								
							| 
						 | 
				
			
			@ -9,19 +9,23 @@ require (
 | 
			
		|||
	github.com/google/go-cmp v0.5.8
 | 
			
		||||
	github.com/gorilla/websocket v1.5.0
 | 
			
		||||
	github.com/lucas-clemente/quic-go v0.27.0
 | 
			
		||||
	github.com/marten-seemann/qtls-go1-16 v0.1.5
 | 
			
		||||
	github.com/marten-seemann/qtls-go1-17 v0.1.1
 | 
			
		||||
	github.com/marten-seemann/qtls-go1-18 v0.1.1
 | 
			
		||||
	github.com/miekg/dns v1.1.49
 | 
			
		||||
	github.com/pelletier/go-toml v1.9.5
 | 
			
		||||
	github.com/pires/go-proxyproto v0.6.2
 | 
			
		||||
	github.com/refraction-networking/utls v1.1.0
 | 
			
		||||
	github.com/sagernet/sing v0.0.0-20220523024450-2216901ec429
 | 
			
		||||
	github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb
 | 
			
		||||
	github.com/stretchr/testify v1.7.1
 | 
			
		||||
	github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
 | 
			
		||||
	github.com/xtls/go v0.0.0-20210920065950-d4af136d3672
 | 
			
		||||
	go.starlark.net v0.0.0-20220328144851-d1966c6b9fcd
 | 
			
		||||
	golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4
 | 
			
		||||
	golang.org/x/net v0.0.0-20220421235706-1d1ef9303861
 | 
			
		||||
	golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898
 | 
			
		||||
	golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2
 | 
			
		||||
	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
 | 
			
		||||
	golang.org/x/sys v0.0.0-20220422013727-9388b58f7150
 | 
			
		||||
	golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a
 | 
			
		||||
	google.golang.org/grpc v1.46.2
 | 
			
		||||
	google.golang.org/protobuf v1.28.0
 | 
			
		||||
	h12.io/socks v1.0.3
 | 
			
		||||
| 
						 | 
				
			
			@ -34,19 +38,19 @@ require (
 | 
			
		|||
	github.com/francoispqt/gojay v1.2.13 // indirect
 | 
			
		||||
	github.com/fsnotify/fsnotify v1.5.3 // indirect
 | 
			
		||||
	github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
 | 
			
		||||
	github.com/marten-seemann/qtls-go1-16 v0.1.5 // indirect
 | 
			
		||||
	github.com/marten-seemann/qtls-go1-17 v0.1.1 // indirect
 | 
			
		||||
	github.com/marten-seemann/qtls-go1-18 v0.1.1 // indirect
 | 
			
		||||
	github.com/klauspost/cpuid/v2 v2.0.12 // indirect
 | 
			
		||||
	github.com/nxadm/tail v1.4.8 // indirect
 | 
			
		||||
	github.com/onsi/ginkgo v1.16.5 // indirect
 | 
			
		||||
	github.com/pmezard/go-difflib v1.0.0 // indirect
 | 
			
		||||
	github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
 | 
			
		||||
	golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
 | 
			
		||||
	golang.org/x/text v0.3.7 // indirect
 | 
			
		||||
	golang.org/x/tools v0.1.10 // indirect
 | 
			
		||||
	golang.org/x/tools v0.1.11-0.20220325154526-54af36eca237 // indirect
 | 
			
		||||
	golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect
 | 
			
		||||
	golang.zx2c4.com/wireguard v0.0.0-20220407013110-ef5c587f782d // indirect
 | 
			
		||||
	google.golang.org/genproto v0.0.0-20220422154200-b37d22cd5731 // indirect
 | 
			
		||||
	gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
 | 
			
		||||
	gopkg.in/yaml.v2 v2.4.0 // indirect
 | 
			
		||||
	gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
 | 
			
		||||
	lukechampine.com/blake3 v1.1.7 // indirect
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										27
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										27
									
								
								go.sum
								
								
								
								
							| 
						 | 
				
			
			@ -111,6 +111,9 @@ github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0
 | 
			
		|||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 | 
			
		||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
 | 
			
		||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 | 
			
		||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
 | 
			
		||||
github.com/klauspost/cpuid/v2 v2.0.12 h1:p9dKCg8i4gmOxtv35DvrYoWqYzQrvEVdjQ762Y0OqZE=
 | 
			
		||||
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
 | 
			
		||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
 | 
			
		||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 | 
			
		||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 | 
			
		||||
| 
						 | 
				
			
			@ -171,6 +174,10 @@ github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr
 | 
			
		|||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
 | 
			
		||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 | 
			
		||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
 | 
			
		||||
github.com/sagernet/sing v0.0.0-20220522025344-b21aa294fca3 h1:z6cVzCta0vPVKo4lsiHMEDmw3cSFC5TGojXobbTS1DA=
 | 
			
		||||
github.com/sagernet/sing v0.0.0-20220522025344-b21aa294fca3/go.mod h1:7aFl1bLxdWLIhptc1DwhMWpRfT62rJYzKPYuYlzYs5w=
 | 
			
		||||
github.com/sagernet/sing v0.0.0-20220523024450-2216901ec429 h1:31vx64WHtycaqw0bGLl6ImJvmHsXqHoPzkuwKmTqbx8=
 | 
			
		||||
github.com/sagernet/sing v0.0.0-20220523024450-2216901ec429/go.mod h1:7aFl1bLxdWLIhptc1DwhMWpRfT62rJYzKPYuYlzYs5w=
 | 
			
		||||
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U=
 | 
			
		||||
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
 | 
			
		||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
 | 
			
		||||
| 
						 | 
				
			
			@ -226,8 +233,8 @@ golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACk
 | 
			
		|||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898 h1:SLP7Q4Di66FONjDJbCYrCRrh97focO6sLogHO7/g8F0=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 | 
			
		||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 | 
			
		||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 | 
			
		||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 | 
			
		||||
| 
						 | 
				
			
			@ -255,8 +262,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
 | 
			
		|||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 | 
			
		||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
 | 
			
		||||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 | 
			
		||||
golang.org/x/net v0.0.0-20220421235706-1d1ef9303861 h1:yssD99+7tqHWO5Gwh81phT+67hg+KttniBr6UnEXOY8=
 | 
			
		||||
golang.org/x/net v0.0.0-20220421235706-1d1ef9303861/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
 | 
			
		||||
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 h1:NWy5+hlRbC7HK+PmcXVUmW1IMyFce7to56IUvhUFm7Y=
 | 
			
		||||
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
 | 
			
		||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 | 
			
		||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 | 
			
		||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 | 
			
		||||
| 
						 | 
				
			
			@ -292,8 +299,8 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
 | 
			
		|||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 h1:xHms4gcpe1YE7A3yIllJXP16CMAGuqwO2lX1mTyyRRc=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 | 
			
		||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
			
		||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
			
		||||
| 
						 | 
				
			
			@ -317,14 +324,16 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
 | 
			
		|||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 | 
			
		||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 | 
			
		||||
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 | 
			
		||||
golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20=
 | 
			
		||||
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
 | 
			
		||||
golang.org/x/tools v0.1.11-0.20220325154526-54af36eca237 h1:mAhaIX1KEgotq+ju3XYdXUHvll7bzJDTgiDzIAKDdPc=
 | 
			
		||||
golang.org/x/tools v0.1.11-0.20220325154526-54af36eca237/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f h1:GGU+dLjvlC3qDwqYgL6UgRmHXhOOgns0bZu2Ty5mm6U=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
golang.zx2c4.com/wireguard v0.0.0-20220407013110-ef5c587f782d h1:q4JksJ2n0fmbXC0Aj0eOs6E0AcPqnKglxWXWFqGD6x0=
 | 
			
		||||
golang.zx2c4.com/wireguard v0.0.0-20220407013110-ef5c587f782d/go.mod h1:bVQfyl2sCM/QIIGHpWbFGfHPuDvqnCNkT6MQLTCjO/U=
 | 
			
		||||
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
 | 
			
		||||
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
 | 
			
		||||
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
 | 
			
		||||
| 
						 | 
				
			
			@ -393,5 +402,7 @@ honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWh
 | 
			
		|||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 | 
			
		||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 | 
			
		||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 | 
			
		||||
lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0=
 | 
			
		||||
lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=
 | 
			
		||||
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
 | 
			
		||||
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,46 @@
 | 
			
		|||
package conf
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/golang/protobuf/proto"
 | 
			
		||||
	"github.com/xtls/xray-core/common/net"
 | 
			
		||||
	"github.com/xtls/xray-core/proxy/shadowsocks_2022"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Shadowsocks2022ServerConfig struct {
 | 
			
		||||
	Cipher      string       `json:"method"`
 | 
			
		||||
	Key         string       `json:"key"`
 | 
			
		||||
	NetworkList *NetworkList `json:"network"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (v *Shadowsocks2022ServerConfig) Build() (proto.Message, error) {
 | 
			
		||||
	var network []net.Network
 | 
			
		||||
	if v.NetworkList != nil {
 | 
			
		||||
		network = v.NetworkList.Build()
 | 
			
		||||
	}
 | 
			
		||||
	return &shadowsocks_2022.ServerConfig{
 | 
			
		||||
		Method:  v.Cipher,
 | 
			
		||||
		Key:     v.Key,
 | 
			
		||||
		Network: network,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Shadowsocks2022ClientConfig struct {
 | 
			
		||||
	Address              *Address `json:"address"`
 | 
			
		||||
	Port                 uint16   `json:"port"`
 | 
			
		||||
	Cipher               string   `json:"method"`
 | 
			
		||||
	Key                  string   `json:"key"`
 | 
			
		||||
	ReducedIvHeadEntropy bool     `json:"reducedIvHeadEntropy"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (v *Shadowsocks2022ClientConfig) Build() (proto.Message, error) {
 | 
			
		||||
	if v.Address == nil {
 | 
			
		||||
		return nil, newError("shadowsocks 2022: missing server address")
 | 
			
		||||
	}
 | 
			
		||||
	return &shadowsocks_2022.ClientConfig{
 | 
			
		||||
		Address:              v.Address.Build(),
 | 
			
		||||
		Port:                 uint32(v.Port),
 | 
			
		||||
		Method:               v.Cipher,
 | 
			
		||||
		Key:                  v.Key,
 | 
			
		||||
		ReducedIvHeadEntropy: v.ReducedIvHeadEntropy,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -18,28 +18,30 @@ import (
 | 
			
		|||
 | 
			
		||||
var (
 | 
			
		||||
	inboundConfigLoader = NewJSONConfigLoader(ConfigCreatorCache{
 | 
			
		||||
		"dokodemo-door": func() interface{} { return new(DokodemoConfig) },
 | 
			
		||||
		"http":          func() interface{} { return new(HTTPServerConfig) },
 | 
			
		||||
		"shadowsocks":   func() interface{} { return new(ShadowsocksServerConfig) },
 | 
			
		||||
		"socks":         func() interface{} { return new(SocksServerConfig) },
 | 
			
		||||
		"vless":         func() interface{} { return new(VLessInboundConfig) },
 | 
			
		||||
		"vmess":         func() interface{} { return new(VMessInboundConfig) },
 | 
			
		||||
		"trojan":        func() interface{} { return new(TrojanServerConfig) },
 | 
			
		||||
		"mtproto":       func() interface{} { return new(MTProtoServerConfig) },
 | 
			
		||||
		"dokodemo-door":    func() interface{} { return new(DokodemoConfig) },
 | 
			
		||||
		"http":             func() interface{} { return new(HTTPServerConfig) },
 | 
			
		||||
		"shadowsocks":      func() interface{} { return new(ShadowsocksServerConfig) },
 | 
			
		||||
		"socks":            func() interface{} { return new(SocksServerConfig) },
 | 
			
		||||
		"vless":            func() interface{} { return new(VLessInboundConfig) },
 | 
			
		||||
		"vmess":            func() interface{} { return new(VMessInboundConfig) },
 | 
			
		||||
		"trojan":           func() interface{} { return new(TrojanServerConfig) },
 | 
			
		||||
		"mtproto":          func() interface{} { return new(MTProtoServerConfig) },
 | 
			
		||||
		"shadowsocks-2022": func() interface{} { return new(Shadowsocks2022ServerConfig) },
 | 
			
		||||
	}, "protocol", "settings")
 | 
			
		||||
 | 
			
		||||
	outboundConfigLoader = NewJSONConfigLoader(ConfigCreatorCache{
 | 
			
		||||
		"blackhole":   func() interface{} { return new(BlackholeConfig) },
 | 
			
		||||
		"loopback":    func() interface{} { return new(LoopbackConfig) },
 | 
			
		||||
		"freedom":     func() interface{} { return new(FreedomConfig) },
 | 
			
		||||
		"http":        func() interface{} { return new(HTTPClientConfig) },
 | 
			
		||||
		"shadowsocks": func() interface{} { return new(ShadowsocksClientConfig) },
 | 
			
		||||
		"socks":       func() interface{} { return new(SocksClientConfig) },
 | 
			
		||||
		"vless":       func() interface{} { return new(VLessOutboundConfig) },
 | 
			
		||||
		"vmess":       func() interface{} { return new(VMessOutboundConfig) },
 | 
			
		||||
		"trojan":      func() interface{} { return new(TrojanClientConfig) },
 | 
			
		||||
		"mtproto":     func() interface{} { return new(MTProtoClientConfig) },
 | 
			
		||||
		"dns":         func() interface{} { return new(DNSOutboundConfig) },
 | 
			
		||||
		"blackhole":        func() interface{} { return new(BlackholeConfig) },
 | 
			
		||||
		"loopback":         func() interface{} { return new(LoopbackConfig) },
 | 
			
		||||
		"freedom":          func() interface{} { return new(FreedomConfig) },
 | 
			
		||||
		"http":             func() interface{} { return new(HTTPClientConfig) },
 | 
			
		||||
		"shadowsocks":      func() interface{} { return new(ShadowsocksClientConfig) },
 | 
			
		||||
		"socks":            func() interface{} { return new(SocksClientConfig) },
 | 
			
		||||
		"vless":            func() interface{} { return new(VLessOutboundConfig) },
 | 
			
		||||
		"vmess":            func() interface{} { return new(VMessOutboundConfig) },
 | 
			
		||||
		"trojan":           func() interface{} { return new(TrojanClientConfig) },
 | 
			
		||||
		"mtproto":          func() interface{} { return new(MTProtoClientConfig) },
 | 
			
		||||
		"dns":              func() interface{} { return new(DNSOutboundConfig) },
 | 
			
		||||
		"shadowsocks-2022": func() interface{} { return new(Shadowsocks2022ClientConfig) },
 | 
			
		||||
	}, "protocol", "settings")
 | 
			
		||||
 | 
			
		||||
	ctllog = log.New(os.Stderr, "xctl> ", 0)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,283 @@
 | 
			
		|||
// Code generated by protoc-gen-go. DO NOT EDIT.
 | 
			
		||||
// versions:
 | 
			
		||||
// 	protoc-gen-go v1.28.0
 | 
			
		||||
// 	protoc        v3.20.1
 | 
			
		||||
// source: proxy/shadowsocks_2022/config.proto
 | 
			
		||||
 | 
			
		||||
package shadowsocks_2022
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	net "github.com/xtls/xray-core/common/net"
 | 
			
		||||
	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 | 
			
		||||
	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
 | 
			
		||||
	reflect "reflect"
 | 
			
		||||
	sync "sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// Verify that this generated code is sufficiently up-to-date.
 | 
			
		||||
	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
 | 
			
		||||
	// Verify that runtime/protoimpl is sufficiently up-to-date.
 | 
			
		||||
	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type ServerConfig struct {
 | 
			
		||||
	state         protoimpl.MessageState
 | 
			
		||||
	sizeCache     protoimpl.SizeCache
 | 
			
		||||
	unknownFields protoimpl.UnknownFields
 | 
			
		||||
 | 
			
		||||
	Method  string        `protobuf:"bytes,1,opt,name=method,proto3" json:"method,omitempty"`
 | 
			
		||||
	Key     string        `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
 | 
			
		||||
	Network []net.Network `protobuf:"varint,3,rep,packed,name=network,proto3,enum=xray.common.net.Network" json:"network,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (x *ServerConfig) Reset() {
 | 
			
		||||
	*x = ServerConfig{}
 | 
			
		||||
	if protoimpl.UnsafeEnabled {
 | 
			
		||||
		mi := &file_proxy_shadowsocks_2022_config_proto_msgTypes[0]
 | 
			
		||||
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 | 
			
		||||
		ms.StoreMessageInfo(mi)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (x *ServerConfig) String() string {
 | 
			
		||||
	return protoimpl.X.MessageStringOf(x)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*ServerConfig) ProtoMessage() {}
 | 
			
		||||
 | 
			
		||||
func (x *ServerConfig) ProtoReflect() protoreflect.Message {
 | 
			
		||||
	mi := &file_proxy_shadowsocks_2022_config_proto_msgTypes[0]
 | 
			
		||||
	if protoimpl.UnsafeEnabled && x != nil {
 | 
			
		||||
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 | 
			
		||||
		if ms.LoadMessageInfo() == nil {
 | 
			
		||||
			ms.StoreMessageInfo(mi)
 | 
			
		||||
		}
 | 
			
		||||
		return ms
 | 
			
		||||
	}
 | 
			
		||||
	return mi.MessageOf(x)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Deprecated: Use ServerConfig.ProtoReflect.Descriptor instead.
 | 
			
		||||
func (*ServerConfig) Descriptor() ([]byte, []int) {
 | 
			
		||||
	return file_proxy_shadowsocks_2022_config_proto_rawDescGZIP(), []int{0}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (x *ServerConfig) GetMethod() string {
 | 
			
		||||
	if x != nil {
 | 
			
		||||
		return x.Method
 | 
			
		||||
	}
 | 
			
		||||
	return ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (x *ServerConfig) GetKey() string {
 | 
			
		||||
	if x != nil {
 | 
			
		||||
		return x.Key
 | 
			
		||||
	}
 | 
			
		||||
	return ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (x *ServerConfig) GetNetwork() []net.Network {
 | 
			
		||||
	if x != nil {
 | 
			
		||||
		return x.Network
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ClientConfig struct {
 | 
			
		||||
	state         protoimpl.MessageState
 | 
			
		||||
	sizeCache     protoimpl.SizeCache
 | 
			
		||||
	unknownFields protoimpl.UnknownFields
 | 
			
		||||
 | 
			
		||||
	Address              *net.IPOrDomain `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
 | 
			
		||||
	Port                 uint32          `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"`
 | 
			
		||||
	Method               string          `protobuf:"bytes,3,opt,name=method,proto3" json:"method,omitempty"`
 | 
			
		||||
	Key                  string          `protobuf:"bytes,4,opt,name=key,proto3" json:"key,omitempty"`
 | 
			
		||||
	ReducedIvHeadEntropy bool            `protobuf:"varint,5,opt,name=reduced_iv_head_entropy,json=reducedIvHeadEntropy,proto3" json:"reduced_iv_head_entropy,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (x *ClientConfig) Reset() {
 | 
			
		||||
	*x = ClientConfig{}
 | 
			
		||||
	if protoimpl.UnsafeEnabled {
 | 
			
		||||
		mi := &file_proxy_shadowsocks_2022_config_proto_msgTypes[1]
 | 
			
		||||
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 | 
			
		||||
		ms.StoreMessageInfo(mi)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (x *ClientConfig) String() string {
 | 
			
		||||
	return protoimpl.X.MessageStringOf(x)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*ClientConfig) ProtoMessage() {}
 | 
			
		||||
 | 
			
		||||
func (x *ClientConfig) ProtoReflect() protoreflect.Message {
 | 
			
		||||
	mi := &file_proxy_shadowsocks_2022_config_proto_msgTypes[1]
 | 
			
		||||
	if protoimpl.UnsafeEnabled && x != nil {
 | 
			
		||||
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 | 
			
		||||
		if ms.LoadMessageInfo() == nil {
 | 
			
		||||
			ms.StoreMessageInfo(mi)
 | 
			
		||||
		}
 | 
			
		||||
		return ms
 | 
			
		||||
	}
 | 
			
		||||
	return mi.MessageOf(x)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Deprecated: Use ClientConfig.ProtoReflect.Descriptor instead.
 | 
			
		||||
func (*ClientConfig) Descriptor() ([]byte, []int) {
 | 
			
		||||
	return file_proxy_shadowsocks_2022_config_proto_rawDescGZIP(), []int{1}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (x *ClientConfig) GetAddress() *net.IPOrDomain {
 | 
			
		||||
	if x != nil {
 | 
			
		||||
		return x.Address
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (x *ClientConfig) GetPort() uint32 {
 | 
			
		||||
	if x != nil {
 | 
			
		||||
		return x.Port
 | 
			
		||||
	}
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (x *ClientConfig) GetMethod() string {
 | 
			
		||||
	if x != nil {
 | 
			
		||||
		return x.Method
 | 
			
		||||
	}
 | 
			
		||||
	return ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (x *ClientConfig) GetKey() string {
 | 
			
		||||
	if x != nil {
 | 
			
		||||
		return x.Key
 | 
			
		||||
	}
 | 
			
		||||
	return ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (x *ClientConfig) GetReducedIvHeadEntropy() bool {
 | 
			
		||||
	if x != nil {
 | 
			
		||||
		return x.ReducedIvHeadEntropy
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var File_proxy_shadowsocks_2022_config_proto protoreflect.FileDescriptor
 | 
			
		||||
 | 
			
		||||
var file_proxy_shadowsocks_2022_config_proto_rawDesc = []byte{
 | 
			
		||||
	0x0a, 0x23, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f,
 | 
			
		||||
	0x63, 0x6b, 0x73, 0x5f, 0x32, 0x30, 0x32, 0x32, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e,
 | 
			
		||||
	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1b, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78,
 | 
			
		||||
	0x79, 0x2e, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x5f, 0x32, 0x30,
 | 
			
		||||
	0x32, 0x32, 0x1a, 0x18, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x6e,
 | 
			
		||||
	0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x18, 0x63, 0x6f,
 | 
			
		||||
	0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
 | 
			
		||||
	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6c, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
 | 
			
		||||
	0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64,
 | 
			
		||||
	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x10,
 | 
			
		||||
	0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79,
 | 
			
		||||
	0x12, 0x32, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x03, 0x20, 0x03, 0x28,
 | 
			
		||||
	0x0e, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
 | 
			
		||||
	0x6e, 0x65, 0x74, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x07, 0x6e, 0x65, 0x74,
 | 
			
		||||
	0x77, 0x6f, 0x72, 0x6b, 0x22, 0xba, 0x01, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43,
 | 
			
		||||
	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x35, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
 | 
			
		||||
	0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f,
 | 
			
		||||
	0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d,
 | 
			
		||||
	0x61, 0x69, 0x6e, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04,
 | 
			
		||||
	0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74,
 | 
			
		||||
	0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
 | 
			
		||||
	0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
 | 
			
		||||
	0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x35, 0x0a, 0x17, 0x72, 0x65,
 | 
			
		||||
	0x64, 0x75, 0x63, 0x65, 0x64, 0x5f, 0x69, 0x76, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x65, 0x6e,
 | 
			
		||||
	0x74, 0x72, 0x6f, 0x70, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x72, 0x65, 0x64,
 | 
			
		||||
	0x75, 0x63, 0x65, 0x64, 0x49, 0x76, 0x48, 0x65, 0x61, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x6f, 0x70,
 | 
			
		||||
	0x79, 0x42, 0x72, 0x0a, 0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72,
 | 
			
		||||
	0x6f, 0x78, 0x79, 0x2e, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x5f,
 | 
			
		||||
	0x32, 0x30, 0x32, 0x32, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
 | 
			
		||||
	0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72,
 | 
			
		||||
	0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f,
 | 
			
		||||
	0x63, 0x6b, 0x73, 0x5f, 0x32, 0x30, 0x32, 0x32, 0xaa, 0x02, 0x1a, 0x58, 0x72, 0x61, 0x79, 0x2e,
 | 
			
		||||
	0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x53, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b,
 | 
			
		||||
	0x73, 0x32, 0x30, 0x32, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	file_proxy_shadowsocks_2022_config_proto_rawDescOnce sync.Once
 | 
			
		||||
	file_proxy_shadowsocks_2022_config_proto_rawDescData = file_proxy_shadowsocks_2022_config_proto_rawDesc
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func file_proxy_shadowsocks_2022_config_proto_rawDescGZIP() []byte {
 | 
			
		||||
	file_proxy_shadowsocks_2022_config_proto_rawDescOnce.Do(func() {
 | 
			
		||||
		file_proxy_shadowsocks_2022_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_proxy_shadowsocks_2022_config_proto_rawDescData)
 | 
			
		||||
	})
 | 
			
		||||
	return file_proxy_shadowsocks_2022_config_proto_rawDescData
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var file_proxy_shadowsocks_2022_config_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
 | 
			
		||||
var file_proxy_shadowsocks_2022_config_proto_goTypes = []interface{}{
 | 
			
		||||
	(*ServerConfig)(nil),   // 0: xray.proxy.shadowsocks_2022.ServerConfig
 | 
			
		||||
	(*ClientConfig)(nil),   // 1: xray.proxy.shadowsocks_2022.ClientConfig
 | 
			
		||||
	(net.Network)(0),       // 2: xray.common.net.Network
 | 
			
		||||
	(*net.IPOrDomain)(nil), // 3: xray.common.net.IPOrDomain
 | 
			
		||||
}
 | 
			
		||||
var file_proxy_shadowsocks_2022_config_proto_depIdxs = []int32{
 | 
			
		||||
	2, // 0: xray.proxy.shadowsocks_2022.ServerConfig.network:type_name -> xray.common.net.Network
 | 
			
		||||
	3, // 1: xray.proxy.shadowsocks_2022.ClientConfig.address:type_name -> xray.common.net.IPOrDomain
 | 
			
		||||
	2, // [2:2] is the sub-list for method output_type
 | 
			
		||||
	2, // [2:2] is the sub-list for method input_type
 | 
			
		||||
	2, // [2:2] is the sub-list for extension type_name
 | 
			
		||||
	2, // [2:2] is the sub-list for extension extendee
 | 
			
		||||
	0, // [0:2] is the sub-list for field type_name
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() { file_proxy_shadowsocks_2022_config_proto_init() }
 | 
			
		||||
func file_proxy_shadowsocks_2022_config_proto_init() {
 | 
			
		||||
	if File_proxy_shadowsocks_2022_config_proto != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if !protoimpl.UnsafeEnabled {
 | 
			
		||||
		file_proxy_shadowsocks_2022_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
 | 
			
		||||
			switch v := v.(*ServerConfig); i {
 | 
			
		||||
			case 0:
 | 
			
		||||
				return &v.state
 | 
			
		||||
			case 1:
 | 
			
		||||
				return &v.sizeCache
 | 
			
		||||
			case 2:
 | 
			
		||||
				return &v.unknownFields
 | 
			
		||||
			default:
 | 
			
		||||
				return nil
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		file_proxy_shadowsocks_2022_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
 | 
			
		||||
			switch v := v.(*ClientConfig); i {
 | 
			
		||||
			case 0:
 | 
			
		||||
				return &v.state
 | 
			
		||||
			case 1:
 | 
			
		||||
				return &v.sizeCache
 | 
			
		||||
			case 2:
 | 
			
		||||
				return &v.unknownFields
 | 
			
		||||
			default:
 | 
			
		||||
				return nil
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	type x struct{}
 | 
			
		||||
	out := protoimpl.TypeBuilder{
 | 
			
		||||
		File: protoimpl.DescBuilder{
 | 
			
		||||
			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 | 
			
		||||
			RawDescriptor: file_proxy_shadowsocks_2022_config_proto_rawDesc,
 | 
			
		||||
			NumEnums:      0,
 | 
			
		||||
			NumMessages:   2,
 | 
			
		||||
			NumExtensions: 0,
 | 
			
		||||
			NumServices:   0,
 | 
			
		||||
		},
 | 
			
		||||
		GoTypes:           file_proxy_shadowsocks_2022_config_proto_goTypes,
 | 
			
		||||
		DependencyIndexes: file_proxy_shadowsocks_2022_config_proto_depIdxs,
 | 
			
		||||
		MessageInfos:      file_proxy_shadowsocks_2022_config_proto_msgTypes,
 | 
			
		||||
	}.Build()
 | 
			
		||||
	File_proxy_shadowsocks_2022_config_proto = out.File
 | 
			
		||||
	file_proxy_shadowsocks_2022_config_proto_rawDesc = nil
 | 
			
		||||
	file_proxy_shadowsocks_2022_config_proto_goTypes = nil
 | 
			
		||||
	file_proxy_shadowsocks_2022_config_proto_depIdxs = nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
syntax = "proto3";
 | 
			
		||||
 | 
			
		||||
package xray.proxy.shadowsocks_2022;
 | 
			
		||||
option csharp_namespace = "Xray.Proxy.Shadowsocks2022";
 | 
			
		||||
option go_package = "github.com/xtls/xray-core/proxy/shadowsocks_2022";
 | 
			
		||||
option java_package = "com.xray.proxy.shadowsocks_2022";
 | 
			
		||||
option java_multiple_files = true;
 | 
			
		||||
 | 
			
		||||
import "common/net/network.proto";
 | 
			
		||||
import "common/net/address.proto";
 | 
			
		||||
 | 
			
		||||
message ServerConfig {
 | 
			
		||||
  string method = 1;
 | 
			
		||||
  string key = 2;
 | 
			
		||||
  repeated xray.common.net.Network network = 3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message ClientConfig {
 | 
			
		||||
  xray.common.net.IPOrDomain address = 1;
 | 
			
		||||
  uint32 port = 2;
 | 
			
		||||
  string method = 3;
 | 
			
		||||
  string key = 4;
 | 
			
		||||
  bool reduced_iv_head_entropy = 5;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
package shadowsocks_2022
 | 
			
		||||
 | 
			
		||||
import "github.com/xtls/xray-core/common/errors"
 | 
			
		||||
 | 
			
		||||
type errPathObjHolder struct{}
 | 
			
		||||
 | 
			
		||||
func newError(values ...interface{}) *errors.Error {
 | 
			
		||||
	return errors.New(values...).WithPathObj(errPathObjHolder{})
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,158 @@
 | 
			
		|||
package shadowsocks_2022
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
 | 
			
		||||
	C "github.com/sagernet/sing/common"
 | 
			
		||||
	B "github.com/sagernet/sing/common/buf"
 | 
			
		||||
	"github.com/sagernet/sing/common/bufio"
 | 
			
		||||
	M "github.com/sagernet/sing/common/metadata"
 | 
			
		||||
	N "github.com/sagernet/sing/common/network"
 | 
			
		||||
	"github.com/sagernet/sing/common/random"
 | 
			
		||||
	"github.com/sagernet/sing/protocol/shadowsocks"
 | 
			
		||||
	"github.com/sagernet/sing/protocol/shadowsocks/shadowaead_2022"
 | 
			
		||||
	"github.com/xtls/xray-core/common"
 | 
			
		||||
	"github.com/xtls/xray-core/common/buf"
 | 
			
		||||
	"github.com/xtls/xray-core/common/log"
 | 
			
		||||
	"github.com/xtls/xray-core/common/net"
 | 
			
		||||
	"github.com/xtls/xray-core/common/session"
 | 
			
		||||
	"github.com/xtls/xray-core/features/routing"
 | 
			
		||||
	"github.com/xtls/xray-core/transport/internet/stat"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	common.Must(common.RegisterConfig((*ServerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
 | 
			
		||||
		return NewServer(ctx, config.(*ServerConfig))
 | 
			
		||||
	}))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Inbound struct {
 | 
			
		||||
	networks []net.Network
 | 
			
		||||
	service  shadowsocks.Service
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewServer(ctx context.Context, config *ServerConfig) (*Inbound, error) {
 | 
			
		||||
	networks := config.Network
 | 
			
		||||
	if len(networks) == 0 {
 | 
			
		||||
		networks = []net.Network{
 | 
			
		||||
			net.Network_TCP,
 | 
			
		||||
			net.Network_UDP,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	inbound := &Inbound{
 | 
			
		||||
		networks: networks,
 | 
			
		||||
	}
 | 
			
		||||
	if !C.Contains(shadowaead_2022.List, config.Method) {
 | 
			
		||||
		return nil, newError("unsupported method ", config.Method)
 | 
			
		||||
	}
 | 
			
		||||
	if config.Key == "" {
 | 
			
		||||
		return nil, newError("missing key")
 | 
			
		||||
	}
 | 
			
		||||
	psk, err := base64.StdEncoding.DecodeString(config.Key)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, newError("parse config").Base(err)
 | 
			
		||||
	}
 | 
			
		||||
	service, err := shadowaead_2022.NewService(config.Method, psk, "", random.Default, 500, inbound)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, newError("create service").Base(err)
 | 
			
		||||
	}
 | 
			
		||||
	inbound.service = service
 | 
			
		||||
	return inbound, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (i *Inbound) Network() []net.Network {
 | 
			
		||||
	return i.networks
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (i *Inbound) Process(ctx context.Context, network net.Network, connection stat.Connection, dispatcher routing.Dispatcher) error {
 | 
			
		||||
	inbound := session.InboundFromContext(ctx)
 | 
			
		||||
	if inbound == nil {
 | 
			
		||||
		panic("no inbound metadata")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var metadata M.Metadata
 | 
			
		||||
	if inbound.Source.IsValid() {
 | 
			
		||||
		metadata.Source = M.ParseSocksaddr(inbound.Source.NetAddr())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx = session.ContextWithDispatcher(ctx, dispatcher)
 | 
			
		||||
 | 
			
		||||
	if network == net.Network_TCP {
 | 
			
		||||
		return i.service.NewConnection(ctx, connection, metadata)
 | 
			
		||||
	} else {
 | 
			
		||||
		reader := buf.NewReader(connection)
 | 
			
		||||
		pc := &natPacketConn{connection}
 | 
			
		||||
		for {
 | 
			
		||||
			mb, err := reader.ReadMultiBuffer()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			for _, buffer := range mb {
 | 
			
		||||
				err = i.service.NewPacket(ctx, pc, B.As(buffer.Bytes()), metadata)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (i *Inbound) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
 | 
			
		||||
	ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
 | 
			
		||||
		From:   metadata.Source,
 | 
			
		||||
		To:     metadata.Destination,
 | 
			
		||||
		Status: log.AccessAccepted,
 | 
			
		||||
	})
 | 
			
		||||
	newError("tunnelling request to tcp:", metadata.Destination).WriteToLog(session.ExportIDToError(ctx))
 | 
			
		||||
	dispatcher := session.DispatcherFromContext(ctx)
 | 
			
		||||
	link, err := dispatcher.Dispatch(ctx, toDestination(metadata.Destination, net.Network_TCP))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	outConn := &pipeConnWrapper{
 | 
			
		||||
		&buf.BufferedReader{Reader: link.Reader},
 | 
			
		||||
		link.Writer,
 | 
			
		||||
		conn,
 | 
			
		||||
	}
 | 
			
		||||
	return bufio.CopyConn(ctx, conn, outConn)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (i *Inbound) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
 | 
			
		||||
	ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
 | 
			
		||||
		From:   metadata.Source,
 | 
			
		||||
		To:     metadata.Destination,
 | 
			
		||||
		Status: log.AccessAccepted,
 | 
			
		||||
	})
 | 
			
		||||
	newError("tunnelling request to udp:", metadata.Destination).WriteToLog(session.ExportIDToError(ctx))
 | 
			
		||||
	dispatcher := session.DispatcherFromContext(ctx)
 | 
			
		||||
	destination := toDestination(metadata.Destination, net.Network_UDP)
 | 
			
		||||
	link, err := dispatcher.Dispatch(ctx, destination)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	outConn := &packetConnWrapper{
 | 
			
		||||
		Reader: link.Reader,
 | 
			
		||||
		Writer: link.Writer,
 | 
			
		||||
		Dest:   destination,
 | 
			
		||||
	}
 | 
			
		||||
	return bufio.CopyPacketConn(ctx, conn, outConn)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (i *Inbound) HandleError(err error) {
 | 
			
		||||
	newError(err).AtWarning().WriteToLog()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type natPacketConn struct {
 | 
			
		||||
	net.Conn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *natPacketConn) ReadPacket(buffer *B.Buffer) (addr M.Socksaddr, err error) {
 | 
			
		||||
	_, err = buffer.ReadFrom(c)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *natPacketConn) WritePacket(buffer *B.Buffer, addr M.Socksaddr) error {
 | 
			
		||||
	_, err := buffer.WriteTo(c)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,166 @@
 | 
			
		|||
package shadowsocks_2022
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"io"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	C "github.com/sagernet/sing/common"
 | 
			
		||||
	B "github.com/sagernet/sing/common/buf"
 | 
			
		||||
	"github.com/sagernet/sing/common/bufio"
 | 
			
		||||
	N "github.com/sagernet/sing/common/network"
 | 
			
		||||
	"github.com/sagernet/sing/common/random"
 | 
			
		||||
	"github.com/sagernet/sing/protocol/shadowsocks"
 | 
			
		||||
	"github.com/sagernet/sing/protocol/shadowsocks/shadowaead_2022"
 | 
			
		||||
	"github.com/xtls/xray-core/common"
 | 
			
		||||
	"github.com/xtls/xray-core/common/buf"
 | 
			
		||||
	"github.com/xtls/xray-core/common/net"
 | 
			
		||||
	"github.com/xtls/xray-core/common/session"
 | 
			
		||||
	"github.com/xtls/xray-core/transport"
 | 
			
		||||
	"github.com/xtls/xray-core/transport/internet"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	common.Must(common.RegisterConfig((*ClientConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
 | 
			
		||||
		return NewClient(ctx, config.(*ClientConfig))
 | 
			
		||||
	}))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Outbound struct {
 | 
			
		||||
	ctx    context.Context
 | 
			
		||||
	server net.Destination
 | 
			
		||||
	method shadowsocks.Method
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewClient(ctx context.Context, config *ClientConfig) (*Outbound, error) {
 | 
			
		||||
	o := &Outbound{
 | 
			
		||||
		ctx: ctx,
 | 
			
		||||
		server: net.Destination{
 | 
			
		||||
			Address: config.Address.AsAddress(),
 | 
			
		||||
			Port:    net.Port(config.Port),
 | 
			
		||||
			Network: net.Network_TCP,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	if C.Contains(shadowaead_2022.List, config.Method) {
 | 
			
		||||
		if config.Key == "" {
 | 
			
		||||
			return nil, newError("missing psk")
 | 
			
		||||
		}
 | 
			
		||||
		var pskList [][]byte
 | 
			
		||||
		for _, ks := range strings.Split(config.Key, ":") {
 | 
			
		||||
			psk, err := base64.StdEncoding.DecodeString(ks)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, newError("decode key ", ks).Base(err)
 | 
			
		||||
			}
 | 
			
		||||
			pskList = append(pskList, psk)
 | 
			
		||||
		}
 | 
			
		||||
		var rng io.Reader = random.Default
 | 
			
		||||
		if config.ReducedIvHeadEntropy {
 | 
			
		||||
			rng = &shadowsocks.ReducedEntropyReader{
 | 
			
		||||
				Reader: rng,
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		method, err := shadowaead_2022.New(config.Method, pskList, "", rng)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, newError("create method").Base(err)
 | 
			
		||||
		}
 | 
			
		||||
		o.method = method
 | 
			
		||||
	} else {
 | 
			
		||||
		return nil, newError("unknown method ", config.Method)
 | 
			
		||||
	}
 | 
			
		||||
	return o, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *Outbound) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error {
 | 
			
		||||
	var inboundConn net.Conn
 | 
			
		||||
	inbound := session.InboundFromContext(ctx)
 | 
			
		||||
	if inbound != nil {
 | 
			
		||||
		inboundConn = inbound.Conn
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	outbound := session.OutboundFromContext(ctx)
 | 
			
		||||
	if outbound == nil || !outbound.Target.IsValid() {
 | 
			
		||||
		return newError("target not specified")
 | 
			
		||||
	}
 | 
			
		||||
	/*if statConn, ok := inboundConn.(*internet.StatCounterConn); ok {
 | 
			
		||||
		inboundConn = statConn.Connection
 | 
			
		||||
	}*/
 | 
			
		||||
	destination := outbound.Target
 | 
			
		||||
	network := destination.Network
 | 
			
		||||
 | 
			
		||||
	newError("tunneling request to ", destination, " via ", o.server.NetAddr()).WriteToLog(session.ExportIDToError(ctx))
 | 
			
		||||
 | 
			
		||||
	serverDestination := o.server
 | 
			
		||||
	serverDestination.Network = network
 | 
			
		||||
	connection, err := dialer.Dial(ctx, serverDestination)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return newError("failed to connect to server").Base(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if network == net.Network_TCP {
 | 
			
		||||
		serverConn := o.method.DialEarlyConn(connection, toSocksaddr(destination))
 | 
			
		||||
		var handshake bool
 | 
			
		||||
		if timeoutReader, isTimeoutReader := link.Reader.(buf.TimeoutReader); isTimeoutReader {
 | 
			
		||||
			mb, err := timeoutReader.ReadMultiBufferTimeout(time.Millisecond * 100)
 | 
			
		||||
			if err != nil && err != buf.ErrNotTimeoutReader && err != buf.ErrReadTimeout {
 | 
			
		||||
				return newError("read payload").Base(err)
 | 
			
		||||
			}
 | 
			
		||||
			_payload := B.StackNew()
 | 
			
		||||
			payload := C.Dup(_payload)
 | 
			
		||||
			for {
 | 
			
		||||
				payload.FullReset()
 | 
			
		||||
				nb, n := buf.SplitBytes(mb, payload.FreeBytes())
 | 
			
		||||
				if n > 0 {
 | 
			
		||||
					payload.Truncate(n)
 | 
			
		||||
					_, err = serverConn.Write(payload.Bytes())
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						return newError("write payload").Base(err)
 | 
			
		||||
					}
 | 
			
		||||
					handshake = true
 | 
			
		||||
				}
 | 
			
		||||
				if nb.IsEmpty() {
 | 
			
		||||
					break
 | 
			
		||||
				} else {
 | 
			
		||||
					mb = nb
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			runtime.KeepAlive(_payload)
 | 
			
		||||
		}
 | 
			
		||||
		if !handshake {
 | 
			
		||||
			_, err = serverConn.Write(nil)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return newError("client handshake").Base(err)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		conn := &pipeConnWrapper{
 | 
			
		||||
			W:    link.Writer,
 | 
			
		||||
			Conn: inboundConn,
 | 
			
		||||
		}
 | 
			
		||||
		if ir, ok := link.Reader.(io.Reader); ok {
 | 
			
		||||
			conn.R = ir
 | 
			
		||||
		} else {
 | 
			
		||||
			conn.R = &buf.BufferedReader{Reader: link.Reader}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return bufio.CopyConn(ctx, conn, serverConn)
 | 
			
		||||
	} else {
 | 
			
		||||
		var packetConn N.PacketConn
 | 
			
		||||
		if pc, isPacketConn := inboundConn.(N.PacketConn); isPacketConn {
 | 
			
		||||
			packetConn = pc
 | 
			
		||||
		} else if nc, isNetPacket := inboundConn.(net.PacketConn); isNetPacket {
 | 
			
		||||
			packetConn = &bufio.PacketConnWrapper{PacketConn: nc}
 | 
			
		||||
		} else {
 | 
			
		||||
			packetConn = &packetConnWrapper{
 | 
			
		||||
				Reader: link.Reader,
 | 
			
		||||
				Writer: link.Writer,
 | 
			
		||||
				Conn:   inboundConn,
 | 
			
		||||
				Dest:   destination,
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		serverConn := o.method.DialPacketConn(connection)
 | 
			
		||||
		return bufio.CopyPacketConn(ctx, packetConn, serverConn)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,143 @@
 | 
			
		|||
package shadowsocks_2022
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"io"
 | 
			
		||||
 | 
			
		||||
	B "github.com/sagernet/sing/common/buf"
 | 
			
		||||
	M "github.com/sagernet/sing/common/metadata"
 | 
			
		||||
	"github.com/xtls/xray-core/common"
 | 
			
		||||
	"github.com/xtls/xray-core/common/buf"
 | 
			
		||||
	"github.com/xtls/xray-core/common/net"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
 | 
			
		||||
 | 
			
		||||
func toDestination(socksaddr M.Socksaddr, network net.Network) net.Destination {
 | 
			
		||||
	if socksaddr.Family().IsFqdn() {
 | 
			
		||||
		return net.Destination{
 | 
			
		||||
			Network: network,
 | 
			
		||||
			Address: net.DomainAddress(socksaddr.Fqdn),
 | 
			
		||||
			Port:    net.Port(socksaddr.Port),
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		return net.Destination{
 | 
			
		||||
			Network: network,
 | 
			
		||||
			Address: net.IPAddress(socksaddr.Addr.AsSlice()),
 | 
			
		||||
			Port:    net.Port(socksaddr.Port),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func toSocksaddr(destination net.Destination) M.Socksaddr {
 | 
			
		||||
	var addr M.Socksaddr
 | 
			
		||||
	switch destination.Address.Family() {
 | 
			
		||||
	case net.AddressFamilyDomain:
 | 
			
		||||
		addr.Fqdn = destination.Address.Domain()
 | 
			
		||||
	default:
 | 
			
		||||
		addr.Addr = M.AddrFromIP(destination.Address.IP())
 | 
			
		||||
	}
 | 
			
		||||
	addr.Port = uint16(destination.Port)
 | 
			
		||||
	return addr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type pipeConnWrapper struct {
 | 
			
		||||
	R io.Reader
 | 
			
		||||
	W buf.Writer
 | 
			
		||||
	net.Conn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *pipeConnWrapper) Close() error {
 | 
			
		||||
	common.Interrupt(w.R)
 | 
			
		||||
	common.Interrupt(w.W)
 | 
			
		||||
	common.Close(w.Conn)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *pipeConnWrapper) Read(b []byte) (n int, err error) {
 | 
			
		||||
	return w.R.Read(b)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *pipeConnWrapper) Write(p []byte) (n int, err error) {
 | 
			
		||||
	n = len(p)
 | 
			
		||||
	var mb buf.MultiBuffer
 | 
			
		||||
	pLen := len(p)
 | 
			
		||||
	for pLen > 0 {
 | 
			
		||||
		buffer := buf.New()
 | 
			
		||||
		if pLen > buf.Size {
 | 
			
		||||
			_, err = buffer.Write(p[:buf.Size])
 | 
			
		||||
			p = p[buf.Size:]
 | 
			
		||||
		} else {
 | 
			
		||||
			buffer.Write(p)
 | 
			
		||||
		}
 | 
			
		||||
		pLen -= int(buffer.Len())
 | 
			
		||||
		mb = append(mb, buffer)
 | 
			
		||||
	}
 | 
			
		||||
	err = w.W.WriteMultiBuffer(mb)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		n = 0
 | 
			
		||||
		buf.ReleaseMulti(mb)
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type packetConnWrapper struct {
 | 
			
		||||
	buf.Reader
 | 
			
		||||
	buf.Writer
 | 
			
		||||
	net.Conn
 | 
			
		||||
	Dest   net.Destination
 | 
			
		||||
	cached buf.MultiBuffer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *packetConnWrapper) ReadPacket(buffer *B.Buffer) (M.Socksaddr, error) {
 | 
			
		||||
	if w.cached != nil {
 | 
			
		||||
		mb, bb := buf.SplitFirst(w.cached)
 | 
			
		||||
		if bb == nil {
 | 
			
		||||
			w.cached = nil
 | 
			
		||||
		} else {
 | 
			
		||||
			buffer.Write(bb.Bytes())
 | 
			
		||||
			w.cached = mb
 | 
			
		||||
			var destination net.Destination
 | 
			
		||||
			if bb.UDP != nil {
 | 
			
		||||
				destination = *bb.UDP
 | 
			
		||||
			} else {
 | 
			
		||||
				destination = w.Dest
 | 
			
		||||
			}
 | 
			
		||||
			bb.Release()
 | 
			
		||||
			return toSocksaddr(destination), nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	mb, err := w.ReadMultiBuffer()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return M.Socksaddr{}, err
 | 
			
		||||
	}
 | 
			
		||||
	nb, bb := buf.SplitFirst(mb)
 | 
			
		||||
	if bb == nil {
 | 
			
		||||
		return M.Socksaddr{}, nil
 | 
			
		||||
	} else {
 | 
			
		||||
		buffer.Write(bb.Bytes())
 | 
			
		||||
		w.cached = nb
 | 
			
		||||
		var destination net.Destination
 | 
			
		||||
		if bb.UDP != nil {
 | 
			
		||||
			destination = *bb.UDP
 | 
			
		||||
		} else {
 | 
			
		||||
			destination = w.Dest
 | 
			
		||||
		}
 | 
			
		||||
		bb.Release()
 | 
			
		||||
		return toSocksaddr(destination), nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *packetConnWrapper) WritePacket(buffer *B.Buffer, destination M.Socksaddr) error {
 | 
			
		||||
	vBuf := buf.New()
 | 
			
		||||
	vBuf.Write(buffer.Bytes())
 | 
			
		||||
	endpoint := toDestination(destination, net.Network_UDP)
 | 
			
		||||
	vBuf.UDP = &endpoint
 | 
			
		||||
	return w.Writer.WriteMultiBuffer(buf.MultiBuffer{vBuf})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *packetConnWrapper) Close() error {
 | 
			
		||||
	common.Interrupt(w.Reader)
 | 
			
		||||
	common.Close(w.Conn)
 | 
			
		||||
	buf.ReleaseMulti(w.cached)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue