mirror of
https://github.com/v2fly/v2ray-core.git
synced 2025-12-27 12:35:21 -05:00
massive refactoring for interoperability
This commit is contained in:
118
router.go
Normal file
118
router.go
Normal file
@@ -0,0 +1,118 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"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() {
|
||||
d.RLock()
|
||||
defer d.RUnlock()
|
||||
|
||||
if d.Dispatcher != nil {
|
||||
d.Dispatcher.Close()
|
||||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
r.RLock()
|
||||
defer r.RUnlock()
|
||||
|
||||
if r.Router != nil {
|
||||
r.Router.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (r *syncRouter) Set(router Router) {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
r.Router = router
|
||||
}
|
||||
Reference in New Issue
Block a user