geoip.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. package targeting
  2. import (
  3. "log"
  4. "math"
  5. "net"
  6. "strings"
  7. "time"
  8. "github.com/abh/geodns/countries"
  9. "github.com/abh/geoip"
  10. "github.com/golang/geo/s2"
  11. )
  12. type GeoIPData struct {
  13. country *geoip.GeoIP
  14. hasCountry bool
  15. countryLastLoad time.Time
  16. city *geoip.GeoIP
  17. cityLastLoad time.Time
  18. hasCity bool
  19. asn *geoip.GeoIP
  20. hasAsn bool
  21. asnLastLoad time.Time
  22. }
  23. const MAX_DISTANCE = 360
  24. type Location struct {
  25. Latitude float64
  26. Longitude float64
  27. }
  28. func (l *Location) MaxDistance() float64 {
  29. return MAX_DISTANCE
  30. }
  31. func (l *Location) Distance(to *Location) float64 {
  32. if to == nil {
  33. return MAX_DISTANCE
  34. }
  35. ll1 := s2.LatLngFromDegrees(l.Latitude, l.Longitude)
  36. ll2 := s2.LatLngFromDegrees(to.Latitude, to.Longitude)
  37. angle := ll1.Distance(ll2)
  38. return math.Abs(angle.Degrees())
  39. }
  40. var geoIP = &GeoIPData{}
  41. func GeoIP() *GeoIPData {
  42. // mutex this and allow it to reload as needed?
  43. return geoIP
  44. }
  45. func (g *GeoIPData) GetCountry(ip net.IP) (country, continent string, netmask int) {
  46. if g.country == nil {
  47. return "", "", 0
  48. }
  49. country, netmask = g.country.GetCountry(ip.String())
  50. if len(country) > 0 {
  51. country = strings.ToLower(country)
  52. continent = countries.CountryContinent[country]
  53. }
  54. return
  55. }
  56. func (g *GeoIPData) GetCountryRegion(ip net.IP) (country, continent, regionGroup, region string, netmask int, location *Location) {
  57. if g.city == nil {
  58. log.Println("No city database available")
  59. country, continent, netmask = g.GetCountry(ip)
  60. return
  61. }
  62. record := g.city.GetRecord(ip.String())
  63. if record == nil {
  64. return
  65. }
  66. location = &Location{float64(record.Latitude), float64(record.Longitude)}
  67. country = record.CountryCode
  68. region = record.Region
  69. if len(country) > 0 {
  70. country = strings.ToLower(country)
  71. continent = countries.CountryContinent[country]
  72. if len(region) > 0 {
  73. region = country + "-" + strings.ToLower(region)
  74. regionGroup = countries.CountryRegionGroup(country, region)
  75. }
  76. }
  77. return
  78. }
  79. func (g *GeoIPData) GetASN(ip net.IP) (asn string, netmask int) {
  80. if g.asn == nil {
  81. log.Println("No asn database available")
  82. return
  83. }
  84. name, netmask := g.asn.GetName(ip.String())
  85. if len(name) > 0 {
  86. index := strings.Index(name, " ")
  87. if index > 0 {
  88. asn = strings.ToLower(name[:index])
  89. }
  90. }
  91. return
  92. }
  93. func (g *GeoIPData) SetDirectory(directory string) {
  94. // directory := Config.GeoIPDataDirectory()
  95. if len(directory) > 0 {
  96. geoip.SetCustomDirectory(directory)
  97. }
  98. }
  99. func (g *GeoIPData) SetupGeoIPCountry() {
  100. if g.country != nil {
  101. return
  102. }
  103. gi, err := geoip.OpenType(geoip.GEOIP_COUNTRY_EDITION)
  104. if gi == nil || err != nil {
  105. log.Printf("Could not open country GeoIPData database: %s\n", err)
  106. return
  107. }
  108. g.countryLastLoad = time.Now()
  109. g.hasCity = true
  110. g.country = gi
  111. }
  112. func (g *GeoIPData) SetupGeoIPCity() {
  113. if g.city != nil {
  114. return
  115. }
  116. gi, err := geoip.OpenType(geoip.GEOIP_CITY_EDITION_REV1)
  117. if gi == nil || err != nil {
  118. log.Printf("Could not open city GeoIPData database: %s\n", err)
  119. return
  120. }
  121. g.cityLastLoad = time.Now()
  122. g.hasCity = true
  123. g.city = gi
  124. }
  125. func (g *GeoIPData) SetupGeoIPASN() {
  126. if g.asn != nil {
  127. return
  128. }
  129. gi, err := geoip.OpenType(geoip.GEOIP_ASNUM_EDITION)
  130. if gi == nil || err != nil {
  131. log.Printf("Could not open ASN GeoIPData database: %s\n", err)
  132. return
  133. }
  134. g.asnLastLoad = time.Now()
  135. g.hasAsn = true
  136. g.asn = gi
  137. }