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  }