router.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. package adapter
  2. import (
  3. "context"
  4. "crypto/tls"
  5. "net"
  6. "net/http"
  7. "sync"
  8. "time"
  9. C "github.com/sagernet/sing-box/constant"
  10. "github.com/sagernet/sing-tun"
  11. M "github.com/sagernet/sing/common/metadata"
  12. N "github.com/sagernet/sing/common/network"
  13. "github.com/sagernet/sing/common/ntp"
  14. "github.com/sagernet/sing/common/x/list"
  15. "go4.org/netipx"
  16. )
  17. type Router interface {
  18. Lifecycle
  19. ConnectionRouter
  20. PreMatch(metadata InboundContext, context tun.DirectRouteContext, timeout time.Duration) (tun.DirectRouteDestination, error)
  21. ConnectionRouterEx
  22. RuleSet(tag string) (RuleSet, bool)
  23. NeedWIFIState() bool
  24. Rules() []Rule
  25. AppendTracker(tracker ConnectionTracker)
  26. ResetNetwork()
  27. }
  28. type ConnectionTracker interface {
  29. RoutedConnection(ctx context.Context, conn net.Conn, metadata InboundContext, matchedRule Rule, matchOutbound Outbound) net.Conn
  30. RoutedPacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext, matchedRule Rule, matchOutbound Outbound) N.PacketConn
  31. }
  32. // Deprecated: Use ConnectionRouterEx instead.
  33. type ConnectionRouter interface {
  34. RouteConnection(ctx context.Context, conn net.Conn, metadata InboundContext) error
  35. RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext) error
  36. }
  37. type ConnectionRouterEx interface {
  38. ConnectionRouter
  39. RouteConnectionEx(ctx context.Context, conn net.Conn, metadata InboundContext, onClose N.CloseHandlerFunc)
  40. RoutePacketConnectionEx(ctx context.Context, conn N.PacketConn, metadata InboundContext, onClose N.CloseHandlerFunc)
  41. }
  42. type RuleSet interface {
  43. Name() string
  44. StartContext(ctx context.Context, startContext *HTTPStartContext) error
  45. PostStart() error
  46. Metadata() RuleSetMetadata
  47. ExtractIPSet() []*netipx.IPSet
  48. IncRef()
  49. DecRef()
  50. Cleanup()
  51. RegisterCallback(callback RuleSetUpdateCallback) *list.Element[RuleSetUpdateCallback]
  52. UnregisterCallback(element *list.Element[RuleSetUpdateCallback])
  53. Close() error
  54. HeadlessRule
  55. }
  56. type RuleSetUpdateCallback func(it RuleSet)
  57. type RuleSetMetadata struct {
  58. ContainsProcessRule bool
  59. ContainsWIFIRule bool
  60. ContainsIPCIDRRule bool
  61. }
  62. type HTTPStartContext struct {
  63. ctx context.Context
  64. access sync.Mutex
  65. httpClientCache map[string]*http.Client
  66. }
  67. func NewHTTPStartContext(ctx context.Context) *HTTPStartContext {
  68. return &HTTPStartContext{
  69. ctx: ctx,
  70. httpClientCache: make(map[string]*http.Client),
  71. }
  72. }
  73. func (c *HTTPStartContext) HTTPClient(detour string, dialer N.Dialer) *http.Client {
  74. c.access.Lock()
  75. defer c.access.Unlock()
  76. if httpClient, loaded := c.httpClientCache[detour]; loaded {
  77. return httpClient
  78. }
  79. httpClient := &http.Client{
  80. Transport: &http.Transport{
  81. ForceAttemptHTTP2: true,
  82. TLSHandshakeTimeout: C.TCPTimeout,
  83. DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
  84. return dialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
  85. },
  86. TLSClientConfig: &tls.Config{
  87. Time: ntp.TimeFuncFromContext(c.ctx),
  88. RootCAs: RootPoolFromContext(c.ctx),
  89. },
  90. },
  91. }
  92. c.httpClientCache[detour] = httpClient
  93. return httpClient
  94. }
  95. func (c *HTTPStartContext) Close() {
  96. c.access.Lock()
  97. defer c.access.Unlock()
  98. for _, client := range c.httpClientCache {
  99. client.CloseIdleConnections()
  100. }
  101. }