github.com/v2fly/v2ray-core/v4@v4.45.2/app/proxyman/outbound/outbound.go (about)

     1  package outbound
     2  
     3  //go:generate go run github.com/v2fly/v2ray-core/v4/common/errors/errorgen
     4  
     5  import (
     6  	"context"
     7  	"strings"
     8  	"sync"
     9  
    10  	core "github.com/v2fly/v2ray-core/v4"
    11  	"github.com/v2fly/v2ray-core/v4/app/proxyman"
    12  	"github.com/v2fly/v2ray-core/v4/common"
    13  	"github.com/v2fly/v2ray-core/v4/common/errors"
    14  	"github.com/v2fly/v2ray-core/v4/features/outbound"
    15  )
    16  
    17  // Manager is to manage all outbound handlers.
    18  type Manager struct {
    19  	access           sync.RWMutex
    20  	defaultHandler   outbound.Handler
    21  	taggedHandler    map[string]outbound.Handler
    22  	untaggedHandlers []outbound.Handler
    23  	running          bool
    24  }
    25  
    26  // New creates a new Manager.
    27  func New(ctx context.Context, config *proxyman.OutboundConfig) (*Manager, error) {
    28  	m := &Manager{
    29  		taggedHandler: make(map[string]outbound.Handler),
    30  	}
    31  	return m, nil
    32  }
    33  
    34  // Type implements common.HasType.
    35  func (m *Manager) Type() interface{} {
    36  	return outbound.ManagerType()
    37  }
    38  
    39  // Start implements core.Feature
    40  func (m *Manager) Start() error {
    41  	m.access.Lock()
    42  	defer m.access.Unlock()
    43  
    44  	m.running = true
    45  
    46  	for _, h := range m.taggedHandler {
    47  		if err := h.Start(); err != nil {
    48  			return err
    49  		}
    50  	}
    51  
    52  	for _, h := range m.untaggedHandlers {
    53  		if err := h.Start(); err != nil {
    54  			return err
    55  		}
    56  	}
    57  
    58  	return nil
    59  }
    60  
    61  // Close implements core.Feature
    62  func (m *Manager) Close() error {
    63  	m.access.Lock()
    64  	defer m.access.Unlock()
    65  
    66  	m.running = false
    67  
    68  	var errs []error
    69  	for _, h := range m.taggedHandler {
    70  		errs = append(errs, h.Close())
    71  	}
    72  
    73  	for _, h := range m.untaggedHandlers {
    74  		errs = append(errs, h.Close())
    75  	}
    76  
    77  	return errors.Combine(errs...)
    78  }
    79  
    80  // GetDefaultHandler implements outbound.Manager.
    81  func (m *Manager) GetDefaultHandler() outbound.Handler {
    82  	m.access.RLock()
    83  	defer m.access.RUnlock()
    84  
    85  	if m.defaultHandler == nil {
    86  		return nil
    87  	}
    88  	return m.defaultHandler
    89  }
    90  
    91  // GetHandler implements outbound.Manager.
    92  func (m *Manager) GetHandler(tag string) outbound.Handler {
    93  	m.access.RLock()
    94  	defer m.access.RUnlock()
    95  	if handler, found := m.taggedHandler[tag]; found {
    96  		return handler
    97  	}
    98  	return nil
    99  }
   100  
   101  // AddHandler implements outbound.Manager.
   102  func (m *Manager) AddHandler(ctx context.Context, handler outbound.Handler) error {
   103  	m.access.Lock()
   104  	defer m.access.Unlock()
   105  
   106  	if m.defaultHandler == nil {
   107  		m.defaultHandler = handler
   108  	}
   109  
   110  	tag := handler.Tag()
   111  	if len(tag) > 0 {
   112  		m.taggedHandler[tag] = handler
   113  	} else {
   114  		m.untaggedHandlers = append(m.untaggedHandlers, handler)
   115  	}
   116  
   117  	if m.running {
   118  		return handler.Start()
   119  	}
   120  
   121  	return nil
   122  }
   123  
   124  // RemoveHandler implements outbound.Manager.
   125  func (m *Manager) RemoveHandler(ctx context.Context, tag string) error {
   126  	if tag == "" {
   127  		return common.ErrNoClue
   128  	}
   129  	m.access.Lock()
   130  	defer m.access.Unlock()
   131  
   132  	delete(m.taggedHandler, tag)
   133  	if m.defaultHandler != nil && m.defaultHandler.Tag() == tag {
   134  		m.defaultHandler = nil
   135  	}
   136  
   137  	return nil
   138  }
   139  
   140  // Select implements outbound.HandlerSelector.
   141  func (m *Manager) Select(selectors []string) []string {
   142  	m.access.RLock()
   143  	defer m.access.RUnlock()
   144  
   145  	tags := make([]string, 0, len(selectors))
   146  
   147  	for tag := range m.taggedHandler {
   148  		match := false
   149  		for _, selector := range selectors {
   150  			if strings.HasPrefix(tag, selector) {
   151  				match = true
   152  				break
   153  			}
   154  		}
   155  		if match {
   156  			tags = append(tags, tag)
   157  		}
   158  	}
   159  
   160  	return tags
   161  }
   162  
   163  func init() {
   164  	common.Must(common.RegisterConfig((*proxyman.OutboundConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
   165  		return New(ctx, config.(*proxyman.OutboundConfig))
   166  	}))
   167  	common.Must(common.RegisterConfig((*core.OutboundHandlerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
   168  		return NewHandler(ctx, config.(*core.OutboundHandlerConfig))
   169  	}))
   170  }