mirror of
https://github.com/Sagit-chu/flvx.git
synced 2026-10-03 01:06:36 +08:00
chore: remove mobile wrappers and harden go-backend service control
This commit is contained in:
@@ -238,6 +238,7 @@ func (h *Handler) resolveUserTunnelAndLimiter(userID, tunnelID int64) (int64, *i
|
||||
FROM user_tunnel ut
|
||||
LEFT JOIN speed_limit sl ON sl.id = ut.speed_id
|
||||
WHERE ut.user_id = ? AND ut.tunnel_id = ?
|
||||
ORDER BY ut.id ASC
|
||||
LIMIT 1
|
||||
`, userID, tunnelID)
|
||||
var userTunnelID int64
|
||||
@@ -256,6 +257,32 @@ func (h *Handler) resolveUserTunnelAndLimiter(userID, tunnelID int64) (int64, *i
|
||||
return userTunnelID, &v, nil
|
||||
}
|
||||
|
||||
func (h *Handler) listUserTunnelIDs(userID, tunnelID int64) ([]int64, error) {
|
||||
rows, err := h.repo.DB().Query(`
|
||||
SELECT id
|
||||
FROM user_tunnel
|
||||
WHERE user_id = ? AND tunnel_id = ?
|
||||
ORDER BY id ASC
|
||||
`, userID, tunnelID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
out := make([]int64, 0)
|
||||
for rows.Next() {
|
||||
var id int64
|
||||
if err := rows.Scan(&id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, id)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (h *Handler) syncForwardServices(forward *forwardRecord, method string, allowFallbackAdd bool) error {
|
||||
if h == nil || forward == nil {
|
||||
return errors.New("invalid forward sync context")
|
||||
@@ -311,20 +338,62 @@ func (h *Handler) controlForwardServices(forward *forwardRecord, commandType str
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
base := buildForwardServiceBase(forward.ID, forward.UserID, userTunnelID)
|
||||
payload := map[string]interface{}{
|
||||
"services": buildForwardControlServiceNames(base, commandType),
|
||||
userTunnelIDs, err := h.listUserTunnelIDs(forward.UserID, forward.TunnelID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bases := buildForwardServiceBaseCandidates(forward.ID, forward.UserID, userTunnelID, userTunnelIDs)
|
||||
seen := map[int64]struct{}{}
|
||||
for _, fp := range ports {
|
||||
if _, ok := seen[fp.NodeID]; ok {
|
||||
continue
|
||||
}
|
||||
seen[fp.NodeID] = struct{}{}
|
||||
_, err := h.sendNodeCommand(fp.NodeID, commandType, payload, false, tolerateNotFound)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
var lastNotFoundErr error
|
||||
nodeHandled := false
|
||||
|
||||
for _, base := range bases {
|
||||
payload := map[string]interface{}{
|
||||
"services": buildForwardControlServiceNames(base, commandType),
|
||||
}
|
||||
_, err := h.sendNodeCommand(fp.NodeID, commandType, payload, false, false)
|
||||
if err == nil {
|
||||
nodeHandled = true
|
||||
break
|
||||
}
|
||||
|
||||
if !isNotFoundError(err) {
|
||||
return err
|
||||
}
|
||||
lastNotFoundErr = err
|
||||
|
||||
if shouldTryLegacySingleService(commandType) {
|
||||
legacyPayload := map[string]interface{}{
|
||||
"services": []string{base},
|
||||
}
|
||||
_, legacyErr := h.sendNodeCommand(fp.NodeID, commandType, legacyPayload, false, false)
|
||||
if legacyErr == nil {
|
||||
nodeHandled = true
|
||||
break
|
||||
}
|
||||
if !isNotFoundError(legacyErr) {
|
||||
return legacyErr
|
||||
}
|
||||
lastNotFoundErr = legacyErr
|
||||
}
|
||||
}
|
||||
|
||||
if nodeHandled {
|
||||
continue
|
||||
}
|
||||
if tolerateNotFound {
|
||||
continue
|
||||
}
|
||||
if lastNotFoundErr != nil {
|
||||
return lastNotFoundErr
|
||||
}
|
||||
return errors.New("service control failed")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -852,6 +921,31 @@ func buildForwardServiceBase(forwardID, userID, userTunnelID int64) string {
|
||||
return fmt.Sprintf("%d_%d_%d", forwardID, userID, userTunnelID)
|
||||
}
|
||||
|
||||
func buildForwardServiceBaseCandidates(forwardID, userID, preferredUserTunnelID int64, userTunnelIDs []int64) []string {
|
||||
orderedIDs := make([]int64, 0, len(userTunnelIDs)+2)
|
||||
seen := make(map[int64]struct{}, len(userTunnelIDs)+2)
|
||||
|
||||
appendID := func(id int64) {
|
||||
if _, ok := seen[id]; ok {
|
||||
return
|
||||
}
|
||||
seen[id] = struct{}{}
|
||||
orderedIDs = append(orderedIDs, id)
|
||||
}
|
||||
|
||||
appendID(preferredUserTunnelID)
|
||||
for _, id := range userTunnelIDs {
|
||||
appendID(id)
|
||||
}
|
||||
appendID(0)
|
||||
|
||||
bases := make([]string, 0, len(orderedIDs))
|
||||
for _, id := range orderedIDs {
|
||||
bases = append(bases, buildForwardServiceBase(forwardID, userID, id))
|
||||
}
|
||||
return bases
|
||||
}
|
||||
|
||||
func buildForwardControlServiceNames(base, commandType string) []string {
|
||||
names := []string{base + "_tcp", base + "_udp"}
|
||||
if strings.EqualFold(strings.TrimSpace(commandType), "DeleteService") {
|
||||
@@ -860,6 +954,19 @@ func buildForwardControlServiceNames(base, commandType string) []string {
|
||||
return names
|
||||
}
|
||||
|
||||
func shouldTryLegacySingleService(commandType string) bool {
|
||||
cmd := strings.ToLower(strings.TrimSpace(commandType))
|
||||
return cmd == "pauseservice" || cmd == "resumeservice"
|
||||
}
|
||||
|
||||
func isNotFoundError(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
msg := strings.ToLower(strings.TrimSpace(err.Error()))
|
||||
return strings.Contains(msg, "not found") || strings.Contains(msg, "不存在")
|
||||
}
|
||||
|
||||
func buildForwardServiceConfigs(baseName string, forward *forwardRecord, tunnel *tunnelRecord, node *nodeRecord, port int, limiter *int) []map[string]interface{} {
|
||||
protocols := []string{"tcp", "udp"}
|
||||
services := make([]map[string]interface{}, 0, 2)
|
||||
|
||||
@@ -25,3 +25,31 @@ func TestBuildForwardControlServiceNamesDelete(t *testing.T) {
|
||||
t.Fatalf("expected %v, got %v", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildForwardServiceBaseCandidates(t *testing.T) {
|
||||
got := buildForwardServiceBaseCandidates(12, 34, 56, []int64{56, 78, 90})
|
||||
want := []string{"12_34_56", "12_34_78", "12_34_90", "12_34_0"}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("expected %v, got %v", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildForwardServiceBaseCandidatesWithZeroPreferred(t *testing.T) {
|
||||
got := buildForwardServiceBaseCandidates(12, 34, 0, []int64{78, 0, 90})
|
||||
want := []string{"12_34_0", "12_34_78", "12_34_90"}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("expected %v, got %v", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShouldTryLegacySingleService(t *testing.T) {
|
||||
if !shouldTryLegacySingleService("PauseService") {
|
||||
t.Fatalf("PauseService should require legacy fallback")
|
||||
}
|
||||
if !shouldTryLegacySingleService("resumeService") {
|
||||
t.Fatalf("ResumeService should require legacy fallback")
|
||||
}
|
||||
if shouldTryLegacySingleService("DeleteService") {
|
||||
t.Fatalf("DeleteService should not require legacy fallback")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user