github.com/imannamdari/v2ray-core/v5@v5.0.5/app/proxyman/inbound/inbound.go (about)

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