1
0

rule_set.go 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. package route
  2. import (
  3. "context"
  4. "net"
  5. "net/http"
  6. "sync"
  7. "github.com/sagernet/sing-box/adapter"
  8. C "github.com/sagernet/sing-box/constant"
  9. "github.com/sagernet/sing-box/option"
  10. "github.com/sagernet/sing/common"
  11. E "github.com/sagernet/sing/common/exceptions"
  12. "github.com/sagernet/sing/common/logger"
  13. M "github.com/sagernet/sing/common/metadata"
  14. N "github.com/sagernet/sing/common/network"
  15. "go4.org/netipx"
  16. )
  17. func NewRuleSet(ctx context.Context, router adapter.Router, logger logger.ContextLogger, options option.RuleSet) (adapter.RuleSet, error) {
  18. switch options.Type {
  19. case C.RuleSetTypeLocal:
  20. return NewLocalRuleSet(ctx, router, options)
  21. case C.RuleSetTypeRemote:
  22. return NewRemoteRuleSet(ctx, router, logger, options), nil
  23. default:
  24. return nil, E.New("unknown rule set type: ", options.Type)
  25. }
  26. }
  27. func extractIPSetFromRule(rawRule adapter.HeadlessRule) []*netipx.IPSet {
  28. switch rule := rawRule.(type) {
  29. case *DefaultHeadlessRule:
  30. return common.FlatMap(rule.destinationIPCIDRItems, func(rawItem RuleItem) []*netipx.IPSet {
  31. switch item := rawItem.(type) {
  32. case *IPCIDRItem:
  33. return []*netipx.IPSet{item.ipSet}
  34. default:
  35. return nil
  36. }
  37. })
  38. case *LogicalHeadlessRule:
  39. return common.FlatMap(rule.rules, extractIPSetFromRule)
  40. default:
  41. panic("unexpected rule type")
  42. }
  43. }
  44. var _ adapter.RuleSetStartContext = (*RuleSetStartContext)(nil)
  45. type RuleSetStartContext struct {
  46. access sync.Mutex
  47. httpClientCache map[string]*http.Client
  48. }
  49. func NewRuleSetStartContext() *RuleSetStartContext {
  50. return &RuleSetStartContext{
  51. httpClientCache: make(map[string]*http.Client),
  52. }
  53. }
  54. func (c *RuleSetStartContext) HTTPClient(detour string, dialer N.Dialer) *http.Client {
  55. c.access.Lock()
  56. defer c.access.Unlock()
  57. if httpClient, loaded := c.httpClientCache[detour]; loaded {
  58. return httpClient
  59. }
  60. httpClient := &http.Client{
  61. Transport: &http.Transport{
  62. ForceAttemptHTTP2: true,
  63. TLSHandshakeTimeout: C.TCPTimeout,
  64. DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
  65. return dialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
  66. },
  67. },
  68. }
  69. c.httpClientCache[detour] = httpClient
  70. return httpClient
  71. }
  72. func (c *RuleSetStartContext) Close() {
  73. c.access.Lock()
  74. defer c.access.Unlock()
  75. for _, client := range c.httpClientCache {
  76. client.CloseIdleConnections()
  77. }
  78. }