github.com/eagleql/xray-core@v1.4.4/app/proxyman/inbound/inbound.go (about) 1 package inbound 2 3 //go:generate go run github.com/eagleql/xray-core/common/errors/errorgen 4 5 import ( 6 "context" 7 "sync" 8 9 "github.com/eagleql/xray-core/app/proxyman" 10 "github.com/eagleql/xray-core/common" 11 "github.com/eagleql/xray-core/common/serial" 12 "github.com/eagleql/xray-core/common/session" 13 "github.com/eagleql/xray-core/core" 14 "github.com/eagleql/xray-core/features/inbound" 15 ) 16 17 // Manager is to manage all inbound handlers. 18 type Manager struct { 19 access sync.RWMutex 20 untaggedHandler []inbound.Handler 21 taggedHandlers map[string]inbound.Handler 22 running bool 23 } 24 25 // New returns a new Manager for inbound handlers. 26 func New(ctx context.Context, config *proxyman.InboundConfig) (*Manager, error) { 27 m := &Manager{ 28 taggedHandlers: make(map[string]inbound.Handler), 29 } 30 return m, nil 31 } 32 33 // Type implements common.HasType. 34 func (*Manager) Type() interface{} { 35 return inbound.ManagerType() 36 } 37 38 // AddHandler implements inbound.Manager. 39 func (m *Manager) AddHandler(ctx context.Context, handler inbound.Handler) error { 40 m.access.Lock() 41 defer m.access.Unlock() 42 43 tag := handler.Tag() 44 if len(tag) > 0 { 45 if _, found := m.taggedHandlers[tag]; found { 46 return newError("existing tag found: " + tag) 47 } 48 m.taggedHandlers[tag] = handler 49 } else { 50 m.untaggedHandler = append(m.untaggedHandler, handler) 51 } 52 53 if m.running { 54 return handler.Start() 55 } 56 57 return nil 58 } 59 60 // GetHandler implements inbound.Manager. 61 func (m *Manager) GetHandler(ctx context.Context, tag string) (inbound.Handler, error) { 62 m.access.RLock() 63 defer m.access.RUnlock() 64 65 handler, found := m.taggedHandlers[tag] 66 if !found { 67 return nil, newError("handler not found: ", tag) 68 } 69 return handler, nil 70 } 71 72 // RemoveHandler implements inbound.Manager. 73 func (m *Manager) RemoveHandler(ctx context.Context, tag string) error { 74 if tag == "" { 75 return common.ErrNoClue 76 } 77 78 m.access.Lock() 79 defer m.access.Unlock() 80 81 if handler, found := m.taggedHandlers[tag]; found { 82 if err := handler.Close(); err != nil { 83 newError("failed to close handler ", tag).Base(err).AtWarning().WriteToLog(session.ExportIDToError(ctx)) 84 } 85 delete(m.taggedHandlers, tag) 86 return nil 87 } 88 89 return common.ErrNoClue 90 } 91 92 // Start implements common.Runnable. 93 func (m *Manager) Start() error { 94 m.access.Lock() 95 defer m.access.Unlock() 96 97 m.running = true 98 99 for _, handler := range m.taggedHandlers { 100 if err := handler.Start(); err != nil { 101 return err 102 } 103 } 104 105 for _, handler := range m.untaggedHandler { 106 if err := handler.Start(); err != nil { 107 return err 108 } 109 } 110 return nil 111 } 112 113 // Close implements common.Closable. 114 func (m *Manager) Close() error { 115 m.access.Lock() 116 defer m.access.Unlock() 117 118 m.running = false 119 120 var errors []interface{} 121 for _, handler := range m.taggedHandlers { 122 if err := handler.Close(); err != nil { 123 errors = append(errors, err) 124 } 125 } 126 for _, handler := range m.untaggedHandler { 127 if err := handler.Close(); err != nil { 128 errors = append(errors, err) 129 } 130 } 131 132 if len(errors) > 0 { 133 return newError("failed to close all handlers").Base(newError(serial.Concat(errors...))) 134 } 135 136 return nil 137 } 138 139 // NewHandler creates a new inbound.Handler based on the given config. 140 func NewHandler(ctx context.Context, config *core.InboundHandlerConfig) (inbound.Handler, error) { 141 rawReceiverSettings, err := config.ReceiverSettings.GetInstance() 142 if err != nil { 143 return nil, err 144 } 145 proxySettings, err := config.ProxySettings.GetInstance() 146 if err != nil { 147 return nil, err 148 } 149 tag := config.Tag 150 151 receiverSettings, ok := rawReceiverSettings.(*proxyman.ReceiverConfig) 152 if !ok { 153 return nil, newError("not a ReceiverConfig").AtError() 154 } 155 156 streamSettings := receiverSettings.StreamSettings 157 if streamSettings != nil && streamSettings.SocketSettings != nil { 158 ctx = session.ContextWithSockopt(ctx, &session.Sockopt{ 159 Mark: streamSettings.SocketSettings.Mark, 160 }) 161 } 162 163 allocStrategy := receiverSettings.AllocationStrategy 164 if allocStrategy == nil || allocStrategy.Type == proxyman.AllocationStrategy_Always { 165 return NewAlwaysOnInboundHandler(ctx, tag, receiverSettings, proxySettings) 166 } 167 168 if allocStrategy.Type == proxyman.AllocationStrategy_Random { 169 return NewDynamicInboundHandler(ctx, tag, receiverSettings, proxySettings) 170 } 171 return nil, newError("unknown allocation strategy: ", receiverSettings.AllocationStrategy.Type).AtError() 172 } 173 174 func init() { 175 common.Must(common.RegisterConfig((*proxyman.InboundConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { 176 return New(ctx, config.(*proxyman.InboundConfig)) 177 })) 178 common.Must(common.RegisterConfig((*core.InboundHandlerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { 179 return NewHandler(ctx, config.(*core.InboundHandlerConfig)) 180 })) 181 }