github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/app/proxyman/inbound/inbound.go (about)

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