geoip_gen.go 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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. )
  14. const (
  15. apnicFile = "http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest"
  16. )
  17. type IPEntry struct {
  18. IP []byte
  19. Bits uint32
  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(fmt.Errorf("Unexpected status %d", resp.StatusCode))
  28. }
  29. defer resp.Body.Close()
  30. scanner := bufio.NewScanner(resp.Body)
  31. ips := make([]IPEntry, 0, 8192)
  32. for scanner.Scan() {
  33. line := scanner.Text()
  34. line = strings.TrimSpace(line)
  35. parts := strings.Split(line, "|")
  36. if len(parts) < 5 {
  37. continue
  38. }
  39. if strings.ToLower(parts[1]) != "cn" || strings.ToLower(parts[2]) != "ipv4" {
  40. continue
  41. }
  42. ip := parts[3]
  43. count, err := strconv.Atoi(parts[4])
  44. if err != nil {
  45. continue
  46. }
  47. mask := uint32(math.Floor(math.Log2(float64(count)) + 0.5))
  48. ipBytes := net.ParseIP(ip)
  49. if len(ipBytes) == 0 {
  50. panic("Invalid IP " + ip)
  51. }
  52. ips = append(ips, IPEntry{
  53. IP: []byte(ipBytes),
  54. Bits: mask,
  55. })
  56. }
  57. file, err := os.OpenFile("geoip_data.go", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
  58. if err != nil {
  59. log.Fatalf("Failed to generate geoip_data.go: %v", err)
  60. }
  61. defer file.Close()
  62. fmt.Fprintln(file, "package geoip")
  63. fmt.Fprintln(file, "import \"v2ray.com/core/app/router\"")
  64. fmt.Fprintln(file, "var ChinaIPs []*router.IP")
  65. fmt.Fprintln(file, "func init() {")
  66. fmt.Fprintln(file, "ChinaIPs = []*router.IP {")
  67. for _, ip := range ips {
  68. fmt.Fprintln(file, "&router.IP{", formatArray(ip.IP[12:16]), ",", ip.Bits, "},")
  69. }
  70. fmt.Fprintln(file, "}")
  71. fmt.Fprintln(file, "}")
  72. }
  73. func formatArray(a []byte) string {
  74. r := "[]byte{"
  75. for idx, v := range a {
  76. if idx > 0 {
  77. r += ","
  78. }
  79. r += fmt.Sprintf("%d", v)
  80. }
  81. r += "}"
  82. return r
  83. }