chinaip_gen.go 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  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("chinaip_init.go", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
  58. if err != nil {
  59. log.Fatalf("Failed to generate chinaip_init.go: %v", err)
  60. }
  61. defer file.Close()
  62. fmt.Fprintln(file, "package router")
  63. fmt.Fprintln(file, "var chinaIPs []*IP")
  64. fmt.Fprintln(file, "func init() {")
  65. fmt.Fprintln(file, "chinaIPs = []*IP {")
  66. for _, ip := range ips {
  67. fmt.Fprintln(file, "&IP{", formatArray(ip.IP[12:16]), ",", ip.Bits, "},")
  68. }
  69. fmt.Fprintln(file, "}")
  70. fmt.Fprintln(file, "}")
  71. }
  72. func formatArray(a []byte) string {
  73. r := "[]byte{"
  74. for idx, v := range a {
  75. if idx > 0 {
  76. r += ","
  77. }
  78. r += fmt.Sprintf("%d", v)
  79. }
  80. r += "}"
  81. return r
  82. }