geoip_gen.go 1.8 KB

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