mirror of
https://github.com/octoleo/syncthing.git
synced 2024-12-23 11:28:59 +00:00
Godeps
This commit is contained in:
parent
dd364c962f
commit
bbe0d34f43
10
cmd/strelaypoolsrv/Godeps/Godeps.json
generated
10
cmd/strelaypoolsrv/Godeps/Godeps.json
generated
@ -29,6 +29,16 @@
|
|||||||
"ImportPath": "github.com/juju/ratelimit",
|
"ImportPath": "github.com/juju/ratelimit",
|
||||||
"Rev": "772f5c38e468398c4511514f4f6aa9a4185bc0a0"
|
"Rev": "772f5c38e468398c4511514f4f6aa9a4185bc0a0"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/oschwald/geoip2-golang",
|
||||||
|
"Comment": "v0.1.0-28-gfe8132a",
|
||||||
|
"Rev": "fe8132a35233b371398441ab4c5655ae1244564a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/oschwald/maxminddb-golang",
|
||||||
|
"Comment": "v0.2.0-41-gcf814d2",
|
||||||
|
"Rev": "cf814d2e9ee3d6ef5b756c0696548eb2f5508e03"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/syncthing/syncthing/lib/dialer",
|
"ImportPath": "github.com/syncthing/syncthing/lib/dialer",
|
||||||
"Comment": "v0.12.6-6-g38e9b92",
|
"Comment": "v0.12.6-6-g38e9b92",
|
||||||
|
3
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/geoip2-golang/.gitmodules
generated
vendored
Normal file
3
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/geoip2-golang/.gitmodules
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "test-data"]
|
||||||
|
path = test-data
|
||||||
|
url = git://github.com/maxmind/MaxMind-DB.git
|
20
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/geoip2-golang/.travis.yml
generated
vendored
Normal file
20
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/geoip2-golang/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
language: go
|
||||||
|
|
||||||
|
go:
|
||||||
|
- 1.2
|
||||||
|
- 1.3
|
||||||
|
- 1.4
|
||||||
|
- 1.5
|
||||||
|
- 1.6
|
||||||
|
- tip
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- "if [[ $TRAVIS_GO_VERSION == 1.6 ]]; then go get -v github.com/golang/lint/golint; fi"
|
||||||
|
|
||||||
|
script:
|
||||||
|
- go test -race -cpu 1,4 -v
|
||||||
|
- go test -race -v -tags appengine
|
||||||
|
- "if [[ $TRAVIS_GO_VERSION == 1.6 ]]; then go vet ./...; fi"
|
||||||
|
- "if [[ $TRAVIS_GO_VERSION == 1.6 ]]; then golint .; fi"
|
||||||
|
|
||||||
|
sudo: false
|
13
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/geoip2-golang/LICENSE
generated
vendored
Normal file
13
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/geoip2-golang/LICENSE
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
Copyright (c) 2015, Gregory J. Oschwald <oschwald@gmail.com>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
PERFORMANCE OF THIS SOFTWARE.
|
90
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/geoip2-golang/README.md
generated
vendored
Normal file
90
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/geoip2-golang/README.md
generated
vendored
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
# GeoIP2 Reader for Go #
|
||||||
|
|
||||||
|
[![Build Status](https://travis-ci.org/oschwald/geoip2-golang.png?branch=master)](https://travis-ci.org/oschwald/geoip2-golang)
|
||||||
|
[![GoDoc](https://godoc.org/github.com/oschwald/geoip2-golang?status.png)](https://godoc.org/github.com/oschwald/geoip2-golang)
|
||||||
|
|
||||||
|
This library reads MaxMind [GeoLite2](http://dev.maxmind.com/geoip/geoip2/geolite2/)
|
||||||
|
and [GeoIP2](http://www.maxmind.com/en/geolocation_landing) databases.
|
||||||
|
|
||||||
|
This library is built using
|
||||||
|
[the Go maxminddb reader](https://github.com/oschwald/maxminddb-golang).
|
||||||
|
All data for the database record is decoded using this library. If you only
|
||||||
|
need several fields, you may get superior performance by using maxminddb's
|
||||||
|
`Lookup` directly with a result struct that only contains the required fields.
|
||||||
|
(See [example_test.go](https://github.com/oschwald/maxminddb-golang/blob/master/example_test.go)
|
||||||
|
in the maxminddb repository for an example of this.)
|
||||||
|
|
||||||
|
## Installation ##
|
||||||
|
|
||||||
|
```
|
||||||
|
go get github.com/oschwald/geoip2-golang
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage ##
|
||||||
|
|
||||||
|
[See GoDoc](http://godoc.org/github.com/oschwald/geoip2-golang) for
|
||||||
|
documentation and examples.
|
||||||
|
|
||||||
|
## Example ##
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/oschwald/geoip2-golang"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
db, err := geoip2.Open("GeoIP2-City.mmdb")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer db.Close()
|
||||||
|
// If you are using strings that may be invalid, check that ip is not nil
|
||||||
|
ip := net.ParseIP("81.2.69.142")
|
||||||
|
record, err := db.City(ip)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Portuguese (BR) city name: %v\n", record.City.Names["pt-BR"])
|
||||||
|
fmt.Printf("English subdivision name: %v\n", record.Subdivisions[0].Names["en"])
|
||||||
|
fmt.Printf("Russian country name: %v\n", record.Country.Names["ru"])
|
||||||
|
fmt.Printf("ISO country code: %v\n", record.Country.IsoCode)
|
||||||
|
fmt.Printf("Time zone: %v\n", record.Location.TimeZone)
|
||||||
|
fmt.Printf("Coordinates: %v, %v\n", record.Location.Latitude, record.Location.Longitude)
|
||||||
|
// Output:
|
||||||
|
// Portuguese (BR) city name: Londres
|
||||||
|
// English subdivision name: England
|
||||||
|
// Russian country name: Великобритания
|
||||||
|
// ISO country code: GB
|
||||||
|
// Time zone: Europe/London
|
||||||
|
// Coordinates: 51.5142, -0.0931
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing ##
|
||||||
|
|
||||||
|
Make sure you checked out test data submodule:
|
||||||
|
|
||||||
|
```
|
||||||
|
git submodule init
|
||||||
|
git submodule update
|
||||||
|
```
|
||||||
|
|
||||||
|
Execute test suite:
|
||||||
|
|
||||||
|
```
|
||||||
|
go test
|
||||||
|
```
|
||||||
|
|
||||||
|
## Contributing ##
|
||||||
|
|
||||||
|
Contributions welcome! Please fork the repository and open a pull request
|
||||||
|
with your changes.
|
||||||
|
|
||||||
|
## License ##
|
||||||
|
|
||||||
|
This is free software, licensed under the ISC license.
|
202
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/geoip2-golang/reader.go
generated
vendored
Normal file
202
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/geoip2-golang/reader.go
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
// Package geoip2 provides a wrapper around the maxminddb package for
|
||||||
|
// easy use with the MaxMind GeoIP2 and GeoLite2 databases. The records for
|
||||||
|
// the IP address is returned from this package as well-formed structures
|
||||||
|
// that match the internal layout of data from MaxMind.
|
||||||
|
package geoip2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/oschwald/maxminddb-golang"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The City structure corresponds to the data in the GeoIP2/GeoLite2 City
|
||||||
|
// databases.
|
||||||
|
type City struct {
|
||||||
|
City struct {
|
||||||
|
GeoNameID uint `maxminddb:"geoname_id"`
|
||||||
|
Names map[string]string `maxminddb:"names"`
|
||||||
|
} `maxminddb:"city"`
|
||||||
|
Continent struct {
|
||||||
|
Code string `maxminddb:"code"`
|
||||||
|
GeoNameID uint `maxminddb:"geoname_id"`
|
||||||
|
Names map[string]string `maxminddb:"names"`
|
||||||
|
} `maxminddb:"continent"`
|
||||||
|
Country struct {
|
||||||
|
GeoNameID uint `maxminddb:"geoname_id"`
|
||||||
|
IsoCode string `maxminddb:"iso_code"`
|
||||||
|
Names map[string]string `maxminddb:"names"`
|
||||||
|
} `maxminddb:"country"`
|
||||||
|
Location struct {
|
||||||
|
Latitude float64 `maxminddb:"latitude"`
|
||||||
|
Longitude float64 `maxminddb:"longitude"`
|
||||||
|
MetroCode uint `maxminddb:"metro_code"`
|
||||||
|
TimeZone string `maxminddb:"time_zone"`
|
||||||
|
} `maxminddb:"location"`
|
||||||
|
Postal struct {
|
||||||
|
Code string `maxminddb:"code"`
|
||||||
|
} `maxminddb:"postal"`
|
||||||
|
RegisteredCountry struct {
|
||||||
|
GeoNameID uint `maxminddb:"geoname_id"`
|
||||||
|
IsoCode string `maxminddb:"iso_code"`
|
||||||
|
Names map[string]string `maxminddb:"names"`
|
||||||
|
} `maxminddb:"registered_country"`
|
||||||
|
RepresentedCountry struct {
|
||||||
|
GeoNameID uint `maxminddb:"geoname_id"`
|
||||||
|
IsoCode string `maxminddb:"iso_code"`
|
||||||
|
Names map[string]string `maxminddb:"names"`
|
||||||
|
Type string `maxminddb:"type"`
|
||||||
|
} `maxminddb:"represented_country"`
|
||||||
|
Subdivisions []struct {
|
||||||
|
GeoNameID uint `maxminddb:"geoname_id"`
|
||||||
|
IsoCode string `maxminddb:"iso_code"`
|
||||||
|
Names map[string]string `maxminddb:"names"`
|
||||||
|
} `maxminddb:"subdivisions"`
|
||||||
|
Traits struct {
|
||||||
|
IsAnonymousProxy bool `maxminddb:"is_anonymous_proxy"`
|
||||||
|
IsSatelliteProvider bool `maxminddb:"is_satellite_provider"`
|
||||||
|
} `maxminddb:"traits"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Country structure corresponds to the data in the GeoIP2/GeoLite2
|
||||||
|
// Country databases.
|
||||||
|
type Country struct {
|
||||||
|
Continent struct {
|
||||||
|
Code string `maxminddb:"code"`
|
||||||
|
GeoNameID uint `maxminddb:"geoname_id"`
|
||||||
|
Names map[string]string `maxminddb:"names"`
|
||||||
|
} `maxminddb:"continent"`
|
||||||
|
Country struct {
|
||||||
|
GeoNameID uint `maxminddb:"geoname_id"`
|
||||||
|
IsoCode string `maxminddb:"iso_code"`
|
||||||
|
Names map[string]string `maxminddb:"names"`
|
||||||
|
} `maxminddb:"country"`
|
||||||
|
RegisteredCountry struct {
|
||||||
|
GeoNameID uint `maxminddb:"geoname_id"`
|
||||||
|
IsoCode string `maxminddb:"iso_code"`
|
||||||
|
Names map[string]string `maxminddb:"names"`
|
||||||
|
} `maxminddb:"registered_country"`
|
||||||
|
RepresentedCountry struct {
|
||||||
|
GeoNameID uint `maxminddb:"geoname_id"`
|
||||||
|
IsoCode string `maxminddb:"iso_code"`
|
||||||
|
Names map[string]string `maxminddb:"names"`
|
||||||
|
Type string `maxminddb:"type"`
|
||||||
|
} `maxminddb:"represented_country"`
|
||||||
|
Traits struct {
|
||||||
|
IsAnonymousProxy bool `maxminddb:"is_anonymous_proxy"`
|
||||||
|
IsSatelliteProvider bool `maxminddb:"is_satellite_provider"`
|
||||||
|
} `maxminddb:"traits"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// The AnonymousIP structure corresponds to the data in the GeoIP2
|
||||||
|
// Anonymous IP database.
|
||||||
|
type AnonymousIP struct {
|
||||||
|
IsAnonymous bool `maxminddb:"is_anonymous"`
|
||||||
|
IsAnonymousVPN bool `maxminddb:"is_anonymous_vpn"`
|
||||||
|
IsHostingProvider bool `maxminddb:"is_hosting_provider"`
|
||||||
|
IsPublicProxy bool `maxminddb:"is_public_proxy"`
|
||||||
|
IsTorExitNode bool `maxminddb:"is_tor_exit_node"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// The ConnectionType structure corresponds to the data in the GeoIP2
|
||||||
|
// Connection-Type database.
|
||||||
|
type ConnectionType struct {
|
||||||
|
ConnectionType string `maxminddb:"connection_type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Domain structure corresponds to the data in the GeoIP2 Domain database.
|
||||||
|
type Domain struct {
|
||||||
|
Domain string `maxminddb:"domain"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// The ISP structure corresponds to the data in the GeoIP2 ISP database.
|
||||||
|
type ISP struct {
|
||||||
|
AutonomousSystemNumber uint `maxminddb:"autonomous_system_number"`
|
||||||
|
AutonomousSystemOrganization string `maxminddb:"autonomous_system_organization"`
|
||||||
|
ISP string `maxminddb:"isp"`
|
||||||
|
Organization string `maxminddb:"organization"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reader holds the maxminddb.Reader structure. It should be created
|
||||||
|
// using the Open function.
|
||||||
|
type Reader struct {
|
||||||
|
mmdbReader *maxminddb.Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open takes a string path to a file and returns a Reader structure or an
|
||||||
|
// error. The database file is opened using a memory map. Use the Close method
|
||||||
|
// on the Reader object to return the resources to the system.
|
||||||
|
func Open(file string) (*Reader, error) {
|
||||||
|
reader, err := maxminddb.Open(file)
|
||||||
|
return &Reader{mmdbReader: reader}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromBytes takes a byte slice corresponding to a GeoIP2/GeoLite2 database
|
||||||
|
// file and returns a Reader structure or an error.
|
||||||
|
func FromBytes(bytes []byte) (*Reader, error) {
|
||||||
|
reader, err := maxminddb.FromBytes(bytes)
|
||||||
|
return &Reader{mmdbReader: reader}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// City takes an IP address as a net.IP struct and returns a City struct
|
||||||
|
// and/or an error. Although this can be used with other databases, this
|
||||||
|
// method generally should be used with the GeoIP2 or GeoLite2 City databases.
|
||||||
|
func (r *Reader) City(ipAddress net.IP) (*City, error) {
|
||||||
|
var city City
|
||||||
|
err := r.mmdbReader.Lookup(ipAddress, &city)
|
||||||
|
return &city, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Country takes an IP address as a net.IP struct and returns a Country struct
|
||||||
|
// and/or an error. Although this can be used with other databases, this
|
||||||
|
// method generally should be used with the GeoIP2 or GeoLite2 Country
|
||||||
|
// databases.
|
||||||
|
func (r *Reader) Country(ipAddress net.IP) (*Country, error) {
|
||||||
|
var country Country
|
||||||
|
err := r.mmdbReader.Lookup(ipAddress, &country)
|
||||||
|
return &country, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnonymousIP takes an IP address as a net.IP struct and returns a
|
||||||
|
// AnonymousIP struct and/or an error.
|
||||||
|
func (r *Reader) AnonymousIP(ipAddress net.IP) (*AnonymousIP, error) {
|
||||||
|
var anonIP AnonymousIP
|
||||||
|
err := r.mmdbReader.Lookup(ipAddress, &anonIP)
|
||||||
|
return &anonIP, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConnectionType takes an IP address as a net.IP struct and returns a
|
||||||
|
// ConnectionType struct and/or an error
|
||||||
|
func (r *Reader) ConnectionType(ipAddress net.IP) (*ConnectionType, error) {
|
||||||
|
var val ConnectionType
|
||||||
|
err := r.mmdbReader.Lookup(ipAddress, &val)
|
||||||
|
return &val, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Domain takes an IP address as a net.IP struct and returns a
|
||||||
|
// Domain struct and/or an error
|
||||||
|
func (r *Reader) Domain(ipAddress net.IP) (*Domain, error) {
|
||||||
|
var val Domain
|
||||||
|
err := r.mmdbReader.Lookup(ipAddress, &val)
|
||||||
|
return &val, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ISP takes an IP address as a net.IP struct and returns a ISP struct and/or
|
||||||
|
// an error
|
||||||
|
func (r *Reader) ISP(ipAddress net.IP) (*ISP, error) {
|
||||||
|
var val ISP
|
||||||
|
err := r.mmdbReader.Lookup(ipAddress, &val)
|
||||||
|
return &val, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Metadata takes no arguments and returns a struct containing metadata about
|
||||||
|
// the MaxMind database in use by the Reader.
|
||||||
|
func (r *Reader) Metadata() maxminddb.Metadata {
|
||||||
|
return r.mmdbReader.Metadata
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close unmaps the database file from virtual memory and returns the
|
||||||
|
// resources to the system.
|
||||||
|
func (r *Reader) Close() error {
|
||||||
|
return r.mmdbReader.Close()
|
||||||
|
}
|
3
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/.gitmodules
generated
vendored
Normal file
3
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/.gitmodules
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "test-data"]
|
||||||
|
path = test-data
|
||||||
|
url = git://github.com/maxmind/MaxMind-DB.git
|
23
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/.travis.yml
generated
vendored
Normal file
23
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
language: go
|
||||||
|
|
||||||
|
go:
|
||||||
|
- 1.2
|
||||||
|
- 1.3
|
||||||
|
- 1.4
|
||||||
|
- 1.5
|
||||||
|
- 1.6
|
||||||
|
- tip
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- "if [[ $TRAVIS_GO_VERSION == 1.6 ]]; then go get -v github.com/golang/lint/golint; fi"
|
||||||
|
|
||||||
|
install:
|
||||||
|
- go get gopkg.in/check.v1
|
||||||
|
|
||||||
|
script:
|
||||||
|
- go test -race -cpu 1,4 -v
|
||||||
|
- go test -race -v -tags appengine
|
||||||
|
- "if [[ $TRAVIS_GO_VERSION == 1.6 ]]; then go vet ./...; fi"
|
||||||
|
- "if [[ $TRAVIS_GO_VERSION == 1.6 ]]; then golint .; fi"
|
||||||
|
|
||||||
|
sudo: false
|
13
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/LICENSE
generated
vendored
Normal file
13
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/LICENSE
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
Copyright (c) 2015, Gregory J. Oschwald <oschwald@gmail.com>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
PERFORMANCE OF THIS SOFTWARE.
|
37
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/README.md
generated
vendored
Normal file
37
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/README.md
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# MaxMind DB Reader for Go #
|
||||||
|
|
||||||
|
[![Build Status](https://travis-ci.org/oschwald/maxminddb-golang.png?branch=master)](https://travis-ci.org/oschwald/maxminddb-golang)
|
||||||
|
[![Windows Build Status](https://ci.appveyor.com/api/projects/status/4j2f9oep8nnfrmov/branch/master?svg=true)](https://ci.appveyor.com/project/oschwald/maxminddb-golang/branch/master)
|
||||||
|
[![GoDoc](https://godoc.org/github.com/oschwald/maxminddb-golang?status.png)](https://godoc.org/github.com/oschwald/maxminddb-golang)
|
||||||
|
|
||||||
|
|
||||||
|
This is a Go reader for the MaxMind DB format. This can be used to read
|
||||||
|
[GeoLite2](http://dev.maxmind.com/geoip/geoip2/geolite2/) and
|
||||||
|
[GeoIP2](http://www.maxmind.com/en/geolocation_landing) databases.
|
||||||
|
|
||||||
|
This is not an official MaxMind API.
|
||||||
|
|
||||||
|
## Installation ##
|
||||||
|
|
||||||
|
```
|
||||||
|
go get github.com/oschwald/maxminddb-golang
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage ##
|
||||||
|
|
||||||
|
[See GoDoc](http://godoc.org/github.com/oschwald/maxminddb-golang) for
|
||||||
|
documentation and examples.
|
||||||
|
|
||||||
|
## Examples ##
|
||||||
|
|
||||||
|
See [GoDoc](http://godoc.org/github.com/oschwald/maxminddb-golang) or
|
||||||
|
`example_test.go` for examples.
|
||||||
|
|
||||||
|
## Contributing ##
|
||||||
|
|
||||||
|
Contributions welcome! Please fork the repository and open a pull request
|
||||||
|
with your changes.
|
||||||
|
|
||||||
|
## License ##
|
||||||
|
|
||||||
|
This is free software, licensed under the ISC License.
|
19
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/appveyor.yml
generated
vendored
Normal file
19
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/appveyor.yml
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
version: "{build}"
|
||||||
|
|
||||||
|
os: Windows Server 2012 R2
|
||||||
|
|
||||||
|
clone_folder: c:\gopath\src\github.com\oschwald\maxminddb-golang
|
||||||
|
|
||||||
|
environment:
|
||||||
|
GOPATH: c:\gopath
|
||||||
|
|
||||||
|
install:
|
||||||
|
- echo %PATH%
|
||||||
|
- echo %GOPATH%
|
||||||
|
- git submodule update --init --recursive
|
||||||
|
- go version
|
||||||
|
- go env
|
||||||
|
- go get -v -t ./...
|
||||||
|
|
||||||
|
build_script:
|
||||||
|
- go test -v ./...
|
530
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/decoder.go
generated
vendored
Normal file
530
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/decoder.go
generated
vendored
Normal file
@ -0,0 +1,530 @@
|
|||||||
|
package maxminddb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"math/big"
|
||||||
|
"reflect"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type decoder struct {
|
||||||
|
buffer []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type dataType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
_Extended dataType = iota
|
||||||
|
_Pointer
|
||||||
|
_String
|
||||||
|
_Float64
|
||||||
|
_Bytes
|
||||||
|
_Uint16
|
||||||
|
_Uint32
|
||||||
|
_Map
|
||||||
|
_Int32
|
||||||
|
_Uint64
|
||||||
|
_Uint128
|
||||||
|
_Slice
|
||||||
|
_Container
|
||||||
|
_Marker
|
||||||
|
_Bool
|
||||||
|
_Float32
|
||||||
|
)
|
||||||
|
|
||||||
|
func (d *decoder) decode(offset uint, result reflect.Value) (uint, error) {
|
||||||
|
typeNum, size, newOffset := d.decodeCtrlData(offset)
|
||||||
|
return d.decodeFromType(typeNum, size, newOffset, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) decodeCtrlData(offset uint) (dataType, uint, uint) {
|
||||||
|
newOffset := offset + 1
|
||||||
|
ctrlByte := d.buffer[offset]
|
||||||
|
|
||||||
|
typeNum := dataType(ctrlByte >> 5)
|
||||||
|
if typeNum == _Extended {
|
||||||
|
typeNum = dataType(d.buffer[newOffset] + 7)
|
||||||
|
newOffset++
|
||||||
|
}
|
||||||
|
|
||||||
|
var size uint
|
||||||
|
size, newOffset = d.sizeFromCtrlByte(ctrlByte, newOffset, typeNum)
|
||||||
|
return typeNum, size, newOffset
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) sizeFromCtrlByte(ctrlByte byte, offset uint, typeNum dataType) (uint, uint) {
|
||||||
|
size := uint(ctrlByte & 0x1f)
|
||||||
|
if typeNum == _Extended {
|
||||||
|
return size, offset
|
||||||
|
}
|
||||||
|
|
||||||
|
var bytesToRead uint
|
||||||
|
if size > 28 {
|
||||||
|
bytesToRead = size - 28
|
||||||
|
}
|
||||||
|
|
||||||
|
newOffset := offset + bytesToRead
|
||||||
|
sizeBytes := d.buffer[offset:newOffset]
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case size == 29:
|
||||||
|
size = 29 + uint(sizeBytes[0])
|
||||||
|
case size == 30:
|
||||||
|
size = 285 + uint(uintFromBytes(0, sizeBytes))
|
||||||
|
case size > 30:
|
||||||
|
size = uint(uintFromBytes(0, sizeBytes)) + 65821
|
||||||
|
}
|
||||||
|
return size, newOffset
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) decodeFromType(dtype dataType, size uint, offset uint, result reflect.Value) (uint, error) {
|
||||||
|
if result.Kind() == reflect.Ptr {
|
||||||
|
result = reflect.Indirect(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch dtype {
|
||||||
|
case _Bool:
|
||||||
|
return d.unmarshalBool(size, offset, result)
|
||||||
|
case _Bytes:
|
||||||
|
return d.unmarshalBytes(size, offset, result)
|
||||||
|
case _Float32:
|
||||||
|
return d.unmarshalFloat32(size, offset, result)
|
||||||
|
case _Float64:
|
||||||
|
return d.unmarshalFloat64(size, offset, result)
|
||||||
|
case _Int32:
|
||||||
|
return d.unmarshalInt32(size, offset, result)
|
||||||
|
case _Map:
|
||||||
|
return d.unmarshalMap(size, offset, result)
|
||||||
|
case _Pointer:
|
||||||
|
return d.unmarshalPointer(size, offset, result)
|
||||||
|
case _Slice:
|
||||||
|
return d.unmarshalSlice(size, offset, result)
|
||||||
|
case _String:
|
||||||
|
return d.unmarshalString(size, offset, result)
|
||||||
|
case _Uint16:
|
||||||
|
return d.unmarshalUint(size, offset, result, 16)
|
||||||
|
case _Uint32:
|
||||||
|
return d.unmarshalUint(size, offset, result, 32)
|
||||||
|
case _Uint64:
|
||||||
|
return d.unmarshalUint(size, offset, result, 64)
|
||||||
|
case _Uint128:
|
||||||
|
return d.unmarshalUint128(size, offset, result)
|
||||||
|
default:
|
||||||
|
return 0, newInvalidDatabaseError("unknown type: %d", dtype)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) unmarshalBool(size uint, offset uint, result reflect.Value) (uint, error) {
|
||||||
|
if size > 1 {
|
||||||
|
return 0, newInvalidDatabaseError("the MaxMind DB file's data section contains bad data (bool size of %v)", size)
|
||||||
|
}
|
||||||
|
value, newOffset, err := d.decodeBool(size, offset)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
switch result.Kind() {
|
||||||
|
default:
|
||||||
|
return newOffset, fmt.Errorf("trying to unmarshal %v into %v", value, result.Type())
|
||||||
|
case reflect.Bool:
|
||||||
|
result.SetBool(value)
|
||||||
|
return newOffset, nil
|
||||||
|
case reflect.Interface:
|
||||||
|
result.Set(reflect.ValueOf(value))
|
||||||
|
return newOffset, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) unmarshalBytes(size uint, offset uint, result reflect.Value) (uint, error) {
|
||||||
|
|
||||||
|
value, newOffset, err := d.decodeBytes(size, offset)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
switch result.Kind() {
|
||||||
|
default:
|
||||||
|
return newOffset, fmt.Errorf("trying to unmarshal %v into %v", value, result.Type())
|
||||||
|
case reflect.Slice:
|
||||||
|
result.SetBytes(value)
|
||||||
|
return newOffset, nil
|
||||||
|
case reflect.Interface:
|
||||||
|
result.Set(reflect.ValueOf(value))
|
||||||
|
return newOffset, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) unmarshalFloat32(size uint, offset uint, result reflect.Value) (uint, error) {
|
||||||
|
if size != 4 {
|
||||||
|
return 0, newInvalidDatabaseError("the MaxMind DB file's data section contains bad data (float32 size of %v)", size)
|
||||||
|
}
|
||||||
|
value, newOffset, err := d.decodeFloat32(size, offset)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch result.Kind() {
|
||||||
|
default:
|
||||||
|
return newOffset, fmt.Errorf("trying to unmarshal %v into %v", value, result.Type())
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
result.SetFloat(float64(value))
|
||||||
|
return newOffset, nil
|
||||||
|
case reflect.Interface:
|
||||||
|
result.Set(reflect.ValueOf(value))
|
||||||
|
return newOffset, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) unmarshalFloat64(size uint, offset uint, result reflect.Value) (uint, error) {
|
||||||
|
|
||||||
|
if size != 8 {
|
||||||
|
return 0, newInvalidDatabaseError("the MaxMind DB file's data section contains bad data (float 64 size of %v)", size)
|
||||||
|
}
|
||||||
|
value, newOffset, err := d.decodeFloat64(size, offset)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
switch result.Kind() {
|
||||||
|
default:
|
||||||
|
return newOffset, fmt.Errorf("trying to unmarshal %v into %v", value, result.Type())
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
result.SetFloat(value)
|
||||||
|
return newOffset, nil
|
||||||
|
case reflect.Interface:
|
||||||
|
result.Set(reflect.ValueOf(value))
|
||||||
|
return newOffset, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) unmarshalInt32(size uint, offset uint, result reflect.Value) (uint, error) {
|
||||||
|
if size > 4 {
|
||||||
|
return 0, newInvalidDatabaseError("the MaxMind DB file's data section contains bad data (int32 size of %v)", size)
|
||||||
|
}
|
||||||
|
value, newOffset, err := d.decodeInt(size, offset)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch result.Kind() {
|
||||||
|
default:
|
||||||
|
return newOffset, fmt.Errorf("trying to unmarshal %v into %v", value, result.Type())
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
result.SetInt(int64(value))
|
||||||
|
return newOffset, nil
|
||||||
|
case reflect.Interface:
|
||||||
|
result.Set(reflect.ValueOf(value))
|
||||||
|
return newOffset, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) unmarshalMap(size uint, offset uint, result reflect.Value) (uint, error) {
|
||||||
|
switch result.Kind() {
|
||||||
|
default:
|
||||||
|
return 0, fmt.Errorf("trying to unmarshal a map into %v", result.Type())
|
||||||
|
case reflect.Struct:
|
||||||
|
return d.decodeStruct(size, offset, result)
|
||||||
|
case reflect.Map:
|
||||||
|
return d.decodeMap(size, offset, result)
|
||||||
|
case reflect.Interface:
|
||||||
|
rv := reflect.ValueOf(make(map[string]interface{}, size))
|
||||||
|
newOffset, err := d.decodeMap(size, offset, rv)
|
||||||
|
result.Set(rv)
|
||||||
|
return newOffset, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) unmarshalPointer(size uint, offset uint, result reflect.Value) (uint, error) {
|
||||||
|
pointer, newOffset := d.decodePointer(size, offset)
|
||||||
|
_, err := d.decode(pointer, result)
|
||||||
|
return newOffset, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) unmarshalSlice(size uint, offset uint, result reflect.Value) (uint, error) {
|
||||||
|
|
||||||
|
switch result.Kind() {
|
||||||
|
default:
|
||||||
|
return 0, fmt.Errorf("trying to unmarshal an array into %v", result.Type())
|
||||||
|
case reflect.Slice:
|
||||||
|
return d.decodeSlice(size, offset, result)
|
||||||
|
case reflect.Interface:
|
||||||
|
a := []interface{}{}
|
||||||
|
rv := reflect.ValueOf(&a).Elem()
|
||||||
|
newOffset, err := d.decodeSlice(size, offset, rv)
|
||||||
|
result.Set(rv)
|
||||||
|
return newOffset, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) unmarshalString(size uint, offset uint, result reflect.Value) (uint, error) {
|
||||||
|
|
||||||
|
value, newOffset, err := d.decodeString(size, offset)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
switch result.Kind() {
|
||||||
|
default:
|
||||||
|
return newOffset, fmt.Errorf("trying to unmarshal %v into %v", value, result.Type())
|
||||||
|
case reflect.String:
|
||||||
|
result.SetString(value)
|
||||||
|
return newOffset, nil
|
||||||
|
case reflect.Interface:
|
||||||
|
result.Set(reflect.ValueOf(value))
|
||||||
|
return newOffset, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) unmarshalUint(size uint, offset uint, result reflect.Value, uintType uint) (uint, error) {
|
||||||
|
if size > uintType/8 {
|
||||||
|
return 0, newInvalidDatabaseError("the MaxMind DB file's data section contains bad data (uint%v size of %v)", uintType, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
value, newOffset, err := d.decodeUint(size, offset)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch result.Kind() {
|
||||||
|
default:
|
||||||
|
return newOffset, fmt.Errorf("trying to unmarshal %v into %v", value, result.Type())
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
result.SetUint(value)
|
||||||
|
return newOffset, nil
|
||||||
|
case reflect.Interface:
|
||||||
|
result.Set(reflect.ValueOf(value))
|
||||||
|
return newOffset, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) unmarshalUint128(size uint, offset uint, result reflect.Value) (uint, error) {
|
||||||
|
if size > 16 {
|
||||||
|
return 0, newInvalidDatabaseError("the MaxMind DB file's data section contains bad data (uint128 size of %v)", size)
|
||||||
|
}
|
||||||
|
value, newOffset, err := d.decodeUint128(size, offset)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX - this should allow *big.Int rather than just bigInt
|
||||||
|
// Currently this is reported as invalid
|
||||||
|
switch result.Kind() {
|
||||||
|
default:
|
||||||
|
return newOffset, fmt.Errorf("trying to unmarshal %v into %v", value, result.Type())
|
||||||
|
case reflect.Struct:
|
||||||
|
result.Set(reflect.ValueOf(*value))
|
||||||
|
return newOffset, nil
|
||||||
|
case reflect.Interface, reflect.Ptr:
|
||||||
|
result.Set(reflect.ValueOf(value))
|
||||||
|
return newOffset, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) decodeBool(size uint, offset uint) (bool, uint, error) {
|
||||||
|
return size != 0, offset, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) decodeBytes(size uint, offset uint) ([]byte, uint, error) {
|
||||||
|
newOffset := offset + size
|
||||||
|
bytes := make([]byte, size)
|
||||||
|
copy(bytes, d.buffer[offset:newOffset])
|
||||||
|
return bytes, newOffset, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) decodeFloat64(size uint, offset uint) (float64, uint, error) {
|
||||||
|
newOffset := offset + size
|
||||||
|
bits := binary.BigEndian.Uint64(d.buffer[offset:newOffset])
|
||||||
|
return math.Float64frombits(bits), newOffset, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) decodeFloat32(size uint, offset uint) (float32, uint, error) {
|
||||||
|
newOffset := offset + size
|
||||||
|
bits := binary.BigEndian.Uint32(d.buffer[offset:newOffset])
|
||||||
|
return math.Float32frombits(bits), newOffset, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) decodeInt(size uint, offset uint) (int, uint, error) {
|
||||||
|
newOffset := offset + size
|
||||||
|
var val int32
|
||||||
|
for _, b := range d.buffer[offset:newOffset] {
|
||||||
|
val = (val << 8) | int32(b)
|
||||||
|
}
|
||||||
|
return int(val), newOffset, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) decodeMap(size uint, offset uint, result reflect.Value) (uint, error) {
|
||||||
|
if result.IsNil() {
|
||||||
|
result.Set(reflect.MakeMap(result.Type()))
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := uint(0); i < size; i++ {
|
||||||
|
var key string
|
||||||
|
var err error
|
||||||
|
key, offset, err = d.decodeKeyString(offset)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
value := reflect.New(result.Type().Elem())
|
||||||
|
offset, err = d.decode(offset, value)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
result.SetMapIndex(reflect.ValueOf(key), value.Elem())
|
||||||
|
}
|
||||||
|
return offset, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) decodePointer(size uint, offset uint) (uint, uint) {
|
||||||
|
pointerSize := ((size >> 3) & 0x3) + 1
|
||||||
|
newOffset := offset + pointerSize
|
||||||
|
pointerBytes := d.buffer[offset:newOffset]
|
||||||
|
var prefix uint64
|
||||||
|
if pointerSize == 4 {
|
||||||
|
prefix = 0
|
||||||
|
} else {
|
||||||
|
prefix = uint64(size & 0x7)
|
||||||
|
}
|
||||||
|
unpacked := uint(uintFromBytes(prefix, pointerBytes))
|
||||||
|
|
||||||
|
var pointerValueOffset uint
|
||||||
|
switch pointerSize {
|
||||||
|
case 1:
|
||||||
|
pointerValueOffset = 0
|
||||||
|
case 2:
|
||||||
|
pointerValueOffset = 2048
|
||||||
|
case 3:
|
||||||
|
pointerValueOffset = 526336
|
||||||
|
case 4:
|
||||||
|
pointerValueOffset = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pointer := unpacked + pointerValueOffset
|
||||||
|
|
||||||
|
return pointer, newOffset
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) decodeSlice(size uint, offset uint, result reflect.Value) (uint, error) {
|
||||||
|
result.Set(reflect.MakeSlice(result.Type(), int(size), int(size)))
|
||||||
|
for i := 0; i < int(size); i++ {
|
||||||
|
var err error
|
||||||
|
offset, err = d.decode(offset, result.Index(i))
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return offset, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) decodeString(size uint, offset uint) (string, uint, error) {
|
||||||
|
newOffset := offset + size
|
||||||
|
return string(d.buffer[offset:newOffset]), newOffset, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
fieldMap = map[reflect.Type]map[string]int{}
|
||||||
|
fieldMapMu sync.RWMutex
|
||||||
|
)
|
||||||
|
|
||||||
|
func (d *decoder) decodeStruct(size uint, offset uint, result reflect.Value) (uint, error) {
|
||||||
|
resultType := result.Type()
|
||||||
|
|
||||||
|
fieldMapMu.RLock()
|
||||||
|
fields, ok := fieldMap[resultType]
|
||||||
|
fieldMapMu.RUnlock()
|
||||||
|
if !ok {
|
||||||
|
numFields := resultType.NumField()
|
||||||
|
fields = make(map[string]int, numFields)
|
||||||
|
for i := 0; i < numFields; i++ {
|
||||||
|
fieldType := resultType.Field(i)
|
||||||
|
|
||||||
|
fieldName := fieldType.Name
|
||||||
|
if tag := fieldType.Tag.Get("maxminddb"); tag != "" {
|
||||||
|
fieldName = tag
|
||||||
|
}
|
||||||
|
fields[fieldName] = i
|
||||||
|
}
|
||||||
|
fieldMapMu.Lock()
|
||||||
|
fieldMap[resultType] = fields
|
||||||
|
fieldMapMu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := uint(0); i < size; i++ {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
key string
|
||||||
|
)
|
||||||
|
key, offset, err = d.decodeStructKey(offset)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
i, ok := fields[key]
|
||||||
|
if !ok {
|
||||||
|
offset = d.nextValueOffset(offset, 1)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
offset, err = d.decode(offset, result.Field(i))
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return offset, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) decodeUint(size uint, offset uint) (uint64, uint, error) {
|
||||||
|
newOffset := offset + size
|
||||||
|
val := uintFromBytes(0, d.buffer[offset:newOffset])
|
||||||
|
|
||||||
|
return val, newOffset, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) decodeUint128(size uint, offset uint) (*big.Int, uint, error) {
|
||||||
|
newOffset := offset + size
|
||||||
|
val := new(big.Int)
|
||||||
|
val.SetBytes(d.buffer[offset:newOffset])
|
||||||
|
|
||||||
|
return val, newOffset, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func uintFromBytes(prefix uint64, uintBytes []byte) uint64 {
|
||||||
|
val := prefix
|
||||||
|
for _, b := range uintBytes {
|
||||||
|
val = (val << 8) | uint64(b)
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *decoder) decodeKeyString(offset uint) (string, uint, error) {
|
||||||
|
typeNum, size, newOffset := d.decodeCtrlData(offset)
|
||||||
|
if typeNum == _Pointer {
|
||||||
|
pointer, ptrOffset := d.decodePointer(size, newOffset)
|
||||||
|
key, _, err := d.decodeKeyString(pointer)
|
||||||
|
return key, ptrOffset, err
|
||||||
|
}
|
||||||
|
if typeNum != _String {
|
||||||
|
return "", 0, newInvalidDatabaseError("unexpected type when decoding string: %v", typeNum)
|
||||||
|
}
|
||||||
|
return d.decodeString(size, newOffset)
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is used to skip ahead to the next value without decoding
|
||||||
|
// the one at the offset passed in. The size bits have different meanings for
|
||||||
|
// different data types
|
||||||
|
func (d *decoder) nextValueOffset(offset uint, numberToSkip uint) uint {
|
||||||
|
if numberToSkip == 0 {
|
||||||
|
return offset
|
||||||
|
}
|
||||||
|
typeNum, size, offset := d.decodeCtrlData(offset)
|
||||||
|
switch typeNum {
|
||||||
|
case _Pointer:
|
||||||
|
_, offset = d.decodePointer(size, offset)
|
||||||
|
case _Map:
|
||||||
|
numberToSkip += 2 * size
|
||||||
|
case _Slice:
|
||||||
|
numberToSkip += size
|
||||||
|
case _Bool:
|
||||||
|
default:
|
||||||
|
offset += size
|
||||||
|
}
|
||||||
|
return d.nextValueOffset(offset, numberToSkip-1)
|
||||||
|
}
|
17
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/errors.go
generated
vendored
Normal file
17
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/errors.go
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package maxminddb
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// InvalidDatabaseError is returned when the database contains invalid data
|
||||||
|
// and cannot be parsed.
|
||||||
|
type InvalidDatabaseError struct {
|
||||||
|
message string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newInvalidDatabaseError(format string, args ...interface{}) InvalidDatabaseError {
|
||||||
|
return InvalidDatabaseError{fmt.Sprintf(format, args...)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e InvalidDatabaseError) Error() string {
|
||||||
|
return e.message
|
||||||
|
}
|
7
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/key_appengine.go
generated
vendored
Normal file
7
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/key_appengine.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
// +build appengine
|
||||||
|
|
||||||
|
package maxminddb
|
||||||
|
|
||||||
|
func (d *decoder) decodeStructKey(offset uint) (string, uint, error) {
|
||||||
|
return d.decodeKeyString(offset)
|
||||||
|
}
|
28
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/key_other.go
generated
vendored
Normal file
28
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/key_other.go
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// +build !appengine
|
||||||
|
|
||||||
|
package maxminddb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// decodeStructKey returns a string which points into the database. Don't keep
|
||||||
|
// it around.
|
||||||
|
func (d *decoder) decodeStructKey(offset uint) (string, uint, error) {
|
||||||
|
typeNum, size, newOffset := d.decodeCtrlData(offset)
|
||||||
|
switch typeNum {
|
||||||
|
case _Pointer:
|
||||||
|
pointer, ptrOffset := d.decodePointer(size, newOffset)
|
||||||
|
s, _, err := d.decodeStructKey(pointer)
|
||||||
|
return s, ptrOffset, err
|
||||||
|
case _String:
|
||||||
|
var s string
|
||||||
|
val := (*reflect.StringHeader)(unsafe.Pointer(&s))
|
||||||
|
val.Data = uintptr(unsafe.Pointer(&d.buffer[newOffset]))
|
||||||
|
val.Len = int(size)
|
||||||
|
return s, newOffset + size, nil
|
||||||
|
default:
|
||||||
|
return "", 0, newInvalidDatabaseError("unexpected type when decoding struct key: %v", typeNum)
|
||||||
|
}
|
||||||
|
}
|
15
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/mmap_unix.go
generated
vendored
Normal file
15
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/mmap_unix.go
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// +build !windows,!appengine
|
||||||
|
|
||||||
|
package maxminddb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
func mmap(fd int, length int) (data []byte, err error) {
|
||||||
|
return syscall.Mmap(fd, 0, length, syscall.PROT_READ, syscall.MAP_SHARED)
|
||||||
|
}
|
||||||
|
|
||||||
|
func munmap(b []byte) (err error) {
|
||||||
|
return syscall.Munmap(b)
|
||||||
|
}
|
82
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/mmap_windows.go
generated
vendored
Normal file
82
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/mmap_windows.go
generated
vendored
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
package maxminddb
|
||||||
|
|
||||||
|
// Windows support largely borrowed from mmap-go.
|
||||||
|
//
|
||||||
|
// Copyright 2011 Evan Shaw. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
type memoryMap []byte
|
||||||
|
|
||||||
|
// Windows
|
||||||
|
var handleLock sync.Mutex
|
||||||
|
var handleMap = map[uintptr]syscall.Handle{}
|
||||||
|
|
||||||
|
func mmap(fd int, length int) (data []byte, err error) {
|
||||||
|
h, errno := syscall.CreateFileMapping(syscall.Handle(fd), nil,
|
||||||
|
uint32(syscall.PAGE_READONLY), 0, uint32(length), nil)
|
||||||
|
if h == 0 {
|
||||||
|
return nil, os.NewSyscallError("CreateFileMapping", errno)
|
||||||
|
}
|
||||||
|
|
||||||
|
addr, errno := syscall.MapViewOfFile(h, uint32(syscall.FILE_MAP_READ), 0,
|
||||||
|
0, uintptr(length))
|
||||||
|
if addr == 0 {
|
||||||
|
return nil, os.NewSyscallError("MapViewOfFile", errno)
|
||||||
|
}
|
||||||
|
handleLock.Lock()
|
||||||
|
handleMap[addr] = h
|
||||||
|
handleLock.Unlock()
|
||||||
|
|
||||||
|
m := memoryMap{}
|
||||||
|
dh := m.header()
|
||||||
|
dh.Data = addr
|
||||||
|
dh.Len = length
|
||||||
|
dh.Cap = dh.Len
|
||||||
|
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *memoryMap) header() *reflect.SliceHeader {
|
||||||
|
return (*reflect.SliceHeader)(unsafe.Pointer(m))
|
||||||
|
}
|
||||||
|
|
||||||
|
func flush(addr, len uintptr) error {
|
||||||
|
errno := syscall.FlushViewOfFile(addr, len)
|
||||||
|
return os.NewSyscallError("FlushViewOfFile", errno)
|
||||||
|
}
|
||||||
|
|
||||||
|
func munmap(b []byte) (err error) {
|
||||||
|
m := memoryMap(b)
|
||||||
|
dh := m.header()
|
||||||
|
|
||||||
|
addr := dh.Data
|
||||||
|
length := uintptr(dh.Len)
|
||||||
|
|
||||||
|
flush(addr, length)
|
||||||
|
err = syscall.UnmapViewOfFile(addr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
handleLock.Lock()
|
||||||
|
defer handleLock.Unlock()
|
||||||
|
handle, ok := handleMap[addr]
|
||||||
|
if !ok {
|
||||||
|
// should be impossible; we would've errored above
|
||||||
|
return errors.New("unknown base address")
|
||||||
|
}
|
||||||
|
delete(handleMap, addr)
|
||||||
|
|
||||||
|
e := syscall.CloseHandle(syscall.Handle(handle))
|
||||||
|
return os.NewSyscallError("CloseHandle", e)
|
||||||
|
}
|
221
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/reader.go
generated
vendored
Normal file
221
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/reader.go
generated
vendored
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
package maxminddb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
const dataSectionSeparatorSize = 16
|
||||||
|
|
||||||
|
var metadataStartMarker = []byte("\xAB\xCD\xEFMaxMind.com")
|
||||||
|
|
||||||
|
// Reader holds the data corresponding to the MaxMind DB file. Its only public
|
||||||
|
// field is Metadata, which contains the metadata from the MaxMind DB file.
|
||||||
|
type Reader struct {
|
||||||
|
hasMappedFile bool
|
||||||
|
buffer []byte
|
||||||
|
decoder decoder
|
||||||
|
Metadata Metadata
|
||||||
|
ipv4Start uint
|
||||||
|
}
|
||||||
|
|
||||||
|
// Metadata holds the metadata decoded from the MaxMind DB file. In particular
|
||||||
|
// in has the format version, the build time as Unix epoch time, the database
|
||||||
|
// type and description, the IP version supported, and a slice of the natural
|
||||||
|
// languages included.
|
||||||
|
type Metadata struct {
|
||||||
|
BinaryFormatMajorVersion uint `maxminddb:"binary_format_major_version"`
|
||||||
|
BinaryFormatMinorVersion uint `maxminddb:"binary_format_minor_version"`
|
||||||
|
BuildEpoch uint `maxminddb:"build_epoch"`
|
||||||
|
DatabaseType string `maxminddb:"database_type"`
|
||||||
|
Description map[string]string `maxminddb:"description"`
|
||||||
|
IPVersion uint `maxminddb:"ip_version"`
|
||||||
|
Languages []string `maxminddb:"languages"`
|
||||||
|
NodeCount uint `maxminddb:"node_count"`
|
||||||
|
RecordSize uint `maxminddb:"record_size"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromBytes takes a byte slice corresponding to a MaxMind DB file and returns
|
||||||
|
// a Reader structure or an error.
|
||||||
|
func FromBytes(buffer []byte) (*Reader, error) {
|
||||||
|
metadataStart := bytes.LastIndex(buffer, metadataStartMarker)
|
||||||
|
|
||||||
|
if metadataStart == -1 {
|
||||||
|
return nil, newInvalidDatabaseError("error opening database: invalid MaxMind DB file")
|
||||||
|
}
|
||||||
|
|
||||||
|
metadataStart += len(metadataStartMarker)
|
||||||
|
metadataDecoder := decoder{buffer[metadataStart:]}
|
||||||
|
|
||||||
|
var metadata Metadata
|
||||||
|
|
||||||
|
rvMetdata := reflect.ValueOf(&metadata)
|
||||||
|
_, err := metadataDecoder.decode(0, rvMetdata)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
searchTreeSize := metadata.NodeCount * metadata.RecordSize / 4
|
||||||
|
dataSectionStart := searchTreeSize + dataSectionSeparatorSize
|
||||||
|
dataSectionEnd := uint(metadataStart - len(metadataStartMarker))
|
||||||
|
if dataSectionStart > dataSectionEnd {
|
||||||
|
return nil, newInvalidDatabaseError("the MaxMind DB contains invalid metadata")
|
||||||
|
}
|
||||||
|
d := decoder{
|
||||||
|
buffer[searchTreeSize+dataSectionSeparatorSize : metadataStart-len(metadataStartMarker)],
|
||||||
|
}
|
||||||
|
|
||||||
|
reader := &Reader{
|
||||||
|
buffer: buffer,
|
||||||
|
decoder: d,
|
||||||
|
Metadata: metadata,
|
||||||
|
ipv4Start: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.ipv4Start, err = reader.startNode()
|
||||||
|
|
||||||
|
return reader, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Reader) startNode() (uint, error) {
|
||||||
|
if r.Metadata.IPVersion != 6 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeCount := r.Metadata.NodeCount
|
||||||
|
|
||||||
|
node := uint(0)
|
||||||
|
var err error
|
||||||
|
for i := 0; i < 96 && node < nodeCount; i++ {
|
||||||
|
node, err = r.readNode(node, 0)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return node, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lookup takes an IP address as a net.IP structure and a pointer to the
|
||||||
|
// result value to decode into. The result value pointed to must be a data
|
||||||
|
// value that corresponds to a record in the database. This may include a
|
||||||
|
// struct representation of the data, a map capable of holding the data or an
|
||||||
|
// empty interface{} value.
|
||||||
|
//
|
||||||
|
// If result is a pointer to a struct, the struct need not include a field
|
||||||
|
// for every value that may be in the database. If a field is not present in
|
||||||
|
// the structure, the decoder will not decode that field, reducing the time
|
||||||
|
// required to decode the record.
|
||||||
|
//
|
||||||
|
// Currently the decoder expect most data types to correspond exactly (e.g.,
|
||||||
|
// a uint64 database type must be decoded into a uint64 Go type). In the
|
||||||
|
// future, this may be made more flexible.
|
||||||
|
func (r *Reader) Lookup(ipAddress net.IP, result interface{}) error {
|
||||||
|
if ipAddress == nil {
|
||||||
|
return errors.New("ipAddress passed to Lookup cannot be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
ipV4Address := ipAddress.To4()
|
||||||
|
if ipV4Address != nil {
|
||||||
|
ipAddress = ipV4Address
|
||||||
|
}
|
||||||
|
if len(ipAddress) == 16 && r.Metadata.IPVersion == 4 {
|
||||||
|
return fmt.Errorf("error looking up '%s': you attempted to look up an IPv6 address in an IPv4-only database", ipAddress.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
pointer, err := r.findAddressInTree(ipAddress)
|
||||||
|
|
||||||
|
if pointer == 0 {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.retrieveData(pointer, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Reader) findAddressInTree(ipAddress net.IP) (uint, error) {
|
||||||
|
|
||||||
|
bitCount := uint(len(ipAddress) * 8)
|
||||||
|
|
||||||
|
var node uint
|
||||||
|
if bitCount == 32 {
|
||||||
|
node = r.ipv4Start
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeCount := r.Metadata.NodeCount
|
||||||
|
|
||||||
|
for i := uint(0); i < bitCount && node < nodeCount; i++ {
|
||||||
|
bit := uint(1) & (uint(ipAddress[i>>3]) >> (7 - (i % 8)))
|
||||||
|
|
||||||
|
var err error
|
||||||
|
node, err = r.readNode(node, bit)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if node == nodeCount {
|
||||||
|
// Record is empty
|
||||||
|
return 0, nil
|
||||||
|
} else if node > nodeCount {
|
||||||
|
return node, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, newInvalidDatabaseError("invalid node in search tree")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Reader) readNode(nodeNumber uint, index uint) (uint, error) {
|
||||||
|
RecordSize := r.Metadata.RecordSize
|
||||||
|
|
||||||
|
baseOffset := nodeNumber * RecordSize / 4
|
||||||
|
|
||||||
|
var nodeBytes []byte
|
||||||
|
var prefix uint64
|
||||||
|
switch RecordSize {
|
||||||
|
case 24:
|
||||||
|
offset := baseOffset + index*3
|
||||||
|
nodeBytes = r.buffer[offset : offset+3]
|
||||||
|
case 28:
|
||||||
|
prefix = uint64(r.buffer[baseOffset+3])
|
||||||
|
if index != 0 {
|
||||||
|
prefix &= 0x0F
|
||||||
|
} else {
|
||||||
|
prefix = (0xF0 & prefix) >> 4
|
||||||
|
}
|
||||||
|
offset := baseOffset + index*4
|
||||||
|
nodeBytes = r.buffer[offset : offset+3]
|
||||||
|
case 32:
|
||||||
|
offset := baseOffset + index*4
|
||||||
|
nodeBytes = r.buffer[offset : offset+4]
|
||||||
|
default:
|
||||||
|
return 0, newInvalidDatabaseError("unknown record size: %d", RecordSize)
|
||||||
|
}
|
||||||
|
return uint(uintFromBytes(prefix, nodeBytes)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Reader) retrieveData(pointer uint, result interface{}) error {
|
||||||
|
rv := reflect.ValueOf(result)
|
||||||
|
if rv.Kind() != reflect.Ptr || rv.IsNil() {
|
||||||
|
return errors.New("result param must be a pointer")
|
||||||
|
}
|
||||||
|
|
||||||
|
offset, err := r.resolveDataPointer(pointer)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = r.decoder.decode(offset, rv)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Reader) resolveDataPointer(pointer uint) (uint, error) {
|
||||||
|
nodeCount := r.Metadata.NodeCount
|
||||||
|
|
||||||
|
resolved := pointer - nodeCount - dataSectionSeparatorSize
|
||||||
|
|
||||||
|
if resolved > uint(len(r.buffer)) {
|
||||||
|
return 0, newInvalidDatabaseError("the MaxMind DB file's search tree is corrupt")
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolved, nil
|
||||||
|
}
|
26
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/reader_appengine.go
generated
vendored
Normal file
26
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/reader_appengine.go
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// +build appengine
|
||||||
|
|
||||||
|
package maxminddb
|
||||||
|
|
||||||
|
import "io/ioutil"
|
||||||
|
|
||||||
|
// Open takes a string path to a MaxMind DB file and returns a Reader
|
||||||
|
// structure or an error. The database file is opened using a memory map,
|
||||||
|
// except on Google App Engine where mmap is not supported; there the database
|
||||||
|
// is loaded into memory. Use the Close method on the Reader object to return
|
||||||
|
// the resources to the system.
|
||||||
|
func Open(file string) (*Reader, error) {
|
||||||
|
bytes, err := ioutil.ReadFile(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return FromBytes(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close unmaps the database file from virtual memory and returns the
|
||||||
|
// resources to the system. If called on a Reader opened using FromBytes
|
||||||
|
// or Open on Google App Engine, this method does nothing.
|
||||||
|
func (r *Reader) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
56
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/reader_other.go
generated
vendored
Normal file
56
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/reader_other.go
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
// +build !appengine
|
||||||
|
|
||||||
|
package maxminddb
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
|
||||||
|
// Open takes a string path to a MaxMind DB file and returns a Reader
|
||||||
|
// structure or an error. The database file is opened using a memory map,
|
||||||
|
// except on Google App Engine where mmap is not supported; there the database
|
||||||
|
// is loaded into memory. Use the Close method on the Reader object to return
|
||||||
|
// the resources to the system.
|
||||||
|
func Open(file string) (*Reader, error) {
|
||||||
|
mapFile, err := os.Open(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if rerr := mapFile.Close(); rerr != nil {
|
||||||
|
err = rerr
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
stats, err := mapFile.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fileSize := int(stats.Size())
|
||||||
|
mmap, err := mmap(int(mapFile.Fd()), fileSize)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
reader, err := FromBytes(mmap)
|
||||||
|
if err != nil {
|
||||||
|
if err2 := munmap(mmap); err2 != nil {
|
||||||
|
// failing to unmap the file is probably the more severe error
|
||||||
|
return nil, err2
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.hasMappedFile = true
|
||||||
|
return reader, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close unmaps the database file from virtual memory and returns the
|
||||||
|
// resources to the system. If called on a Reader opened using FromBytes
|
||||||
|
// or Open on Google App Engine, this method does nothing.
|
||||||
|
func (r *Reader) Close() (err error) {
|
||||||
|
if r.hasMappedFile {
|
||||||
|
err = munmap(r.buffer)
|
||||||
|
r.hasMappedFile = false
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
108
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/traverse.go
generated
vendored
Normal file
108
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/traverse.go
generated
vendored
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
package maxminddb
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
// Internal structure used to keep track of nodes we still need to visit.
|
||||||
|
type netNode struct {
|
||||||
|
ip net.IP
|
||||||
|
bit uint
|
||||||
|
pointer uint
|
||||||
|
}
|
||||||
|
|
||||||
|
// Networks represents a set of subnets that we are iterating over.
|
||||||
|
type Networks struct {
|
||||||
|
reader *Reader
|
||||||
|
nodes []netNode // Nodes we still have to visit.
|
||||||
|
lastNode netNode
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Networks returns an iterator that can be used to traverse all networks in
|
||||||
|
// the database.
|
||||||
|
//
|
||||||
|
// Please note that a MaxMind DB may map IPv4 networks into several locations
|
||||||
|
// in in an IPv6 database. This iterator will iterate over all of these
|
||||||
|
// locations separately.
|
||||||
|
func (r *Reader) Networks() *Networks {
|
||||||
|
s := 4
|
||||||
|
if r.Metadata.IPVersion == 6 {
|
||||||
|
s = 16
|
||||||
|
}
|
||||||
|
return &Networks{
|
||||||
|
reader: r,
|
||||||
|
nodes: []netNode{
|
||||||
|
netNode{
|
||||||
|
ip: make(net.IP, s),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next prepares the next network for reading with the Network method. It
|
||||||
|
// returns true if there is another network to be processed and false if there
|
||||||
|
// are no more networks or if there is an error.
|
||||||
|
func (n *Networks) Next() bool {
|
||||||
|
for len(n.nodes) > 0 {
|
||||||
|
node := n.nodes[len(n.nodes)-1]
|
||||||
|
n.nodes = n.nodes[:len(n.nodes)-1]
|
||||||
|
|
||||||
|
for {
|
||||||
|
if node.pointer < n.reader.Metadata.NodeCount {
|
||||||
|
ipRight := make(net.IP, len(node.ip))
|
||||||
|
copy(ipRight, node.ip)
|
||||||
|
if len(ipRight) <= int(node.bit>>3) {
|
||||||
|
n.err = newInvalidDatabaseError(
|
||||||
|
"invalid search tree at %v/%v", ipRight, node.bit)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
ipRight[node.bit>>3] |= 1 << uint(7-(node.bit%8))
|
||||||
|
|
||||||
|
rightPointer, err := n.reader.readNode(node.pointer, 1)
|
||||||
|
if err != nil {
|
||||||
|
n.err = err
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
node.bit++
|
||||||
|
n.nodes = append(n.nodes, netNode{
|
||||||
|
pointer: rightPointer,
|
||||||
|
ip: ipRight,
|
||||||
|
bit: node.bit,
|
||||||
|
})
|
||||||
|
|
||||||
|
node.pointer, err = n.reader.readNode(node.pointer, 0)
|
||||||
|
if err != nil {
|
||||||
|
n.err = err
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if node.pointer > n.reader.Metadata.NodeCount {
|
||||||
|
n.lastNode = node
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Network returns the current network or an error if there is a problem
|
||||||
|
// decoding the data for the network. It takes a pointer to a result value to
|
||||||
|
// decode the network's data into.
|
||||||
|
func (n *Networks) Network(result interface{}) (*net.IPNet, error) {
|
||||||
|
if err := n.reader.retrieveData(n.lastNode.pointer, result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &net.IPNet{
|
||||||
|
IP: n.lastNode.ip,
|
||||||
|
Mask: net.CIDRMask(int(n.lastNode.bit), len(n.lastNode.ip)*8),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Err returns an error, if any, that was encountered during iteration.
|
||||||
|
func (n *Networks) Err() error {
|
||||||
|
return n.err
|
||||||
|
}
|
185
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/verifier.go
generated
vendored
Normal file
185
cmd/strelaypoolsrv/Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/verifier.go
generated
vendored
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
package maxminddb
|
||||||
|
|
||||||
|
import "reflect"
|
||||||
|
|
||||||
|
type verifier struct {
|
||||||
|
reader *Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify checks that the database is valid. It validates the search tree,
|
||||||
|
// the data section, and the metadata section. This verifier is stricter than
|
||||||
|
// the specification and may return errors on databases that are readable.
|
||||||
|
func (r *Reader) Verify() error {
|
||||||
|
v := verifier{r}
|
||||||
|
if err := v.verifyMetadata(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return v.verifyDatabase()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *verifier) verifyMetadata() error {
|
||||||
|
metadata := v.reader.Metadata
|
||||||
|
|
||||||
|
if metadata.BinaryFormatMajorVersion != 2 {
|
||||||
|
return testError(
|
||||||
|
"binary_format_major_version",
|
||||||
|
2,
|
||||||
|
metadata.BinaryFormatMajorVersion,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if metadata.BinaryFormatMinorVersion != 0 {
|
||||||
|
return testError(
|
||||||
|
"binary_format_minor_version",
|
||||||
|
0,
|
||||||
|
metadata.BinaryFormatMinorVersion,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if metadata.DatabaseType == "" {
|
||||||
|
return testError(
|
||||||
|
"database_type",
|
||||||
|
"non-empty string",
|
||||||
|
metadata.DatabaseType,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(metadata.Description) == 0 {
|
||||||
|
return testError(
|
||||||
|
"description",
|
||||||
|
"non-empty slice",
|
||||||
|
metadata.Description,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if metadata.IPVersion != 4 && metadata.IPVersion != 6 {
|
||||||
|
return testError(
|
||||||
|
"ip_version",
|
||||||
|
"4 or 6",
|
||||||
|
metadata.IPVersion,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if metadata.RecordSize != 24 &&
|
||||||
|
metadata.RecordSize != 28 &&
|
||||||
|
metadata.RecordSize != 32 {
|
||||||
|
return testError(
|
||||||
|
"record_size",
|
||||||
|
"24, 28, or 32",
|
||||||
|
metadata.RecordSize,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if metadata.NodeCount == 0 {
|
||||||
|
return testError(
|
||||||
|
"node_count",
|
||||||
|
"positive integer",
|
||||||
|
metadata.NodeCount,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *verifier) verifyDatabase() error {
|
||||||
|
offsets, err := v.verifySearchTree()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := v.verifyDataSectionSeparator(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return v.verifyDataSection(offsets)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *verifier) verifySearchTree() (map[uint]bool, error) {
|
||||||
|
offsets := make(map[uint]bool)
|
||||||
|
|
||||||
|
it := v.reader.Networks()
|
||||||
|
for it.Next() {
|
||||||
|
offset, err := v.reader.resolveDataPointer(it.lastNode.pointer)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
offsets[offset] = true
|
||||||
|
}
|
||||||
|
if err := it.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return offsets, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *verifier) verifyDataSectionSeparator() error {
|
||||||
|
separatorStart := v.reader.Metadata.NodeCount * v.reader.Metadata.RecordSize / 4
|
||||||
|
|
||||||
|
separator := v.reader.buffer[separatorStart : separatorStart+dataSectionSeparatorSize]
|
||||||
|
|
||||||
|
for _, b := range separator {
|
||||||
|
if b != 0 {
|
||||||
|
return newInvalidDatabaseError("unexpected byte in data separator: %v", separator)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *verifier) verifyDataSection(offsets map[uint]bool) error {
|
||||||
|
pointerCount := len(offsets)
|
||||||
|
|
||||||
|
decoder := v.reader.decoder
|
||||||
|
|
||||||
|
var offset uint
|
||||||
|
bufferLen := uint(len(decoder.buffer))
|
||||||
|
for offset < bufferLen {
|
||||||
|
var data interface{}
|
||||||
|
rv := reflect.ValueOf(&data)
|
||||||
|
newOffset, err := decoder.decode(offset, rv)
|
||||||
|
if err != nil {
|
||||||
|
return newInvalidDatabaseError("received decoding error (%v) at offset of %v", err, offset)
|
||||||
|
}
|
||||||
|
if newOffset <= offset {
|
||||||
|
return newInvalidDatabaseError("data section offset unexpectedly went from %v to %v", offset, newOffset)
|
||||||
|
}
|
||||||
|
|
||||||
|
pointer := offset
|
||||||
|
|
||||||
|
if _, ok := offsets[pointer]; ok {
|
||||||
|
delete(offsets, pointer)
|
||||||
|
} else {
|
||||||
|
return newInvalidDatabaseError("found data (%v) at %v that the search tree does not point to", data, pointer)
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = newOffset
|
||||||
|
}
|
||||||
|
|
||||||
|
if offset != bufferLen {
|
||||||
|
return newInvalidDatabaseError(
|
||||||
|
"unexpected data at the end of the data section (last offset: %v, end: %v)",
|
||||||
|
offset,
|
||||||
|
bufferLen,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(offsets) != 0 {
|
||||||
|
return newInvalidDatabaseError(
|
||||||
|
"found %v pointers (of %v) in the search tree that we did not see in the data section",
|
||||||
|
len(offsets),
|
||||||
|
pointerCount,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func testError(
|
||||||
|
field string,
|
||||||
|
expected interface{},
|
||||||
|
actual interface{},
|
||||||
|
) error {
|
||||||
|
return newInvalidDatabaseError(
|
||||||
|
"%v - Expected: %v Actual: %v",
|
||||||
|
field,
|
||||||
|
expected,
|
||||||
|
actual,
|
||||||
|
)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user