Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
6ac03c18cc | |||
22855ebec2 |
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/bazel-*
|
24
BUILD.bazel
Normal file
24
BUILD.bazel
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
load("@bazel_gazelle//:def.bzl", "gazelle")
|
||||||
|
|
||||||
|
gazelle(name = "gazelle")
|
||||||
|
|
||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = ["main.go"],
|
||||||
|
importpath = "git.eve.moe/jackyyf/navigator",
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
deps = [
|
||||||
|
"//ipgeo:go_default_library",
|
||||||
|
"//mapping:go_default_library",
|
||||||
|
"@com_github_ipipdotnet_ipdb_go//:go_default_library",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
go_binary(
|
||||||
|
name = "navigator",
|
||||||
|
pure = "on",
|
||||||
|
embed = [":go_default_library"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
43
WORKSPACE
Normal file
43
WORKSPACE
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||||
|
|
||||||
|
http_archive(
|
||||||
|
name = "io_bazel_rules_go",
|
||||||
|
urls = [
|
||||||
|
"https://storage.googleapis.com/bazel-mirror/github.com/bazelbuild/rules_go/releases/download/v0.20.3/rules_go-v0.20.3.tar.gz",
|
||||||
|
"https://github.com/bazelbuild/rules_go/releases/download/v0.20.3/rules_go-v0.20.3.tar.gz",
|
||||||
|
],
|
||||||
|
sha256 = "e88471aea3a3a4f19ec1310a55ba94772d087e9ce46e41ae38ecebe17935de7b",
|
||||||
|
)
|
||||||
|
|
||||||
|
http_archive(
|
||||||
|
name = "bazel_gazelle",
|
||||||
|
urls = [
|
||||||
|
"https://storage.googleapis.com/bazel-mirror/github.com/bazelbuild/bazel-gazelle/releases/download/v0.19.1/bazel-gazelle-v0.19.1.tar.gz",
|
||||||
|
"https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.19.1/bazel-gazelle-v0.19.1.tar.gz",
|
||||||
|
],
|
||||||
|
sha256 = "86c6d481b3f7aedc1d60c1c211c6f76da282ae197c3b3160f54bd3a8f847896f",
|
||||||
|
)
|
||||||
|
|
||||||
|
load("@io_bazel_rules_go//go:deps.bzl", "go_rules_dependencies", "go_register_toolchains")
|
||||||
|
|
||||||
|
go_rules_dependencies()
|
||||||
|
|
||||||
|
go_register_toolchains()
|
||||||
|
|
||||||
|
load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies", "go_repository")
|
||||||
|
|
||||||
|
gazelle_dependencies()
|
||||||
|
|
||||||
|
go_repository(
|
||||||
|
name = "com_github_ipipdotnet_ipdb_go",
|
||||||
|
importpath = "github.com/ipipdotnet/ipdb-go",
|
||||||
|
sum = "h1:Afa0qx/SgRevzIK8Qg1TevuD5M28kFLWbzPvU+GQJ08=",
|
||||||
|
version = "v1.2.0",
|
||||||
|
)
|
||||||
|
|
||||||
|
go_repository(
|
||||||
|
name = "net_starlark_go",
|
||||||
|
importpath = "go.starlark.net",
|
||||||
|
sum = "h1:ZP11CRSzO9uOTTOVkH6yodtI3kSY69vUID8lx8B0M3s=",
|
||||||
|
version = "v0.0.0-20191113183327-aaf7be003892",
|
||||||
|
)
|
14
ipgeo/BUILD.bazel
Normal file
14
ipgeo/BUILD.bazel
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = ["ipdb.go"],
|
||||||
|
importpath = "git.eve.moe/jackyyf/navigator/ipgeo",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
deps = [
|
||||||
|
"//mapping/elf:go_default_library",
|
||||||
|
"@com_github_ipipdotnet_ipdb_go//:go_default_library",
|
||||||
|
"@net_starlark_go//starlark:go_default_library",
|
||||||
|
"@net_starlark_go//starlarkstruct:go_default_library",
|
||||||
|
],
|
||||||
|
)
|
21
main.go
21
main.go
@ -151,6 +151,27 @@ func main() {
|
|||||||
log.Printf("%s => %s\n", ip, server)
|
log.Printf("%s => %s\n", ip, server)
|
||||||
fmt.Fprint(resp, server)
|
fmt.Fprint(resp, server)
|
||||||
})
|
})
|
||||||
|
http.HandleFunc("/getNodes", func(resp http.ResponseWriter, req *http.Request) {
|
||||||
|
ip := req.FormValue("ip")
|
||||||
|
if net.ParseIP(ip).To4() == nil {
|
||||||
|
responseWithError(resp, http.StatusBadRequest, errIPv4Only)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
nodes := mapping.GetNodes()
|
||||||
|
if nodes == nil {
|
||||||
|
responseWithJsonError(resp, http.StatusInternalServerError, "Unable to get nodes")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
suffix := mapping.GetSuffix(ip)
|
||||||
|
resp.Header().Set("Content-Type", "application/json")
|
||||||
|
resp.WriteHeader(http.StatusOK)
|
||||||
|
jsonEncoder := json.NewEncoder(resp)
|
||||||
|
ret := make([]string, 0, len(nodes))
|
||||||
|
for _, node := range nodes {
|
||||||
|
ret = append(ret, node+suffix)
|
||||||
|
}
|
||||||
|
jsonEncoder.Encode(ret)
|
||||||
|
})
|
||||||
clientApi := http.NewServeMux()
|
clientApi := http.NewServeMux()
|
||||||
http.Handle("/client/", http.StripPrefix("/client", clientApi))
|
http.Handle("/client/", http.StripPrefix("/client", clientApi))
|
||||||
clientV1Api := http.NewServeMux()
|
clientV1Api := http.NewServeMux()
|
||||||
|
9
mapping/BUILD.bazel
Normal file
9
mapping/BUILD.bazel
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = ["map.go"],
|
||||||
|
importpath = "git.eve.moe/jackyyf/navigator/mapping",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
deps = ["//mapping/elf:go_default_library"],
|
||||||
|
)
|
9
mapping/elf/BUILD.bazel
Normal file
9
mapping/elf/BUILD.bazel
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = ["core.go"],
|
||||||
|
importpath = "git.eve.moe/jackyyf/navigator/mapping/elf",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
deps = ["@net_starlark_go//starlark:go_default_library"],
|
||||||
|
)
|
@ -4,11 +4,14 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"go.starlark.net/starlark"
|
"go.starlark.net/starlark"
|
||||||
)
|
)
|
||||||
@ -36,6 +39,7 @@ var (
|
|||||||
reloadSignal = make(chan os.Signal)
|
reloadSignal = make(chan os.Signal)
|
||||||
pool *threadPool
|
pool *threadPool
|
||||||
counter uint64
|
counter uint64
|
||||||
|
rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
)
|
)
|
||||||
|
|
||||||
func newThreadPool(size int) *threadPool {
|
func newThreadPool(size int) *threadPool {
|
||||||
@ -147,9 +151,56 @@ func GetMapping(ip string) string {
|
|||||||
log.Println("Starlark execute error:", err.Error())
|
log.Println("Starlark execute error:", err.Error())
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
if r, ok := ret.(starlark.String); ok {
|
switch r := ret.(type) {
|
||||||
|
case starlark.String:
|
||||||
return string(r)
|
return string(r)
|
||||||
|
case *starlark.List:
|
||||||
|
val := r.Index(rnd.Intn(r.Len()))
|
||||||
|
if s, ok := val.(starlark.String); ok {
|
||||||
|
return string(s)
|
||||||
}
|
}
|
||||||
|
goto scriptError
|
||||||
|
case starlark.Tuple:
|
||||||
|
val := r.Index(rnd.Intn(r.Len()))
|
||||||
|
if s, ok := val.(starlark.String); ok {
|
||||||
|
return string(s)
|
||||||
|
}
|
||||||
|
goto scriptError
|
||||||
|
case *starlark.Dict:
|
||||||
|
values := r.Items()
|
||||||
|
options := make([]string, r.Len())
|
||||||
|
tot := int64(0)
|
||||||
|
for i := range values {
|
||||||
|
if v, ok := values[i].Index(0).(starlark.String); ok {
|
||||||
|
options[i] = string(v)
|
||||||
|
} else {
|
||||||
|
goto scriptError
|
||||||
|
}
|
||||||
|
if v, ok := values[i].Index(1).(starlark.Int); ok {
|
||||||
|
if weight, ok := v.Int64(); ok {
|
||||||
|
tot += weight
|
||||||
|
} else {
|
||||||
|
goto scriptError
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
goto scriptError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Strings(options)
|
||||||
|
pos := rnd.Int63n(tot)
|
||||||
|
for _, option := range options {
|
||||||
|
w, _, _ := r.Get(starlark.String(option))
|
||||||
|
v, _ := w.(starlark.Int).Int64()
|
||||||
|
pos -= v
|
||||||
|
if pos < 0 {
|
||||||
|
return option
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Println("Unexpected code execution,",
|
||||||
|
"check random logic for *starlark.Dict")
|
||||||
|
return options[len(options)-1]
|
||||||
|
}
|
||||||
|
scriptError:
|
||||||
log.Println("Script returned unexpected result:", ret.String())
|
log.Println("Script returned unexpected result:", ret.String())
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,7 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
defaultServer = flag.String("fallback-node",
|
defaultServer = flag.String("fallback-node",
|
||||||
"xe-mci1-us.edge.eve.network",
|
"xe-mci1-us", "Default CDN node in case of any script error")
|
||||||
"Default CDN node in case of any script error")
|
|
||||||
defaultSuffix = flag.String("fallback-suffix",
|
defaultSuffix = flag.String("fallback-suffix",
|
||||||
".edge.eve.network",
|
".edge.eve.network",
|
||||||
"Default CDN suffix in case of any script error")
|
"Default CDN suffix in case of any script error")
|
||||||
@ -19,11 +18,15 @@ func Initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Get(ip string) string {
|
func Get(ip string) string {
|
||||||
ret := elf.GetMapping(ip)
|
node := elf.GetMapping(ip)
|
||||||
if ret == "" {
|
if node == "" {
|
||||||
return *defaultServer
|
node = *defaultServer
|
||||||
}
|
}
|
||||||
return ret
|
suffix := elf.GetSuffix(ip)
|
||||||
|
if suffix == "" {
|
||||||
|
suffix = *defaultSuffix
|
||||||
|
}
|
||||||
|
return node + suffix
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetSuffix(ip string) string {
|
func GetSuffix(ip string) string {
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
WHOLESALE_INTERNET_10GE = "xe-mci1-us"
|
WHOLESALE_INTERNET_10GE = "xe-mci1-us"
|
||||||
HETZNER_FSN_1GE = "ge-fsn1-de"
|
HETZNER_FSN_1GE = "ge-fsn1-de"
|
||||||
HETZNER_HEL_1GE = "ge-hel1-fi"
|
HETZNER_HEL_1GE = "ge-hel1-fi"
|
||||||
|
CLOUDCONE_LAX1_1GE = "ge-lax1-us"
|
||||||
|
CLOUDCONE_LAX2_1GE = "ge-lax2-us"
|
||||||
|
CLOUDCONE_LAX_LB = (CLOUDCONE_LAX1_1GE, CLOUDCONE_LAX2_1GE)
|
||||||
default_server = WHOLESALE_INTERNET_10GE
|
default_server = WHOLESALE_INTERNET_10GE
|
||||||
|
|
||||||
CHINA_MAINLAND_SUFFIX = ".eveedge.link"
|
CHINA_MAINLAND_SUFFIX = ".eveedge.link"
|
||||||
@ -11,12 +14,20 @@ default_suffix = GLOBAL_SUFFIX
|
|||||||
def getMapping(ip):
|
def getMapping(ip):
|
||||||
info = geoLookup(ip)
|
info = geoLookup(ip)
|
||||||
if not info:
|
if not info:
|
||||||
return default_server + default_suffix
|
return default_server
|
||||||
if info.IspDomain == "ChinaMobile":
|
if info.IspDomain == "ChinaMobile":
|
||||||
return HETZNER_FSN_1GE + CHINA_MAINLAND_SUFFIX
|
return HETZNER_FSN_1GE
|
||||||
|
if info.IspDomain == "ChinaTelecom":
|
||||||
|
return CLOUDCONE_LAX_LB
|
||||||
if info.CountryCode == "CN":
|
if info.CountryCode == "CN":
|
||||||
return default_server + CHINA_MAINLAND_SUFFIX
|
return default_server
|
||||||
return default_server + GLOBAL_SUFFIX
|
if ip == "0.11.45.14":
|
||||||
|
return {
|
||||||
|
default_server: 3,
|
||||||
|
CLOUDCONE_LAX1_1GE: 2,
|
||||||
|
CLOUDCONE_LAX2_1GE: 1,
|
||||||
|
}
|
||||||
|
return default_server
|
||||||
|
|
||||||
def getNodes():
|
def getNodes():
|
||||||
return ["xe-mci1-us", "ge-fsn1-de", "ge-lax1-us"]
|
return ["xe-mci1-us", "ge-fsn1-de", "ge-lax1-us"]
|
||||||
|
Reference in New Issue
Block a user