github.com/openethereum/go-ethereum@v1.9.7/dashboard/geoip.go (about) 1 // Copyright 2019 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 17 package dashboard 18 19 import ( 20 "net" 21 "time" 22 23 "github.com/apilayer/freegeoip" 24 ) 25 26 // geoDBInfo contains all the geographical information we could extract based on an IP 27 // address. 28 type geoDBInfo struct { 29 Country struct { 30 Names struct { 31 English string `maxminddb:"en" json:"en,omitempty"` 32 } `maxminddb:"names" json:"names,omitempty"` 33 } `maxminddb:"country" json:"country,omitempty"` 34 City struct { 35 Names struct { 36 English string `maxminddb:"en" json:"en,omitempty"` 37 } `maxminddb:"names" json:"names,omitempty"` 38 } `maxminddb:"city" json:"city,omitempty"` 39 Location struct { 40 Latitude float64 `maxminddb:"latitude" json:"latitude,omitempty"` 41 Longitude float64 `maxminddb:"longitude" json:"longitude,omitempty"` 42 } `maxminddb:"location" json:"location,omitempty"` 43 } 44 45 // geoLocation contains geographical information. 46 type geoLocation struct { 47 Country string `json:"country,omitempty"` 48 City string `json:"city,omitempty"` 49 Latitude float64 `json:"latitude,omitempty"` 50 Longitude float64 `json:"longitude,omitempty"` 51 } 52 53 // geoDB represents a geoip database that can be queried for IP to geographical 54 // information conversions. 55 type geoDB struct { 56 geodb *freegeoip.DB 57 } 58 59 // Open creates a new geoip database with an up-to-date database from the internet. 60 func openGeoDB() (*geoDB, error) { 61 // Initiate a geoip database to cross reference locations 62 db, err := freegeoip.OpenURL(freegeoip.MaxMindDB, 24*time.Hour, time.Hour) 63 if err != nil { 64 return nil, err 65 } 66 // Wait until the database is updated to the latest data 67 select { 68 case <-db.NotifyOpen(): 69 case err := <-db.NotifyError(): 70 return nil, err 71 } 72 // Assemble and return our custom wrapper 73 return &geoDB{geodb: db}, nil 74 } 75 76 // Close terminates the database background updater. 77 func (db *geoDB) close() error { 78 db.geodb.Close() 79 return nil 80 } 81 82 // Lookup converts an IP address to a geographical location. 83 func (db *geoDB) lookup(ip net.IP) *geoDBInfo { 84 result := new(geoDBInfo) 85 db.geodb.Lookup(ip, result) 86 return result 87 } 88 89 // Location retrieves the geographical location of the given IP address. 90 func (db *geoDB) location(ip string) *geoLocation { 91 location := db.lookup(net.ParseIP(ip)) 92 return &geoLocation{ 93 Country: location.Country.Names.English, 94 City: location.City.Names.English, 95 Latitude: location.Location.Latitude, 96 Longitude: location.Location.Longitude, 97 } 98 }