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 }