github.com/sagernet/sing-box@v1.9.0-rc.20/route/rule_set.go (about)

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