udphop.go 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. package maskcompat
  2. import "strings"
  3. // UpgradeLegacyUDPHop moves the quicParams.udpHop range xray-core 26.9.9 stopped reading
  4. // into the client-only "udphop" UDP mask, whose intervalRemote mode is what the key did.
  5. func UpgradeLegacyUDPHop(finalmask any) bool {
  6. fm, _ := finalmask.(map[string]any)
  7. quicParams, _ := fm["quicParams"].(map[string]any)
  8. legacy, found := quicParams["udpHop"]
  9. if !found {
  10. return false
  11. }
  12. delete(quicParams, "udpHop")
  13. if len(quicParams) == 0 {
  14. delete(fm, "quicParams")
  15. }
  16. hop, _ := legacy.(map[string]any)
  17. ports := hop["ports"]
  18. if isEmptyHopValue(ports) || hasUDPHopMask(fm) {
  19. return true
  20. }
  21. settings := map[string]any{"mode": "intervalRemote", "remotePorts": ports}
  22. if interval := hop["interval"]; !isEmptyHopValue(interval) {
  23. settings["interval"] = interval
  24. }
  25. masks, _ := fm["udp"].([]any)
  26. fm["udp"] = append(masks, map[string]any{"type": "udphop", "settings": settings})
  27. return true
  28. }
  29. func hasUDPHopMask(fm map[string]any) bool {
  30. masks, _ := fm["udp"].([]any)
  31. for _, entry := range masks {
  32. mask, _ := entry.(map[string]any)
  33. if maskType, _ := mask["type"].(string); strings.EqualFold(maskType, "udphop") {
  34. return true
  35. }
  36. }
  37. return false
  38. }
  39. func isEmptyHopValue(value any) bool {
  40. switch v := value.(type) {
  41. case nil:
  42. return true
  43. case string:
  44. return strings.TrimSpace(v) == ""
  45. case float64:
  46. return v == 0
  47. }
  48. return false
  49. }