mirror of
https://github.com/Sagit-chu/flvx.git
synced 2026-10-06 18:06:36 +08:00
Merge branch 'main' into opencode/silent-wizard
This commit is contained in:
@@ -59,6 +59,8 @@ type chainNodeRecord struct {
|
|||||||
NodeID int64
|
NodeID int64
|
||||||
Port int
|
Port int
|
||||||
NodeName string
|
NodeName string
|
||||||
|
Protocol string
|
||||||
|
Strategy string
|
||||||
}
|
}
|
||||||
|
|
||||||
type diagnosisTarget struct {
|
type diagnosisTarget struct {
|
||||||
@@ -862,7 +864,7 @@ func firstPortFromRange(portRange string) int {
|
|||||||
|
|
||||||
func (h *Handler) listChainNodesForTunnel(tunnelID int64) ([]chainNodeRecord, error) {
|
func (h *Handler) listChainNodesForTunnel(tunnelID int64) ([]chainNodeRecord, error) {
|
||||||
rows, err := h.repo.DB().Query(`
|
rows, err := h.repo.DB().Query(`
|
||||||
SELECT ct.chain_type, COALESCE(ct.inx, 0), ct.node_id, COALESCE(ct.port, 0), n.name
|
SELECT ct.chain_type, COALESCE(ct.inx, 0), ct.node_id, COALESCE(ct.port, 0), n.name, ct.protocol, ct.strategy
|
||||||
FROM chain_tunnel ct
|
FROM chain_tunnel ct
|
||||||
LEFT JOIN node n ON n.id = ct.node_id
|
LEFT JOIN node n ON n.id = ct.node_id
|
||||||
WHERE ct.tunnel_id = ?
|
WHERE ct.tunnel_id = ?
|
||||||
@@ -877,7 +879,9 @@ func (h *Handler) listChainNodesForTunnel(tunnelID int64) ([]chainNodeRecord, er
|
|||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var item chainNodeRecord
|
var item chainNodeRecord
|
||||||
var name sql.NullString
|
var name sql.NullString
|
||||||
if err := rows.Scan(&item.ChainType, &item.Inx, &item.NodeID, &item.Port, &name); err != nil {
|
var protocol sql.NullString
|
||||||
|
var strategy sql.NullString
|
||||||
|
if err := rows.Scan(&item.ChainType, &item.Inx, &item.NodeID, &item.Port, &name, &protocol, &strategy); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if strings.TrimSpace(name.String) == "" {
|
if strings.TrimSpace(name.String) == "" {
|
||||||
@@ -885,6 +889,8 @@ func (h *Handler) listChainNodesForTunnel(tunnelID int64) ([]chainNodeRecord, er
|
|||||||
} else {
|
} else {
|
||||||
item.NodeName = name.String
|
item.NodeName = name.String
|
||||||
}
|
}
|
||||||
|
item.Protocol = defaultString(protocol.String, "tls")
|
||||||
|
item.Strategy = defaultString(strategy.String, "round")
|
||||||
result = append(result, item)
|
result = append(result, item)
|
||||||
}
|
}
|
||||||
if err := rows.Err(); err != nil {
|
if err := rows.Err(); err != nil {
|
||||||
@@ -1039,7 +1045,10 @@ func buildForwardServiceConfigs(baseName string, forward *forwardRecord, tunnel
|
|||||||
service["metadata"] = map[string]interface{}{"interface": node.InterfaceName}
|
service["metadata"] = map[string]interface{}{"interface": node.InterfaceName}
|
||||||
}
|
}
|
||||||
if limiter != nil && *limiter > 0 {
|
if limiter != nil && *limiter > 0 {
|
||||||
service["limiter"] = strconv.Itoa(*limiter)
|
// Convert Mbps to Bytes/s
|
||||||
|
// 1 Mbps = 1,000,000 bits/s = 125,000 Bytes/s
|
||||||
|
// We use decimal Mbps standard as is common in networking
|
||||||
|
service["limiter"] = strconv.Itoa(*limiter * 125000)
|
||||||
}
|
}
|
||||||
services = append(services, service)
|
services = append(services, service)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -775,6 +775,82 @@ func (h *Handler) tunnelBatchDelete(w http.ResponseWriter, r *http.Request) {
|
|||||||
response.WriteJSON(w, response.OK(map[string]interface{}{"successCount": success, "failCount": fail}))
|
response.WriteJSON(w, response.OK(map[string]interface{}{"successCount": success, "failCount": fail}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Handler) reconstructTunnelState(tunnelID int64) (*tunnelCreateState, error) {
|
||||||
|
tunnel, err := h.getTunnelRecord(tunnelID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
chainRows, err := h.listChainNodesForTunnel(tunnelID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
state := &tunnelCreateState{
|
||||||
|
TunnelID: tunnelID,
|
||||||
|
Type: tunnel.Type,
|
||||||
|
InNodes: make([]tunnelRuntimeNode, 0),
|
||||||
|
ChainHops: make([][]tunnelRuntimeNode, 0),
|
||||||
|
OutNodes: make([]tunnelRuntimeNode, 0),
|
||||||
|
Nodes: make(map[int64]*nodeRecord),
|
||||||
|
NodeIDList: make([]int64, 0),
|
||||||
|
}
|
||||||
|
|
||||||
|
inNodes, chainHops, outNodes := splitChainNodeGroups(chainRows)
|
||||||
|
|
||||||
|
for _, r := range inNodes {
|
||||||
|
state.InNodes = append(state.InNodes, tunnelRuntimeNode{
|
||||||
|
NodeID: r.NodeID,
|
||||||
|
Protocol: r.Protocol,
|
||||||
|
Strategy: r.Strategy,
|
||||||
|
ChainType: 1,
|
||||||
|
})
|
||||||
|
state.NodeIDList = append(state.NodeIDList, r.NodeID)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, r := range outNodes {
|
||||||
|
state.OutNodes = append(state.OutNodes, tunnelRuntimeNode{
|
||||||
|
NodeID: r.NodeID,
|
||||||
|
Protocol: r.Protocol,
|
||||||
|
Strategy: r.Strategy,
|
||||||
|
ChainType: 3,
|
||||||
|
Port: r.Port,
|
||||||
|
})
|
||||||
|
state.NodeIDList = append(state.NodeIDList, r.NodeID)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, hop := range chainHops {
|
||||||
|
stateHop := make([]tunnelRuntimeNode, 0)
|
||||||
|
for _, r := range hop {
|
||||||
|
stateHop = append(stateHop, tunnelRuntimeNode{
|
||||||
|
NodeID: r.NodeID,
|
||||||
|
Protocol: r.Protocol,
|
||||||
|
Strategy: r.Strategy,
|
||||||
|
ChainType: 2,
|
||||||
|
Inx: int(r.Inx),
|
||||||
|
Port: r.Port,
|
||||||
|
})
|
||||||
|
state.NodeIDList = append(state.NodeIDList, r.NodeID)
|
||||||
|
}
|
||||||
|
state.ChainHops = append(state.ChainHops, stateHop)
|
||||||
|
}
|
||||||
|
|
||||||
|
seen := make(map[int64]struct{})
|
||||||
|
for _, id := range state.NodeIDList {
|
||||||
|
if _, ok := seen[id]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
seen[id] = struct{}{}
|
||||||
|
node, err := h.getNodeRecord(id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
state.Nodes[id] = node
|
||||||
|
}
|
||||||
|
|
||||||
|
return state, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Handler) tunnelBatchRedeploy(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) tunnelBatchRedeploy(w http.ResponseWriter, r *http.Request) {
|
||||||
ids := idsFromBody(r, w)
|
ids := idsFromBody(r, w)
|
||||||
if ids == nil {
|
if ids == nil {
|
||||||
@@ -783,6 +859,26 @@ func (h *Handler) tunnelBatchRedeploy(w http.ResponseWriter, r *http.Request) {
|
|||||||
success := 0
|
success := 0
|
||||||
fail := 0
|
fail := 0
|
||||||
for _, tunnelID := range ids {
|
for _, tunnelID := range ids {
|
||||||
|
tunnel, err := h.getTunnelRecord(tunnelID)
|
||||||
|
if err != nil {
|
||||||
|
fail++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if tunnel.Type == 2 {
|
||||||
|
h.cleanupTunnelRuntime(tunnelID)
|
||||||
|
state, err := h.reconstructTunnelState(tunnelID)
|
||||||
|
if err != nil {
|
||||||
|
fail++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
_, _, applyErr := h.applyTunnelRuntime(state)
|
||||||
|
if applyErr != nil {
|
||||||
|
fail++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
forwards, err := h.listForwardsByTunnel(tunnelID)
|
forwards, err := h.listForwardsByTunnel(tunnelID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fail++
|
fail++
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package service
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -30,6 +31,7 @@ import (
|
|||||||
logger_parser "github.com/go-gost/x/config/parsing/logger"
|
logger_parser "github.com/go-gost/x/config/parsing/logger"
|
||||||
selector_parser "github.com/go-gost/x/config/parsing/selector"
|
selector_parser "github.com/go-gost/x/config/parsing/selector"
|
||||||
tls_util "github.com/go-gost/x/internal/util/tls"
|
tls_util "github.com/go-gost/x/internal/util/tls"
|
||||||
|
xtraffic "github.com/go-gost/x/limiter/traffic"
|
||||||
cache_limiter "github.com/go-gost/x/limiter/traffic/cache"
|
cache_limiter "github.com/go-gost/x/limiter/traffic/cache"
|
||||||
"github.com/go-gost/x/metadata"
|
"github.com/go-gost/x/metadata"
|
||||||
mdutil "github.com/go-gost/x/metadata/util"
|
mdutil "github.com/go-gost/x/metadata/util"
|
||||||
@@ -181,6 +183,32 @@ func ParseService(cfg *config.ServiceConfig) (service.Service, error) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var trafficLimiter listener.Option
|
||||||
|
if cfg.Limiter != "" {
|
||||||
|
lim := registry.TrafficLimiterRegistry().Get(cfg.Limiter)
|
||||||
|
if lim == nil {
|
||||||
|
// Try to parse as simple number (bandwidth in bytes/sec)
|
||||||
|
if val, err := strconv.Atoi(cfg.Limiter); err == nil && val > 0 {
|
||||||
|
lim = xtraffic.NewTrafficLimiter(
|
||||||
|
xtraffic.LimitsOption(fmt.Sprintf("%s %dB %dB", xtraffic.ServiceLimitKey, val, val)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if lim == nil {
|
||||||
|
lim = xtraffic.NewTrafficLimiter(
|
||||||
|
xtraffic.LimitsOption(fmt.Sprintf("%s %s %s", xtraffic.ServiceLimitKey, cfg.Limiter, cfg.Limiter)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trafficLimiter = listener.TrafficLimiterOption(
|
||||||
|
cache_limiter.NewCachedTrafficLimiter(
|
||||||
|
lim,
|
||||||
|
cache_limiter.RefreshIntervalOption(limiterRefreshInterval),
|
||||||
|
cache_limiter.CleanupIntervalOption(limiterCleanupInterval),
|
||||||
|
cache_limiter.ScopeOption(limiterScope),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
listenOpts := []listener.Option{
|
listenOpts := []listener.Option{
|
||||||
listener.AddrOption(cfg.Addr),
|
listener.AddrOption(cfg.Addr),
|
||||||
listener.RouterOption(xchain.NewRouter(routerOpts...)),
|
listener.RouterOption(xchain.NewRouter(routerOpts...)),
|
||||||
@@ -188,14 +216,6 @@ func ParseService(cfg *config.ServiceConfig) (service.Service, error) {
|
|||||||
listener.AuthOption(auth_parser.Info(cfg.Listener.Auth)),
|
listener.AuthOption(auth_parser.Info(cfg.Listener.Auth)),
|
||||||
listener.TLSConfigOption(tlsConfig),
|
listener.TLSConfigOption(tlsConfig),
|
||||||
listener.AdmissionOption(xadmission.AdmissionGroup(admissions...)),
|
listener.AdmissionOption(xadmission.AdmissionGroup(admissions...)),
|
||||||
listener.TrafficLimiterOption(
|
|
||||||
cache_limiter.NewCachedTrafficLimiter(
|
|
||||||
registry.TrafficLimiterRegistry().Get(cfg.Limiter),
|
|
||||||
cache_limiter.RefreshIntervalOption(limiterRefreshInterval),
|
|
||||||
cache_limiter.CleanupIntervalOption(limiterCleanupInterval),
|
|
||||||
cache_limiter.ScopeOption(limiterScope),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
listener.ConnLimiterOption(registry.ConnLimiterRegistry().Get(cfg.CLimiter)),
|
listener.ConnLimiterOption(registry.ConnLimiterRegistry().Get(cfg.CLimiter)),
|
||||||
listener.ServiceOption(cfg.Name),
|
listener.ServiceOption(cfg.Name),
|
||||||
listener.ProxyProtocolOption(ppv),
|
listener.ProxyProtocolOption(ppv),
|
||||||
@@ -203,6 +223,9 @@ func ParseService(cfg *config.ServiceConfig) (service.Service, error) {
|
|||||||
listener.NetnsOption(netnsIn),
|
listener.NetnsOption(netnsIn),
|
||||||
listener.LoggerOption(listenerLogger),
|
listener.LoggerOption(listenerLogger),
|
||||||
}
|
}
|
||||||
|
if trafficLimiter != nil {
|
||||||
|
listenOpts = append(listenOpts, trafficLimiter)
|
||||||
|
}
|
||||||
|
|
||||||
if netnsIn != "" {
|
if netnsIn != "" {
|
||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
|
|||||||
@@ -136,6 +136,9 @@ func (l *trafficLimiter) In(ctx context.Context, key string, opts ...limiter.Opt
|
|||||||
return nil
|
return nil
|
||||||
|
|
||||||
case limiter.ScopeClient:
|
case limiter.ScopeClient:
|
||||||
|
if lim, ok := l.inLimits.Get(key); ok && lim != nil {
|
||||||
|
return lim.(traffic.Limiter)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
case limiter.ScopeConn:
|
case limiter.ScopeConn:
|
||||||
@@ -215,6 +218,9 @@ func (l *trafficLimiter) Out(ctx context.Context, key string, opts ...limiter.Op
|
|||||||
return nil
|
return nil
|
||||||
|
|
||||||
case limiter.ScopeClient:
|
case limiter.ScopeClient:
|
||||||
|
if lim, ok := l.outLimits.Get(key); ok && lim != nil {
|
||||||
|
return lim.(traffic.Limiter)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
case limiter.ScopeConn:
|
case limiter.ScopeConn:
|
||||||
|
|||||||
Reference in New Issue
Block a user