mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-05-27 14:43:00 +03:00
Add new admin panel, failover, dns fallback, providers, limiters. Update XHTTP
This commit is contained in:
@@ -3,8 +3,6 @@ package bandwidth
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
"golang.org/x/time/rate"
|
||||
)
|
||||
|
||||
type connWithDownloadBandwidthLimiter struct {
|
||||
@@ -13,7 +11,7 @@ type connWithDownloadBandwidthLimiter struct {
|
||||
limiter Limiter
|
||||
}
|
||||
|
||||
func NewConnWithDownloadBandwidthLimiter(ctx context.Context, conn net.Conn, limiter *rate.Limiter) *connWithDownloadBandwidthLimiter {
|
||||
func NewConnWithDownloadBandwidthLimiter(ctx context.Context, conn net.Conn, limiter Limiter) *connWithDownloadBandwidthLimiter {
|
||||
return &connWithDownloadBandwidthLimiter{conn, ctx, limiter}
|
||||
}
|
||||
|
||||
@@ -28,12 +26,11 @@ func (conn *connWithDownloadBandwidthLimiter) Write(p []byte) (n int, err error)
|
||||
type connWithUploadBandwidthLimiter struct {
|
||||
net.Conn
|
||||
ctx context.Context
|
||||
limiter *rate.Limiter
|
||||
burst int
|
||||
limiter Limiter
|
||||
}
|
||||
|
||||
func NewConnWithUploadBandwidthLimiter(ctx context.Context, conn net.Conn, limiter *rate.Limiter) *connWithUploadBandwidthLimiter {
|
||||
return &connWithUploadBandwidthLimiter{conn, ctx, limiter, limiter.Burst()}
|
||||
func NewConnWithUploadBandwidthLimiter(ctx context.Context, conn net.Conn, limiter Limiter) *connWithUploadBandwidthLimiter {
|
||||
return &connWithUploadBandwidthLimiter{conn, ctx, limiter}
|
||||
}
|
||||
|
||||
func (conn *connWithUploadBandwidthLimiter) Read(p []byte) (n int, err error) {
|
||||
@@ -65,12 +62,11 @@ func (conn *connWithCloseHandler) Close() error {
|
||||
type packetConnWithDownloadBandwidthLimiter struct {
|
||||
net.PacketConn
|
||||
ctx context.Context
|
||||
limiter *rate.Limiter
|
||||
burst int
|
||||
limiter Limiter
|
||||
}
|
||||
|
||||
func NewPacketConnWithDownloadBandwidthLimiter(ctx context.Context, conn net.PacketConn, limiter *rate.Limiter) *packetConnWithDownloadBandwidthLimiter {
|
||||
return &packetConnWithDownloadBandwidthLimiter{conn, ctx, limiter, limiter.Burst()}
|
||||
func NewPacketConnWithDownloadBandwidthLimiter(ctx context.Context, conn net.PacketConn, limiter Limiter) *packetConnWithDownloadBandwidthLimiter {
|
||||
return &packetConnWithDownloadBandwidthLimiter{conn, ctx, limiter}
|
||||
}
|
||||
|
||||
func (conn *packetConnWithDownloadBandwidthLimiter) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||
@@ -85,11 +81,10 @@ type packetConnWithUploadBandwidthLimiter struct {
|
||||
net.PacketConn
|
||||
ctx context.Context
|
||||
limiter Limiter
|
||||
burst int
|
||||
}
|
||||
|
||||
func NewPacketConnWithUploadBandwidthLimiter(ctx context.Context, conn net.PacketConn, limiter *rate.Limiter) *packetConnWithUploadBandwidthLimiter {
|
||||
return &packetConnWithUploadBandwidthLimiter{conn, ctx, limiter, limiter.Burst()}
|
||||
func NewPacketConnWithUploadBandwidthLimiter(ctx context.Context, conn net.PacketConn, limiter Limiter) *packetConnWithUploadBandwidthLimiter {
|
||||
return &packetConnWithUploadBandwidthLimiter{conn, ctx, limiter}
|
||||
}
|
||||
|
||||
func (conn *packetConnWithUploadBandwidthLimiter) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
||||
@@ -117,3 +112,39 @@ func (conn *packetConnWithCloseHandler) Close() error {
|
||||
conn.onClose()
|
||||
return conn.PacketConn.Close()
|
||||
}
|
||||
|
||||
func connWithDownloadBandwidthWrapper(ctx context.Context, conn net.Conn, limiter Limiter, reverse bool) net.Conn {
|
||||
if reverse {
|
||||
return NewConnWithUploadBandwidthLimiter(ctx, conn, limiter)
|
||||
}
|
||||
return NewConnWithDownloadBandwidthLimiter(ctx, conn, limiter)
|
||||
}
|
||||
|
||||
func connWithUploadBandwidthWrapper(ctx context.Context, conn net.Conn, limiter Limiter, reverse bool) net.Conn {
|
||||
if reverse {
|
||||
return NewConnWithDownloadBandwidthLimiter(ctx, conn, limiter)
|
||||
}
|
||||
return NewConnWithUploadBandwidthLimiter(ctx, conn, limiter)
|
||||
}
|
||||
|
||||
func connWithBidirectionalBandwidthWrapper(ctx context.Context, conn net.Conn, limiter Limiter, reverse bool) net.Conn {
|
||||
return NewConnWithUploadBandwidthLimiter(ctx, NewConnWithDownloadBandwidthLimiter(ctx, conn, limiter), limiter)
|
||||
}
|
||||
|
||||
func packetConnWithDownloadBandwidthWrapper(ctx context.Context, conn net.PacketConn, limiter Limiter, reverse bool) net.PacketConn {
|
||||
if reverse {
|
||||
return NewPacketConnWithUploadBandwidthLimiter(ctx, conn, limiter)
|
||||
}
|
||||
return NewPacketConnWithDownloadBandwidthLimiter(ctx, conn, limiter)
|
||||
}
|
||||
|
||||
func packetConnWithUploadBandwidthWrapper(ctx context.Context, conn net.PacketConn, limiter Limiter, reverse bool) net.PacketConn {
|
||||
if reverse {
|
||||
return NewPacketConnWithDownloadBandwidthLimiter(ctx, conn, limiter)
|
||||
}
|
||||
return NewPacketConnWithUploadBandwidthLimiter(ctx, conn, limiter)
|
||||
}
|
||||
|
||||
func packetConnWithBidirectionalBandwidthWrapper(ctx context.Context, conn net.PacketConn, limiter Limiter, reverse bool) net.PacketConn {
|
||||
return NewPacketConnWithUploadBandwidthLimiter(ctx, NewPacketConnWithDownloadBandwidthLimiter(ctx, conn, limiter), limiter)
|
||||
}
|
||||
|
||||
@@ -2,8 +2,130 @@ package bandwidth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"slices"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
)
|
||||
|
||||
type Limiter interface {
|
||||
WaitN(ctx context.Context, n int) (err error)
|
||||
}
|
||||
|
||||
type FlowKeysLimiter struct {
|
||||
limiter Limiter
|
||||
connIDGetter ConnIDGetter
|
||||
|
||||
waits map[string][]*wait
|
||||
conns map[string]int
|
||||
queue chan struct{}
|
||||
reset time.Time
|
||||
|
||||
mtx sync.Mutex
|
||||
}
|
||||
|
||||
func NewFlowKeysLimiter(connIDGetter ConnIDGetter, limiter Limiter) *FlowKeysLimiter {
|
||||
return &FlowKeysLimiter{
|
||||
limiter: limiter,
|
||||
connIDGetter: connIDGetter,
|
||||
waits: make(map[string][]*wait),
|
||||
conns: make(map[string]int),
|
||||
queue: make(chan struct{}, 1),
|
||||
reset: time.Now().Add(time.Second),
|
||||
}
|
||||
}
|
||||
|
||||
func (l *FlowKeysLimiter) WaitN(ctx context.Context, n int) error {
|
||||
id, _ := l.connIDGetter(ctx, adapter.ContextFrom(ctx))
|
||||
mainWait := &wait{ctx, make(chan struct{}), n}
|
||||
l.mtx.Lock()
|
||||
if waits, ok := l.waits[id]; ok {
|
||||
l.waits[id] = append(waits, mainWait)
|
||||
} else {
|
||||
l.waits[id] = []*wait{mainWait}
|
||||
}
|
||||
l.mtx.Unlock()
|
||||
select {
|
||||
case l.queue <- struct{}{}:
|
||||
case <-mainWait.finish:
|
||||
return nil
|
||||
case <-ctx.Done():
|
||||
l.mtx.Lock()
|
||||
for i, wait := range l.waits[id] {
|
||||
if wait == mainWait {
|
||||
l.waits[id] = slices.Delete(l.waits[id], i, i+1)
|
||||
close(wait.finish)
|
||||
break
|
||||
}
|
||||
}
|
||||
l.mtx.Unlock()
|
||||
return ctx.Err()
|
||||
}
|
||||
for {
|
||||
if ctx.Err() != nil {
|
||||
l.mtx.Lock()
|
||||
for i, wait := range l.waits[id] {
|
||||
if wait == mainWait {
|
||||
l.waits[id] = slices.Delete(l.waits[id], i, i+1)
|
||||
close(wait.finish)
|
||||
break
|
||||
}
|
||||
}
|
||||
l.mtx.Unlock()
|
||||
<-l.queue
|
||||
return ctx.Err()
|
||||
}
|
||||
now := time.Now()
|
||||
if l.reset.Compare(now) == -1 {
|
||||
clear(l.conns)
|
||||
l.reset = now.Add(time.Second)
|
||||
}
|
||||
l.mtx.Lock()
|
||||
var minConnId string
|
||||
var minN int
|
||||
for connID, waits := range l.waits {
|
||||
if len(waits) == 0 {
|
||||
continue
|
||||
}
|
||||
if n, ok := l.conns[connID]; ok {
|
||||
if minConnId == "" {
|
||||
minConnId = connID
|
||||
minN = n
|
||||
continue
|
||||
}
|
||||
if n+waits[0].n < minN {
|
||||
minConnId = connID
|
||||
minN = n
|
||||
}
|
||||
} else {
|
||||
l.conns[connID] = 0
|
||||
minConnId = connID
|
||||
break
|
||||
}
|
||||
}
|
||||
minWait := l.waits[minConnId][0]
|
||||
l.waits[minConnId][0] = nil
|
||||
l.waits[minConnId] = l.waits[minConnId][1:]
|
||||
if len(l.waits) == 0 {
|
||||
delete(l.waits, minConnId)
|
||||
}
|
||||
l.mtx.Unlock()
|
||||
err := l.limiter.WaitN(ctx, minWait.n)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
l.conns[minConnId] = l.conns[minConnId] + minWait.n
|
||||
close(minWait.finish)
|
||||
if minWait == mainWait {
|
||||
<-l.queue
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type wait struct {
|
||||
ctx context.Context
|
||||
finish chan struct{}
|
||||
n int
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
|
||||
case "users":
|
||||
usersStrategies := make(map[string]BandwidthStrategy, len(options.Users))
|
||||
for _, user := range options.Users {
|
||||
userStrategy, err := CreateStrategy(user.Strategy, user.Mode, user.ConnectionType, options.Speed.Value())
|
||||
userStrategy, err := CreateStrategy(user.Strategy, user.Mode, user.ConnectionType, options.Speed.Value(), options.FlowKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -58,7 +58,7 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
|
||||
case "manager":
|
||||
strategy = NewManagerBandwidthStrategy()
|
||||
default:
|
||||
strategy, err = CreateStrategy(options.Strategy, options.Mode, options.ConnectionType, options.Speed.Value())
|
||||
strategy, err = CreateStrategy(options.Strategy, options.Mode, options.ConnectionType, options.Speed.Value(), options.FlowKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -118,9 +118,11 @@ func (h *Outbound) ListenPacket(ctx context.Context, destination M.Socksaddr) (n
|
||||
}
|
||||
|
||||
func (h *Outbound) NewConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) {
|
||||
ctx = adapter.WithContext(ctx, &metadata)
|
||||
conn, err := h.strategy.wrapConn(ctx, conn, &metadata, false)
|
||||
if err != nil {
|
||||
h.logger.ErrorContext(ctx, err)
|
||||
N.CloseOnHandshakeFailure(conn, onClose, err)
|
||||
return
|
||||
}
|
||||
metadata.Inbound = h.Tag()
|
||||
@@ -130,9 +132,11 @@ func (h *Outbound) NewConnectionEx(ctx context.Context, conn net.Conn, metadata
|
||||
}
|
||||
|
||||
func (h *Outbound) NewPacketConnectionEx(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) {
|
||||
ctx = adapter.WithContext(ctx, &metadata)
|
||||
packetConn, err := h.strategy.wrapPacketConn(ctx, bufio.NewNetPacketConn(conn), &metadata, false)
|
||||
if err != nil {
|
||||
h.logger.ErrorContext(ctx, err)
|
||||
N.CloseOnHandshakeFailure(conn, onClose, err)
|
||||
return
|
||||
}
|
||||
metadata.Inbound = h.Tag()
|
||||
|
||||
@@ -15,8 +15,8 @@ import (
|
||||
type (
|
||||
CloseHandlerFunc = func()
|
||||
ConnIDGetter = func(context.Context, *adapter.InboundContext) (string, bool)
|
||||
ConnWrapper = func(ctx context.Context, conn net.Conn, limiter *rate.Limiter, reverse bool) net.Conn
|
||||
PacketConnWrapper = func(ctx context.Context, conn net.PacketConn, limiter *rate.Limiter, reverse bool) net.PacketConn
|
||||
ConnWrapper = func(ctx context.Context, conn net.Conn, limiter Limiter, reverse bool) net.Conn
|
||||
PacketConnWrapper = func(ctx context.Context, conn net.PacketConn, limiter Limiter, reverse bool) net.PacketConn
|
||||
)
|
||||
|
||||
type BandwidthStrategy interface {
|
||||
@@ -25,7 +25,7 @@ type BandwidthStrategy interface {
|
||||
}
|
||||
|
||||
type BandwidthLimiterStrategy interface {
|
||||
getLimiter(ctx context.Context, metadata *adapter.InboundContext) (*rate.Limiter, CloseHandlerFunc, error)
|
||||
getLimiter(ctx context.Context, metadata *adapter.InboundContext) (Limiter, CloseHandlerFunc, error)
|
||||
}
|
||||
|
||||
type DefaultWrapStrategy struct {
|
||||
@@ -55,21 +55,25 @@ func (s *DefaultWrapStrategy) wrapPacketConn(ctx context.Context, conn net.Packe
|
||||
}
|
||||
|
||||
type GlobalBandwidthStrategy struct {
|
||||
limiter *rate.Limiter
|
||||
limiter Limiter
|
||||
}
|
||||
|
||||
func NewGlobalBandwidthStrategy(speed uint64) *GlobalBandwidthStrategy {
|
||||
return &GlobalBandwidthStrategy{
|
||||
limiter: createSpeedLimiter(speed),
|
||||
func NewGlobalBandwidthStrategy(speed uint64, flowKeys []string) (*GlobalBandwidthStrategy, error) {
|
||||
limiter, err := createSpeedLimiter(speed, flowKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &GlobalBandwidthStrategy{
|
||||
limiter: limiter,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *GlobalBandwidthStrategy) getLimiter(ctx context.Context, metadata *adapter.InboundContext) (*rate.Limiter, CloseHandlerFunc, error) {
|
||||
func (s *GlobalBandwidthStrategy) getLimiter(ctx context.Context, metadata *adapter.InboundContext) (Limiter, CloseHandlerFunc, error) {
|
||||
return s.limiter, func() {}, nil
|
||||
}
|
||||
|
||||
type idBandwidthLimiter struct {
|
||||
limiter *rate.Limiter
|
||||
limiter Limiter
|
||||
handles uint32
|
||||
}
|
||||
|
||||
@@ -77,18 +81,20 @@ type ConnectionBandwidthStrategy struct {
|
||||
limiters map[string]*idBandwidthLimiter
|
||||
connIDGetter ConnIDGetter
|
||||
speed uint64
|
||||
flowKeys []string
|
||||
mtx sync.Mutex
|
||||
}
|
||||
|
||||
func NewConnectionBandwidthStrategy(connIDGetter ConnIDGetter, speed uint64) *ConnectionBandwidthStrategy {
|
||||
func NewConnectionBandwidthStrategy(connIDGetter ConnIDGetter, speed uint64, flowKeys []string) *ConnectionBandwidthStrategy {
|
||||
return &ConnectionBandwidthStrategy{
|
||||
limiters: make(map[string]*idBandwidthLimiter),
|
||||
connIDGetter: connIDGetter,
|
||||
speed: speed,
|
||||
flowKeys: flowKeys,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ConnectionBandwidthStrategy) getLimiter(ctx context.Context, metadata *adapter.InboundContext) (*rate.Limiter, CloseHandlerFunc, error) {
|
||||
func (s *ConnectionBandwidthStrategy) getLimiter(ctx context.Context, metadata *adapter.InboundContext) (Limiter, CloseHandlerFunc, error) {
|
||||
s.mtx.Lock()
|
||||
defer s.mtx.Unlock()
|
||||
id, ok := s.connIDGetter(ctx, metadata)
|
||||
@@ -97,8 +103,12 @@ func (s *ConnectionBandwidthStrategy) getLimiter(ctx context.Context, metadata *
|
||||
}
|
||||
limiter, ok := s.limiters[id]
|
||||
if !ok {
|
||||
newLimiter, err := createSpeedLimiter(s.speed, s.flowKeys)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
limiter = &idBandwidthLimiter{
|
||||
limiter: createSpeedLimiter(s.speed),
|
||||
limiter: newLimiter,
|
||||
}
|
||||
s.limiters[id] = limiter
|
||||
}
|
||||
@@ -173,14 +183,37 @@ func (s *ManagerBandwidthStrategy) UpdateStrategies(strategies map[string]Bandwi
|
||||
s.strategies = strategies
|
||||
}
|
||||
|
||||
func CreateStrategy(strategy string, mode string, connectionType string, speed uint64) (BandwidthStrategy, error) {
|
||||
type BypassBandwidthStrategy struct{}
|
||||
|
||||
func NewBypassBandwidthStrategy() *BypassBandwidthStrategy {
|
||||
return &BypassBandwidthStrategy{}
|
||||
}
|
||||
|
||||
func (s *BypassBandwidthStrategy) wrapConn(ctx context.Context, conn net.Conn, metadata *adapter.InboundContext, reverse bool) (net.Conn, error) {
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func (s *BypassBandwidthStrategy) wrapPacketConn(ctx context.Context, conn net.PacketConn, metadata *adapter.InboundContext, reverse bool) (net.PacketConn, error) {
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func CreateStrategy(strategy string, mode string, connectionType string, speed uint64, flowKeys []string) (BandwidthStrategy, error) {
|
||||
var limiterStrategy BandwidthLimiterStrategy
|
||||
switch strategy {
|
||||
case "global":
|
||||
limiterStrategy = NewGlobalBandwidthStrategy(speed)
|
||||
var err error
|
||||
limiterStrategy, err = NewGlobalBandwidthStrategy(speed, flowKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case "connection":
|
||||
var connIDGetter ConnIDGetter
|
||||
switch connectionType {
|
||||
case "hwid":
|
||||
connIDGetter = func(ctx context.Context, metadata *adapter.InboundContext) (string, bool) {
|
||||
id, ok := ctx.Value("hwid").(string)
|
||||
return id, ok
|
||||
}
|
||||
case "mux":
|
||||
connIDGetter = func(ctx context.Context, metadata *adapter.InboundContext) (string, bool) {
|
||||
id, ok := log.MuxIDFromContext(ctx)
|
||||
@@ -189,19 +222,24 @@ func CreateStrategy(strategy string, mode string, connectionType string, speed u
|
||||
}
|
||||
return strconv.FormatUint(uint64(id.ID), 10), ok
|
||||
}
|
||||
case "hwid":
|
||||
connIDGetter = func(ctx context.Context, metadata *adapter.InboundContext) (string, bool) {
|
||||
id, ok := ctx.Value("hwid").(string)
|
||||
return id, ok
|
||||
}
|
||||
case "ip":
|
||||
case "source_ip":
|
||||
connIDGetter = func(ctx context.Context, metadata *adapter.InboundContext) (string, bool) {
|
||||
return metadata.Source.IPAddr().String(), true
|
||||
}
|
||||
case "default", "":
|
||||
connIDGetter = func(ctx context.Context, metadata *adapter.InboundContext) (string, bool) {
|
||||
id, ok := log.IDFromContext(ctx)
|
||||
if !ok {
|
||||
return "", ok
|
||||
}
|
||||
return strconv.FormatUint(uint64(id.ID), 10), ok
|
||||
}
|
||||
default:
|
||||
return nil, E.New("connection type not found: ", connectionType)
|
||||
}
|
||||
limiterStrategy = NewConnectionBandwidthStrategy(connIDGetter, speed)
|
||||
limiterStrategy = NewConnectionBandwidthStrategy(connIDGetter, speed, flowKeys)
|
||||
case "bypass":
|
||||
return NewBypassBandwidthStrategy(), nil
|
||||
default:
|
||||
return nil, E.New("strategy not found: ", strategy)
|
||||
}
|
||||
@@ -216,51 +254,55 @@ func CreateStrategy(strategy string, mode string, connectionType string, speed u
|
||||
case "upload":
|
||||
connWrapper = connWithUploadBandwidthWrapper
|
||||
packetConnWrapper = packetConnWithUploadBandwidthWrapper
|
||||
case "duplex":
|
||||
connWrapper = connWithDuplexBandwidthWrapper
|
||||
packetConnWrapper = packetConnWithDuplexBandwidthWrapper
|
||||
case "bidirectional":
|
||||
connWrapper = connWithBidirectionalBandwidthWrapper
|
||||
packetConnWrapper = packetConnWithBidirectionalBandwidthWrapper
|
||||
default:
|
||||
return nil, E.New("mode not found: ", mode)
|
||||
}
|
||||
return NewDefaultWrapStrategy(limiterStrategy, connWrapper, packetConnWrapper), nil
|
||||
}
|
||||
|
||||
func createSpeedLimiter(speed uint64) *rate.Limiter {
|
||||
return rate.NewLimiter(rate.Limit(float64(speed)), 65536)
|
||||
}
|
||||
|
||||
func connWithDownloadBandwidthWrapper(ctx context.Context, conn net.Conn, limiter *rate.Limiter, reverse bool) net.Conn {
|
||||
if reverse {
|
||||
return NewConnWithUploadBandwidthLimiter(ctx, conn, limiter)
|
||||
func createSpeedLimiter(speed uint64, flowKeys []string) (Limiter, error) {
|
||||
var limiter Limiter = rate.NewLimiter(rate.Limit(float64(speed)), 65536)
|
||||
for i := len(flowKeys) - 1; i >= 0; i-- {
|
||||
getter, err := flowKeysConnIDGetter(flowKeys[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
limiter = NewFlowKeysLimiter(getter, limiter)
|
||||
}
|
||||
return NewConnWithDownloadBandwidthLimiter(ctx, conn, limiter)
|
||||
return limiter, nil
|
||||
}
|
||||
|
||||
func connWithUploadBandwidthWrapper(ctx context.Context, conn net.Conn, limiter *rate.Limiter, reverse bool) net.Conn {
|
||||
if reverse {
|
||||
return NewConnWithDownloadBandwidthLimiter(ctx, conn, limiter)
|
||||
func flowKeysConnIDGetter(name string) (ConnIDGetter, error) {
|
||||
switch name {
|
||||
case "user":
|
||||
return func(ctx context.Context, metadata *adapter.InboundContext) (string, bool) {
|
||||
return metadata.User, true
|
||||
}, nil
|
||||
case "destination":
|
||||
return func(ctx context.Context, metadata *adapter.InboundContext) (string, bool) {
|
||||
return metadata.Destination.String(), true
|
||||
}, nil
|
||||
case "source_ip":
|
||||
return func(ctx context.Context, metadata *adapter.InboundContext) (string, bool) {
|
||||
return metadata.Source.IPAddr().String(), true
|
||||
}, nil
|
||||
case "hwid":
|
||||
return func(ctx context.Context, metadata *adapter.InboundContext) (string, bool) {
|
||||
id, ok := ctx.Value("hwid").(string)
|
||||
return id, ok
|
||||
}, nil
|
||||
case "mux":
|
||||
return func(ctx context.Context, metadata *adapter.InboundContext) (string, bool) {
|
||||
id, ok := log.MuxIDFromContext(ctx)
|
||||
if !ok {
|
||||
return "", ok
|
||||
}
|
||||
return strconv.FormatUint(uint64(id.ID), 10), ok
|
||||
}, nil
|
||||
default:
|
||||
return nil, E.New("flow key not found: ", name)
|
||||
}
|
||||
return NewConnWithUploadBandwidthLimiter(ctx, conn, limiter)
|
||||
}
|
||||
|
||||
func connWithDuplexBandwidthWrapper(ctx context.Context, conn net.Conn, limiter *rate.Limiter, reverse bool) net.Conn {
|
||||
return NewConnWithUploadBandwidthLimiter(ctx, NewConnWithDownloadBandwidthLimiter(ctx, conn, limiter), limiter)
|
||||
}
|
||||
|
||||
func packetConnWithDownloadBandwidthWrapper(ctx context.Context, conn net.PacketConn, limiter *rate.Limiter, reverse bool) net.PacketConn {
|
||||
if reverse {
|
||||
return NewPacketConnWithUploadBandwidthLimiter(ctx, conn, limiter)
|
||||
}
|
||||
return NewPacketConnWithDownloadBandwidthLimiter(ctx, conn, limiter)
|
||||
}
|
||||
|
||||
func packetConnWithUploadBandwidthWrapper(ctx context.Context, conn net.PacketConn, limiter *rate.Limiter, reverse bool) net.PacketConn {
|
||||
if reverse {
|
||||
return NewPacketConnWithDownloadBandwidthLimiter(ctx, conn, limiter)
|
||||
}
|
||||
return NewPacketConnWithUploadBandwidthLimiter(ctx, conn, limiter)
|
||||
}
|
||||
|
||||
func packetConnWithDuplexBandwidthWrapper(ctx context.Context, conn net.PacketConn, limiter *rate.Limiter, reverse bool) net.PacketConn {
|
||||
return NewPacketConnWithUploadBandwidthLimiter(ctx, NewPacketConnWithDownloadBandwidthLimiter(ctx, conn, limiter), limiter)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user