mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-22 08:31:30 +00:00
Fix outbound start sequence
This commit is contained in:
parent
4f12eba944
commit
8d5b9d240a
|
@ -13,6 +13,7 @@ type Outbound interface {
|
|||
Type() string
|
||||
Tag() string
|
||||
Network() []string
|
||||
Dependencies() []string
|
||||
N.Dialer
|
||||
NewConnection(ctx context.Context, conn net.Conn, metadata InboundContext) error
|
||||
NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext) error
|
||||
|
|
17
box.go
17
box.go
|
@ -217,20 +217,9 @@ func (s *Box) preStart() error {
|
|||
return E.Cause(err, "pre-starting ", serviceName)
|
||||
}
|
||||
}
|
||||
for i, out := range s.outbounds {
|
||||
var tag string
|
||||
if out.Tag() == "" {
|
||||
tag = F.ToString(i)
|
||||
} else {
|
||||
tag = out.Tag()
|
||||
}
|
||||
if starter, isStarter := out.(common.Starter); isStarter {
|
||||
s.logger.Trace("initializing outbound/", out.Type(), "[", tag, "]")
|
||||
err := starter.Start()
|
||||
if err != nil {
|
||||
return E.Cause(err, "initialize outbound/", out.Type(), "[", tag, "]")
|
||||
}
|
||||
}
|
||||
err := s.startOutbounds()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.router.Start()
|
||||
}
|
||||
|
|
76
box_outbound.go
Normal file
76
box_outbound.go
Normal file
|
@ -0,0 +1,76 @@
|
|||
package box
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
)
|
||||
|
||||
func (s *Box) startOutbounds() error {
|
||||
outboundTags := make(map[adapter.Outbound]string)
|
||||
outbounds := make(map[string]adapter.Outbound)
|
||||
for i, outboundToStart := range s.outbounds {
|
||||
var outboundTag string
|
||||
if outboundToStart.Tag() == "" {
|
||||
outboundTag = F.ToString(i)
|
||||
} else {
|
||||
outboundTag = outboundToStart.Tag()
|
||||
}
|
||||
outboundTags[outboundToStart] = outboundTag
|
||||
outbounds[outboundTag] = outboundToStart
|
||||
}
|
||||
started := make(map[string]bool)
|
||||
for {
|
||||
canContinue := false
|
||||
startOne:
|
||||
for _, outboundToStart := range s.outbounds {
|
||||
outboundTag := outboundTags[outboundToStart]
|
||||
if started[outboundTag] {
|
||||
continue
|
||||
}
|
||||
dependencies := outboundToStart.Dependencies()
|
||||
for _, dependency := range dependencies {
|
||||
if !started[dependency] {
|
||||
continue startOne
|
||||
}
|
||||
}
|
||||
started[outboundTag] = true
|
||||
canContinue = true
|
||||
if starter, isStarter := outboundToStart.(common.Starter); isStarter {
|
||||
s.logger.Trace("initializing outbound/", outboundToStart.Type(), "[", outboundTag, "]")
|
||||
err := starter.Start()
|
||||
if err != nil {
|
||||
return E.Cause(err, "initialize outbound/", outboundToStart.Type(), "[", outboundTag, "]")
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(started) == len(s.outbounds) {
|
||||
break
|
||||
}
|
||||
if canContinue {
|
||||
continue
|
||||
}
|
||||
currentOutbound := common.Find(s.outbounds, func(it adapter.Outbound) bool {
|
||||
return !started[outboundTags[it]]
|
||||
})
|
||||
var lintOutbound func(oTree []string, oCurrent adapter.Outbound) error
|
||||
lintOutbound = func(oTree []string, oCurrent adapter.Outbound) error {
|
||||
problemOutboundTag := common.Find(oCurrent.Dependencies(), func(it string) bool {
|
||||
return !started[it]
|
||||
})
|
||||
if common.Contains(oTree, problemOutboundTag) {
|
||||
return E.New("circular outbound dependency: ", strings.Join(oTree, " -> "), " -> ", problemOutboundTag)
|
||||
}
|
||||
problemOutbound := outbounds[problemOutboundTag]
|
||||
if problemOutbound == nil {
|
||||
return E.New("dependency[", problemOutbound, "] not found for outbound[", outboundTags[oCurrent], "]")
|
||||
}
|
||||
return lintOutbound(append(oTree, problemOutboundTag), problemOutbound)
|
||||
}
|
||||
return lintOutbound([]string{outboundTags[currentOutbound]}, currentOutbound)
|
||||
}
|
||||
return nil
|
||||
}
|
2
go.mod
2
go.mod
|
@ -25,7 +25,7 @@ require (
|
|||
github.com/sagernet/gvisor v0.0.0-20230611140528-4411f7659a08
|
||||
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32
|
||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
||||
github.com/sagernet/sing v0.2.5-0.20230611070640-2812461739c3
|
||||
github.com/sagernet/sing v0.2.5-0.20230613142554-a3b120b25eab
|
||||
github.com/sagernet/sing-dns v0.1.5-0.20230426113254-25d948c44223
|
||||
github.com/sagernet/sing-mux v0.0.0-20230517134606-1ebe6bb26646
|
||||
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230509053848-d83f8fe1194c
|
||||
|
|
4
go.sum
4
go.sum
|
@ -118,8 +118,8 @@ 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/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.2.5-0.20230611070640-2812461739c3 h1:OnlfGM8HncECbFiV4s6uAX961fm2UpEKSCXYBLZ1Chg=
|
||||
github.com/sagernet/sing v0.2.5-0.20230611070640-2812461739c3/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
|
||||
github.com/sagernet/sing v0.2.5-0.20230613142554-a3b120b25eab h1:9AVUIqqz/UJCgIrcJBU9mb06JXzfQ/FgEmlgdPgo2dk=
|
||||
github.com/sagernet/sing v0.2.5-0.20230613142554-a3b120b25eab/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
|
||||
github.com/sagernet/sing-dns v0.1.5-0.20230426113254-25d948c44223 h1:L4eMuM07iSHY3UCknFnuFuHoe5clZuF2Xnf2wwA6Lwc=
|
||||
github.com/sagernet/sing-dns v0.1.5-0.20230426113254-25d948c44223/go.mod h1:ZKuuqgsHRxDahYrzgSgy4vIAGGuKPlIf4hLcNzYzLkY=
|
||||
github.com/sagernet/sing-mux v0.0.0-20230517134606-1ebe6bb26646 h1:X3ADfMqeGns1Q1FlXc9kaL9FwW1UM6D6tEQo8jFstpc=
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
|
@ -20,11 +21,12 @@ import (
|
|||
)
|
||||
|
||||
type myOutboundAdapter struct {
|
||||
protocol string
|
||||
network []string
|
||||
router adapter.Router
|
||||
logger log.ContextLogger
|
||||
tag string
|
||||
protocol string
|
||||
network []string
|
||||
router adapter.Router
|
||||
logger log.ContextLogger
|
||||
tag string
|
||||
dependencies []string
|
||||
}
|
||||
|
||||
func (a *myOutboundAdapter) Type() string {
|
||||
|
@ -39,10 +41,21 @@ func (a *myOutboundAdapter) Network() []string {
|
|||
return a.network
|
||||
}
|
||||
|
||||
func (a *myOutboundAdapter) Dependencies() []string {
|
||||
return a.dependencies
|
||||
}
|
||||
|
||||
func (a *myOutboundAdapter) NewError(ctx context.Context, err error) {
|
||||
NewError(a.logger, ctx, err)
|
||||
}
|
||||
|
||||
func withDialerDependency(options option.DialerOptions) []string {
|
||||
if options.Detour != "" {
|
||||
return []string{options.Detour}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewConnection(ctx context.Context, this N.Dialer, conn net.Conn, metadata adapter.InboundContext) error {
|
||||
ctx = adapter.WithContext(ctx, &metadata)
|
||||
var outConn net.Conn
|
||||
|
|
|
@ -40,11 +40,12 @@ func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, opti
|
|||
options.UDPFragmentDefault = true
|
||||
outbound := &Direct{
|
||||
myOutboundAdapter: myOutboundAdapter{
|
||||
protocol: C.TypeDirect,
|
||||
network: []string{N.NetworkTCP, N.NetworkUDP},
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
protocol: C.TypeDirect,
|
||||
network: []string{N.NetworkTCP, N.NetworkUDP},
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
dependencies: withDialerDependency(options.DialerOptions),
|
||||
},
|
||||
domainStrategy: dns.DomainStrategy(options.DomainStrategy),
|
||||
fallbackDelay: time.Duration(options.FallbackDelay),
|
||||
|
|
|
@ -39,11 +39,12 @@ func NewHTTP(router adapter.Router, logger log.ContextLogger, tag string, option
|
|||
}
|
||||
return &HTTP{
|
||||
myOutboundAdapter{
|
||||
protocol: C.TypeHTTP,
|
||||
network: []string{N.NetworkTCP},
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
protocol: C.TypeHTTP,
|
||||
network: []string{N.NetworkTCP},
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
dependencies: withDialerDependency(options.DialerOptions),
|
||||
},
|
||||
sHTTP.NewClient(sHTTP.Options{
|
||||
Dialer: detour,
|
||||
|
|
|
@ -119,11 +119,12 @@ func NewHysteria(ctx context.Context, router adapter.Router, logger log.ContextL
|
|||
}
|
||||
return &Hysteria{
|
||||
myOutboundAdapter: myOutboundAdapter{
|
||||
protocol: C.TypeHysteria,
|
||||
network: options.Network.Build(),
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
protocol: C.TypeHysteria,
|
||||
network: options.Network.Build(),
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
dependencies: withDialerDependency(options.DialerOptions),
|
||||
},
|
||||
ctx: ctx,
|
||||
dialer: dialer.New(router, options.DialerOptions),
|
||||
|
|
|
@ -29,10 +29,11 @@ type Selector struct {
|
|||
func NewSelector(router adapter.Router, logger log.ContextLogger, tag string, options option.SelectorOutboundOptions) (*Selector, error) {
|
||||
outbound := &Selector{
|
||||
myOutboundAdapter: myOutboundAdapter{
|
||||
protocol: C.TypeSelector,
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
protocol: C.TypeSelector,
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
dependencies: options.Outbounds,
|
||||
},
|
||||
tags: options.Outbounds,
|
||||
defaultTag: options.Default,
|
||||
|
|
|
@ -41,11 +41,12 @@ func NewShadowsocks(ctx context.Context, router adapter.Router, logger log.Conte
|
|||
}
|
||||
outbound := &Shadowsocks{
|
||||
myOutboundAdapter: myOutboundAdapter{
|
||||
protocol: C.TypeShadowsocks,
|
||||
network: options.Network.Build(),
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
protocol: C.TypeShadowsocks,
|
||||
network: options.Network.Build(),
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
dependencies: withDialerDependency(options.DialerOptions),
|
||||
},
|
||||
dialer: dialer.New(router, options.DialerOptions),
|
||||
method: method,
|
||||
|
|
|
@ -39,11 +39,12 @@ type ShadowsocksR struct {
|
|||
func NewShadowsocksR(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowsocksROutboundOptions) (*ShadowsocksR, error) {
|
||||
outbound := &ShadowsocksR{
|
||||
myOutboundAdapter: myOutboundAdapter{
|
||||
protocol: C.TypeShadowsocksR,
|
||||
network: options.Network.Build(),
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
protocol: C.TypeShadowsocksR,
|
||||
network: options.Network.Build(),
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
dependencies: withDialerDependency(options.DialerOptions),
|
||||
},
|
||||
dialer: dialer.New(router, options.DialerOptions),
|
||||
serverAddr: options.ServerOptions.Build(),
|
||||
|
|
|
@ -27,11 +27,12 @@ type ShadowTLS struct {
|
|||
func NewShadowTLS(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowTLSOutboundOptions) (*ShadowTLS, error) {
|
||||
outbound := &ShadowTLS{
|
||||
myOutboundAdapter: myOutboundAdapter{
|
||||
protocol: C.TypeShadowTLS,
|
||||
network: []string{N.NetworkTCP},
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
protocol: C.TypeShadowTLS,
|
||||
network: []string{N.NetworkTCP},
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
dependencies: withDialerDependency(options.DialerOptions),
|
||||
},
|
||||
}
|
||||
if options.TLS == nil || !options.TLS.Enabled {
|
||||
|
|
|
@ -39,11 +39,12 @@ func NewSocks(router adapter.Router, logger log.ContextLogger, tag string, optio
|
|||
}
|
||||
outbound := &Socks{
|
||||
myOutboundAdapter: myOutboundAdapter{
|
||||
protocol: C.TypeSocks,
|
||||
network: options.Network.Build(),
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
protocol: C.TypeSocks,
|
||||
network: options.Network.Build(),
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
dependencies: withDialerDependency(options.DialerOptions),
|
||||
},
|
||||
client: socks.NewClient(dialer.New(router, options.DialerOptions), options.ServerOptions.Build(), version, options.Username, options.Password),
|
||||
resolve: version == socks.Version4,
|
||||
|
|
|
@ -46,11 +46,12 @@ type SSH struct {
|
|||
func NewSSH(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.SSHOutboundOptions) (*SSH, error) {
|
||||
outbound := &SSH{
|
||||
myOutboundAdapter: myOutboundAdapter{
|
||||
protocol: C.TypeSSH,
|
||||
network: []string{N.NetworkTCP},
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
protocol: C.TypeSSH,
|
||||
network: []string{N.NetworkTCP},
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
dependencies: withDialerDependency(options.DialerOptions),
|
||||
},
|
||||
ctx: ctx,
|
||||
dialer: dialer.New(router, options.DialerOptions),
|
||||
|
|
|
@ -68,11 +68,12 @@ func NewTor(ctx context.Context, router adapter.Router, logger log.ContextLogger
|
|||
}
|
||||
return &Tor{
|
||||
myOutboundAdapter: myOutboundAdapter{
|
||||
protocol: C.TypeTor,
|
||||
network: []string{N.NetworkTCP},
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
protocol: C.TypeTor,
|
||||
network: []string{N.NetworkTCP},
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
dependencies: withDialerDependency(options.DialerOptions),
|
||||
},
|
||||
ctx: ctx,
|
||||
proxy: NewProxyListener(ctx, logger, dialer.New(router, options.DialerOptions)),
|
||||
|
|
|
@ -35,11 +35,12 @@ type Trojan struct {
|
|||
func NewTrojan(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.TrojanOutboundOptions) (*Trojan, error) {
|
||||
outbound := &Trojan{
|
||||
myOutboundAdapter: myOutboundAdapter{
|
||||
protocol: C.TypeTrojan,
|
||||
network: options.Network.Build(),
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
protocol: C.TypeTrojan,
|
||||
network: options.Network.Build(),
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
dependencies: withDialerDependency(options.DialerOptions),
|
||||
},
|
||||
dialer: dialer.New(router, options.DialerOptions),
|
||||
serverAddr: options.ServerOptions.Build(),
|
||||
|
|
|
@ -39,10 +39,11 @@ type URLTest struct {
|
|||
func NewURLTest(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.URLTestOutboundOptions) (*URLTest, error) {
|
||||
outbound := &URLTest{
|
||||
myOutboundAdapter: myOutboundAdapter{
|
||||
protocol: C.TypeURLTest,
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
protocol: C.TypeURLTest,
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
dependencies: options.Outbounds,
|
||||
},
|
||||
ctx: ctx,
|
||||
tags: options.Outbounds,
|
||||
|
|
|
@ -38,11 +38,12 @@ type VLESS struct {
|
|||
func NewVLESS(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.VLESSOutboundOptions) (*VLESS, error) {
|
||||
outbound := &VLESS{
|
||||
myOutboundAdapter: myOutboundAdapter{
|
||||
protocol: C.TypeVLESS,
|
||||
network: options.Network.Build(),
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
protocol: C.TypeVLESS,
|
||||
network: options.Network.Build(),
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
dependencies: withDialerDependency(options.DialerOptions),
|
||||
},
|
||||
dialer: dialer.New(router, options.DialerOptions),
|
||||
serverAddr: options.ServerOptions.Build(),
|
||||
|
|
|
@ -37,11 +37,12 @@ type VMess struct {
|
|||
func NewVMess(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.VMessOutboundOptions) (*VMess, error) {
|
||||
outbound := &VMess{
|
||||
myOutboundAdapter: myOutboundAdapter{
|
||||
protocol: C.TypeVMess,
|
||||
network: options.Network.Build(),
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
protocol: C.TypeVMess,
|
||||
network: options.Network.Build(),
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
dependencies: withDialerDependency(options.DialerOptions),
|
||||
},
|
||||
dialer: dialer.New(router, options.DialerOptions),
|
||||
serverAddr: options.ServerOptions.Build(),
|
||||
|
|
|
@ -40,11 +40,12 @@ type WireGuard struct {
|
|||
func NewWireGuard(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.WireGuardOutboundOptions) (*WireGuard, error) {
|
||||
outbound := &WireGuard{
|
||||
myOutboundAdapter: myOutboundAdapter{
|
||||
protocol: C.TypeWireGuard,
|
||||
network: options.Network.Build(),
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
protocol: C.TypeWireGuard,
|
||||
network: options.Network.Build(),
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
dependencies: withDialerDependency(options.DialerOptions),
|
||||
},
|
||||
}
|
||||
var reserved [3]uint8
|
||||
|
|
|
@ -8,13 +8,6 @@ import (
|
|||
"net/netip"
|
||||
"os"
|
||||
|
||||
"github.com/sagernet/sing-tun"
|
||||
"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"
|
||||
wgTun "github.com/sagernet/wireguard-go/tun"
|
||||
|
||||
"github.com/sagernet/gvisor/pkg/buffer"
|
||||
"github.com/sagernet/gvisor/pkg/tcpip"
|
||||
"github.com/sagernet/gvisor/pkg/tcpip/adapters/gonet"
|
||||
|
@ -25,6 +18,12 @@ import (
|
|||
"github.com/sagernet/gvisor/pkg/tcpip/transport/icmp"
|
||||
"github.com/sagernet/gvisor/pkg/tcpip/transport/tcp"
|
||||
"github.com/sagernet/gvisor/pkg/tcpip/transport/udp"
|
||||
"github.com/sagernet/sing-tun"
|
||||
"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"
|
||||
wgTun "github.com/sagernet/wireguard-go/tun"
|
||||
)
|
||||
|
||||
var _ Device = (*StackDevice)(nil)
|
||||
|
|
|
@ -10,14 +10,13 @@ import (
|
|||
"net/netip"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-tun"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
|
||||
"github.com/sagernet/gvisor/pkg/tcpip"
|
||||
"github.com/sagernet/gvisor/pkg/tcpip/adapters/gonet"
|
||||
"github.com/sagernet/gvisor/pkg/tcpip/stack"
|
||||
"github.com/sagernet/gvisor/pkg/tcpip/transport/tcp"
|
||||
"github.com/sagernet/gvisor/pkg/waiter"
|
||||
"github.com/sagernet/sing-tun"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
)
|
||||
|
||||
func DialTCPWithBind(ctx context.Context, s *stack.Stack, localAddr, remoteAddr tcpip.FullAddress, network tcpip.NetworkProtocolNumber) (*gonet.TCPConn, error) {
|
||||
|
|
Loading…
Reference in a new issue