mirror of
				https://github.com/v2fly/v2ray-core.git
				synced 2025-11-03 19:29:22 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			116 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			116 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package core
 | 
						|
 | 
						|
import (
 | 
						|
	"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) {
 | 
						|
	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) {
 | 
						|
	r.Lock()
 | 
						|
	defer r.Unlock()
 | 
						|
 | 
						|
	r.Router = router
 | 
						|
}
 |