router.go 2.8 KB

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