github.com/sagernet/sing-box@v1.9.0-rc.20/common/dialer/detour.go (about) 1 package dialer 2 3 import ( 4 "context" 5 "net" 6 "sync" 7 8 "github.com/sagernet/sing-box/adapter" 9 E "github.com/sagernet/sing/common/exceptions" 10 M "github.com/sagernet/sing/common/metadata" 11 N "github.com/sagernet/sing/common/network" 12 ) 13 14 type DetourDialer struct { 15 router adapter.Router 16 detour string 17 dialer N.Dialer 18 initOnce sync.Once 19 initErr error 20 } 21 22 func NewDetour(router adapter.Router, detour string) N.Dialer { 23 return &DetourDialer{router: router, detour: detour} 24 } 25 26 func (d *DetourDialer) Start() error { 27 _, err := d.Dialer() 28 return err 29 } 30 31 func (d *DetourDialer) Dialer() (N.Dialer, error) { 32 d.initOnce.Do(func() { 33 var loaded bool 34 d.dialer, loaded = d.router.Outbound(d.detour) 35 if !loaded { 36 d.initErr = E.New("outbound detour not found: ", d.detour) 37 } 38 }) 39 return d.dialer, d.initErr 40 } 41 42 func (d *DetourDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) { 43 dialer, err := d.Dialer() 44 if err != nil { 45 return nil, err 46 } 47 return dialer.DialContext(ctx, network, destination) 48 } 49 50 func (d *DetourDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) { 51 dialer, err := d.Dialer() 52 if err != nil { 53 return nil, err 54 } 55 return dialer.ListenPacket(ctx, destination) 56 } 57 58 func (d *DetourDialer) Upstream() any { 59 detour, _ := d.Dialer() 60 return detour 61 }