mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-07-08 17:23:20 +03:00
Compare commits
18 Commits
v1.3-beta9
...
v1.3-beta8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fbb01555c8 | ||
|
|
3c217fea63 | ||
|
|
a02c676d33 | ||
|
|
c2ae261c8d | ||
|
|
1fe69cc08c | ||
|
|
dacb885930 | ||
|
|
31682c313b | ||
|
|
6fd73131cb | ||
|
|
f3ff76abcc | ||
|
|
d9757bfaff | ||
|
|
9d97ed6220 | ||
|
|
054211d091 | ||
|
|
69b92810d6 | ||
|
|
ea23267ced | ||
|
|
bbe2b1ab09 | ||
|
|
d3530a54fb | ||
|
|
c238df9309 | ||
|
|
a223262678 |
3
box.go
3
box.go
@@ -62,7 +62,6 @@ func New(options Options) (*Box, error) {
|
|||||||
defaultLogWriter = io.Discard
|
defaultLogWriter = io.Discard
|
||||||
}
|
}
|
||||||
logFactory, err := log.New(log.Options{
|
logFactory, err := log.New(log.Options{
|
||||||
Context: ctx,
|
|
||||||
Options: common.PtrValueOrDefault(options.Log),
|
Options: common.PtrValueOrDefault(options.Log),
|
||||||
Observable: needClashAPI,
|
Observable: needClashAPI,
|
||||||
DefaultWriter: defaultLogWriter,
|
DefaultWriter: defaultLogWriter,
|
||||||
@@ -143,7 +142,7 @@ func New(options Options) (*Box, error) {
|
|||||||
preServices := make(map[string]adapter.Service)
|
preServices := make(map[string]adapter.Service)
|
||||||
postServices := make(map[string]adapter.Service)
|
postServices := make(map[string]adapter.Service)
|
||||||
if needClashAPI {
|
if needClashAPI {
|
||||||
clashServer, err := experimental.NewClashServer(ctx, router, logFactory.(log.ObservableFactory), common.PtrValueOrDefault(options.Experimental.ClashAPI))
|
clashServer, err := experimental.NewClashServer(router, logFactory.(log.ObservableFactory), common.PtrValueOrDefault(options.Experimental.ClashAPI))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.Cause(err, "create clash api server")
|
return nil, E.Cause(err, "create clash api server")
|
||||||
}
|
}
|
||||||
|
|||||||
44
cmd/sing-box/debug.go
Normal file
44
cmd/sing-box/debug.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
//go:build debug
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
_ "net/http/pprof"
|
||||||
|
"runtime"
|
||||||
|
"runtime/debug"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/common/badjson"
|
||||||
|
"github.com/sagernet/sing-box/log"
|
||||||
|
|
||||||
|
"github.com/dustin/go-humanize"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
http.HandleFunc("/debug/gc", func(writer http.ResponseWriter, request *http.Request) {
|
||||||
|
writer.WriteHeader(http.StatusNoContent)
|
||||||
|
go debug.FreeOSMemory()
|
||||||
|
})
|
||||||
|
http.HandleFunc("/debug/memory", func(writer http.ResponseWriter, request *http.Request) {
|
||||||
|
var memStats runtime.MemStats
|
||||||
|
runtime.ReadMemStats(&memStats)
|
||||||
|
|
||||||
|
var memObject badjson.JSONObject
|
||||||
|
memObject.Put("heap", humanize.IBytes(memStats.HeapInuse))
|
||||||
|
memObject.Put("stack", humanize.IBytes(memStats.StackInuse))
|
||||||
|
memObject.Put("idle", humanize.IBytes(memStats.HeapIdle-memStats.HeapReleased))
|
||||||
|
memObject.Put("goroutines", runtime.NumGoroutine())
|
||||||
|
memObject.Put("rss", rusageMaxRSS())
|
||||||
|
|
||||||
|
encoder := json.NewEncoder(writer)
|
||||||
|
encoder.SetIndent("", " ")
|
||||||
|
encoder.Encode(memObject)
|
||||||
|
})
|
||||||
|
go func() {
|
||||||
|
err := http.ListenAndServe("0.0.0.0:8964", nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Debug(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
package box
|
//go:build debug
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"runtime"
|
"runtime"
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
//go:build !linux
|
//go:build debug && !linux
|
||||||
|
|
||||||
package box
|
package main
|
||||||
|
|
||||||
func rusageMaxRSS() float64 {
|
func rusageMaxRSS() float64 {
|
||||||
return -1
|
return -1
|
||||||
@@ -28,10 +28,9 @@ type Client struct {
|
|||||||
maxConnections int
|
maxConnections int
|
||||||
minStreams int
|
minStreams int
|
||||||
maxStreams int
|
maxStreams int
|
||||||
paddingEnabled bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClient(ctx context.Context, dialer N.Dialer, protocol Protocol, maxConnections int, minStreams int, maxStreams int, paddingEnabled bool) (*Client, error) {
|
func NewClient(ctx context.Context, dialer N.Dialer, protocol Protocol, maxConnections int, minStreams int, maxStreams int) *Client {
|
||||||
return &Client{
|
return &Client{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
dialer: dialer,
|
dialer: dialer,
|
||||||
@@ -39,11 +38,10 @@ func NewClient(ctx context.Context, dialer N.Dialer, protocol Protocol, maxConne
|
|||||||
maxConnections: maxConnections,
|
maxConnections: maxConnections,
|
||||||
minStreams: minStreams,
|
minStreams: minStreams,
|
||||||
maxStreams: maxStreams,
|
maxStreams: maxStreams,
|
||||||
paddingEnabled: paddingEnabled,
|
}
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClientWithOptions(ctx context.Context, dialer N.Dialer, options option.MultiplexOptions) (*Client, error) {
|
func NewClientWithOptions(ctx context.Context, dialer N.Dialer, options option.MultiplexOptions) (N.Dialer, error) {
|
||||||
if !options.Enabled {
|
if !options.Enabled {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@@ -54,7 +52,7 @@ func NewClientWithOptions(ctx context.Context, dialer N.Dialer, options option.M
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return NewClient(ctx, dialer, protocol, options.MaxConnections, options.MinStreams, options.MaxStreams, options.Padding)
|
return NewClient(ctx, dialer, protocol, options.MaxConnections, options.MinStreams, options.MaxStreams), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
func (c *Client) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||||
@@ -122,16 +120,17 @@ func (c *Client) offer() (abstractSession, error) {
|
|||||||
sessions = append(sessions, element.Value)
|
sessions = append(sessions, element.Value)
|
||||||
element = element.Next()
|
element = element.Next()
|
||||||
}
|
}
|
||||||
session := common.MinBy(common.Filter(sessions, abstractSession.CanTakeNewRequest), abstractSession.NumStreams)
|
sLen := len(sessions)
|
||||||
if session == nil {
|
if sLen == 0 {
|
||||||
return c.offerNew()
|
return c.offerNew()
|
||||||
}
|
}
|
||||||
|
session := common.MinBy(sessions, abstractSession.NumStreams)
|
||||||
numStreams := session.NumStreams()
|
numStreams := session.NumStreams()
|
||||||
if numStreams == 0 {
|
if numStreams == 0 {
|
||||||
return session, nil
|
return session, nil
|
||||||
}
|
}
|
||||||
if c.maxConnections > 0 {
|
if c.maxConnections > 0 {
|
||||||
if len(sessions) >= c.maxConnections || numStreams < c.minStreams {
|
if sLen >= c.maxConnections || numStreams < c.minStreams {
|
||||||
return session, nil
|
return session, nil
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -147,19 +146,10 @@ func (c *Client) offerNew() (abstractSession, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var version byte
|
if vectorisedWriter, isVectorised := bufio.CreateVectorisedWriter(conn); isVectorised {
|
||||||
if c.paddingEnabled {
|
conn = &vectorisedProtocolConn{protocolConn{Conn: conn, protocol: c.protocol}, vectorisedWriter}
|
||||||
version = Version1
|
|
||||||
} else {
|
} else {
|
||||||
version = Version0
|
conn = &protocolConn{Conn: conn, protocol: c.protocol}
|
||||||
}
|
|
||||||
conn = newProtocolConn(conn, Request{
|
|
||||||
Version: version,
|
|
||||||
Protocol: c.protocol,
|
|
||||||
PaddingEnabled: c.paddingEnabled,
|
|
||||||
})
|
|
||||||
if c.paddingEnabled {
|
|
||||||
conn = newPaddingConn(conn)
|
|
||||||
}
|
}
|
||||||
session, err := c.protocol.newClient(conn)
|
session, err := c.protocol.newClient(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -169,15 +159,6 @@ func (c *Client) offerNew() (abstractSession, error) {
|
|||||||
return session, nil
|
return session, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) Reset() {
|
|
||||||
c.access.Lock()
|
|
||||||
defer c.access.Unlock()
|
|
||||||
for _, session := range c.connections.Array() {
|
|
||||||
session.Close()
|
|
||||||
}
|
|
||||||
c.connections.Init()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) Close() error {
|
func (c *Client) Close() error {
|
||||||
c.access.Lock()
|
c.access.Lock()
|
||||||
defer c.access.Unlock()
|
defer c.access.Unlock()
|
||||||
@@ -224,7 +205,7 @@ func (c *ClientConn) Write(b []byte) (n int, err error) {
|
|||||||
Network: N.NetworkTCP,
|
Network: N.NetworkTCP,
|
||||||
Destination: c.destination,
|
Destination: c.destination,
|
||||||
}
|
}
|
||||||
_buffer := buf.StackNewSize(streamRequestLen(request) + len(b))
|
_buffer := buf.StackNewSize(requestLen(request) + len(b))
|
||||||
defer common.KeepAlive(_buffer)
|
defer common.KeepAlive(_buffer)
|
||||||
buffer := common.Dup(_buffer)
|
buffer := common.Dup(_buffer)
|
||||||
defer buffer.Release()
|
defer buffer.Release()
|
||||||
@@ -318,7 +299,7 @@ func (c *ClientPacketConn) writeRequest(payload []byte) (n int, err error) {
|
|||||||
Network: N.NetworkUDP,
|
Network: N.NetworkUDP,
|
||||||
Destination: c.destination,
|
Destination: c.destination,
|
||||||
}
|
}
|
||||||
rLen := streamRequestLen(request)
|
rLen := requestLen(request)
|
||||||
if len(payload) > 0 {
|
if len(payload) > 0 {
|
||||||
rLen += 2 + len(payload)
|
rLen += 2 + len(payload)
|
||||||
}
|
}
|
||||||
@@ -463,7 +444,7 @@ func (c *ClientPacketAddrConn) writeRequest(payload []byte, destination M.Socksa
|
|||||||
Destination: c.destination,
|
Destination: c.destination,
|
||||||
PacketAddr: true,
|
PacketAddr: true,
|
||||||
}
|
}
|
||||||
rLen := streamRequestLen(request)
|
rLen := requestLen(request)
|
||||||
if len(payload) > 0 {
|
if len(payload) > 0 {
|
||||||
rLen += M.SocksaddrSerializer.AddrPortLen(destination) + 2 + len(payload)
|
rLen += M.SocksaddrSerializer.AddrPortLen(destination) + 2 + len(payload)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,235 +0,0 @@
|
|||||||
package mux
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/transport/v2rayhttp"
|
|
||||||
"github.com/sagernet/sing/common/atomic"
|
|
||||||
"github.com/sagernet/sing/common/buf"
|
|
||||||
"github.com/sagernet/sing/common/bufio"
|
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
|
||||||
N "github.com/sagernet/sing/common/network"
|
|
||||||
|
|
||||||
"golang.org/x/net/http2"
|
|
||||||
)
|
|
||||||
|
|
||||||
const idleTimeout = 30 * time.Second
|
|
||||||
|
|
||||||
var _ abstractSession = (*H2MuxServerSession)(nil)
|
|
||||||
|
|
||||||
type H2MuxServerSession struct {
|
|
||||||
server http2.Server
|
|
||||||
active atomic.Int32
|
|
||||||
conn net.Conn
|
|
||||||
inbound chan net.Conn
|
|
||||||
done chan struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewH2MuxServer(conn net.Conn) *H2MuxServerSession {
|
|
||||||
session := &H2MuxServerSession{
|
|
||||||
conn: conn,
|
|
||||||
inbound: make(chan net.Conn),
|
|
||||||
done: make(chan struct{}),
|
|
||||||
server: http2.Server{
|
|
||||||
IdleTimeout: idleTimeout,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
session.server.ServeConn(conn, &http2.ServeConnOpts{
|
|
||||||
Handler: session,
|
|
||||||
})
|
|
||||||
_ = session.Close()
|
|
||||||
}()
|
|
||||||
return session
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *H2MuxServerSession) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
|
|
||||||
s.active.Add(1)
|
|
||||||
defer s.active.Add(-1)
|
|
||||||
writer.WriteHeader(http.StatusOK)
|
|
||||||
conn := newHTTP2Wrapper(&v2rayhttp.ServerHTTPConn{
|
|
||||||
HTTP2Conn: v2rayhttp.NewHTTPConn(request.Body, writer),
|
|
||||||
Flusher: writer.(http.Flusher),
|
|
||||||
})
|
|
||||||
s.inbound <- conn
|
|
||||||
select {
|
|
||||||
case <-conn.done:
|
|
||||||
case <-s.done:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *H2MuxServerSession) Open() (net.Conn, error) {
|
|
||||||
return nil, os.ErrInvalid
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *H2MuxServerSession) Accept() (net.Conn, error) {
|
|
||||||
select {
|
|
||||||
case conn := <-s.inbound:
|
|
||||||
return conn, nil
|
|
||||||
case <-s.done:
|
|
||||||
return nil, os.ErrClosed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *H2MuxServerSession) NumStreams() int {
|
|
||||||
return int(s.active.Load())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *H2MuxServerSession) Close() error {
|
|
||||||
select {
|
|
||||||
case <-s.done:
|
|
||||||
default:
|
|
||||||
close(s.done)
|
|
||||||
}
|
|
||||||
return s.conn.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *H2MuxServerSession) IsClosed() bool {
|
|
||||||
select {
|
|
||||||
case <-s.done:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *H2MuxServerSession) CanTakeNewRequest() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type h2MuxConnWrapper struct {
|
|
||||||
N.ExtendedConn
|
|
||||||
done chan struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func newHTTP2Wrapper(conn net.Conn) *h2MuxConnWrapper {
|
|
||||||
return &h2MuxConnWrapper{
|
|
||||||
ExtendedConn: bufio.NewExtendedConn(conn),
|
|
||||||
done: make(chan struct{}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *h2MuxConnWrapper) Write(p []byte) (n int, err error) {
|
|
||||||
select {
|
|
||||||
case <-w.done:
|
|
||||||
return 0, net.ErrClosed
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
return w.ExtendedConn.Write(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *h2MuxConnWrapper) WriteBuffer(buffer *buf.Buffer) error {
|
|
||||||
select {
|
|
||||||
case <-w.done:
|
|
||||||
return net.ErrClosed
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
return w.ExtendedConn.WriteBuffer(buffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *h2MuxConnWrapper) Close() error {
|
|
||||||
select {
|
|
||||||
case <-w.done:
|
|
||||||
default:
|
|
||||||
close(w.done)
|
|
||||||
}
|
|
||||||
return w.ExtendedConn.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *h2MuxConnWrapper) Upstream() any {
|
|
||||||
return w.ExtendedConn
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ abstractSession = (*H2MuxClientSession)(nil)
|
|
||||||
|
|
||||||
type H2MuxClientSession struct {
|
|
||||||
transport *http2.Transport
|
|
||||||
clientConn *http2.ClientConn
|
|
||||||
done chan struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewH2MuxClient(conn net.Conn) (*H2MuxClientSession, error) {
|
|
||||||
session := &H2MuxClientSession{
|
|
||||||
transport: &http2.Transport{
|
|
||||||
DialTLSContext: func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error) {
|
|
||||||
return conn, nil
|
|
||||||
},
|
|
||||||
ReadIdleTimeout: idleTimeout,
|
|
||||||
},
|
|
||||||
done: make(chan struct{}),
|
|
||||||
}
|
|
||||||
session.transport.ConnPool = session
|
|
||||||
clientConn, err := session.transport.NewClientConn(conn)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
session.clientConn = clientConn
|
|
||||||
return session, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *H2MuxClientSession) GetClientConn(req *http.Request, addr string) (*http2.ClientConn, error) {
|
|
||||||
return s.clientConn, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *H2MuxClientSession) MarkDead(conn *http2.ClientConn) {
|
|
||||||
s.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *H2MuxClientSession) Open() (net.Conn, error) {
|
|
||||||
pipeInReader, pipeInWriter := io.Pipe()
|
|
||||||
request := &http.Request{
|
|
||||||
Method: http.MethodConnect,
|
|
||||||
Body: pipeInReader,
|
|
||||||
URL: &url.URL{Scheme: "https", Host: "localhost"},
|
|
||||||
}
|
|
||||||
conn := v2rayhttp.NewLateHTTPConn(pipeInWriter)
|
|
||||||
go func() {
|
|
||||||
response, err := s.transport.RoundTrip(request)
|
|
||||||
if err != nil {
|
|
||||||
conn.Setup(nil, err)
|
|
||||||
} else if response.StatusCode != 200 {
|
|
||||||
response.Body.Close()
|
|
||||||
conn.Setup(nil, E.New("unexpected status: ", response.StatusCode, " ", response.Status))
|
|
||||||
} else {
|
|
||||||
conn.Setup(response.Body, nil)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return conn, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *H2MuxClientSession) Accept() (net.Conn, error) {
|
|
||||||
return nil, os.ErrInvalid
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *H2MuxClientSession) NumStreams() int {
|
|
||||||
return s.clientConn.State().StreamsActive
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *H2MuxClientSession) Close() error {
|
|
||||||
select {
|
|
||||||
case <-s.done:
|
|
||||||
default:
|
|
||||||
close(s.done)
|
|
||||||
}
|
|
||||||
return s.clientConn.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *H2MuxClientSession) IsClosed() bool {
|
|
||||||
select {
|
|
||||||
case <-s.done:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
return s.clientConn.State().Closed
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *H2MuxClientSession) CanTakeNewRequest() bool {
|
|
||||||
return s.clientConn.CanTakeNewRequest()
|
|
||||||
}
|
|
||||||
@@ -1,240 +0,0 @@
|
|||||||
package mux
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"io"
|
|
||||||
"math/rand"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/sagernet/sing/common"
|
|
||||||
"github.com/sagernet/sing/common/buf"
|
|
||||||
"github.com/sagernet/sing/common/bufio"
|
|
||||||
N "github.com/sagernet/sing/common/network"
|
|
||||||
"github.com/sagernet/sing/common/rw"
|
|
||||||
)
|
|
||||||
|
|
||||||
const kFirstPaddings = 16
|
|
||||||
|
|
||||||
type paddingConn struct {
|
|
||||||
N.ExtendedConn
|
|
||||||
writer N.VectorisedWriter
|
|
||||||
readPadding int
|
|
||||||
writePadding int
|
|
||||||
readRemaining int
|
|
||||||
paddingRemaining int
|
|
||||||
}
|
|
||||||
|
|
||||||
func newPaddingConn(conn net.Conn) net.Conn {
|
|
||||||
writer, isVectorised := bufio.CreateVectorisedWriter(conn)
|
|
||||||
if isVectorised {
|
|
||||||
return &vectorisedPaddingConn{
|
|
||||||
paddingConn{
|
|
||||||
ExtendedConn: bufio.NewExtendedConn(conn),
|
|
||||||
writer: bufio.NewVectorisedWriter(conn),
|
|
||||||
},
|
|
||||||
writer,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return &paddingConn{
|
|
||||||
ExtendedConn: bufio.NewExtendedConn(conn),
|
|
||||||
writer: bufio.NewVectorisedWriter(conn),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *paddingConn) Read(p []byte) (n int, err error) {
|
|
||||||
if c.readRemaining > 0 {
|
|
||||||
if len(p) > c.readRemaining {
|
|
||||||
p = p[:c.readRemaining]
|
|
||||||
}
|
|
||||||
n, err = c.ExtendedConn.Read(p)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.readRemaining -= n
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if c.paddingRemaining > 0 {
|
|
||||||
err = rw.SkipN(c.ExtendedConn, c.paddingRemaining)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.paddingRemaining = 0
|
|
||||||
}
|
|
||||||
if c.readPadding < kFirstPaddings {
|
|
||||||
var paddingHdr []byte
|
|
||||||
if len(p) >= 4 {
|
|
||||||
paddingHdr = p[:4]
|
|
||||||
} else {
|
|
||||||
_paddingHdr := make([]byte, 4)
|
|
||||||
defer common.KeepAlive(_paddingHdr)
|
|
||||||
paddingHdr = common.Dup(_paddingHdr)
|
|
||||||
}
|
|
||||||
_, err = io.ReadFull(c.ExtendedConn, paddingHdr)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
originalDataSize := int(binary.BigEndian.Uint16(paddingHdr[:2]))
|
|
||||||
paddingLen := int(binary.BigEndian.Uint16(paddingHdr[2:]))
|
|
||||||
if len(p) > originalDataSize {
|
|
||||||
p = p[:originalDataSize]
|
|
||||||
}
|
|
||||||
n, err = c.ExtendedConn.Read(p)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.readPadding++
|
|
||||||
c.readRemaining = originalDataSize - n
|
|
||||||
c.paddingRemaining = paddingLen
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return c.ExtendedConn.Read(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *paddingConn) Write(p []byte) (n int, err error) {
|
|
||||||
for pLen := len(p); pLen > 0; {
|
|
||||||
var data []byte
|
|
||||||
if pLen > 65535 {
|
|
||||||
data = p[:65535]
|
|
||||||
p = p[65535:]
|
|
||||||
pLen -= 65535
|
|
||||||
} else {
|
|
||||||
data = p
|
|
||||||
pLen = 0
|
|
||||||
}
|
|
||||||
var writeN int
|
|
||||||
writeN, err = c.write(data)
|
|
||||||
n += writeN
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *paddingConn) write(p []byte) (n int, err error) {
|
|
||||||
if c.writePadding < kFirstPaddings {
|
|
||||||
paddingLen := 256 + rand.Intn(512)
|
|
||||||
_buffer := buf.StackNewSize(4 + len(p) + paddingLen)
|
|
||||||
defer common.KeepAlive(_buffer)
|
|
||||||
buffer := common.Dup(_buffer)
|
|
||||||
defer buffer.Release()
|
|
||||||
header := buffer.Extend(4)
|
|
||||||
binary.BigEndian.PutUint16(header[:2], uint16(len(p)))
|
|
||||||
binary.BigEndian.PutUint16(header[2:], uint16(paddingLen))
|
|
||||||
common.Must1(buffer.Write(p))
|
|
||||||
buffer.Extend(paddingLen)
|
|
||||||
_, err = c.ExtendedConn.Write(buffer.Bytes())
|
|
||||||
if err == nil {
|
|
||||||
n = len(p)
|
|
||||||
}
|
|
||||||
c.writePadding++
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return c.ExtendedConn.Write(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *paddingConn) ReadBuffer(buffer *buf.Buffer) error {
|
|
||||||
p := buffer.FreeBytes()
|
|
||||||
if c.readRemaining > 0 {
|
|
||||||
if len(p) > c.readRemaining {
|
|
||||||
p = p[:c.readRemaining]
|
|
||||||
}
|
|
||||||
n, err := c.ExtendedConn.Read(p)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
c.readRemaining -= n
|
|
||||||
buffer.Truncate(n)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if c.paddingRemaining > 0 {
|
|
||||||
err := rw.SkipN(c.ExtendedConn, c.paddingRemaining)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
c.paddingRemaining = 0
|
|
||||||
}
|
|
||||||
if c.readPadding < kFirstPaddings {
|
|
||||||
var paddingHdr []byte
|
|
||||||
if len(p) >= 4 {
|
|
||||||
paddingHdr = p[:4]
|
|
||||||
} else {
|
|
||||||
_paddingHdr := make([]byte, 4)
|
|
||||||
defer common.KeepAlive(_paddingHdr)
|
|
||||||
paddingHdr = common.Dup(_paddingHdr)
|
|
||||||
}
|
|
||||||
_, err := io.ReadFull(c.ExtendedConn, paddingHdr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
originalDataSize := int(binary.BigEndian.Uint16(paddingHdr[:2]))
|
|
||||||
paddingLen := int(binary.BigEndian.Uint16(paddingHdr[2:]))
|
|
||||||
|
|
||||||
if len(p) > originalDataSize {
|
|
||||||
p = p[:originalDataSize]
|
|
||||||
}
|
|
||||||
n, err := c.ExtendedConn.Read(p)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
c.readPadding++
|
|
||||||
c.readRemaining = originalDataSize - n
|
|
||||||
c.paddingRemaining = paddingLen
|
|
||||||
buffer.Truncate(n)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return c.ExtendedConn.ReadBuffer(buffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *paddingConn) WriteBuffer(buffer *buf.Buffer) error {
|
|
||||||
if c.writePadding < kFirstPaddings {
|
|
||||||
bufferLen := buffer.Len()
|
|
||||||
if bufferLen > 65535 {
|
|
||||||
return common.Error(c.Write(buffer.Bytes()))
|
|
||||||
}
|
|
||||||
paddingLen := 256 + rand.Intn(512)
|
|
||||||
header := buffer.ExtendHeader(4)
|
|
||||||
binary.BigEndian.PutUint16(header[:2], uint16(bufferLen))
|
|
||||||
binary.BigEndian.PutUint16(header[2:], uint16(paddingLen))
|
|
||||||
buffer.Extend(paddingLen)
|
|
||||||
c.writePadding++
|
|
||||||
}
|
|
||||||
return c.ExtendedConn.WriteBuffer(buffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *paddingConn) FrontHeadroom() int {
|
|
||||||
return 4 + 256 + 1024
|
|
||||||
}
|
|
||||||
|
|
||||||
type vectorisedPaddingConn struct {
|
|
||||||
paddingConn
|
|
||||||
writer N.VectorisedWriter
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *vectorisedPaddingConn) WriteVectorised(buffers []*buf.Buffer) error {
|
|
||||||
if c.writePadding < kFirstPaddings {
|
|
||||||
bufferLen := buf.LenMulti(buffers)
|
|
||||||
if bufferLen > 65535 {
|
|
||||||
defer buf.ReleaseMulti(buffers)
|
|
||||||
for _, buffer := range buffers {
|
|
||||||
_, err := c.Write(buffer.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
paddingLen := 256 + rand.Intn(512)
|
|
||||||
header := buf.NewSize(4)
|
|
||||||
common.Must(
|
|
||||||
binary.Write(header, binary.BigEndian, uint16(bufferLen)),
|
|
||||||
binary.Write(header, binary.BigEndian, uint16(paddingLen)),
|
|
||||||
)
|
|
||||||
c.writePadding++
|
|
||||||
padding := buf.NewSize(paddingLen)
|
|
||||||
padding.Extend(paddingLen)
|
|
||||||
buffers = append(append([]*buf.Buffer{header}, buffers...), padding)
|
|
||||||
}
|
|
||||||
return c.writer.WriteVectorised(buffers)
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,6 @@ package mux
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"io"
|
"io"
|
||||||
"math/rand"
|
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
@@ -26,7 +25,6 @@ var Destination = M.Socksaddr{
|
|||||||
const (
|
const (
|
||||||
ProtocolSMux Protocol = iota
|
ProtocolSMux Protocol = iota
|
||||||
ProtocolYAMux
|
ProtocolYAMux
|
||||||
ProtocolH2Mux
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Protocol byte
|
type Protocol byte
|
||||||
@@ -37,10 +35,8 @@ func ParseProtocol(name string) (Protocol, error) {
|
|||||||
return ProtocolSMux, nil
|
return ProtocolSMux, nil
|
||||||
case "yamux":
|
case "yamux":
|
||||||
return ProtocolYAMux, nil
|
return ProtocolYAMux, nil
|
||||||
case "h2mux":
|
|
||||||
return ProtocolH2Mux, nil
|
|
||||||
default:
|
default:
|
||||||
return ProtocolSMux, E.New("unknown multiplex protocol: ", name)
|
return ProtocolYAMux, E.New("unknown multiplex protocol: ", name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,13 +49,7 @@ func (p Protocol) newServer(conn net.Conn) (abstractSession, error) {
|
|||||||
}
|
}
|
||||||
return &smuxSession{session}, nil
|
return &smuxSession{session}, nil
|
||||||
case ProtocolYAMux:
|
case ProtocolYAMux:
|
||||||
session, err := yamux.Server(conn, yaMuxConfig())
|
return yamux.Server(conn, yaMuxConfig())
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &yamuxSession{session}, nil
|
|
||||||
case ProtocolH2Mux:
|
|
||||||
return NewH2MuxServer(conn), nil
|
|
||||||
default:
|
default:
|
||||||
panic("unknown protocol")
|
panic("unknown protocol")
|
||||||
}
|
}
|
||||||
@@ -74,13 +64,7 @@ func (p Protocol) newClient(conn net.Conn) (abstractSession, error) {
|
|||||||
}
|
}
|
||||||
return &smuxSession{session}, nil
|
return &smuxSession{session}, nil
|
||||||
case ProtocolYAMux:
|
case ProtocolYAMux:
|
||||||
session, err := yamux.Client(conn, yaMuxConfig())
|
return yamux.Client(conn, yaMuxConfig())
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &yamuxSession{session}, nil
|
|
||||||
case ProtocolH2Mux:
|
|
||||||
return NewH2MuxClient(conn)
|
|
||||||
default:
|
default:
|
||||||
panic("unknown protocol")
|
panic("unknown protocol")
|
||||||
}
|
}
|
||||||
@@ -106,22 +90,17 @@ func (p Protocol) String() string {
|
|||||||
return "smux"
|
return "smux"
|
||||||
case ProtocolYAMux:
|
case ProtocolYAMux:
|
||||||
return "yamux"
|
return "yamux"
|
||||||
case ProtocolH2Mux:
|
|
||||||
return "h2mux"
|
|
||||||
default:
|
default:
|
||||||
return "unknown"
|
return "unknown"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Version0 = iota
|
version0 = 0
|
||||||
Version1
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Request struct {
|
type Request struct {
|
||||||
Version byte
|
Protocol Protocol
|
||||||
Protocol Protocol
|
|
||||||
PaddingEnabled bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadRequest(reader io.Reader) (*Request, error) {
|
func ReadRequest(reader io.Reader) (*Request, error) {
|
||||||
@@ -129,60 +108,22 @@ func ReadRequest(reader io.Reader) (*Request, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if version < Version0 || version > Version1 {
|
if version != version0 {
|
||||||
return nil, E.New("unsupported version: ", version)
|
return nil, E.New("unsupported version: ", version)
|
||||||
}
|
}
|
||||||
protocol, err := rw.ReadByte(reader)
|
protocol, err := rw.ReadByte(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var paddingEnabled bool
|
if protocol > byte(ProtocolYAMux) {
|
||||||
if version == Version1 {
|
return nil, E.New("unsupported protocol: ", protocol)
|
||||||
err = binary.Read(reader, binary.BigEndian, &paddingEnabled)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if paddingEnabled {
|
|
||||||
var paddingLen uint16
|
|
||||||
err = binary.Read(reader, binary.BigEndian, &paddingLen)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
err = rw.SkipN(reader, int(paddingLen))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return &Request{Version: version, Protocol: Protocol(protocol), PaddingEnabled: paddingEnabled}, nil
|
return &Request{Protocol: Protocol(protocol)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func EncodeRequest(request Request, payload []byte) *buf.Buffer {
|
func EncodeRequest(buffer *buf.Buffer, request Request) {
|
||||||
var requestLen int
|
buffer.WriteByte(version0)
|
||||||
requestLen += 2
|
buffer.WriteByte(byte(request.Protocol))
|
||||||
var paddingLen uint16
|
|
||||||
if request.Version == Version1 {
|
|
||||||
requestLen += 1
|
|
||||||
if request.PaddingEnabled {
|
|
||||||
requestLen += 2
|
|
||||||
paddingLen = uint16(256 + rand.Intn(512))
|
|
||||||
requestLen += int(paddingLen)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buffer := buf.NewSize(requestLen + len(payload))
|
|
||||||
common.Must(
|
|
||||||
buffer.WriteByte(request.Version),
|
|
||||||
buffer.WriteByte(byte(request.Protocol)),
|
|
||||||
)
|
|
||||||
if request.Version == Version1 {
|
|
||||||
common.Must(binary.Write(buffer, binary.BigEndian, request.PaddingEnabled))
|
|
||||||
if request.PaddingEnabled {
|
|
||||||
common.Must(binary.Write(buffer, binary.BigEndian, paddingLen))
|
|
||||||
buffer.Extend(int(paddingLen))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
common.Must1(buffer.Write(payload))
|
|
||||||
return buffer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -219,7 +160,7 @@ func ReadStreamRequest(reader io.Reader) (*StreamRequest, error) {
|
|||||||
return &StreamRequest{network, destination, udpAddr}, nil
|
return &StreamRequest{network, destination, udpAddr}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func streamRequestLen(request StreamRequest) int {
|
func requestLen(request StreamRequest) int {
|
||||||
var rLen int
|
var rLen int
|
||||||
rLen += 1 // version
|
rLen += 1 // version
|
||||||
rLen += 2 // flags
|
rLen += 2 // flags
|
||||||
|
|||||||
@@ -22,9 +22,6 @@ func NewConnection(ctx context.Context, router adapter.Router, errorHandler E.Ha
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if request.PaddingEnabled {
|
|
||||||
conn = newPaddingConn(conn)
|
|
||||||
}
|
|
||||||
session, err := request.Protocol.newServer(conn)
|
session, err := request.Protocol.newServer(conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -4,12 +4,11 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
"github.com/sagernet/sing/common/buf"
|
"github.com/sagernet/sing/common/buf"
|
||||||
"github.com/sagernet/sing/common/bufio"
|
"github.com/sagernet/sing/common/bufio"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
"github.com/sagernet/smux"
|
"github.com/sagernet/smux"
|
||||||
|
|
||||||
"github.com/hashicorp/yamux"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type abstractSession interface {
|
type abstractSession interface {
|
||||||
@@ -18,7 +17,6 @@ type abstractSession interface {
|
|||||||
NumStreams() int
|
NumStreams() int
|
||||||
Close() error
|
Close() error
|
||||||
IsClosed() bool
|
IsClosed() bool
|
||||||
CanTakeNewRequest() bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ abstractSession = (*smuxSession)(nil)
|
var _ abstractSession = (*smuxSession)(nil)
|
||||||
@@ -35,49 +33,25 @@ func (s *smuxSession) Accept() (net.Conn, error) {
|
|||||||
return s.AcceptStream()
|
return s.AcceptStream()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *smuxSession) CanTakeNewRequest() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
type yamuxSession struct {
|
|
||||||
*yamux.Session
|
|
||||||
}
|
|
||||||
|
|
||||||
func (y *yamuxSession) CanTakeNewRequest() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
type protocolConn struct {
|
type protocolConn struct {
|
||||||
net.Conn
|
net.Conn
|
||||||
request Request
|
protocol Protocol
|
||||||
protocolWritten bool
|
protocolWritten bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func newProtocolConn(conn net.Conn, request Request) net.Conn {
|
|
||||||
writer, isVectorised := bufio.CreateVectorisedWriter(conn)
|
|
||||||
if isVectorised {
|
|
||||||
return &vectorisedProtocolConn{
|
|
||||||
protocolConn{
|
|
||||||
Conn: conn,
|
|
||||||
request: request,
|
|
||||||
},
|
|
||||||
writer,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return &protocolConn{
|
|
||||||
Conn: conn,
|
|
||||||
request: request,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *protocolConn) Write(p []byte) (n int, err error) {
|
func (c *protocolConn) Write(p []byte) (n int, err error) {
|
||||||
if c.protocolWritten {
|
if c.protocolWritten {
|
||||||
return c.Conn.Write(p)
|
return c.Conn.Write(p)
|
||||||
}
|
}
|
||||||
buffer := EncodeRequest(c.request, p)
|
_buffer := buf.StackNewSize(2 + len(p))
|
||||||
|
defer common.KeepAlive(_buffer)
|
||||||
|
buffer := common.Dup(_buffer)
|
||||||
|
defer buffer.Release()
|
||||||
|
EncodeRequest(buffer, Request{
|
||||||
|
Protocol: c.protocol,
|
||||||
|
})
|
||||||
|
common.Must(common.Error(buffer.Write(p)))
|
||||||
n, err = c.Conn.Write(buffer.Bytes())
|
n, err = c.Conn.Write(buffer.Bytes())
|
||||||
buffer.Release()
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
n--
|
n--
|
||||||
}
|
}
|
||||||
@@ -98,14 +72,20 @@ func (c *protocolConn) Upstream() any {
|
|||||||
|
|
||||||
type vectorisedProtocolConn struct {
|
type vectorisedProtocolConn struct {
|
||||||
protocolConn
|
protocolConn
|
||||||
writer N.VectorisedWriter
|
N.VectorisedWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *vectorisedProtocolConn) WriteVectorised(buffers []*buf.Buffer) error {
|
func (c *vectorisedProtocolConn) WriteVectorised(buffers []*buf.Buffer) error {
|
||||||
if c.protocolWritten {
|
if c.protocolWritten {
|
||||||
return c.writer.WriteVectorised(buffers)
|
return c.VectorisedWriter.WriteVectorised(buffers)
|
||||||
}
|
}
|
||||||
c.protocolWritten = true
|
c.protocolWritten = true
|
||||||
buffer := EncodeRequest(c.request, nil)
|
_buffer := buf.StackNewSize(2)
|
||||||
return c.writer.WriteVectorised(append([]*buf.Buffer{buffer}, buffers...))
|
defer common.KeepAlive(_buffer)
|
||||||
|
buffer := common.Dup(_buffer)
|
||||||
|
defer buffer.Release()
|
||||||
|
EncodeRequest(buffer, Request{
|
||||||
|
Protocol: c.protocol,
|
||||||
|
})
|
||||||
|
return c.VectorisedWriter.WriteVectorised(append([]*buf.Buffer{buffer}, buffers...))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,40 @@ package constant
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/sagernet/sing/common/rw"
|
"github.com/sagernet/sing/common/rw"
|
||||||
)
|
)
|
||||||
|
|
||||||
const dirName = "sing-box"
|
const dirName = "sing-box"
|
||||||
|
|
||||||
var resourcePaths []string
|
var (
|
||||||
|
basePath string
|
||||||
|
tempPath string
|
||||||
|
resourcePaths []string
|
||||||
|
)
|
||||||
|
|
||||||
|
func BasePath(name string) string {
|
||||||
|
if basePath == "" || strings.HasPrefix(name, "/") {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
return filepath.Join(basePath, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateTemp(pattern string) (*os.File, error) {
|
||||||
|
if tempPath == "" {
|
||||||
|
tempPath = os.TempDir()
|
||||||
|
}
|
||||||
|
return os.CreateTemp(tempPath, pattern)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetBasePath(path string) {
|
||||||
|
basePath = path
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetTempPath(path string) {
|
||||||
|
tempPath = path
|
||||||
|
}
|
||||||
|
|
||||||
func FindPath(name string) (string, bool) {
|
func FindPath(name string) (string, bool) {
|
||||||
name = os.ExpandEnv(name)
|
name = os.ExpandEnv(name)
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func applyDebugOptions(options option.DebugOptions) {
|
func applyDebugOptions(options option.DebugOptions) {
|
||||||
applyDebugListenOption(options)
|
|
||||||
if options.GCPercent != nil {
|
if options.GCPercent != nil {
|
||||||
debug.SetGCPercent(*options.GCPercent)
|
debug.SetGCPercent(*options.GCPercent)
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func applyDebugOptions(options option.DebugOptions) {
|
func applyDebugOptions(options option.DebugOptions) {
|
||||||
applyDebugListenOption(options)
|
|
||||||
if options.GCPercent != nil {
|
if options.GCPercent != nil {
|
||||||
debug.SetGCPercent(*options.GCPercent)
|
debug.SetGCPercent(*options.GCPercent)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
package box
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"net/http/pprof"
|
|
||||||
"runtime"
|
|
||||||
"runtime/debug"
|
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/common/badjson"
|
|
||||||
"github.com/sagernet/sing-box/common/json"
|
|
||||||
"github.com/sagernet/sing-box/log"
|
|
||||||
"github.com/sagernet/sing-box/option"
|
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
|
||||||
|
|
||||||
"github.com/dustin/go-humanize"
|
|
||||||
"github.com/go-chi/chi/v5"
|
|
||||||
)
|
|
||||||
|
|
||||||
var debugHTTPServer *http.Server
|
|
||||||
|
|
||||||
func applyDebugListenOption(options option.DebugOptions) {
|
|
||||||
if debugHTTPServer != nil {
|
|
||||||
debugHTTPServer.Close()
|
|
||||||
debugHTTPServer = nil
|
|
||||||
}
|
|
||||||
if options.Listen == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
r := chi.NewMux()
|
|
||||||
r.Route("/debug", func(r chi.Router) {
|
|
||||||
r.Get("/gc", func(writer http.ResponseWriter, request *http.Request) {
|
|
||||||
writer.WriteHeader(http.StatusNoContent)
|
|
||||||
go debug.FreeOSMemory()
|
|
||||||
})
|
|
||||||
r.Get("/memory", func(writer http.ResponseWriter, request *http.Request) {
|
|
||||||
var memStats runtime.MemStats
|
|
||||||
runtime.ReadMemStats(&memStats)
|
|
||||||
|
|
||||||
var memObject badjson.JSONObject
|
|
||||||
memObject.Put("heap", humanize.IBytes(memStats.HeapInuse))
|
|
||||||
memObject.Put("stack", humanize.IBytes(memStats.StackInuse))
|
|
||||||
memObject.Put("idle", humanize.IBytes(memStats.HeapIdle-memStats.HeapReleased))
|
|
||||||
memObject.Put("goroutines", runtime.NumGoroutine())
|
|
||||||
memObject.Put("rss", rusageMaxRSS())
|
|
||||||
|
|
||||||
encoder := json.NewEncoder(writer)
|
|
||||||
encoder.SetIndent("", " ")
|
|
||||||
encoder.Encode(memObject)
|
|
||||||
})
|
|
||||||
r.HandleFunc("/pprof", pprof.Index)
|
|
||||||
r.HandleFunc("/pprof/*", pprof.Index)
|
|
||||||
r.HandleFunc("/pprof/cmdline", pprof.Cmdline)
|
|
||||||
r.HandleFunc("/pprof/profile", pprof.Profile)
|
|
||||||
r.HandleFunc("/pprof/symbol", pprof.Symbol)
|
|
||||||
r.HandleFunc("/pprof/trace", pprof.Trace)
|
|
||||||
})
|
|
||||||
debugHTTPServer = &http.Server{
|
|
||||||
Addr: options.Listen,
|
|
||||||
Handler: r,
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
err := debugHTTPServer.ListenAndServe()
|
|
||||||
if err != nil && !E.IsClosed(err) {
|
|
||||||
log.Error(E.Cause(err, "serve debug HTTP server"))
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
@@ -1,16 +1,3 @@
|
|||||||
#### 1.3-beta9
|
|
||||||
|
|
||||||
* Improve multiplex **1**
|
|
||||||
* Fixes and improvements
|
|
||||||
|
|
||||||
*1*:
|
|
||||||
|
|
||||||
Added new `h2mux` multiplex protocol and `padding` multiplex option, see [Multiplex](/configuration/shared/multiplex).
|
|
||||||
|
|
||||||
#### 1.2.6
|
|
||||||
|
|
||||||
* Fix bugs and update dependencies
|
|
||||||
|
|
||||||
#### 1.3-beta8
|
#### 1.3-beta8
|
||||||
|
|
||||||
* Fix `system` tun stack for ios
|
* Fix `system` tun stack for ios
|
||||||
@@ -20,7 +7,7 @@ Added new `h2mux` multiplex protocol and `padding` multiplex option, see [Multip
|
|||||||
|
|
||||||
*1:
|
*1:
|
||||||
|
|
||||||
This is an incompatible update for XUDP in VLESS if vision flow is enabled.
|
As in Xray, this is an incompatible update for XUDP in VLESS if vision flow is enabled.
|
||||||
|
|
||||||
#### 1.3-beta7
|
#### 1.3-beta7
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,7 @@
|
|||||||
"protocol": "smux",
|
"protocol": "smux",
|
||||||
"max_connections": 4,
|
"max_connections": 4,
|
||||||
"min_streams": 4,
|
"min_streams": 4,
|
||||||
"max_streams": 0,
|
"max_streams": 0
|
||||||
"padding": false
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -29,7 +28,6 @@ Multiplex protocol.
|
|||||||
|----------|------------------------------------|
|
|----------|------------------------------------|
|
||||||
| smux | https://github.com/xtaci/smux |
|
| smux | https://github.com/xtaci/smux |
|
||||||
| yamux | https://github.com/hashicorp/yamux |
|
| yamux | https://github.com/hashicorp/yamux |
|
||||||
| h2mux | https://golang.org/x/net/http2 |
|
|
||||||
|
|
||||||
SMux is used by default.
|
SMux is used by default.
|
||||||
|
|
||||||
@@ -50,12 +48,3 @@ Conflict with `max_streams`.
|
|||||||
Maximum multiplexed streams in a connection before opening a new connection.
|
Maximum multiplexed streams in a connection before opening a new connection.
|
||||||
|
|
||||||
Conflict with `max_connections` and `min_streams`.
|
Conflict with `max_connections` and `min_streams`.
|
||||||
|
|
||||||
#### padding
|
|
||||||
|
|
||||||
!!! info
|
|
||||||
|
|
||||||
Requires sing-box server version 1.3-beta9 or later.
|
|
||||||
|
|
||||||
Enable padding.
|
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
|-------|------------------------------------|
|
|-------|------------------------------------|
|
||||||
| smux | https://github.com/xtaci/smux |
|
| smux | https://github.com/xtaci/smux |
|
||||||
| yamux | https://github.com/hashicorp/yamux |
|
| yamux | https://github.com/hashicorp/yamux |
|
||||||
| h2mux | https://golang.org/x/net/http2 |
|
|
||||||
|
|
||||||
默认使用 SMux。
|
默认使用 SMux。
|
||||||
|
|
||||||
@@ -49,12 +48,3 @@
|
|||||||
在打开新连接之前,连接中的最大多路复用流数量。
|
在打开新连接之前,连接中的最大多路复用流数量。
|
||||||
|
|
||||||
与 `max_connections` 和 `min_streams` 冲突。
|
与 `max_connections` 和 `min_streams` 冲突。
|
||||||
|
|
||||||
#### padding
|
|
||||||
|
|
||||||
!!! info
|
|
||||||
|
|
||||||
需要 sing-box 服务器版本 1.3-beta9 或更高。
|
|
||||||
|
|
||||||
启用填充。
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package experimental
|
package experimental
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
@@ -9,7 +8,7 @@ import (
|
|||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ClashServerConstructor = func(ctx context.Context, router adapter.Router, logFactory log.ObservableFactory, options option.ClashAPIOptions) (adapter.ClashServer, error)
|
type ClashServerConstructor = func(router adapter.Router, logFactory log.ObservableFactory, options option.ClashAPIOptions) (adapter.ClashServer, error)
|
||||||
|
|
||||||
var clashServerConstructor ClashServerConstructor
|
var clashServerConstructor ClashServerConstructor
|
||||||
|
|
||||||
@@ -17,9 +16,9 @@ func RegisterClashServerConstructor(constructor ClashServerConstructor) {
|
|||||||
clashServerConstructor = constructor
|
clashServerConstructor = constructor
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClashServer(ctx context.Context, router adapter.Router, logFactory log.ObservableFactory, options option.ClashAPIOptions) (adapter.ClashServer, error) {
|
func NewClashServer(router adapter.Router, logFactory log.ObservableFactory, options option.ClashAPIOptions) (adapter.ClashServer, error) {
|
||||||
if clashServerConstructor == nil {
|
if clashServerConstructor == nil {
|
||||||
return nil, os.ErrInvalid
|
return nil, os.ErrInvalid
|
||||||
}
|
}
|
||||||
return clashServerConstructor(ctx, router, logFactory, options)
|
return clashServerConstructor(router, logFactory, options)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import (
|
|||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
F "github.com/sagernet/sing/common/format"
|
F "github.com/sagernet/sing/common/format"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
"github.com/sagernet/sing/service/filemanager"
|
|
||||||
"github.com/sagernet/websocket"
|
"github.com/sagernet/websocket"
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
@@ -38,7 +37,6 @@ func init() {
|
|||||||
var _ adapter.ClashServer = (*Server)(nil)
|
var _ adapter.ClashServer = (*Server)(nil)
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
ctx context.Context
|
|
||||||
router adapter.Router
|
router adapter.Router
|
||||||
logger log.Logger
|
logger log.Logger
|
||||||
httpServer *http.Server
|
httpServer *http.Server
|
||||||
@@ -55,11 +53,10 @@ type Server struct {
|
|||||||
externalUIDownloadDetour string
|
externalUIDownloadDetour string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServer(ctx context.Context, router adapter.Router, logFactory log.ObservableFactory, options option.ClashAPIOptions) (adapter.ClashServer, error) {
|
func NewServer(router adapter.Router, logFactory log.ObservableFactory, options option.ClashAPIOptions) (adapter.ClashServer, error) {
|
||||||
trafficManager := trafficontrol.NewManager()
|
trafficManager := trafficontrol.NewManager()
|
||||||
chiRouter := chi.NewRouter()
|
chiRouter := chi.NewRouter()
|
||||||
server := &Server{
|
server := &Server{
|
||||||
ctx: ctx,
|
|
||||||
router: router,
|
router: router,
|
||||||
logger: logFactory.NewLogger("clash-api"),
|
logger: logFactory.NewLogger("clash-api"),
|
||||||
httpServer: &http.Server{
|
httpServer: &http.Server{
|
||||||
@@ -85,7 +82,7 @@ func NewServer(ctx context.Context, router adapter.Router, logFactory log.Observ
|
|||||||
if foundPath, loaded := C.FindPath(cachePath); loaded {
|
if foundPath, loaded := C.FindPath(cachePath); loaded {
|
||||||
cachePath = foundPath
|
cachePath = foundPath
|
||||||
} else {
|
} else {
|
||||||
cachePath = filemanager.BasePath(ctx, cachePath)
|
cachePath = C.BasePath(cachePath)
|
||||||
}
|
}
|
||||||
server.cacheFilePath = cachePath
|
server.cacheFilePath = cachePath
|
||||||
}
|
}
|
||||||
@@ -116,7 +113,7 @@ func NewServer(ctx context.Context, router adapter.Router, logFactory log.Observ
|
|||||||
server.setupMetaAPI(r)
|
server.setupMetaAPI(r)
|
||||||
})
|
})
|
||||||
if options.ExternalUI != "" {
|
if options.ExternalUI != "" {
|
||||||
server.externalUI = filemanager.BasePath(ctx, os.ExpandEnv(options.ExternalUI))
|
server.externalUI = C.BasePath(os.ExpandEnv(options.ExternalUI))
|
||||||
chiRouter.Group(func(r chi.Router) {
|
chiRouter.Group(func(r chi.Router) {
|
||||||
fs := http.StripPrefix("/ui", http.FileServer(http.Dir(server.externalUI)))
|
fs := http.StripPrefix("/ui", http.FileServer(http.Dir(server.externalUI)))
|
||||||
r.Get("/ui", http.RedirectHandler("/ui/", http.StatusTemporaryRedirect).ServeHTTP)
|
r.Get("/ui", http.RedirectHandler("/ui/", http.StatusTemporaryRedirect).ServeHTTP)
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
"github.com/sagernet/sing/service/filemanager"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) checkAndDownloadExternalUI() {
|
func (s *Server) checkAndDownloadExternalUI() {
|
||||||
@@ -79,7 +79,7 @@ func (s *Server) downloadExternalUI() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) downloadZIP(name string, body io.Reader, output string) error {
|
func (s *Server) downloadZIP(name string, body io.Reader, output string) error {
|
||||||
tempFile, err := filemanager.CreateTemp(s.ctx, name)
|
tempFile, err := C.CreateTemp(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -112,7 +112,7 @@ func (s *Server) downloadZIP(name string, body io.Reader, output string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
savePath := filepath.Join(saveDirectory, pathElements[len(pathElements)-1])
|
savePath := filepath.Join(saveDirectory, pathElements[len(pathElements)-1])
|
||||||
err = downloadZIPEntry(s.ctx, file, savePath)
|
err = downloadZIPEntry(file, savePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -120,8 +120,8 @@ func (s *Server) downloadZIP(name string, body io.Reader, output string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func downloadZIPEntry(ctx context.Context, zipFile *zip.File, savePath string) error {
|
func downloadZIPEntry(zipFile *zip.File, savePath string) error {
|
||||||
saveFile, err := filemanager.Create(ctx, savePath)
|
saveFile, err := os.Create(savePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,27 +27,3 @@ func RedirectStderr(path string) error {
|
|||||||
stderrFile = outputFile
|
stderrFile = outputFile
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func RedirectStderrAsUser(path string, uid, gid int) error {
|
|
||||||
if stats, err := os.Stat(path); err == nil && stats.Size() > 0 {
|
|
||||||
_ = os.Rename(path, path+".old")
|
|
||||||
}
|
|
||||||
outputFile, err := os.Create(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = outputFile.Chown(uid, gid)
|
|
||||||
if err != nil {
|
|
||||||
outputFile.Close()
|
|
||||||
os.Remove(outputFile.Name())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = unix.Dup2(int(outputFile.Fd()), int(os.Stderr.Fd()))
|
|
||||||
if err != nil {
|
|
||||||
outputFile.Close()
|
|
||||||
os.Remove(outputFile.Name())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
stderrFile = outputFile
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type PlatformInterface interface {
|
type PlatformInterface interface {
|
||||||
UsePlatformAutoDetectInterfaceControl() bool
|
|
||||||
AutoDetectInterfaceControl(fd int32) error
|
AutoDetectInterfaceControl(fd int32) error
|
||||||
OpenTun(options TunOptions) (int32, error)
|
OpenTun(options TunOptions) (int32, error)
|
||||||
WriteLog(message string)
|
WriteLog(message string)
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import (
|
|||||||
|
|
||||||
type Interface interface {
|
type Interface interface {
|
||||||
Initialize(ctx context.Context, router adapter.Router) error
|
Initialize(ctx context.Context, router adapter.Router) error
|
||||||
UsePlatformAutoDetectInterfaceControl() bool
|
|
||||||
AutoDetectInterfaceControl() control.Func
|
AutoDetectInterfaceControl() control.Func
|
||||||
OpenTun(options *tun.Options, platformOptions option.TunPlatformOptions) (tun.Tun, error)
|
OpenTun(options *tun.Options, platformOptions option.TunPlatformOptions) (tun.Tun, error)
|
||||||
UsePlatformDefaultInterfaceMonitor() bool
|
UsePlatformDefaultInterfaceMonitor() bool
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import (
|
|||||||
"github.com/sagernet/sing/common/control"
|
"github.com/sagernet/sing/common/control"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
"github.com/sagernet/sing/service/filemanager"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type BoxService struct {
|
type BoxService struct {
|
||||||
@@ -31,7 +30,6 @@ func NewService(configContent string, platformInterface PlatformInterface) (*Box
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
ctx = filemanager.WithDefault(ctx, sBasePath, sTempPath, sUserID, sGroupID)
|
|
||||||
instance, err := box.New(box.Options{
|
instance, err := box.New(box.Options{
|
||||||
Context: ctx,
|
Context: ctx,
|
||||||
Options: options,
|
Options: options,
|
||||||
@@ -70,10 +68,6 @@ func (w *platformInterfaceWrapper) Initialize(ctx context.Context, router adapte
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *platformInterfaceWrapper) UsePlatformAutoDetectInterfaceControl() bool {
|
|
||||||
return w.iif.UsePlatformAutoDetectInterfaceControl()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *platformInterfaceWrapper) AutoDetectInterfaceControl() control.Func {
|
func (w *platformInterfaceWrapper) AutoDetectInterfaceControl() control.Func {
|
||||||
return func(network, address string, conn syscall.RawConn) error {
|
return func(network, address string, conn syscall.RawConn) error {
|
||||||
return control.Raw(conn, func(fd uintptr) error {
|
return control.Raw(conn, func(fd uintptr) error {
|
||||||
|
|||||||
@@ -1,31 +1,17 @@
|
|||||||
package libbox
|
package libbox
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
|
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
|
|
||||||
"github.com/dustin/go-humanize"
|
"github.com/dustin/go-humanize"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
func SetBasePath(path string) {
|
||||||
sBasePath string
|
C.SetBasePath(path)
|
||||||
sTempPath string
|
}
|
||||||
sUserID int
|
|
||||||
sGroupID int
|
|
||||||
)
|
|
||||||
|
|
||||||
func Setup(basePath string, tempPath string, userID int, groupID int) {
|
func SetTempPath(path string) {
|
||||||
sBasePath = basePath
|
C.SetTempPath(path)
|
||||||
sTempPath = tempPath
|
|
||||||
sUserID = userID
|
|
||||||
sGroupID = groupID
|
|
||||||
if sUserID == -1 {
|
|
||||||
sUserID = os.Getuid()
|
|
||||||
}
|
|
||||||
if sGroupID == -1 {
|
|
||||||
sGroupID = os.Getgid()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Version() string {
|
func Version() string {
|
||||||
|
|||||||
14
go.mod
14
go.mod
@@ -25,17 +25,17 @@ require (
|
|||||||
github.com/sagernet/gomobile v0.0.0-20230413023804-244d7ff07035
|
github.com/sagernet/gomobile v0.0.0-20230413023804-244d7ff07035
|
||||||
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32
|
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
||||||
github.com/sagernet/sing v0.2.4
|
github.com/sagernet/sing v0.2.4-0.20230418095640-3b5e6c1812d3
|
||||||
github.com/sagernet/sing-dns v0.1.5-0.20230415085626-111ecf799dfc
|
github.com/sagernet/sing-dns v0.1.5-0.20230418025317-8a132998b322
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230417102954-f77257340507
|
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230418025154-6114beeeba6d
|
||||||
github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b
|
github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b
|
||||||
github.com/sagernet/sing-tun v0.1.5-0.20230422121432-209ec123ca7b
|
github.com/sagernet/sing-tun v0.1.4-0.20230419061614-d744d03d9302
|
||||||
github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3
|
github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3
|
||||||
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37
|
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37
|
||||||
github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9
|
github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9
|
||||||
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2
|
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2
|
||||||
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e
|
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e
|
||||||
github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77
|
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c
|
||||||
github.com/spf13/cobra v1.7.0
|
github.com/spf13/cobra v1.7.0
|
||||||
github.com/stretchr/testify v1.8.2
|
github.com/stretchr/testify v1.8.2
|
||||||
go.etcd.io/bbolt v1.3.7
|
go.etcd.io/bbolt v1.3.7
|
||||||
@@ -48,7 +48,7 @@ require (
|
|||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230215201556-9c5414ab4bde
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230215201556-9c5414ab4bde
|
||||||
google.golang.org/grpc v1.54.0
|
google.golang.org/grpc v1.54.0
|
||||||
google.golang.org/protobuf v1.30.0
|
google.golang.org/protobuf v1.30.0
|
||||||
gvisor.dev/gvisor v0.0.0-20230415003630-3981d5d5e523
|
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c
|
||||||
)
|
)
|
||||||
|
|
||||||
//replace github.com/sagernet/sing => ../sing
|
//replace github.com/sagernet/sing => ../sing
|
||||||
@@ -85,7 +85,7 @@ require (
|
|||||||
go.uber.org/multierr v1.6.0 // indirect
|
go.uber.org/multierr v1.6.0 // indirect
|
||||||
golang.org/x/mod v0.8.0 // indirect
|
golang.org/x/mod v0.8.0 // indirect
|
||||||
golang.org/x/text v0.9.0 // indirect
|
golang.org/x/text v0.9.0 // indirect
|
||||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
|
||||||
golang.org/x/tools v0.6.0 // indirect
|
golang.org/x/tools v0.6.0 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
|
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
||||||
|
|||||||
28
go.sum
28
go.sum
@@ -111,16 +111,16 @@ github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byL
|
|||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
||||||
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
||||||
github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
|
github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
|
||||||
github.com/sagernet/sing v0.2.4 h1:gC8BR5sglbJZX23RtMyFa8EETP9YEUADhfbEzU1yVbo=
|
github.com/sagernet/sing v0.2.4-0.20230418095640-3b5e6c1812d3 h1:dkH6SEs3yZlUjSXUAn64LUlFAfAgJqiThaWiBKWJ0Q0=
|
||||||
github.com/sagernet/sing v0.2.4/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
|
github.com/sagernet/sing v0.2.4-0.20230418095640-3b5e6c1812d3/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
|
||||||
github.com/sagernet/sing-dns v0.1.5-0.20230415085626-111ecf799dfc h1:hmbuqKv48SAjiKPoqtJGvS5pEHVPZjTHq9CPwQY2cZ4=
|
github.com/sagernet/sing-dns v0.1.5-0.20230418025317-8a132998b322 h1:UDSeJZ2xB3dj1lySnM5LpF48dGlphGstw2BqtkJwcZI=
|
||||||
github.com/sagernet/sing-dns v0.1.5-0.20230415085626-111ecf799dfc/go.mod h1:ZKuuqgsHRxDahYrzgSgy4vIAGGuKPlIf4hLcNzYzLkY=
|
github.com/sagernet/sing-dns v0.1.5-0.20230418025317-8a132998b322/go.mod h1:2wjxSr1Gbecq9A0ESA9cnR399tQTcpCZEOGytekb+qI=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230417102954-f77257340507 h1:bAHZCdWqJkb8LEW98+YsMVDXGRMUVjka8IC+St6ot88=
|
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230418025154-6114beeeba6d h1:UUxtLujzp5jmtOXqXpSOGvHwHSZcBveKVDzRJ4GlnFU=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230417102954-f77257340507/go.mod h1:UJjvQGw0lyYaDGIDvUraL16fwaAEH1WFw1Y6sUcMPog=
|
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230418025154-6114beeeba6d/go.mod h1:Co3PJXcaZoLwHGBfT0rbSnn9C7ywc41zVYWtDeoeI/Q=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b h1:ouW/6IDCrxkBe19YSbdCd7buHix7b+UZ6BM4Zz74XF4=
|
github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b h1:ouW/6IDCrxkBe19YSbdCd7buHix7b+UZ6BM4Zz74XF4=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b/go.mod h1:oG8bPerYI6cZ74KquY3DvA7ynECyrILPBnce6wtBqeI=
|
github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b/go.mod h1:oG8bPerYI6cZ74KquY3DvA7ynECyrILPBnce6wtBqeI=
|
||||||
github.com/sagernet/sing-tun v0.1.5-0.20230422121432-209ec123ca7b h1:9NsciSJGwzdkXwVvT2c2g+RvkTVkANeBLr2l+soJ7LM=
|
github.com/sagernet/sing-tun v0.1.4-0.20230419061614-d744d03d9302 h1:aPb0T2HQRTG2t7fEwLvFLZSXmhmnBh+SMs2NufhmrsI=
|
||||||
github.com/sagernet/sing-tun v0.1.5-0.20230422121432-209ec123ca7b/go.mod h1:DD7Ce2Gt0GFc6I/1+Uw4D/aUlBsGqrQsC52CMK/V818=
|
github.com/sagernet/sing-tun v0.1.4-0.20230419061614-d744d03d9302/go.mod h1:bvcVzlf9q9dgxt8qKluW+zOXCFoN1+SpBG3sHTq8/9Q=
|
||||||
github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 h1:BHOnxrbC929JonuKqFdJ7ZbDp7zs4oTlH5KFvKtWu9U=
|
github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 h1:BHOnxrbC929JonuKqFdJ7ZbDp7zs4oTlH5KFvKtWu9U=
|
||||||
github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3/go.mod h1:yKrAr+dqZd64DxBXCHWrYicp+n4qbqO73mtwv3dck8U=
|
github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3/go.mod h1:yKrAr+dqZd64DxBXCHWrYicp+n4qbqO73mtwv3dck8U=
|
||||||
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as=
|
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as=
|
||||||
@@ -131,8 +131,8 @@ github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 h1:kDUqhc9Vsk5HJuhfI
|
|||||||
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2/go.mod h1:JKQMZq/O2qnZjdrt+B57olmfgEmLtY9iiSIEYtWvoSM=
|
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2/go.mod h1:JKQMZq/O2qnZjdrt+B57olmfgEmLtY9iiSIEYtWvoSM=
|
||||||
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e h1:7uw2njHFGE+VpWamge6o56j2RWk4omF6uLKKxMmcWvs=
|
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e h1:7uw2njHFGE+VpWamge6o56j2RWk4omF6uLKKxMmcWvs=
|
||||||
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e/go.mod h1:45TUl8+gH4SIKr4ykREbxKWTxkDlSzFENzctB1dVRRY=
|
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e/go.mod h1:45TUl8+gH4SIKr4ykREbxKWTxkDlSzFENzctB1dVRRY=
|
||||||
github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77 h1:g6QtRWQ2dKX7EQP++1JLNtw4C2TNxd4/ov8YUpOPOSo=
|
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c h1:vK2wyt9aWYHHvNLWniwijBu/n4pySypiKRhN32u/JGo=
|
||||||
github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77/go.mod h1:pJDdXzZIwJ+2vmnT0TKzmf8meeum+e2mTDSehw79eE0=
|
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c/go.mod h1:euOmN6O5kk9dQmgSS8Df4psAl3TCjxOz0NW60EWkSaI=
|
||||||
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
|
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
|
||||||
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
|
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
@@ -208,8 +208,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
|
||||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
@@ -236,7 +236,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gvisor.dev/gvisor v0.0.0-20230415003630-3981d5d5e523 h1:zUQYeyyPLnSR6yMvLSOmLH37xDWCZ7BqlpE69fE5K3Q=
|
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c h1:m5lcgWnL3OElQNVyp3qcncItJ2c0sQlSGjYK2+nJTA4=
|
||||||
gvisor.dev/gvisor v0.0.0-20230415003630-3981d5d5e523/go.mod h1:pzr6sy8gDLfVmDAg8OYrlKvGEHw5C3PGTiBXBTCx76Q=
|
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c/go.mod h1:TIvkJD0sxe8pIob3p6T8IzxXunlp6yfgktvTNp+DGNM=
|
||||||
lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0=
|
lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0=
|
||||||
lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=
|
lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ func NewDirect(ctx context.Context, router adapter.Router, logger log.ContextLog
|
|||||||
} else {
|
} else {
|
||||||
udpTimeout = int64(C.UDPTimeout.Seconds())
|
udpTimeout = int64(C.UDPTimeout.Seconds())
|
||||||
}
|
}
|
||||||
inbound.udpNat = udpnat.New[netip.AddrPort](udpTimeout, adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound))
|
inbound.udpNat = udpnat.New[netip.AddrPort](ctx, udpTimeout, adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound))
|
||||||
inbound.connHandler = inbound
|
inbound.connHandler = inbound
|
||||||
inbound.packetHandler = inbound
|
inbound.packetHandler = inbound
|
||||||
inbound.packetUpstream = inbound.udpNat
|
inbound.packetUpstream = inbound.udpNat
|
||||||
|
|||||||
@@ -64,11 +64,11 @@ func newShadowsocks(ctx context.Context, router adapter.Router, logger log.Conte
|
|||||||
var err error
|
var err error
|
||||||
switch {
|
switch {
|
||||||
case options.Method == shadowsocks.MethodNone:
|
case options.Method == shadowsocks.MethodNone:
|
||||||
inbound.service = shadowsocks.NewNoneService(options.UDPTimeout, inbound.upstreamContextHandler())
|
inbound.service = shadowsocks.NewNoneService(ctx, options.UDPTimeout, inbound.upstreamContextHandler())
|
||||||
case common.Contains(shadowaead.List, options.Method):
|
case common.Contains(shadowaead.List, options.Method):
|
||||||
inbound.service, err = shadowaead.NewService(options.Method, nil, options.Password, udpTimeout, inbound.upstreamContextHandler())
|
inbound.service, err = shadowaead.NewService(ctx, options.Method, nil, options.Password, udpTimeout, inbound.upstreamContextHandler())
|
||||||
case common.Contains(shadowaead_2022.List, options.Method):
|
case common.Contains(shadowaead_2022.List, options.Method):
|
||||||
inbound.service, err = shadowaead_2022.NewServiceWithPassword(options.Method, options.Password, udpTimeout, inbound.upstreamContextHandler(), router.TimeFunc())
|
inbound.service, err = shadowaead_2022.NewServiceWithPassword(ctx, options.Method, options.Password, udpTimeout, inbound.upstreamContextHandler(), router.TimeFunc())
|
||||||
default:
|
default:
|
||||||
err = E.New("unsupported method: ", options.Method)
|
err = E.New("unsupported method: ", options.Method)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ func newShadowsocksMulti(ctx context.Context, router adapter.Router, logger log.
|
|||||||
)
|
)
|
||||||
if common.Contains(shadowaead_2022.List, options.Method) {
|
if common.Contains(shadowaead_2022.List, options.Method) {
|
||||||
service, err = shadowaead_2022.NewMultiServiceWithPassword[int](
|
service, err = shadowaead_2022.NewMultiServiceWithPassword[int](
|
||||||
|
ctx,
|
||||||
options.Method,
|
options.Method,
|
||||||
options.Password,
|
options.Password,
|
||||||
udpTimeout,
|
udpTimeout,
|
||||||
@@ -65,6 +66,7 @@ func newShadowsocksMulti(ctx context.Context, router adapter.Router, logger log.
|
|||||||
)
|
)
|
||||||
} else if common.Contains(shadowaead.List, options.Method) {
|
} else if common.Contains(shadowaead.List, options.Method) {
|
||||||
service, err = shadowaead.NewMultiService[int](
|
service, err = shadowaead.NewMultiService[int](
|
||||||
|
ctx,
|
||||||
options.Method,
|
options.Method,
|
||||||
udpTimeout,
|
udpTimeout,
|
||||||
adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound))
|
adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound))
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ func newShadowsocksRelay(ctx context.Context, router adapter.Router, logger log.
|
|||||||
udpTimeout = int64(C.UDPTimeout.Seconds())
|
udpTimeout = int64(C.UDPTimeout.Seconds())
|
||||||
}
|
}
|
||||||
service, err := shadowaead_2022.NewRelayServiceWithPassword[int](
|
service, err := shadowaead_2022.NewRelayServiceWithPassword[int](
|
||||||
|
ctx,
|
||||||
options.Method,
|
options.Method,
|
||||||
options.Password,
|
options.Password,
|
||||||
udpTimeout,
|
udpTimeout,
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ func NewTProxy(ctx context.Context, router adapter.Router, logger log.ContextLog
|
|||||||
}
|
}
|
||||||
tproxy.connHandler = tproxy
|
tproxy.connHandler = tproxy
|
||||||
tproxy.oobPacketHandler = tproxy
|
tproxy.oobPacketHandler = tproxy
|
||||||
tproxy.udpNat = udpnat.New[netip.AddrPort](udpTimeout, tproxy.upstreamContextHandler())
|
tproxy.udpNat = udpnat.New[netip.AddrPort](ctx, udpTimeout, tproxy.upstreamContextHandler())
|
||||||
tproxy.packetUpstream = tproxy.udpNat
|
tproxy.packetUpstream = tproxy.udpNat
|
||||||
return tproxy
|
return tproxy
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,8 +177,7 @@ func (t *Tun) Start() error {
|
|||||||
Router: tunRouter,
|
Router: tunRouter,
|
||||||
Handler: t,
|
Handler: t,
|
||||||
Logger: t.logger,
|
Logger: t.logger,
|
||||||
ForwarderBindInterface: t.platformInterface != nil,
|
UnderPlatform: t.platformInterface != nil,
|
||||||
InterfaceFinder: t.router.InterfaceFinder(),
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
package include
|
package include
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/experimental"
|
"github.com/sagernet/sing-box/experimental"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
@@ -13,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
experimental.RegisterClashServerConstructor(func(ctx context.Context, router adapter.Router, logFactory log.ObservableFactory, options option.ClashAPIOptions) (adapter.ClashServer, error) {
|
experimental.RegisterClashServerConstructor(func(router adapter.Router, logFactory log.ObservableFactory, options option.ClashAPIOptions) (adapter.ClashServer, error) {
|
||||||
return nil, E.New(`clash api is not included in this build, rebuild with -tags with_clash_api`)
|
return nil, E.New(`clash api is not included in this build, rebuild with -tags with_clash_api`)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
package log
|
package log
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
"github.com/sagernet/sing/service/filemanager"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type factoryWithFile struct {
|
type factoryWithFile struct {
|
||||||
@@ -37,7 +36,6 @@ func (f *observableFactoryWithFile) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Options struct {
|
type Options struct {
|
||||||
Context context.Context
|
|
||||||
Options option.LogOptions
|
Options option.LogOptions
|
||||||
Observable bool
|
Observable bool
|
||||||
DefaultWriter io.Writer
|
DefaultWriter io.Writer
|
||||||
@@ -67,7 +65,7 @@ func New(options Options) (Factory, error) {
|
|||||||
logWriter = os.Stdout
|
logWriter = os.Stdout
|
||||||
default:
|
default:
|
||||||
var err error
|
var err error
|
||||||
logFile, err = filemanager.OpenFile(options.Context, logOptions.Output, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
|
logFile, err = os.OpenFile(C.BasePath(logOptions.Output), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type DebugOptions struct {
|
type DebugOptions struct {
|
||||||
Listen string `json:"listen,omitempty"`
|
|
||||||
GCPercent *int `json:"gc_percent,omitempty"`
|
GCPercent *int `json:"gc_percent,omitempty"`
|
||||||
MaxStack *int `json:"max_stack,omitempty"`
|
MaxStack *int `json:"max_stack,omitempty"`
|
||||||
MaxThreads *int `json:"max_threads,omitempty"`
|
MaxThreads *int `json:"max_threads,omitempty"`
|
||||||
|
|||||||
@@ -150,5 +150,4 @@ type MultiplexOptions struct {
|
|||||||
MaxConnections int `json:"max_connections,omitempty"`
|
MaxConnections int `json:"max_connections,omitempty"`
|
||||||
MinStreams int `json:"min_streams,omitempty"`
|
MinStreams int `json:"min_streams,omitempty"`
|
||||||
MaxStreams int `json:"max_streams,omitempty"`
|
MaxStreams int `json:"max_streams,omitempty"`
|
||||||
Padding bool `json:"padding,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ type Shadowsocks struct {
|
|||||||
serverAddr M.Socksaddr
|
serverAddr M.Socksaddr
|
||||||
plugin sip003.Plugin
|
plugin sip003.Plugin
|
||||||
uotClient *uot.Client
|
uotClient *uot.Client
|
||||||
multiplexDialer *mux.Client
|
multiplexDialer N.Dialer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewShadowsocks(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowsocksOutboundOptions) (*Shadowsocks, error) {
|
func NewShadowsocks(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowsocksOutboundOptions) (*Shadowsocks, error) {
|
||||||
@@ -127,15 +127,8 @@ func (h *Shadowsocks) NewPacketConnection(ctx context.Context, conn N.PacketConn
|
|||||||
return NewPacketConnection(ctx, h, conn, metadata)
|
return NewPacketConnection(ctx, h, conn, metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Shadowsocks) InterfaceUpdated() error {
|
|
||||||
if h.multiplexDialer != nil {
|
|
||||||
h.multiplexDialer.Reset()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Shadowsocks) Close() error {
|
func (h *Shadowsocks) Close() error {
|
||||||
return common.Close(common.PtrOrNil(h.multiplexDialer))
|
return common.Close(h.multiplexDialer)
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ N.Dialer = (*shadowsocksDialer)(nil)
|
var _ N.Dialer = (*shadowsocksDialer)(nil)
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ type Trojan struct {
|
|||||||
dialer N.Dialer
|
dialer N.Dialer
|
||||||
serverAddr M.Socksaddr
|
serverAddr M.Socksaddr
|
||||||
key [56]byte
|
key [56]byte
|
||||||
multiplexDialer *mux.Client
|
multiplexDialer N.Dialer
|
||||||
tlsConfig tls.Config
|
tlsConfig tls.Config
|
||||||
transport adapter.V2RayClientTransport
|
transport adapter.V2RayClientTransport
|
||||||
}
|
}
|
||||||
@@ -103,15 +103,8 @@ func (h *Trojan) NewPacketConnection(ctx context.Context, conn N.PacketConn, met
|
|||||||
return NewPacketConnection(ctx, h, conn, metadata)
|
return NewPacketConnection(ctx, h, conn, metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Trojan) InterfaceUpdated() error {
|
|
||||||
if h.multiplexDialer != nil {
|
|
||||||
h.multiplexDialer.Reset()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Trojan) Close() error {
|
func (h *Trojan) Close() error {
|
||||||
return common.Close(common.PtrOrNil(h.multiplexDialer), h.transport)
|
return common.Close(h.multiplexDialer, h.transport)
|
||||||
}
|
}
|
||||||
|
|
||||||
type trojanDialer Trojan
|
type trojanDialer Trojan
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ type VMess struct {
|
|||||||
dialer N.Dialer
|
dialer N.Dialer
|
||||||
client *vmess.Client
|
client *vmess.Client
|
||||||
serverAddr M.Socksaddr
|
serverAddr M.Socksaddr
|
||||||
multiplexDialer *mux.Client
|
multiplexDialer N.Dialer
|
||||||
tlsConfig tls.Config
|
tlsConfig tls.Config
|
||||||
transport adapter.V2RayClientTransport
|
transport adapter.V2RayClientTransport
|
||||||
packetAddr bool
|
packetAddr bool
|
||||||
@@ -97,15 +97,8 @@ func NewVMess(ctx context.Context, router adapter.Router, logger log.ContextLogg
|
|||||||
return outbound, nil
|
return outbound, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *VMess) InterfaceUpdated() error {
|
|
||||||
if h.multiplexDialer != nil {
|
|
||||||
h.multiplexDialer.Reset()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *VMess) Close() error {
|
func (h *VMess) Close() error {
|
||||||
return common.Close(common.PtrOrNil(h.multiplexDialer), h.transport)
|
return common.Close(h.multiplexDialer, h.transport)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *VMess) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
func (h *VMess) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ func NewRouter(
|
|||||||
defaultMark: options.DefaultMark,
|
defaultMark: options.DefaultMark,
|
||||||
platformInterface: platformInterface,
|
platformInterface: platformInterface,
|
||||||
}
|
}
|
||||||
router.dnsClient = dns.NewClient(dnsOptions.DNSClientOptions.DisableCache, dnsOptions.DNSClientOptions.DisableExpire, router.dnsLogger)
|
router.dnsClient = dns.NewClient(ctx, dnsOptions.DNSClientOptions.DisableCache, dnsOptions.DNSClientOptions.DisableExpire, router.dnsLogger)
|
||||||
for i, ruleOptions := range options.Rules {
|
for i, ruleOptions := range options.Rules {
|
||||||
routeRule, err := NewRule(router, router.logger, ruleOptions)
|
routeRule, err := NewRule(router, router.logger, ruleOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -896,7 +896,7 @@ func (r *Router) AutoDetectInterface() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) AutoDetectInterfaceFunc() control.Func {
|
func (r *Router) AutoDetectInterfaceFunc() control.Func {
|
||||||
if r.platformInterface != nil && r.platformInterface.UsePlatformAutoDetectInterfaceControl() {
|
if r.platformInterface != nil {
|
||||||
return r.platformInterface.AutoDetectInterfaceControl()
|
return r.platformInterface.AutoDetectInterfaceControl()
|
||||||
} else {
|
} else {
|
||||||
return control.BindToInterfaceFunc(r.InterfaceFinder(), func(network string, address string) (interfaceName string, interfaceIndex int) {
|
return control.BindToInterfaceFunc(r.InterfaceFinder(), func(network string, address string) (interfaceName string, interfaceIndex int) {
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import (
|
|||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
"github.com/sagernet/sing/common/rw"
|
"github.com/sagernet/sing/common/rw"
|
||||||
"github.com/sagernet/sing/service/filemanager"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *Router) GeoIPReader() *geoip.Reader {
|
func (r *Router) GeoIPReader() *geoip.Reader {
|
||||||
@@ -52,7 +51,7 @@ func (r *Router) prepareGeoIPDatabase() error {
|
|||||||
geoPath = foundPath
|
geoPath = foundPath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
geoPath = filemanager.BasePath(r.ctx, geoPath)
|
geoPath = C.BasePath(geoPath)
|
||||||
if rw.FileExists(geoPath) {
|
if rw.FileExists(geoPath) {
|
||||||
geoReader, codes, err := geoip.Open(geoPath)
|
geoReader, codes, err := geoip.Open(geoPath)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -96,7 +95,7 @@ func (r *Router) prepareGeositeDatabase() error {
|
|||||||
geoPath = foundPath
|
geoPath = foundPath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
geoPath = filemanager.BasePath(r.ctx, geoPath)
|
geoPath = C.BasePath(geoPath)
|
||||||
if !rw.FileExists(geoPath) {
|
if !rw.FileExists(geoPath) {
|
||||||
r.logger.Warn("geosite database not exists: ", geoPath)
|
r.logger.Warn("geosite database not exists: ", geoPath)
|
||||||
var err error
|
var err error
|
||||||
@@ -143,10 +142,10 @@ func (r *Router) downloadGeoIPDatabase(savePath string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if parentDir := filepath.Dir(savePath); parentDir != "" {
|
if parentDir := filepath.Dir(savePath); parentDir != "" {
|
||||||
filemanager.MkdirAll(r.ctx, parentDir, 0o755)
|
os.MkdirAll(parentDir, 0o755)
|
||||||
}
|
}
|
||||||
|
|
||||||
saveFile, err := filemanager.Create(r.ctx, savePath)
|
saveFile, err := os.OpenFile(savePath, os.O_CREATE|os.O_WRONLY, 0o644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return E.Cause(err, "open output file: ", downloadURL)
|
return E.Cause(err, "open output file: ", downloadURL)
|
||||||
}
|
}
|
||||||
@@ -191,10 +190,10 @@ func (r *Router) downloadGeositeDatabase(savePath string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if parentDir := filepath.Dir(savePath); parentDir != "" {
|
if parentDir := filepath.Dir(savePath); parentDir != "" {
|
||||||
filemanager.MkdirAll(r.ctx, parentDir, 0o755)
|
os.MkdirAll(parentDir, 0o755)
|
||||||
}
|
}
|
||||||
|
|
||||||
saveFile, err := filemanager.Create(r.ctx, savePath)
|
saveFile, err := os.OpenFile(savePath, os.O_CREATE|os.O_WRONLY, 0o644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return E.Cause(err, "open output file: ", downloadURL)
|
return E.Cause(err, "open output file: ", downloadURL)
|
||||||
}
|
}
|
||||||
|
|||||||
28
test/go.mod
28
test/go.mod
@@ -9,9 +9,9 @@ replace github.com/sagernet/sing-box => ../
|
|||||||
require (
|
require (
|
||||||
github.com/docker/docker v20.10.18+incompatible
|
github.com/docker/docker v20.10.18+incompatible
|
||||||
github.com/docker/go-connections v0.4.0
|
github.com/docker/go-connections v0.4.0
|
||||||
github.com/gofrs/uuid/v5 v5.0.0
|
github.com/gofrs/uuid v4.4.0+incompatible
|
||||||
github.com/sagernet/sing v0.2.4
|
github.com/sagernet/sing v0.2.4-0.20230418025125-f196b4303e31
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230417102954-f77257340507
|
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230418025154-6114beeeba6d
|
||||||
github.com/spyzhov/ajson v0.7.1
|
github.com/spyzhov/ajson v0.7.1
|
||||||
github.com/stretchr/testify v1.8.2
|
github.com/stretchr/testify v1.8.2
|
||||||
go.uber.org/goleak v1.2.0
|
go.uber.org/goleak v1.2.0
|
||||||
@@ -21,7 +21,7 @@ require (
|
|||||||
require (
|
require (
|
||||||
berty.tech/go-libtor v1.0.385 // indirect
|
berty.tech/go-libtor v1.0.385 // indirect
|
||||||
github.com/Dreamacro/clash v1.15.0 // indirect
|
github.com/Dreamacro/clash v1.15.0 // indirect
|
||||||
github.com/Microsoft/go-winio v0.6.0 // indirect
|
github.com/Microsoft/go-winio v0.5.1 // indirect
|
||||||
github.com/ajg/form v1.5.1 // indirect
|
github.com/ajg/form v1.5.1 // indirect
|
||||||
github.com/andybalholm/brotli v1.0.5 // indirect
|
github.com/andybalholm/brotli v1.0.5 // indirect
|
||||||
github.com/caddyserver/certmagic v0.17.2 // indirect
|
github.com/caddyserver/certmagic v0.17.2 // indirect
|
||||||
@@ -36,6 +36,7 @@ require (
|
|||||||
github.com/go-chi/cors v1.2.1 // indirect
|
github.com/go-chi/cors v1.2.1 // indirect
|
||||||
github.com/go-chi/render v1.0.2 // indirect
|
github.com/go-chi/render v1.0.2 // indirect
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||||
|
github.com/gofrs/uuid/v5 v5.0.0 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/mock v1.6.0 // indirect
|
github.com/golang/mock v1.6.0 // indirect
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
@@ -50,7 +51,7 @@ require (
|
|||||||
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
|
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
|
||||||
github.com/mholt/acmez v1.1.0 // indirect
|
github.com/mholt/acmez v1.1.0 // indirect
|
||||||
github.com/miekg/dns v1.1.53 // indirect
|
github.com/miekg/dns v1.1.53 // indirect
|
||||||
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 // indirect
|
github.com/moby/term v0.0.0-20221105221325-4eb28fa6025c // indirect
|
||||||
github.com/morikuni/aec v1.0.0 // indirect
|
github.com/morikuni/aec v1.0.0 // indirect
|
||||||
github.com/onsi/ginkgo/v2 v2.2.0 // indirect
|
github.com/onsi/ginkgo/v2 v2.2.0 // indirect
|
||||||
github.com/ooni/go-libtor v1.1.7 // indirect
|
github.com/ooni/go-libtor v1.1.7 // indirect
|
||||||
@@ -70,15 +71,15 @@ require (
|
|||||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect
|
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect
|
||||||
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32 // indirect
|
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32 // indirect
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect
|
||||||
github.com/sagernet/sing-dns v0.1.5-0.20230415085626-111ecf799dfc // indirect
|
github.com/sagernet/sing-dns v0.1.5-0.20230418025317-8a132998b322 // indirect
|
||||||
github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b // indirect
|
github.com/sagernet/sing-shadowtls v0.1.0 // indirect
|
||||||
github.com/sagernet/sing-tun v0.1.5-0.20230422121432-209ec123ca7b // indirect
|
github.com/sagernet/sing-tun v0.1.4-0.20230419061614-d744d03d9302 // indirect
|
||||||
github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 // indirect
|
github.com/sagernet/sing-vmess v0.1.3 // indirect
|
||||||
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 // indirect
|
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 // indirect
|
||||||
github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 // indirect
|
github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 // indirect
|
||||||
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 // indirect
|
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 // indirect
|
||||||
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e // indirect
|
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e // indirect
|
||||||
github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77 // indirect
|
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c // indirect
|
||||||
github.com/sirupsen/logrus v1.9.0 // indirect
|
github.com/sirupsen/logrus v1.9.0 // indirect
|
||||||
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect
|
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect
|
||||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
||||||
@@ -92,12 +93,15 @@ require (
|
|||||||
golang.org/x/mod v0.8.0 // indirect
|
golang.org/x/mod v0.8.0 // indirect
|
||||||
golang.org/x/sys v0.7.0 // indirect
|
golang.org/x/sys v0.7.0 // indirect
|
||||||
golang.org/x/text v0.9.0 // indirect
|
golang.org/x/text v0.9.0 // indirect
|
||||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
|
||||||
golang.org/x/tools v0.6.0 // indirect
|
golang.org/x/tools v0.6.0 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
|
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
|
||||||
google.golang.org/grpc v1.54.0 // indirect
|
google.golang.org/grpc v1.54.0 // indirect
|
||||||
google.golang.org/protobuf v1.30.0 // indirect
|
google.golang.org/protobuf v1.30.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
gvisor.dev/gvisor v0.0.0-20230415003630-3981d5d5e523 // indirect
|
gotest.tools/v3 v3.4.0 // indirect
|
||||||
|
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c // indirect
|
||||||
lukechampine.com/blake3 v1.1.7 // indirect
|
lukechampine.com/blake3 v1.1.7 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//replace github.com/sagernet/sing => ../../sing
|
||||||
|
|||||||
53
test/go.sum
53
test/go.sum
@@ -3,8 +3,8 @@ berty.tech/go-libtor v1.0.385/go.mod h1:9swOOQVb+kmvuAlsgWUK/4c52pm69AdbJsxLzk+f
|
|||||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
||||||
github.com/Dreamacro/clash v1.15.0 h1:mlpD950VEggXZBNahV66hyKDRxcczkj3vymoAt78KyE=
|
github.com/Dreamacro/clash v1.15.0 h1:mlpD950VEggXZBNahV66hyKDRxcczkj3vymoAt78KyE=
|
||||||
github.com/Dreamacro/clash v1.15.0/go.mod h1:WNH69bN11LiAdgdSr4hpkEuXVMfBbWyhEKMCTx9BtNE=
|
github.com/Dreamacro/clash v1.15.0/go.mod h1:WNH69bN11LiAdgdSr4hpkEuXVMfBbWyhEKMCTx9BtNE=
|
||||||
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
|
github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY=
|
||||||
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
|
github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||||
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
|
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
|
||||||
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
|
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
|
||||||
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||||
@@ -43,6 +43,8 @@ github.com/go-chi/render v1.0.2 h1:4ER/udB0+fMWB2Jlf15RV3F4A2FDuYi/9f+lFttR/Lg=
|
|||||||
github.com/go-chi/render v1.0.2/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
|
github.com/go-chi/render v1.0.2/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
|
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
|
||||||
|
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||||
github.com/gofrs/uuid/v5 v5.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M=
|
github.com/gofrs/uuid/v5 v5.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M=
|
||||||
github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
|
github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
@@ -82,8 +84,8 @@ github.com/mholt/acmez v1.1.0 h1:IQ9CGHKOHokorxnffsqDvmmE30mDenO1lptYZ1AYkHY=
|
|||||||
github.com/mholt/acmez v1.1.0/go.mod h1:zwo5+fbLLTowAX8o8ETfQzbDtwGEXnPhkmGdKIP+bgs=
|
github.com/mholt/acmez v1.1.0/go.mod h1:zwo5+fbLLTowAX8o8ETfQzbDtwGEXnPhkmGdKIP+bgs=
|
||||||
github.com/miekg/dns v1.1.53 h1:ZBkuHr5dxHtB1caEOlZTLPo7D3L3TWckgUUs/RHfDxw=
|
github.com/miekg/dns v1.1.53 h1:ZBkuHr5dxHtB1caEOlZTLPo7D3L3TWckgUUs/RHfDxw=
|
||||||
github.com/miekg/dns v1.1.53/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
|
github.com/miekg/dns v1.1.53/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
|
||||||
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA=
|
github.com/moby/term v0.0.0-20221105221325-4eb28fa6025c h1:RC8WMpjonrBfyAh6VN/POIPtYD5tRAq0qMqCRjQNK+g=
|
||||||
github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
github.com/moby/term v0.0.0-20221105221325-4eb28fa6025c/go.mod h1:9OcmHNQQUTbk4XCffrLgN1NEKc2mh5u++biHVrvHsSU=
|
||||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
@@ -126,18 +128,18 @@ github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byL
|
|||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
||||||
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
||||||
github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
|
github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
|
||||||
github.com/sagernet/sing v0.2.4 h1:gC8BR5sglbJZX23RtMyFa8EETP9YEUADhfbEzU1yVbo=
|
github.com/sagernet/sing v0.2.4-0.20230418025125-f196b4303e31 h1:qgq8jeY/rbnY9NwYXByO//AP0ByIxnsKUxQx1tOB3W0=
|
||||||
github.com/sagernet/sing v0.2.4/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
|
github.com/sagernet/sing v0.2.4-0.20230418025125-f196b4303e31/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
|
||||||
github.com/sagernet/sing-dns v0.1.5-0.20230415085626-111ecf799dfc h1:hmbuqKv48SAjiKPoqtJGvS5pEHVPZjTHq9CPwQY2cZ4=
|
github.com/sagernet/sing-dns v0.1.5-0.20230418025317-8a132998b322 h1:UDSeJZ2xB3dj1lySnM5LpF48dGlphGstw2BqtkJwcZI=
|
||||||
github.com/sagernet/sing-dns v0.1.5-0.20230415085626-111ecf799dfc/go.mod h1:ZKuuqgsHRxDahYrzgSgy4vIAGGuKPlIf4hLcNzYzLkY=
|
github.com/sagernet/sing-dns v0.1.5-0.20230418025317-8a132998b322/go.mod h1:2wjxSr1Gbecq9A0ESA9cnR399tQTcpCZEOGytekb+qI=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230417102954-f77257340507 h1:bAHZCdWqJkb8LEW98+YsMVDXGRMUVjka8IC+St6ot88=
|
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230418025154-6114beeeba6d h1:UUxtLujzp5jmtOXqXpSOGvHwHSZcBveKVDzRJ4GlnFU=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230417102954-f77257340507/go.mod h1:UJjvQGw0lyYaDGIDvUraL16fwaAEH1WFw1Y6sUcMPog=
|
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230418025154-6114beeeba6d/go.mod h1:Co3PJXcaZoLwHGBfT0rbSnn9C7ywc41zVYWtDeoeI/Q=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b h1:ouW/6IDCrxkBe19YSbdCd7buHix7b+UZ6BM4Zz74XF4=
|
github.com/sagernet/sing-shadowtls v0.1.0 h1:05MYce8aR5xfKIn+y7xRFsdKhKt44QZTSEQW+lG5IWQ=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b/go.mod h1:oG8bPerYI6cZ74KquY3DvA7ynECyrILPBnce6wtBqeI=
|
github.com/sagernet/sing-shadowtls v0.1.0/go.mod h1:Kn1VUIprdkwCgkS6SXYaLmIpKzQbqBIKJBMY+RvBhYc=
|
||||||
github.com/sagernet/sing-tun v0.1.5-0.20230422121432-209ec123ca7b h1:9NsciSJGwzdkXwVvT2c2g+RvkTVkANeBLr2l+soJ7LM=
|
github.com/sagernet/sing-tun v0.1.4-0.20230419061614-d744d03d9302 h1:aPb0T2HQRTG2t7fEwLvFLZSXmhmnBh+SMs2NufhmrsI=
|
||||||
github.com/sagernet/sing-tun v0.1.5-0.20230422121432-209ec123ca7b/go.mod h1:DD7Ce2Gt0GFc6I/1+Uw4D/aUlBsGqrQsC52CMK/V818=
|
github.com/sagernet/sing-tun v0.1.4-0.20230419061614-d744d03d9302/go.mod h1:bvcVzlf9q9dgxt8qKluW+zOXCFoN1+SpBG3sHTq8/9Q=
|
||||||
github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 h1:BHOnxrbC929JonuKqFdJ7ZbDp7zs4oTlH5KFvKtWu9U=
|
github.com/sagernet/sing-vmess v0.1.3 h1:q/+tsF46dvvapL6CpQBgPHJ6nQrDUZqEtLHCbsjO7iM=
|
||||||
github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3/go.mod h1:yKrAr+dqZd64DxBXCHWrYicp+n4qbqO73mtwv3dck8U=
|
github.com/sagernet/sing-vmess v0.1.3/go.mod h1:GVXqAHwe9U21uS+Voh4YBIrADQyE4F9v0ayGSixSQAE=
|
||||||
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as=
|
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as=
|
||||||
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37/go.mod h1:3skNSftZDJWTGVtVaM2jfbce8qHnmH/AGDRe62iNOg0=
|
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37/go.mod h1:3skNSftZDJWTGVtVaM2jfbce8qHnmH/AGDRe62iNOg0=
|
||||||
github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 h1:2ItpW1nMNkPzmBTxV0/eClCklHrFSQMnUGcpUmJxVeE=
|
github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 h1:2ItpW1nMNkPzmBTxV0/eClCklHrFSQMnUGcpUmJxVeE=
|
||||||
@@ -146,8 +148,9 @@ github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 h1:kDUqhc9Vsk5HJuhfI
|
|||||||
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2/go.mod h1:JKQMZq/O2qnZjdrt+B57olmfgEmLtY9iiSIEYtWvoSM=
|
github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2/go.mod h1:JKQMZq/O2qnZjdrt+B57olmfgEmLtY9iiSIEYtWvoSM=
|
||||||
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e h1:7uw2njHFGE+VpWamge6o56j2RWk4omF6uLKKxMmcWvs=
|
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e h1:7uw2njHFGE+VpWamge6o56j2RWk4omF6uLKKxMmcWvs=
|
||||||
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e/go.mod h1:45TUl8+gH4SIKr4ykREbxKWTxkDlSzFENzctB1dVRRY=
|
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e/go.mod h1:45TUl8+gH4SIKr4ykREbxKWTxkDlSzFENzctB1dVRRY=
|
||||||
github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77 h1:g6QtRWQ2dKX7EQP++1JLNtw4C2TNxd4/ov8YUpOPOSo=
|
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c h1:vK2wyt9aWYHHvNLWniwijBu/n4pySypiKRhN32u/JGo=
|
||||||
github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77/go.mod h1:pJDdXzZIwJ+2vmnT0TKzmf8meeum+e2mTDSehw79eE0=
|
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c/go.mod h1:euOmN6O5kk9dQmgSS8Df4psAl3TCjxOz0NW60EWkSaI=
|
||||||
|
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/spyzhov/ajson v0.7.1 h1:1MDIlPc6x0zjNtpa7tDzRAyFAvRX+X8ZsvtYz5lZg6A=
|
github.com/spyzhov/ajson v0.7.1 h1:1MDIlPc6x0zjNtpa7tDzRAyFAvRX+X8ZsvtYz5lZg6A=
|
||||||
@@ -155,6 +158,7 @@ github.com/spyzhov/ajson v0.7.1/go.mod h1:63V+CGM6f1Bu/p4nLIN8885ojBdt88TbLoSFzy
|
|||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
@@ -214,10 +218,13 @@ golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
|||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
@@ -236,12 +243,13 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
|
||||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
|
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
@@ -264,7 +272,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
|||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
|
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
|
||||||
gvisor.dev/gvisor v0.0.0-20230415003630-3981d5d5e523 h1:zUQYeyyPLnSR6yMvLSOmLH37xDWCZ7BqlpE69fE5K3Q=
|
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
|
||||||
gvisor.dev/gvisor v0.0.0-20230415003630-3981d5d5e523/go.mod h1:pzr6sy8gDLfVmDAg8OYrlKvGEHw5C3PGTiBXBTCx76Q=
|
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c h1:m5lcgWnL3OElQNVyp3qcncItJ2c0sQlSGjYK2+nJTA4=
|
||||||
|
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c/go.mod h1:TIvkJD0sxe8pIob3p6T8IzxXunlp6yfgktvTNp+DGNM=
|
||||||
lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0=
|
lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0=
|
||||||
lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=
|
lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=
|
||||||
|
|||||||
@@ -18,40 +18,18 @@ var muxProtocols = []mux.Protocol{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestVMessSMux(t *testing.T) {
|
func TestVMessSMux(t *testing.T) {
|
||||||
testVMessMux(t, option.MultiplexOptions{
|
testVMessMux(t, mux.ProtocolSMux.String())
|
||||||
Enabled: true,
|
|
||||||
Protocol: mux.ProtocolSMux.String(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShadowsocksMux(t *testing.T) {
|
func TestShadowsocksMux(t *testing.T) {
|
||||||
for _, protocol := range muxProtocols {
|
for _, protocol := range muxProtocols {
|
||||||
t.Run(protocol.String(), func(t *testing.T) {
|
t.Run(protocol.String(), func(t *testing.T) {
|
||||||
testShadowsocksMux(t, option.MultiplexOptions{
|
testShadowsocksMux(t, protocol.String())
|
||||||
Enabled: true,
|
|
||||||
Protocol: protocol.String(),
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShadowsockH2Mux(t *testing.T) {
|
func testShadowsocksMux(t *testing.T, protocol string) {
|
||||||
testShadowsocksMux(t, option.MultiplexOptions{
|
|
||||||
Enabled: true,
|
|
||||||
Protocol: mux.ProtocolH2Mux.String(),
|
|
||||||
Padding: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestShadowsockSMuxPadding(t *testing.T) {
|
|
||||||
testShadowsocksMux(t, option.MultiplexOptions{
|
|
||||||
Enabled: true,
|
|
||||||
Protocol: mux.ProtocolSMux.String(),
|
|
||||||
Padding: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func testShadowsocksMux(t *testing.T, options option.MultiplexOptions) {
|
|
||||||
method := shadowaead_2022.List[0]
|
method := shadowaead_2022.List[0]
|
||||||
password := mkBase64(t, 16)
|
password := mkBase64(t, 16)
|
||||||
startInstance(t, option.Options{
|
startInstance(t, option.Options{
|
||||||
@@ -90,9 +68,12 @@ func testShadowsocksMux(t *testing.T, options option.MultiplexOptions) {
|
|||||||
Server: "127.0.0.1",
|
Server: "127.0.0.1",
|
||||||
ServerPort: serverPort,
|
ServerPort: serverPort,
|
||||||
},
|
},
|
||||||
Method: method,
|
Method: method,
|
||||||
Password: password,
|
Password: password,
|
||||||
MultiplexOptions: &options,
|
MultiplexOptions: &option.MultiplexOptions{
|
||||||
|
Enabled: true,
|
||||||
|
Protocol: protocol,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -110,7 +91,7 @@ func testShadowsocksMux(t *testing.T, options option.MultiplexOptions) {
|
|||||||
testSuit(t, clientPort, testPort)
|
testSuit(t, clientPort, testPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testVMessMux(t *testing.T, options option.MultiplexOptions) {
|
func testVMessMux(t *testing.T, protocol string) {
|
||||||
user, _ := uuid.NewV4()
|
user, _ := uuid.NewV4()
|
||||||
startInstance(t, option.Options{
|
startInstance(t, option.Options{
|
||||||
Inbounds: []option.Inbound{
|
Inbounds: []option.Inbound{
|
||||||
@@ -151,9 +132,12 @@ func testVMessMux(t *testing.T, options option.MultiplexOptions) {
|
|||||||
Server: "127.0.0.1",
|
Server: "127.0.0.1",
|
||||||
ServerPort: serverPort,
|
ServerPort: serverPort,
|
||||||
},
|
},
|
||||||
Security: "auto",
|
Security: "auto",
|
||||||
UUID: user.String(),
|
UUID: user.String(),
|
||||||
Multiplex: &options,
|
Multiplex: &option.MultiplexOptions{
|
||||||
|
Enabled: true,
|
||||||
|
Protocol: protocol,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ func TestUDPNatClose(t *testing.T) {
|
|||||||
defer cancel()
|
defer cancel()
|
||||||
connCtx, connCancel := common.ContextWithCancelCause(context.Background())
|
connCtx, connCancel := common.ContextWithCancelCause(context.Background())
|
||||||
defer connCancel(net.ErrClosed)
|
defer connCancel(net.ErrClosed)
|
||||||
service := udpnat.New[int](1, &testUDPNatCloseHandler{connCancel})
|
service := udpnat.New[int](ctx, 1, &testUDPNatCloseHandler{connCancel})
|
||||||
service.NewPacket(ctx, 0, buf.As([]byte("Hello")), M.Metadata{}, func(natConn N.PacketConn) N.PacketWriter {
|
service.NewPacket(ctx, 0, buf.As([]byte("Hello")), M.Metadata{}, func(natConn N.PacketConn) N.PacketWriter {
|
||||||
return &testPacketWriter{}
|
return &testPacketWriter{}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ func newV2RayPlugin(pluginOpts Args, router adapter.Router, dialer N.Dialer, ser
|
|||||||
|
|
||||||
if hostOpt, loaded := pluginOpts.Get("host"); loaded {
|
if hostOpt, loaded := pluginOpts.Get("host"); loaded {
|
||||||
host = hostOpt
|
host = hostOpt
|
||||||
tlsOptions.ServerName = hostOpt
|
|
||||||
}
|
}
|
||||||
if pathOpt, loaded := pluginOpts.Get("path"); loaded {
|
if pathOpt, loaded := pluginOpts.Get("path"); loaded {
|
||||||
path = pathOpt
|
path = pathOpt
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import (
|
|||||||
"github.com/sagernet/sing-box/common/tls"
|
"github.com/sagernet/sing-box/common/tls"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
"github.com/sagernet/sing-box/transport/v2rayhttp"
|
"github.com/sagernet/sing-box/transport/v2rayhttp"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
|
||||||
@@ -34,16 +33,9 @@ type Client struct {
|
|||||||
transport *http2.Transport
|
transport *http2.Transport
|
||||||
options option.V2RayGRPCOptions
|
options option.V2RayGRPCOptions
|
||||||
url *url.URL
|
url *url.URL
|
||||||
host string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, options option.V2RayGRPCOptions, tlsConfig tls.Config) adapter.V2RayClientTransport {
|
func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, options option.V2RayGRPCOptions, tlsConfig tls.Config) adapter.V2RayClientTransport {
|
||||||
var host string
|
|
||||||
if tlsConfig != nil && tlsConfig.ServerName() != "" {
|
|
||||||
host = M.ParseSocksaddrHostPort(tlsConfig.ServerName(), serverAddr.Port).String()
|
|
||||||
} else {
|
|
||||||
host = serverAddr.String()
|
|
||||||
}
|
|
||||||
client := &Client{
|
client := &Client{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
dialer: dialer,
|
dialer: dialer,
|
||||||
@@ -60,7 +52,6 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
|
|||||||
Path: "/" + options.ServiceName + "/Tun",
|
Path: "/" + options.ServiceName + "/Tun",
|
||||||
RawPath: "/" + url.PathEscape(options.ServiceName) + "/Tun",
|
RawPath: "/" + url.PathEscape(options.ServiceName) + "/Tun",
|
||||||
},
|
},
|
||||||
host: host,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if tlsConfig == nil {
|
if tlsConfig == nil {
|
||||||
@@ -90,19 +81,15 @@ func (c *Client) DialContext(ctx context.Context) (net.Conn, error) {
|
|||||||
Body: pipeInReader,
|
Body: pipeInReader,
|
||||||
URL: c.url,
|
URL: c.url,
|
||||||
Header: defaultClientHeader,
|
Header: defaultClientHeader,
|
||||||
Host: c.host,
|
|
||||||
}
|
}
|
||||||
request = request.WithContext(ctx)
|
request = request.WithContext(ctx)
|
||||||
conn := newLateGunConn(pipeInWriter)
|
conn := newLateGunConn(pipeInWriter)
|
||||||
go func() {
|
go func() {
|
||||||
response, err := c.transport.RoundTrip(request)
|
response, err := c.transport.RoundTrip(request)
|
||||||
if err != nil {
|
if err == nil {
|
||||||
conn.setup(nil, err)
|
|
||||||
} else if response.StatusCode != 200 {
|
|
||||||
response.Body.Close()
|
|
||||||
conn.setup(nil, E.New("unexpected status: ", response.StatusCode, " ", response.Status))
|
|
||||||
} else {
|
|
||||||
conn.setup(response.Body, nil)
|
conn.setup(response.Body, nil)
|
||||||
|
} else {
|
||||||
|
conn.setup(nil, err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
return conn, nil
|
return conn, nil
|
||||||
|
|||||||
@@ -139,16 +139,15 @@ func (c *Client) dialHTTP2(ctx context.Context) (net.Conn, error) {
|
|||||||
default:
|
default:
|
||||||
request.Host = c.host[rand.Intn(hostLen)]
|
request.Host = c.host[rand.Intn(hostLen)]
|
||||||
}
|
}
|
||||||
conn := NewLateHTTPConn(pipeInWriter)
|
conn := newLateHTTPConn(pipeInWriter)
|
||||||
go func() {
|
go func() {
|
||||||
response, err := c.transport.RoundTrip(request)
|
response, err := c.transport.RoundTrip(request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
conn.Setup(nil, err)
|
conn.setup(nil, err)
|
||||||
} else if response.StatusCode != 200 {
|
} else if response.StatusCode != 200 {
|
||||||
response.Body.Close()
|
conn.setup(nil, E.New("unexpected status: ", response.StatusCode, " ", response.Status))
|
||||||
conn.Setup(nil, E.New("unexpected status: ", response.StatusCode, " ", response.Status))
|
|
||||||
} else {
|
} else {
|
||||||
conn.Setup(response.Body, nil)
|
conn.setup(response.Body, nil)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
return conn, nil
|
return conn, nil
|
||||||
|
|||||||
@@ -140,14 +140,14 @@ func NewHTTPConn(reader io.Reader, writer io.Writer) HTTP2Conn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLateHTTPConn(writer io.Writer) *HTTP2Conn {
|
func newLateHTTPConn(writer io.Writer) *HTTP2Conn {
|
||||||
return &HTTP2Conn{
|
return &HTTP2Conn{
|
||||||
create: make(chan struct{}),
|
create: make(chan struct{}),
|
||||||
writer: writer,
|
writer: writer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *HTTP2Conn) Setup(reader io.Reader, err error) {
|
func (c *HTTP2Conn) setup(reader io.Reader, err error) {
|
||||||
c.reader = reader
|
c.reader = reader
|
||||||
c.err = err
|
c.err = err
|
||||||
close(c.create)
|
close(c.create)
|
||||||
@@ -199,13 +199,13 @@ func (c *HTTP2Conn) NeedAdditionalReadDeadline() bool {
|
|||||||
|
|
||||||
type ServerHTTPConn struct {
|
type ServerHTTPConn struct {
|
||||||
HTTP2Conn
|
HTTP2Conn
|
||||||
Flusher http.Flusher
|
flusher http.Flusher
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ServerHTTPConn) Write(b []byte) (n int, err error) {
|
func (c *ServerHTTPConn) Write(b []byte) (n int, err error) {
|
||||||
n, err = c.writer.Write(b)
|
n, err = c.writer.Write(b)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
c.Flusher.Flush()
|
c.flusher.Flush()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -246,11 +246,6 @@ func (w *HTTP2ConnWrapper) CloseWrapper() {
|
|||||||
w.closed = true
|
w.closed = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *HTTP2ConnWrapper) Close() error {
|
|
||||||
w.CloseWrapper()
|
|
||||||
return w.ExtendedConn.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *HTTP2ConnWrapper) Upstream() any {
|
func (w *HTTP2ConnWrapper) Upstream() any {
|
||||||
return w.ExtendedConn
|
return w.ExtendedConn
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ func (c *ClientBind) Open(port uint16) (fns []conn.ReceiveFunc, actualPort uint1
|
|||||||
return []conn.ReceiveFunc{c.receive}, 0, nil
|
return []conn.ReceiveFunc{c.receive}, 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClientBind) receive(packets [][]byte, sizes []int, eps []conn.Endpoint) (count int, err error) {
|
func (c *ClientBind) receive(b []byte) (n int, ep conn.Endpoint, err error) {
|
||||||
udpConn, err := c.connect()
|
udpConn, err := c.connect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
select {
|
select {
|
||||||
@@ -113,26 +113,22 @@ func (c *ClientBind) receive(packets [][]byte, sizes []int, eps []conn.Endpoint)
|
|||||||
err = nil
|
err = nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
n, addr, err := udpConn.ReadFrom(packets[0])
|
n, addr, err := udpConn.ReadFrom(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
udpConn.Close()
|
udpConn.Close()
|
||||||
select {
|
select {
|
||||||
case <-c.done:
|
case <-c.done:
|
||||||
default:
|
default:
|
||||||
c.errorHandler.NewError(context.Background(), E.Cause(err, "read packet"))
|
c.errorHandler.NewError(context.Background(), E.Cause(err, "read packet"))
|
||||||
err = nil
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sizes[0] = n
|
|
||||||
if n > 3 {
|
if n > 3 {
|
||||||
b := packets[0]
|
|
||||||
b[1] = 0
|
b[1] = 0
|
||||||
b[2] = 0
|
b[2] = 0
|
||||||
b[3] = 0
|
b[3] = 0
|
||||||
}
|
}
|
||||||
eps[0] = Endpoint(M.SocksaddrFromNet(addr))
|
ep = Endpoint(M.SocksaddrFromNet(addr))
|
||||||
count = 1
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,39 +155,32 @@ func (c *ClientBind) SetMark(mark uint32) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClientBind) Send(bufs [][]byte, ep conn.Endpoint) error {
|
func (c *ClientBind) Send(b []byte, ep conn.Endpoint) error {
|
||||||
udpConn, err := c.connect()
|
udpConn, err := c.connect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
destination := M.Socksaddr(ep.(Endpoint))
|
destination := M.Socksaddr(ep.(Endpoint))
|
||||||
for _, b := range bufs {
|
if len(b) > 3 {
|
||||||
if len(b) > 3 {
|
reserved, loaded := c.reservedForEndpoint[destination]
|
||||||
reserved, loaded := c.reservedForEndpoint[destination]
|
if !loaded {
|
||||||
if !loaded {
|
reserved = c.reserved
|
||||||
reserved = c.reserved
|
|
||||||
}
|
|
||||||
b[1] = reserved[0]
|
|
||||||
b[2] = reserved[1]
|
|
||||||
b[3] = reserved[2]
|
|
||||||
}
|
|
||||||
_, err = udpConn.WriteTo(b, destination)
|
|
||||||
if err != nil {
|
|
||||||
udpConn.Close()
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
b[1] = reserved[0]
|
||||||
|
b[2] = reserved[1]
|
||||||
|
b[3] = reserved[2]
|
||||||
}
|
}
|
||||||
return nil
|
_, err = udpConn.WriteTo(b, destination)
|
||||||
|
if err != nil {
|
||||||
|
udpConn.Close()
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClientBind) ParseEndpoint(s string) (conn.Endpoint, error) {
|
func (c *ClientBind) ParseEndpoint(s string) (conn.Endpoint, error) {
|
||||||
return Endpoint(M.ParseSocksaddr(s)), nil
|
return Endpoint(M.ParseSocksaddr(s)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClientBind) BatchSize() int {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
type wireConn struct {
|
type wireConn struct {
|
||||||
net.PacketConn
|
net.PacketConn
|
||||||
access sync.Mutex
|
access sync.Mutex
|
||||||
|
|||||||
@@ -26,24 +26,23 @@ func NewNATDevice(upstream Device, ipRewrite bool) NatDevice {
|
|||||||
return wrapper
|
return wrapper
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *natDeviceWrapper) Read(bufs [][]byte, sizes []int, offset int) (count int, err error) {
|
func (d *natDeviceWrapper) Read(p []byte, offset int) (int, error) {
|
||||||
select {
|
select {
|
||||||
case packet := <-d.outbound:
|
case packet := <-d.outbound:
|
||||||
defer packet.Release()
|
defer packet.Release()
|
||||||
sizes[0] = copy(bufs[0][offset:], packet.Bytes())
|
return copy(p[offset:], packet.Bytes()), nil
|
||||||
return 1, nil
|
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
return d.Device.Read(bufs, sizes, offset)
|
return d.Device.Read(p, offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *natDeviceWrapper) Write(bufs [][]byte, offset int) (count int, err error) {
|
func (d *natDeviceWrapper) Write(p []byte, offset int) (int, error) {
|
||||||
packet := bufs[0][offset:]
|
packet := p[offset:]
|
||||||
handled, err := d.mapping.WritePacket(packet)
|
handled, err := d.mapping.WritePacket(packet)
|
||||||
if handled {
|
if handled {
|
||||||
return 1, err
|
return len(packet), err
|
||||||
}
|
}
|
||||||
return d.Device.Write(bufs, offset)
|
return d.Device.Write(p, offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *natDeviceWrapper) CreateDestination(session tun.RouteSession, conn tun.RouteContext) tun.DirectDestination {
|
func (d *natDeviceWrapper) CreateDestination(session tun.RouteSession, conn tun.RouteContext) tun.DirectDestination {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (d *natDestinationWrapper) WritePacketBuffer(buffer stack.PacketBufferPtr) error {
|
func (d *natDestinationWrapper) WritePacketBuffer(buffer *stack.PacketBuffer) error {
|
||||||
defer buffer.DecRef()
|
defer buffer.DecRef()
|
||||||
if d.device.writer != nil {
|
if d.device.writer != nil {
|
||||||
d.device.writer.RewritePacketBuffer(buffer)
|
d.device.writer.RewritePacketBuffer(buffer)
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ type StackDevice struct {
|
|||||||
stack *stack.Stack
|
stack *stack.Stack
|
||||||
mtu uint32
|
mtu uint32
|
||||||
events chan wgTun.Event
|
events chan wgTun.Event
|
||||||
outbound chan stack.PacketBufferPtr
|
outbound chan *stack.PacketBuffer
|
||||||
packetOutbound chan *buf.Buffer
|
packetOutbound chan *buf.Buffer
|
||||||
done chan struct{}
|
done chan struct{}
|
||||||
dispatcher stack.NetworkDispatcher
|
dispatcher stack.NetworkDispatcher
|
||||||
@@ -55,7 +55,7 @@ func NewStackDevice(localAddresses []netip.Prefix, mtu uint32, ipRewrite bool) (
|
|||||||
stack: ipStack,
|
stack: ipStack,
|
||||||
mtu: mtu,
|
mtu: mtu,
|
||||||
events: make(chan wgTun.Event, 1),
|
events: make(chan wgTun.Event, 1),
|
||||||
outbound: make(chan stack.PacketBufferPtr, 256),
|
outbound: make(chan *stack.PacketBuffer, 256),
|
||||||
packetOutbound: make(chan *buf.Buffer, 256),
|
packetOutbound: make(chan *buf.Buffer, 256),
|
||||||
done: make(chan struct{}),
|
done: make(chan struct{}),
|
||||||
mapping: tun.NewNatMapping(ipRewrite),
|
mapping: tun.NewNatMapping(ipRewrite),
|
||||||
@@ -171,60 +171,49 @@ func (w *StackDevice) File() *os.File {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *StackDevice) Read(bufs [][]byte, sizes []int, offset int) (count int, err error) {
|
func (w *StackDevice) Read(p []byte, offset int) (n int, err error) {
|
||||||
select {
|
select {
|
||||||
case packetBuffer, ok := <-w.outbound:
|
case packetBuffer, ok := <-w.outbound:
|
||||||
if !ok {
|
if !ok {
|
||||||
return 0, os.ErrClosed
|
return 0, os.ErrClosed
|
||||||
}
|
}
|
||||||
defer packetBuffer.DecRef()
|
defer packetBuffer.DecRef()
|
||||||
p := bufs[0]
|
|
||||||
p = p[offset:]
|
p = p[offset:]
|
||||||
n := 0
|
|
||||||
for _, slice := range packetBuffer.AsSlices() {
|
for _, slice := range packetBuffer.AsSlices() {
|
||||||
n += copy(p[n:], slice)
|
n += copy(p[n:], slice)
|
||||||
}
|
}
|
||||||
sizes[0] = n
|
|
||||||
count = 1
|
|
||||||
return
|
return
|
||||||
case packet := <-w.packetOutbound:
|
case packet := <-w.packetOutbound:
|
||||||
defer packet.Release()
|
defer packet.Release()
|
||||||
sizes[0] = copy(bufs[0][offset:], packet.Bytes())
|
n = copy(p[offset:], packet.Bytes())
|
||||||
count = 1
|
|
||||||
return
|
return
|
||||||
case <-w.done:
|
case <-w.done:
|
||||||
return 0, os.ErrClosed
|
return 0, os.ErrClosed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *StackDevice) Write(bufs [][]byte, offset int) (count int, err error) {
|
func (w *StackDevice) Write(p []byte, offset int) (n int, err error) {
|
||||||
for _, b := range bufs {
|
p = p[offset:]
|
||||||
b = b[offset:]
|
if len(p) == 0 {
|
||||||
if len(b) == 0 {
|
return
|
||||||
continue
|
|
||||||
}
|
|
||||||
handled, err := w.mapping.WritePacket(b)
|
|
||||||
if handled {
|
|
||||||
count++
|
|
||||||
if err != nil {
|
|
||||||
return count, err
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var networkProtocol tcpip.NetworkProtocolNumber
|
|
||||||
switch header.IPVersion(b) {
|
|
||||||
case header.IPv4Version:
|
|
||||||
networkProtocol = header.IPv4ProtocolNumber
|
|
||||||
case header.IPv6Version:
|
|
||||||
networkProtocol = header.IPv6ProtocolNumber
|
|
||||||
}
|
|
||||||
packetBuffer := stack.NewPacketBuffer(stack.PacketBufferOptions{
|
|
||||||
Payload: bufferv2.MakeWithData(b),
|
|
||||||
})
|
|
||||||
w.dispatcher.DeliverNetworkPacket(networkProtocol, packetBuffer)
|
|
||||||
packetBuffer.DecRef()
|
|
||||||
count++
|
|
||||||
}
|
}
|
||||||
|
handled, err := w.mapping.WritePacket(p)
|
||||||
|
if handled {
|
||||||
|
return len(p), err
|
||||||
|
}
|
||||||
|
var networkProtocol tcpip.NetworkProtocolNumber
|
||||||
|
switch header.IPVersion(p) {
|
||||||
|
case header.IPv4Version:
|
||||||
|
networkProtocol = header.IPv4ProtocolNumber
|
||||||
|
case header.IPv6Version:
|
||||||
|
networkProtocol = header.IPv6ProtocolNumber
|
||||||
|
}
|
||||||
|
packetBuffer := stack.NewPacketBuffer(stack.PacketBufferOptions{
|
||||||
|
Payload: bufferv2.MakeWithData(p),
|
||||||
|
})
|
||||||
|
defer packetBuffer.DecRef()
|
||||||
|
w.dispatcher.DeliverNetworkPacket(networkProtocol, packetBuffer)
|
||||||
|
n = len(p)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,7 +229,7 @@ func (w *StackDevice) Name() (string, error) {
|
|||||||
return "sing-box", nil
|
return "sing-box", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *StackDevice) Events() <-chan wgTun.Event {
|
func (w *StackDevice) Events() chan wgTun.Event {
|
||||||
return w.events
|
return w.events
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,10 +248,6 @@ func (w *StackDevice) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *StackDevice) BatchSize() int {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *StackDevice) CreateDestination(session tun.RouteSession, conn tun.RouteContext) tun.DirectDestination {
|
func (w *StackDevice) CreateDestination(session tun.RouteSession, conn tun.RouteContext) tun.DirectDestination {
|
||||||
w.mapping.CreateSession(session, conn)
|
w.mapping.CreateSession(session, conn)
|
||||||
return &stackNatDestination{
|
return &stackNatDestination{
|
||||||
@@ -284,7 +269,7 @@ func (d *stackNatDestination) WritePacket(buffer *buf.Buffer) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *stackNatDestination) WritePacketBuffer(buffer stack.PacketBufferPtr) error {
|
func (d *stackNatDestination) WritePacketBuffer(buffer *stack.PacketBuffer) error {
|
||||||
if d.device.writer != nil {
|
if d.device.writer != nil {
|
||||||
d.device.writer.RewritePacketBuffer(buffer)
|
d.device.writer.RewritePacketBuffer(buffer)
|
||||||
}
|
}
|
||||||
@@ -336,7 +321,7 @@ func (ep *wireEndpoint) ARPHardwareType() header.ARPHardwareType {
|
|||||||
return header.ARPHardwareNone
|
return header.ARPHardwareNone
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ep *wireEndpoint) AddHeader(buffer stack.PacketBufferPtr) {
|
func (ep *wireEndpoint) AddHeader(buffer *stack.PacketBuffer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ep *wireEndpoint) WritePackets(list stack.PacketBufferList) (int, tcpip.Error) {
|
func (ep *wireEndpoint) WritePackets(list stack.PacketBufferList) (int, tcpip.Error) {
|
||||||
|
|||||||
@@ -27,6 +27,14 @@ type SystemDevice struct {
|
|||||||
addr6 netip.Addr
|
addr6 netip.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*func (w *SystemDevice) NewEndpoint() (stack.LinkEndpoint, error) {
|
||||||
|
gTun, isGTun := w.device.(tun.GVisorTun)
|
||||||
|
if !isGTun {
|
||||||
|
return nil, tun.ErrGVisorUnsupported
|
||||||
|
}
|
||||||
|
return gTun.NewEndpoint()
|
||||||
|
}*/
|
||||||
|
|
||||||
func NewSystemDevice(router adapter.Router, interfaceName string, localPrefixes []netip.Prefix, mtu uint32) (*SystemDevice, error) {
|
func NewSystemDevice(router adapter.Router, interfaceName string, localPrefixes []netip.Prefix, mtu uint32) (*SystemDevice, error) {
|
||||||
var inet4Addresses []netip.Prefix
|
var inet4Addresses []netip.Prefix
|
||||||
var inet6Addresses []netip.Prefix
|
var inet6Addresses []netip.Prefix
|
||||||
@@ -95,23 +103,12 @@ func (w *SystemDevice) File() *os.File {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *SystemDevice) Read(bufs [][]byte, sizes []int, offset int) (count int, err error) {
|
func (w *SystemDevice) Read(p []byte, offset int) (int, error) {
|
||||||
sizes[0], err = w.device.Read(bufs[0][offset-tun.PacketOffset:])
|
return w.device.Read(p[offset-tun.PacketOffset:])
|
||||||
if err == nil {
|
|
||||||
count = 1
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *SystemDevice) Write(bufs [][]byte, offset int) (count int, err error) {
|
func (w *SystemDevice) Write(p []byte, offset int) (int, error) {
|
||||||
for _, b := range bufs {
|
return w.device.Write(p[offset:])
|
||||||
_, err = w.device.Write(b[offset:])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *SystemDevice) Flush() error {
|
func (w *SystemDevice) Flush() error {
|
||||||
@@ -126,14 +123,10 @@ func (w *SystemDevice) Name() (string, error) {
|
|||||||
return w.name, nil
|
return w.name, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *SystemDevice) Events() <-chan wgTun.Event {
|
func (w *SystemDevice) Events() chan wgTun.Event {
|
||||||
return w.events
|
return w.events
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *SystemDevice) Close() error {
|
func (w *SystemDevice) Close() error {
|
||||||
return w.device.Close()
|
return w.device.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *SystemDevice) BatchSize() int {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|||||||
95
transport/wireguard/server_bind.go
Normal file
95
transport/wireguard/server_bind.go
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
package wireguard
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing/common/buf"
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
"github.com/sagernet/wireguard-go/conn"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ conn.Bind = (*ServerBind)(nil)
|
||||||
|
|
||||||
|
type ServerBind struct {
|
||||||
|
inbound chan serverPacket
|
||||||
|
done chan struct{}
|
||||||
|
writeBack N.PacketWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewServerBind(writeBack N.PacketWriter) *ServerBind {
|
||||||
|
return &ServerBind{
|
||||||
|
inbound: make(chan serverPacket, 256),
|
||||||
|
done: make(chan struct{}),
|
||||||
|
writeBack: writeBack,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ServerBind) Abort() error {
|
||||||
|
select {
|
||||||
|
case <-s.done:
|
||||||
|
return io.ErrClosedPipe
|
||||||
|
default:
|
||||||
|
close(s.done)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type serverPacket struct {
|
||||||
|
buffer *buf.Buffer
|
||||||
|
source M.Socksaddr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ServerBind) Open(port uint16) (fns []conn.ReceiveFunc, actualPort uint16, err error) {
|
||||||
|
fns = []conn.ReceiveFunc{s.receive}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ServerBind) receive(b []byte) (n int, ep conn.Endpoint, err error) {
|
||||||
|
select {
|
||||||
|
case packet := <-s.inbound:
|
||||||
|
defer packet.buffer.Release()
|
||||||
|
n = copy(b, packet.buffer.Bytes())
|
||||||
|
ep = Endpoint(packet.source)
|
||||||
|
return
|
||||||
|
case <-s.done:
|
||||||
|
err = io.ErrClosedPipe
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ServerBind) WriteIsThreadUnsafe() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ServerBind) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
|
||||||
|
select {
|
||||||
|
case s.inbound <- serverPacket{
|
||||||
|
buffer: buffer,
|
||||||
|
source: destination,
|
||||||
|
}:
|
||||||
|
return nil
|
||||||
|
case <-s.done:
|
||||||
|
return io.ErrClosedPipe
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ServerBind) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ServerBind) SetMark(mark uint32) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ServerBind) Send(b []byte, ep conn.Endpoint) error {
|
||||||
|
return s.writeBack.WritePacket(buf.As(b), M.Socksaddr(ep.(Endpoint)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ServerBind) ParseEndpoint(addr string) (conn.Endpoint, error) {
|
||||||
|
destination := M.ParseSocksaddr(addr)
|
||||||
|
if !destination.IsValid() || destination.Port == 0 {
|
||||||
|
return nil, E.New("invalid endpoint: ", addr)
|
||||||
|
}
|
||||||
|
return Endpoint(destination), nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user