1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 |
- package rule
- import (
- "context"
- "strings"
- "github.com/sagernet/sing-box/adapter"
- E "github.com/sagernet/sing/common/exceptions"
- F "github.com/sagernet/sing/common/format"
- "github.com/sagernet/sing/service"
- )
- var _ RuleItem = (*PreferredByItem)(nil)
- type PreferredByItem struct {
- ctx context.Context
- outboundTags []string
- outbounds []adapter.OutboundWithPreferredRoutes
- }
- func NewPreferredByItem(ctx context.Context, outboundTags []string) *PreferredByItem {
- return &PreferredByItem{
- ctx: ctx,
- outboundTags: outboundTags,
- }
- }
- func (r *PreferredByItem) Start() error {
- outboundManager := service.FromContext[adapter.OutboundManager](r.ctx)
- for _, outboundTag := range r.outboundTags {
- rawOutbound, loaded := outboundManager.Outbound(outboundTag)
- if !loaded {
- return E.New("outbound not found: ", outboundTag)
- }
- outboundWithPreferredRoutes, withRoutes := rawOutbound.(adapter.OutboundWithPreferredRoutes)
- if !withRoutes {
- return E.New("outbound type does not support preferred routes: ", rawOutbound.Type())
- }
- r.outbounds = append(r.outbounds, outboundWithPreferredRoutes)
- }
- return nil
- }
- func (r *PreferredByItem) Match(metadata *adapter.InboundContext) bool {
- var domainHost string
- if metadata.Domain != "" {
- domainHost = metadata.Domain
- } else {
- domainHost = metadata.Destination.Fqdn
- }
- if domainHost != "" {
- for _, outbound := range r.outbounds {
- if outbound.PreferredDomain(domainHost) {
- return true
- }
- }
- }
- if metadata.Destination.IsIP() {
- for _, outbound := range r.outbounds {
- if outbound.PreferredAddress(metadata.Destination.Addr) {
- return true
- }
- }
- }
- if len(metadata.DestinationAddresses) > 0 {
- for _, address := range metadata.DestinationAddresses {
- for _, outbound := range r.outbounds {
- if outbound.PreferredAddress(address) {
- return true
- }
- }
- }
- }
- return false
- }
- func (r *PreferredByItem) String() string {
- description := "preferred_by="
- pLen := len(r.outboundTags)
- if pLen == 1 {
- description += F.ToString(r.outboundTags[0])
- } else {
- description += "[" + strings.Join(F.MapToString(r.outboundTags), " ") + "]"
- }
- return description
- }
|