123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- package ip
- import (
- "bufio"
- "io"
- "net"
- "os"
- "strconv"
- "strings"
- )
- // IP ip struct info.
- type IP struct {
- Begin uint32
- End uint32
- ISPCode int
- ISP string
- CountryCode int
- Country string
- ProvinceCode int
- Province string
- CityCode int
- City string
- DistrictCode int
- District string
- Latitude float64
- Longitude float64
- }
- // Zone ip struct info.
- type Zone struct {
- ID int64 `json:"id"`
- Addr string `json:"addr"`
- ISP string `json:"isp"`
- Country string `json:"country"`
- Province string `json:"province"`
- City string `json:"city"`
- Latitude float64 `json:"latitude"`
- Longitude float64 `json:"longitude"`
- CountryCode int `json:"country_code,omitempty"`
- }
- // List struct info list.
- type List struct {
- IPs []*IP
- }
- // New create Xip instance and return.
- func New(path string) (list *List, err error) {
- var (
- ip *IP
- file *os.File
- line []byte
- )
- list = new(List)
- if file, err = os.Open(path); err != nil {
- return
- }
- defer file.Close()
- reader := bufio.NewReader(file)
- for {
- if line, _, err = reader.ReadLine(); err != nil {
- if err == io.EOF {
- err = nil
- break
- }
- continue
- }
- lines := strings.Fields(string(line))
- if len(lines) < 13 {
- continue
- }
- // lines[2]:country lines[3]:province lines[4]:city lines[5]:unit
- if lines[3] == "香港" || lines[3] == "澳门" || lines[3] == "台湾" {
- lines[2] = lines[3]
- lines[3] = lines[4]
- lines[4] = "*"
- }
- // ex.: from 中国 中国 * to 中国 ”“ ”“
- if lines[2] == lines[3] || lines[3] == "*" {
- lines[3] = ""
- lines[4] = ""
- } else if lines[3] == lines[4] || lines[4] == "*" {
- // ex.: from 中国 北京 北京 to 中国 北京 ”“
- lines[4] = ""
- }
- ip = &IP{
- Begin: InetAtoN(lines[0]),
- End: InetAtoN(lines[1]),
- Country: lines[2],
- Province: lines[3],
- City: lines[4],
- ISP: lines[6],
- }
- ip.Latitude, _ = strconv.ParseFloat(lines[7], 64)
- ip.Longitude, _ = strconv.ParseFloat(lines[8], 64)
- ip.CountryCode, _ = strconv.Atoi(lines[12])
- list.IPs = append(list.IPs, ip)
- }
- return
- }
- // IP ip zone info by ip
- func (l *List) IP(ipStr string) (ip *IP) {
- addr := InetAtoN(ipStr)
- i, j := 0, len(l.IPs)
- for i < j {
- h := i + (j-i)/2 // avoid overflow when computing h
- ip = l.IPs[h]
- // i ≤ h < j
- if addr < ip.Begin {
- j = h
- } else if addr > ip.End {
- i = h + 1
- } else {
- break
- }
- }
- return
- }
- // Zone get ip info from ip
- func (l *List) Zone(addr string) (zone *Zone) {
- ip := l.IP(addr)
- if ip == nil {
- return
- }
- return &Zone{
- ID: ZoneID(ip.Country, ip.Province, ip.City),
- Addr: addr,
- ISP: ip.ISP,
- Country: ip.Country,
- Province: ip.Province,
- City: ip.City,
- Latitude: ip.Latitude,
- Longitude: ip.Longitude,
- CountryCode: ip.CountryCode,
- }
- }
- // All return ipInfos.
- func (l *List) All() []*IP {
- return l.IPs
- }
- // ExternalIP get external ip.
- func ExternalIP() (res []string) {
- inters, err := net.Interfaces()
- if err != nil {
- return
- }
- for _, inter := range inters {
- if !strings.HasPrefix(inter.Name, "lo") {
- addrs, err := inter.Addrs()
- if err != nil {
- continue
- }
- for _, addr := range addrs {
- if ipnet, ok := addr.(*net.IPNet); ok {
- if ipnet.IP.IsLoopback() || ipnet.IP.IsLinkLocalMulticast() || ipnet.IP.IsLinkLocalUnicast() {
- continue
- }
- if ip4 := ipnet.IP.To4(); ip4 != nil {
- switch true {
- case ip4[0] == 10:
- continue
- case ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31:
- continue
- case ip4[0] == 192 && ip4[1] == 168:
- continue
- default:
- res = append(res, ipnet.IP.String())
- }
- }
- }
- }
- }
- }
- return
- }
- // InternalIP get internal ip.
- func InternalIP() string {
- inters, err := net.Interfaces()
- if err != nil {
- return ""
- }
- for _, inter := range inters {
- if !strings.HasPrefix(inter.Name, "lo") {
- addrs, err := inter.Addrs()
- if err != nil {
- continue
- }
- for _, addr := range addrs {
- if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
- if ipnet.IP.To4() != nil {
- return ipnet.IP.String()
- }
- }
- }
- }
- }
- return ""
- }
- // InetAtoN conver ip addr to uint32.
- func InetAtoN(s string) (sum uint32) {
- ip := net.ParseIP(s)
- if ip == nil {
- return
- }
- ip = ip.To4()
- if ip == nil {
- return
- }
- sum += uint32(ip[0]) << 24
- sum += uint32(ip[1]) << 16
- sum += uint32(ip[2]) << 8
- sum += uint32(ip[3])
- return sum
- }
- // InetNtoA conver uint32 to ip addr.
- func InetNtoA(sum uint32) string {
- ip := make(net.IP, net.IPv4len)
- ip[0] = byte((sum >> 24) & 0xFF)
- ip[1] = byte((sum >> 16) & 0xFF)
- ip[2] = byte((sum >> 8) & 0xFF)
- ip[3] = byte(sum & 0xFF)
- return ip.String()
- }
|