rule_set.go 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  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. E "github.com/sagernet/sing/common/exceptions"
  11. "github.com/sagernet/sing/common/logger"
  12. M "github.com/sagernet/sing/common/metadata"
  13. N "github.com/sagernet/sing/common/network"
  14. )
  15. func NewRuleSet(ctx context.Context, router adapter.Router, logger logger.ContextLogger, options option.RuleSet) (adapter.RuleSet, error) {
  16. switch options.Type {
  17. case C.RuleSetTypeLocal:
  18. return NewLocalRuleSet(router, options)
  19. case C.RuleSetTypeRemote:
  20. return NewRemoteRuleSet(ctx, router, logger, options), nil
  21. default:
  22. return nil, E.New("unknown rule set type: ", options.Type)
  23. }
  24. }
  25. var _ adapter.RuleSetStartContext = (*RuleSetStartContext)(nil)
  26. type RuleSetStartContext struct {
  27. access sync.Mutex
  28. httpClientCache map[string]*http.Client
  29. }
  30. func NewRuleSetStartContext() *RuleSetStartContext {
  31. return &RuleSetStartContext{
  32. httpClientCache: make(map[string]*http.Client),
  33. }
  34. }
  35. func (c *RuleSetStartContext) HTTPClient(detour string, dialer N.Dialer) *http.Client {
  36. c.access.Lock()
  37. defer c.access.Unlock()
  38. if httpClient, loaded := c.httpClientCache[detour]; loaded {
  39. return httpClient
  40. }
  41. httpClient := &http.Client{
  42. Transport: &http.Transport{
  43. ForceAttemptHTTP2: true,
  44. TLSHandshakeTimeout: C.TCPTimeout,
  45. DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
  46. return dialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
  47. },
  48. },
  49. }
  50. c.httpClientCache[detour] = httpClient
  51. return httpClient
  52. }
  53. func (c *RuleSetStartContext) Close() {
  54. c.access.Lock()
  55. defer c.access.Unlock()
  56. for _, client := range c.httpClientCache {
  57. client.CloseIdleConnections()
  58. }
  59. }