| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 | package coreimport (	"context"	"sync"	"v2ray.com/core/common"	"v2ray.com/core/common/errors"	"v2ray.com/core/common/net"	"v2ray.com/core/transport/ray")// Dispatcher is a feature that dispatches inbound requests to outbound handlers based on rules.// Dispatcher is required to be registered in a V2Ray instance to make V2Ray function properly.type Dispatcher interface {	Feature	// Dispatch returns a Ray for transporting data for the given request.	Dispatch(ctx context.Context, dest net.Destination) (ray.InboundRay, error)}type syncDispatcher struct {	sync.RWMutex	Dispatcher}func (d *syncDispatcher) Dispatch(ctx context.Context, dest net.Destination) (ray.InboundRay, error) {	d.RLock()	defer d.RUnlock()	if d.Dispatcher == nil {		return nil, newError("Dispatcher not set.").AtError()	}	return d.Dispatcher.Dispatch(ctx, dest)}func (d *syncDispatcher) Start() error {	d.RLock()	defer d.RUnlock()	if d.Dispatcher == nil {		return newError("Dispatcher not set.").AtError()	}	return d.Dispatcher.Start()}func (d *syncDispatcher) Close() error {	d.RLock()	defer d.RUnlock()	return common.Close(d.Dispatcher)}func (d *syncDispatcher) Set(disp Dispatcher) {	if disp == nil {		return	}	d.Close()	d.Lock()	defer d.Unlock()	d.Dispatcher = disp}var (	// ErrNoClue is for the situation that existing information is not enough to make a decision. For example, Router may return this error when there is no suitable route.	ErrNoClue = errors.New("not enough information for making a decision"))// Router is a feature to choose a outbound tag for the given request.type Router interface {	Feature	// PickRoute returns a tag of an OutboundHandler based on the given context.	PickRoute(ctx context.Context) (string, error)}type syncRouter struct {	sync.RWMutex	Router}func (r *syncRouter) PickRoute(ctx context.Context) (string, error) {	r.RLock()	defer r.RUnlock()	if r.Router == nil {		return "", ErrNoClue	}	return r.Router.PickRoute(ctx)}func (r *syncRouter) Start() error {	r.RLock()	defer r.RUnlock()	if r.Router == nil {		return nil	}	return r.Router.Start()}func (r *syncRouter) Close() error {	r.RLock()	defer r.RUnlock()	return common.Close(r.Router)}func (r *syncRouter) Set(router Router) {	if router == nil {		return	}	r.Close()	r.Lock()	defer r.Unlock()	r.Router = router}
 |