cache.go 3.1 KB

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