router.go 3.1 KB

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