parser.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. package provider
  2. import (
  3. "errors"
  4. "fmt"
  5. "time"
  6. "github.com/metacubex/mihomo/common/structure"
  7. "github.com/metacubex/mihomo/common/utils"
  8. "github.com/metacubex/mihomo/component/resource"
  9. C "github.com/metacubex/mihomo/constant"
  10. types "github.com/metacubex/mihomo/constant/provider"
  11. )
  12. var (
  13. errVehicleType = errors.New("unsupport vehicle type")
  14. errSubPath = errors.New("path is not subpath of home directory")
  15. )
  16. type healthCheckSchema struct {
  17. Enable bool `provider:"enable"`
  18. URL string `provider:"url"`
  19. Interval int `provider:"interval"`
  20. TestTimeout int `provider:"timeout,omitempty"`
  21. Lazy bool `provider:"lazy,omitempty"`
  22. ExpectedStatus string `provider:"expected-status,omitempty"`
  23. }
  24. type OverrideSchema struct {
  25. TFO *bool `provider:"tfo,omitempty"`
  26. MPTcp *bool `provider:"mptcp,omitempty"`
  27. UDP *bool `provider:"udp,omitempty"`
  28. UDPOverTCP *bool `provider:"udp-over-tcp,omitempty"`
  29. Up *string `provider:"up,omitempty"`
  30. Down *string `provider:"down,omitempty"`
  31. DialerProxy *string `provider:"dialer-proxy,omitempty"`
  32. SkipCertVerify *bool `provider:"skip-cert-verify,omitempty"`
  33. Interface *string `provider:"interface-name,omitempty"`
  34. RoutingMark *int `provider:"routing-mark,omitempty"`
  35. IPVersion *string `provider:"ip-version,omitempty"`
  36. AdditionalPrefix *string `provider:"additional-prefix,omitempty"`
  37. AdditionalSuffix *string `provider:"additional-suffix,omitempty"`
  38. }
  39. type proxyProviderSchema struct {
  40. Type string `provider:"type"`
  41. Path string `provider:"path,omitempty"`
  42. URL string `provider:"url,omitempty"`
  43. Proxy string `provider:"proxy,omitempty"`
  44. Interval int `provider:"interval,omitempty"`
  45. Filter string `provider:"filter,omitempty"`
  46. ExcludeFilter string `provider:"exclude-filter,omitempty"`
  47. ExcludeType string `provider:"exclude-type,omitempty"`
  48. DialerProxy string `provider:"dialer-proxy,omitempty"`
  49. HealthCheck healthCheckSchema `provider:"health-check,omitempty"`
  50. Override OverrideSchema `provider:"override,omitempty"`
  51. Header map[string][]string `provider:"header,omitempty"`
  52. }
  53. func ParseProxyProvider(name string, mapping map[string]any) (types.ProxyProvider, error) {
  54. decoder := structure.NewDecoder(structure.Option{TagName: "provider", WeaklyTypedInput: true})
  55. schema := &proxyProviderSchema{
  56. HealthCheck: healthCheckSchema{
  57. Lazy: true,
  58. },
  59. }
  60. if err := decoder.Decode(mapping, schema); err != nil {
  61. return nil, err
  62. }
  63. expectedStatus, err := utils.NewUnsignedRanges[uint16](schema.HealthCheck.ExpectedStatus)
  64. if err != nil {
  65. return nil, err
  66. }
  67. var hcInterval uint
  68. if schema.HealthCheck.Enable {
  69. if schema.HealthCheck.Interval == 0 {
  70. schema.HealthCheck.Interval = 300
  71. }
  72. hcInterval = uint(schema.HealthCheck.Interval)
  73. }
  74. hc := NewHealthCheck([]C.Proxy{}, schema.HealthCheck.URL, uint(schema.HealthCheck.TestTimeout), hcInterval, schema.HealthCheck.Lazy, expectedStatus)
  75. var vehicle types.Vehicle
  76. switch schema.Type {
  77. case "file":
  78. path := C.Path.Resolve(schema.Path)
  79. vehicle = resource.NewFileVehicle(path)
  80. case "http":
  81. path := C.Path.GetPathByHash("proxies", schema.URL)
  82. if schema.Path != "" {
  83. path = C.Path.Resolve(schema.Path)
  84. if !C.Path.IsSafePath(path) {
  85. return nil, fmt.Errorf("%w: %s", errSubPath, path)
  86. }
  87. }
  88. vehicle = resource.NewHTTPVehicle(schema.URL, path, schema.Proxy, schema.Header)
  89. default:
  90. return nil, fmt.Errorf("%w: %s", errVehicleType, schema.Type)
  91. }
  92. interval := time.Duration(uint(schema.Interval)) * time.Second
  93. filter := schema.Filter
  94. excludeFilter := schema.ExcludeFilter
  95. excludeType := schema.ExcludeType
  96. dialerProxy := schema.DialerProxy
  97. override := schema.Override
  98. return NewProxySetProvider(name, interval, filter, excludeFilter, excludeType, dialerProxy, override, vehicle, hc)
  99. }