geoip_gen.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. // +build generate
  2. package main
  3. import (
  4. "bufio"
  5. "fmt"
  6. "log"
  7. "math"
  8. "net"
  9. "net/http"
  10. "os"
  11. "strconv"
  12. "strings"
  13. "v2ray.com/core/app/router"
  14. "v2ray.com/core/common/errors"
  15. "v2ray.com/core/tools/geoip"
  16. "github.com/golang/protobuf/proto"
  17. )
  18. const (
  19. apnicFile = "http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest"
  20. )
  21. func main() {
  22. resp, err := http.Get(apnicFile)
  23. if err != nil {
  24. panic(err)
  25. }
  26. if resp.StatusCode != 200 {
  27. panic(errors.Format("Unexpected status %d", resp.StatusCode))
  28. }
  29. defer resp.Body.Close()
  30. scanner := bufio.NewScanner(resp.Body)
  31. ips := &geoip.CountryIPRange{
  32. Ips: make([]*router.CIDR, 0, 8192),
  33. }
  34. for scanner.Scan() {
  35. line := scanner.Text()
  36. line = strings.TrimSpace(line)
  37. parts := strings.Split(line, "|")
  38. if len(parts) < 5 {
  39. continue
  40. }
  41. if strings.ToLower(parts[1]) != "cn" || strings.ToLower(parts[2]) != "ipv4" {
  42. continue
  43. }
  44. ip := parts[3]
  45. count, err := strconv.Atoi(parts[4])
  46. if err != nil {
  47. continue
  48. }
  49. mask := uint32(math.Floor(math.Log2(float64(count)) + 0.5))
  50. ipBytes := net.ParseIP(ip)
  51. if len(ipBytes) == 0 {
  52. panic("Invalid IP " + ip)
  53. }
  54. ips.Ips = append(ips.Ips, &router.CIDR{
  55. Ip: []byte(ipBytes)[12:16],
  56. Prefix: 32 - mask,
  57. })
  58. }
  59. ipbytes, err := proto.Marshal(ips)
  60. if err != nil {
  61. log.Fatalf("Failed to marshal country IPs: %v", err)
  62. }
  63. file, err := os.OpenFile("geoip_data.go", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
  64. if err != nil {
  65. log.Fatalf("Failed to generate geoip_data.go: %v", err)
  66. }
  67. defer file.Close()
  68. fmt.Fprintln(file, "package geoip")
  69. fmt.Fprintln(file, "var ChinaIPs = "+formatArray(ipbytes))
  70. }
  71. func formatArray(a []byte) string {
  72. r := "[]byte{"
  73. for idx, val := range a {
  74. if idx > 0 {
  75. r += ","
  76. }
  77. r += fmt.Sprintf("%d", val)
  78. }
  79. r += "}"
  80. return r
  81. }