cache.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. package memconservative
  2. import (
  3. "os"
  4. "strings"
  5. "google.golang.org/protobuf/proto"
  6. "github.com/v2fly/v2ray-core/v5/app/router/routercommon"
  7. "github.com/v2fly/v2ray-core/v5/common/platform"
  8. )
  9. type GeoIPCache map[string]*routercommon.GeoIP
  10. func (g GeoIPCache) Has(key string) bool {
  11. return !(g.Get(key) == nil)
  12. }
  13. func (g GeoIPCache) Get(key string) *routercommon.GeoIP {
  14. if g == nil {
  15. return nil
  16. }
  17. return g[key]
  18. }
  19. func (g GeoIPCache) Set(key string, value *routercommon.GeoIP) {
  20. if g == nil {
  21. g = make(map[string]*routercommon.GeoIP)
  22. }
  23. g[key] = value
  24. }
  25. func (g GeoIPCache) Unmarshal(filename, code string) (*routercommon.GeoIP, error) {
  26. asset := platform.GetAssetLocation(filename)
  27. idx := strings.ToLower(asset + ":" + code)
  28. if g.Has(idx) {
  29. return g.Get(idx), nil
  30. }
  31. geoipBytes, err := Decode(asset, code)
  32. switch err {
  33. case nil:
  34. var geoip routercommon.GeoIP
  35. if err := proto.Unmarshal(geoipBytes, &geoip); err != nil {
  36. return nil, err
  37. }
  38. g.Set(idx, &geoip)
  39. return &geoip, nil
  40. case errCodeNotFound:
  41. return nil, newError("country code ", code, " not found in ", filename)
  42. case errFailedToReadBytes, errFailedToReadExpectedLenBytes,
  43. errInvalidGeodataFile, errInvalidGeodataVarintLength:
  44. newError("failed to decode geoip file: ", filename, ", fallback to the original ReadFile method")
  45. geoipBytes, err = os.ReadFile(asset)
  46. if err != nil {
  47. return nil, err
  48. }
  49. var geoipList routercommon.GeoIPList
  50. if err := proto.Unmarshal(geoipBytes, &geoipList); err != nil {
  51. return nil, err
  52. }
  53. for _, geoip := range geoipList.GetEntry() {
  54. if strings.EqualFold(code, geoip.GetCountryCode()) {
  55. g.Set(idx, geoip)
  56. return geoip, nil
  57. }
  58. }
  59. default:
  60. return nil, err
  61. }
  62. return nil, newError("country code ", code, " not found in ", filename)
  63. }
  64. type GeoSiteCache map[string]*routercommon.GeoSite
  65. func (g GeoSiteCache) Has(key string) bool {
  66. return !(g.Get(key) == nil)
  67. }
  68. func (g GeoSiteCache) Get(key string) *routercommon.GeoSite {
  69. if g == nil {
  70. return nil
  71. }
  72. return g[key]
  73. }
  74. func (g GeoSiteCache) Set(key string, value *routercommon.GeoSite) {
  75. if g == nil {
  76. g = make(map[string]*routercommon.GeoSite)
  77. }
  78. g[key] = value
  79. }
  80. func (g GeoSiteCache) Unmarshal(filename, code string) (*routercommon.GeoSite, error) {
  81. asset := platform.GetAssetLocation(filename)
  82. idx := strings.ToLower(asset + ":" + code)
  83. if g.Has(idx) {
  84. return g.Get(idx), nil
  85. }
  86. geositeBytes, err := Decode(asset, code)
  87. switch err {
  88. case nil:
  89. var geosite routercommon.GeoSite
  90. if err := proto.Unmarshal(geositeBytes, &geosite); err != nil {
  91. return nil, err
  92. }
  93. g.Set(idx, &geosite)
  94. return &geosite, nil
  95. case errCodeNotFound:
  96. return nil, newError("list ", code, " not found in ", filename)
  97. case errFailedToReadBytes, errFailedToReadExpectedLenBytes,
  98. errInvalidGeodataFile, errInvalidGeodataVarintLength:
  99. newError("failed to decode geoip file: ", filename, ", fallback to the original ReadFile method")
  100. geositeBytes, err = os.ReadFile(asset)
  101. if err != nil {
  102. return nil, err
  103. }
  104. var geositeList routercommon.GeoSiteList
  105. if err := proto.Unmarshal(geositeBytes, &geositeList); err != nil {
  106. return nil, err
  107. }
  108. for _, geosite := range geositeList.GetEntry() {
  109. if strings.EqualFold(code, geosite.GetCountryCode()) {
  110. g.Set(idx, geosite)
  111. return geosite, nil
  112. }
  113. }
  114. default:
  115. return nil, err
  116. }
  117. return nil, newError("list ", code, " not found in ", filename)
  118. }