sing-box/common/dialer/detour.go

70 lines
1.5 KiB
Go
Raw Normal View History

package dialer
import (
"context"
"net"
"sync"
2022-07-08 15:03:57 +00:00
"github.com/sagernet/sing-box/adapter"
2023-11-09 08:59:44 +00:00
"github.com/sagernet/sing/common/bufio/deadline"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
)
2022-07-07 13:47:21 +00:00
type DetourDialer struct {
router adapter.Router
2022-07-06 15:11:48 +00:00
detour string
dialer N.Dialer
initOnce sync.Once
initErr error
}
2022-07-06 15:11:48 +00:00
func NewDetour(router adapter.Router, detour string) N.Dialer {
2022-07-07 13:47:21 +00:00
return &DetourDialer{router: router, detour: detour}
2022-07-06 15:11:48 +00:00
}
2022-07-07 13:47:21 +00:00
func (d *DetourDialer) Start() error {
2022-07-06 15:11:48 +00:00
_, err := d.Dialer()
return err
}
2022-07-07 13:47:21 +00:00
func (d *DetourDialer) Dialer() (N.Dialer, error) {
d.initOnce.Do(func() {
var loaded bool
2022-07-06 15:11:48 +00:00
d.dialer, loaded = d.router.Outbound(d.detour)
if !loaded {
2022-07-06 15:11:48 +00:00
d.initErr = E.New("outbound detour not found: ", d.detour)
}
})
return d.dialer, d.initErr
}
2022-07-07 13:47:21 +00:00
func (d *DetourDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
dialer, err := d.Dialer()
if err != nil {
return nil, err
}
2023-11-09 08:59:44 +00:00
conn, err := dialer.DialContext(ctx, network, destination)
if err != nil {
return nil, err
}
if deadline.NeedAdditionalReadDeadline(conn) {
conn = deadline.NewConn(conn)
}
return conn, nil
}
2022-07-07 13:47:21 +00:00
func (d *DetourDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
dialer, err := d.Dialer()
if err != nil {
return nil, err
}
return dialer.ListenPacket(ctx, destination)
}
2022-07-07 13:47:21 +00:00
func (d *DetourDialer) Upstream() any {
detour, _ := d.Dialer()
return detour
}