├── go.sum ├── README.md ├── go.mod ├── .gitignore ├── resolverarray.go ├── stringmap.go ├── stringarray.go ├── route.go └── LICENSE /go.sum: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nkngomobile 2 | nkngomobile 3 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/nknorg/nkngomobile 2 | 3 | go 1.18 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | .idea -------------------------------------------------------------------------------- /resolverarray.go: -------------------------------------------------------------------------------- 1 | package nkngomobile 2 | 3 | import ( 4 | mathRand "math/rand" 5 | ) 6 | 7 | type Resolver interface { 8 | Resolve(address string) (string, error) 9 | } 10 | 11 | // ResolverArray is a wrapper type for gomobile compatibility. ResolverArray is not 12 | // protected by lock and should not be read and write at the same time. 13 | type ResolverArray struct{ elems []Resolver } 14 | 15 | // NewResolverArray creates a ResolverArray from a list of string elements. 16 | func NewResolverArray(elems ...Resolver) *ResolverArray { 17 | return &ResolverArray{elems} 18 | } 19 | 20 | // NewResolverArrayFromResolver creates a ResolverArray from a single string input. 21 | // The input string will be split to string array by whitespace. 22 | func NewResolverArrayFromResolver(e Resolver) *ResolverArray { 23 | return &ResolverArray{[]Resolver{e}} 24 | } 25 | 26 | // Elems returns the string array elements. 27 | func (ia *ResolverArray) Elems() []Resolver { 28 | if ia == nil { 29 | return nil 30 | } 31 | return ia.elems 32 | } 33 | 34 | // Len returns the string array length. 35 | func (ia *ResolverArray) Len() int { 36 | return len(ia.Elems()) 37 | } 38 | 39 | // Append adds an element to the string array. 40 | func (ia *ResolverArray) Append(a Resolver) { 41 | ia.elems = append(ia.elems, a) 42 | } 43 | 44 | // Get gets an element to the string array. 45 | func (ia *ResolverArray) Get(i int) Resolver { 46 | return ia.Elems()[i] 47 | } 48 | 49 | // RandomElem returns a randome element from the string array. The random number 50 | // is generated using math/rand and thus not cryptographically secure. 51 | func (ia *ResolverArray) RandomElem() Resolver { 52 | if ia.Len() == 0 { 53 | return nil 54 | } 55 | return ia.Elems()[mathRand.Intn(ia.Len())] 56 | } 57 | -------------------------------------------------------------------------------- /stringmap.go: -------------------------------------------------------------------------------- 1 | package nkngomobile 2 | 3 | import "errors" 4 | 5 | // StringMapFunc is a wrapper type for gomobile compatibility. 6 | type StringMapFunc interface{ OnVisit(string, string) bool } 7 | 8 | // StringMap is a wrapper type for gomobile compatibility. StringMap is not 9 | // protected by lock and should not be read and write at the same time. 10 | type StringMap struct{ _map map[string]string } 11 | 12 | // NewStringMap creates a StringMap from a map. 13 | func NewStringMap(m map[string]string) *StringMap { 14 | return &StringMap{m} 15 | } 16 | 17 | // NewStringMapWithSize creates an empty StringMap with a given size. 18 | func NewStringMapWithSize(size int) *StringMap { 19 | return &StringMap{make(map[string]string, size)} 20 | } 21 | 22 | func (sm *StringMap) Map() map[string]string { 23 | if sm == nil { 24 | return nil 25 | } 26 | return sm._map 27 | } 28 | 29 | // Get returns the value of a key, or ErrKeyNotInMap if key does not exist. 30 | func (sm *StringMap) Get(key string) (string, error) { 31 | if value, ok := sm._map[key]; ok { 32 | return value, nil 33 | } 34 | return "", errors.New("key not in map") 35 | } 36 | 37 | // Set sets the value of a key to a value. 38 | func (sm *StringMap) Set(key string, value string) { 39 | sm._map[key] = value 40 | } 41 | 42 | // Delete deletes a key and its value from the map. 43 | func (sm *StringMap) Delete(key string) { 44 | delete(sm._map, key) 45 | } 46 | 47 | // Len returns the number of elements in the map. 48 | func (sm *StringMap) Len() int { 49 | return len(sm._map) 50 | } 51 | 52 | // Range iterates over the StringMap and call the OnVisit callback function with 53 | // each element in the map. If the OnVisit function returns false, the iterator 54 | // will stop and no longer visit the rest elements. 55 | func (sm *StringMap) Range(cb StringMapFunc) { 56 | if cb != nil { 57 | for key, value := range sm._map { 58 | if !cb.OnVisit(key, value) { 59 | return 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /stringarray.go: -------------------------------------------------------------------------------- 1 | package nkngomobile 2 | 3 | import ( 4 | "encoding/json" 5 | mathRand "math/rand" 6 | "strings" 7 | ) 8 | 9 | // StringArray is a wrapper type for gomobile compatibility. StringArray is not 10 | // protected by lock and should not be read and write at the same time. 11 | type StringArray struct{ elems []string } 12 | 13 | // NewStringArray creates a StringArray from a list of string elements. 14 | func NewStringArray(elems ...string) *StringArray { 15 | return &StringArray{elems} 16 | } 17 | 18 | // NewStringArrayFromString creates a StringArray from a single string input. 19 | // The input string will be split to string array by whitespace. 20 | func NewStringArrayFromString(s string) *StringArray { 21 | return &StringArray{strings.Fields(s)} 22 | } 23 | 24 | // Elems returns the string array elements. 25 | func (sa *StringArray) Elems() []string { 26 | if sa == nil { 27 | return nil 28 | } 29 | return sa.elems 30 | } 31 | 32 | // Len returns the string array length. 33 | func (sa *StringArray) Len() int { 34 | return len(sa.Elems()) 35 | } 36 | 37 | // Append adds an element to the string array. 38 | func (sa *StringArray) Append(s string) { 39 | sa.elems = append(sa.elems, s) 40 | } 41 | 42 | // Get gets an element to the string array. 43 | func (sa *StringArray) Get(i int) string { 44 | return sa.Elems()[i] 45 | } 46 | 47 | // RandomElem returns a randome element from the string array. The random number 48 | // is generated using math/rand and thus not cryptographically secure. 49 | func (sa *StringArray) RandomElem() string { 50 | if sa.Len() == 0 { 51 | return "" 52 | } 53 | return sa.Elems()[mathRand.Intn(sa.Len())] 54 | } 55 | 56 | // Join returns a single string by concatenates the elements 57 | func (sa *StringArray) Join(separator string) string { 58 | if sa == nil { 59 | return "" 60 | } 61 | return strings.Join(sa.elems, separator) 62 | } 63 | 64 | func (sa *StringArray) GetJson() string { 65 | if sa == nil || sa.Len() == 0 { 66 | return "[]" 67 | } 68 | b, err := json.Marshal(sa.elems) 69 | if err != nil { 70 | return "[]" 71 | } 72 | if b == nil { 73 | return "[]" 74 | } 75 | return string(b) 76 | } 77 | -------------------------------------------------------------------------------- /route.go: -------------------------------------------------------------------------------- 1 | package nkngomobile 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "log" 7 | "net" 8 | "sort" 9 | ) 10 | 11 | var ErrInvalidIP = errors.New("invalid IP address") 12 | 13 | func IpToUint32(s string) (uint32, error) { 14 | ip := net.ParseIP(s) 15 | if ip == nil { 16 | return 0, ErrInvalidIP 17 | } 18 | 19 | ip = ip.To4() 20 | if ip == nil { 21 | return 0, ErrInvalidIP 22 | } 23 | 24 | return uint32(ip[3]) | uint32(ip[2])<<8 | uint32(ip[1])<<16 | uint32(ip[0])<<24, nil 25 | } 26 | 27 | func Uint32ToIP(n uint32) net.IP { 28 | return net.IPv4(byte(n>>24), byte(n>>16&0xFF), byte(n>>8)&0xFF, byte(n&0xFF)) 29 | } 30 | 31 | // IpRangeToCIDR both side inclusive 32 | func IpRangeToCIDR(start, end uint32) []string { 33 | if start > end { 34 | return nil 35 | } 36 | 37 | // use uint64 to prevent overflow 38 | ip := int64(start) 39 | tail := int64(0) 40 | cidr := make([]string, 0) 41 | 42 | // decrease mask bit 43 | for { 44 | // count number of tailing zero bits 45 | for ; tail < 32; tail++ { 46 | if (ip>>(tail+1))<<(tail+1) != ip { 47 | break 48 | } 49 | } 50 | if ip+(1< int64(end) { 51 | break 52 | } 53 | cidr = append(cidr, fmt.Sprintf("%s/%d", Uint32ToIP(uint32(ip)).String(), 32-tail)) 54 | ip += 1 << tail 55 | } 56 | 57 | // increase mask bit 58 | for { 59 | for ; tail >= 0; tail-- { 60 | if ip+(1<