geoip.go 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // Copyright 2018 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package dashboard
  17. import (
  18. "net"
  19. "time"
  20. "github.com/apilayer/freegeoip"
  21. )
  22. // geoDBInfo contains all the geographical information we could extract based on an IP
  23. // address.
  24. type geoDBInfo struct {
  25. Country struct {
  26. Names struct {
  27. English string `maxminddb:"en" json:"en,omitempty"`
  28. } `maxminddb:"names" json:"names,omitempty"`
  29. } `maxminddb:"country" json:"country,omitempty"`
  30. City struct {
  31. Names struct {
  32. English string `maxminddb:"en" json:"en,omitempty"`
  33. } `maxminddb:"names" json:"names,omitempty"`
  34. } `maxminddb:"city" json:"city,omitempty"`
  35. Location struct {
  36. Latitude float64 `maxminddb:"latitude" json:"latitude,omitempty"`
  37. Longitude float64 `maxminddb:"longitude" json:"longitude,omitempty"`
  38. } `maxminddb:"location" json:"location,omitempty"`
  39. }
  40. // geoLocation contains geographical information.
  41. type geoLocation struct {
  42. Country string `json:"country,omitempty"`
  43. City string `json:"city,omitempty"`
  44. Latitude float64 `json:"latitude,omitempty"`
  45. Longitude float64 `json:"longitude,omitempty"`
  46. }
  47. // geoDB represents a geoip database that can be queried for IP to geographical
  48. // information conversions.
  49. type geoDB struct {
  50. geodb *freegeoip.DB
  51. }
  52. // Open creates a new geoip database with an up-to-date database from the internet.
  53. func openGeoDB() (*geoDB, error) {
  54. // Initiate a geoip database to cross reference locations
  55. db, err := freegeoip.OpenURL(freegeoip.MaxMindDB, 24*time.Hour, time.Hour)
  56. if err != nil {
  57. return nil, err
  58. }
  59. // Wait until the database is updated to the latest data
  60. select {
  61. case <-db.NotifyOpen():
  62. case err := <-db.NotifyError():
  63. return nil, err
  64. }
  65. // Assemble and return our custom wrapper
  66. return &geoDB{geodb: db}, nil
  67. }
  68. // Close terminates the database background updater.
  69. func (db *geoDB) close() error {
  70. db.geodb.Close()
  71. return nil
  72. }
  73. // Lookup converts an IP address to a geographical location.
  74. func (db *geoDB) lookup(ip net.IP) *geoDBInfo {
  75. result := new(geoDBInfo)
  76. db.geodb.Lookup(ip, result)
  77. return result
  78. }
  79. // Location retrieves the geographical location of the given IP address.
  80. func (db *geoDB) location(ip string) *geoLocation {
  81. location := db.lookup(net.ParseIP(ip))
  82. return &geoLocation{
  83. Country: location.Country.Names.English,
  84. City: location.City.Names.English,
  85. Latitude: location.Location.Latitude,
  86. Longitude: location.Location.Longitude,
  87. }
  88. }