2018-01-10 06:22:37 -05:00
package core
import (
"context"
"sync"
2018-02-08 09:39:46 -05:00
"v2ray.com/core/common"
2018-04-16 18:31:10 -04:00
"v2ray.com/core/common/buf"
2018-01-10 06:22:37 -05:00
"v2ray.com/core/common/errors"
"v2ray.com/core/common/net"
)
2018-04-16 18:31:10 -04:00
// Link is a utility for connecting between an inbound and an outbound proxy handler.
type Link struct {
Reader buf . Reader
Writer buf . Writer
}
2018-01-10 06:22:37 -05:00
// 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.
2018-04-16 18:31:10 -04:00
Dispatch ( ctx context . Context , dest net . Destination ) ( * Link , error )
2018-01-10 06:22:37 -05:00
}
type syncDispatcher struct {
sync . RWMutex
Dispatcher
}
2018-04-16 18:31:10 -04:00
func ( d * syncDispatcher ) Dispatch ( ctx context . Context , dest net . Destination ) ( * Link , error ) {
2018-01-10 06:22:37 -05:00
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 ( )
}
2018-02-08 09:39:46 -05:00
func ( d * syncDispatcher ) Close ( ) error {
2018-01-10 06:22:37 -05:00
d . RLock ( )
defer d . RUnlock ( )
2018-02-08 09:39:46 -05:00
return common . Close ( d . Dispatcher )
2018-01-10 06:22:37 -05:00
}
func ( d * syncDispatcher ) Set ( disp Dispatcher ) {
2018-02-20 15:22:41 -05:00
if disp == nil {
return
}
2018-01-10 06:22:37 -05:00
d . Lock ( )
defer d . Unlock ( )
2018-02-20 16:07:58 -05:00
common . Close ( d . Dispatcher )
2018-01-10 06:22:37 -05:00
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" )
)
2018-03-25 21:47:45 -04:00
// Router is a feature to choose an outbound tag for the given request.
2018-01-10 06:22:37 -05:00
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 ( )
}
2018-02-08 09:39:46 -05:00
func ( r * syncRouter ) Close ( ) error {
2018-01-10 06:22:37 -05:00
r . RLock ( )
defer r . RUnlock ( )
2018-02-08 09:39:46 -05:00
return common . Close ( r . Router )
2018-01-10 06:22:37 -05:00
}
func ( r * syncRouter ) Set ( router Router ) {
2018-02-20 15:22:41 -05:00
if router == nil {
return
}
2018-01-10 06:22:37 -05:00
r . Lock ( )
defer r . Unlock ( )
2018-02-20 16:07:58 -05:00
common . Close ( r . Router )
2018-01-10 06:22:37 -05:00
r . Router = router
}