github.com/aaabigfish/gopkg@v1.1.0/net/ip/ip.go (about) 1 package ip 2 3 import ( 4 "bufio" 5 "io" 6 "net" 7 "os" 8 "strconv" 9 "strings" 10 ) 11 12 // IP ip struct info. 13 type IP struct { 14 Begin uint32 15 End uint32 16 ISPCode int 17 ISP string 18 CountryCode int 19 Country string 20 ProvinceCode int 21 Province string 22 CityCode int 23 City string 24 DistrictCode int 25 District string 26 Latitude float64 27 Longitude float64 28 } 29 30 // Zone ip struct info. 31 type Zone struct { 32 ID int64 `json:"id"` 33 Addr string `json:"addr"` 34 ISP string `json:"isp"` 35 Country string `json:"country"` 36 Province string `json:"province"` 37 City string `json:"city"` 38 Latitude float64 `json:"latitude"` 39 Longitude float64 `json:"longitude"` 40 CountryCode int `json:"country_code,omitempty"` 41 } 42 43 // List struct info list. 44 type List struct { 45 IPs []*IP 46 } 47 48 // New create Xip instance and return. 49 func New(path string) (list *List, err error) { 50 var ( 51 ip *IP 52 file *os.File 53 line []byte 54 ) 55 list = new(List) 56 if file, err = os.Open(path); err != nil { 57 return 58 } 59 defer file.Close() 60 reader := bufio.NewReader(file) 61 for { 62 if line, _, err = reader.ReadLine(); err != nil { 63 if err == io.EOF { 64 err = nil 65 break 66 } 67 continue 68 } 69 lines := strings.Fields(string(line)) 70 if len(lines) < 13 { 71 continue 72 } 73 // lines[2]:country lines[3]:province lines[4]:city lines[5]:unit 74 if lines[3] == "香港" || lines[3] == "澳门" || lines[3] == "台湾" { 75 lines[2] = lines[3] 76 lines[3] = lines[4] 77 lines[4] = "*" 78 } 79 // ex.: from 中国 中国 * to 中国 ”“ ”“ 80 if lines[2] == lines[3] || lines[3] == "*" { 81 lines[3] = "" 82 lines[4] = "" 83 } else if lines[3] == lines[4] || lines[4] == "*" { 84 // ex.: from 中国 北京 北京 to 中国 北京 ”“ 85 lines[4] = "" 86 } 87 ip = &IP{ 88 Begin: InetAtoN(lines[0]), 89 End: InetAtoN(lines[1]), 90 Country: lines[2], 91 Province: lines[3], 92 City: lines[4], 93 ISP: lines[6], 94 } 95 ip.Latitude, _ = strconv.ParseFloat(lines[7], 64) 96 ip.Longitude, _ = strconv.ParseFloat(lines[8], 64) 97 ip.CountryCode, _ = strconv.Atoi(lines[12]) 98 list.IPs = append(list.IPs, ip) 99 } 100 return 101 } 102 103 // IP ip zone info by ip 104 func (l *List) IP(ipStr string) (ip *IP) { 105 addr := InetAtoN(ipStr) 106 i, j := 0, len(l.IPs) 107 for i < j { 108 h := i + (j-i)/2 // avoid overflow when computing h 109 ip = l.IPs[h] 110 // i ≤ h < j 111 if addr < ip.Begin { 112 j = h 113 } else if addr > ip.End { 114 i = h + 1 115 } else { 116 break 117 } 118 } 119 return 120 } 121 122 // Zone get ip info from ip 123 func (l *List) Zone(addr string) (zone *Zone) { 124 ip := l.IP(addr) 125 if ip == nil { 126 return 127 } 128 return &Zone{ 129 ID: ZoneID(ip.Country, ip.Province, ip.City), 130 Addr: addr, 131 ISP: ip.ISP, 132 Country: ip.Country, 133 Province: ip.Province, 134 City: ip.City, 135 Latitude: ip.Latitude, 136 Longitude: ip.Longitude, 137 CountryCode: ip.CountryCode, 138 } 139 } 140 141 // All return ipInfos. 142 func (l *List) All() []*IP { 143 return l.IPs 144 } 145 146 // ExternalIP get external ip. 147 func ExternalIP() (res []string) { 148 inters, err := net.Interfaces() 149 if err != nil { 150 return 151 } 152 for _, inter := range inters { 153 if !strings.HasPrefix(inter.Name, "lo") { 154 addrs, err := inter.Addrs() 155 if err != nil { 156 continue 157 } 158 for _, addr := range addrs { 159 if ipnet, ok := addr.(*net.IPNet); ok { 160 if ipnet.IP.IsLoopback() || ipnet.IP.IsLinkLocalMulticast() || ipnet.IP.IsLinkLocalUnicast() { 161 continue 162 } 163 if ip4 := ipnet.IP.To4(); ip4 != nil { 164 switch true { 165 case ip4[0] == 10: 166 continue 167 case ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31: 168 continue 169 case ip4[0] == 192 && ip4[1] == 168: 170 continue 171 default: 172 res = append(res, ipnet.IP.String()) 173 } 174 } 175 } 176 } 177 } 178 } 179 return 180 } 181 182 // InternalIP get internal ip. 183 func InternalIP() string { 184 inters, err := net.Interfaces() 185 if err != nil { 186 return "" 187 } 188 for _, inter := range inters { 189 if !strings.HasPrefix(inter.Name, "lo") { 190 addrs, err := inter.Addrs() 191 if err != nil { 192 continue 193 } 194 for _, addr := range addrs { 195 if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { 196 if ipnet.IP.To4() != nil { 197 return ipnet.IP.String() 198 } 199 } 200 } 201 } 202 } 203 return "" 204 } 205 206 // InetAtoN conver ip addr to uint32. 207 func InetAtoN(s string) (sum uint32) { 208 ip := net.ParseIP(s) 209 if ip == nil { 210 return 211 } 212 ip = ip.To4() 213 if ip == nil { 214 return 215 } 216 sum += uint32(ip[0]) << 24 217 sum += uint32(ip[1]) << 16 218 sum += uint32(ip[2]) << 8 219 sum += uint32(ip[3]) 220 return sum 221 } 222 223 // InetNtoA conver uint32 to ip addr. 224 func InetNtoA(sum uint32) string { 225 ip := make(net.IP, net.IPv4len) 226 ip[0] = byte((sum >> 24) & 0xFF) 227 ip[1] = byte((sum >> 16) & 0xFF) 228 ip[2] = byte((sum >> 8) & 0xFF) 229 ip[3] = byte(sum & 0xFF) 230 return ip.String() 231 }