mirror of
https://github.com/lionsoul2014/ip2region.git
synced 2025-12-08 19:25:22 +00:00
98 lines
2.0 KiB
Go
98 lines
2.0 KiB
Go
// Copyright 2022 The Ip2Region Authors. All rights reserved.
|
|
// Use of this source code is governed by a Apache2.0-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package xdb
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
type Version struct {
|
|
Id int
|
|
Name string
|
|
Bytes int
|
|
SegmentIndexSize int
|
|
|
|
// function to compare two ips
|
|
IPCompare func([]byte, []byte) int
|
|
}
|
|
|
|
const (
|
|
IPv4VersionNo = 4
|
|
IPv6VersionNo = 6
|
|
)
|
|
|
|
var (
|
|
IPvx = &Version{}
|
|
IPv4 = &Version{
|
|
Id: IPv4VersionNo,
|
|
Name: "IPv4",
|
|
Bytes: 4,
|
|
SegmentIndexSize: 14, // 4 + 4 + 2 + 4,
|
|
IPCompare: func(ip1, ip2 []byte) int {
|
|
// ip1 - with Big endian byte order parsed from an input
|
|
// ip2 - with Little endian byte order read from the xdb index
|
|
ip2[0], ip2[3] = ip2[3], ip2[0]
|
|
ip2[1], ip2[2] = ip2[2], ip2[1]
|
|
return bytes.Compare(ip1, ip2)
|
|
},
|
|
}
|
|
IPv6 = &Version{
|
|
Id: IPv6VersionNo,
|
|
Name: "IPv6",
|
|
Bytes: 16,
|
|
SegmentIndexSize: 38, // 16 + 16 + 2 + 4,
|
|
IPCompare: func(ip1, ip2 []byte) int {
|
|
return bytes.Compare(ip1, ip2)
|
|
},
|
|
}
|
|
)
|
|
|
|
func VersionFromIP(ip string) (*Version, error) {
|
|
r, err := ParseIP(ip)
|
|
if err != nil {
|
|
return IPvx, fmt.Errorf("parse ip fail: %w", err)
|
|
}
|
|
|
|
if len(r) == 4 {
|
|
return IPv4, nil
|
|
}
|
|
|
|
return IPv6, nil
|
|
}
|
|
|
|
func VersionFromName(name string) (*Version, error) {
|
|
switch strings.ToUpper(name) {
|
|
case "V4", "IPV4":
|
|
return IPv4, nil
|
|
case "V6", "IPV6":
|
|
return IPv6, nil
|
|
default:
|
|
return IPvx, fmt.Errorf("invalid version name `%s`", name)
|
|
}
|
|
}
|
|
|
|
func VersionFromHeader(header *Header) (*Version, error) {
|
|
// old structure with IPv4 supports ONLY
|
|
if header.Version == Structure20 {
|
|
return IPv4, nil
|
|
}
|
|
|
|
// structure 3.0 after IPv6 supporting
|
|
if header.Version != Structure30 {
|
|
return IPvx, fmt.Errorf("invalid version `%d`", header.IPVersion)
|
|
}
|
|
|
|
switch header.IPVersion {
|
|
case IPv4VersionNo:
|
|
return IPv4, nil
|
|
case IPv6VersionNo:
|
|
return IPv6, nil
|
|
default:
|
|
return IPvx, fmt.Errorf("invalid version `%d`", header.Version)
|
|
}
|
|
}
|