mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-06-07 08:07:20 +02:00
132 lines
2.9 KiB
Go
132 lines
2.9 KiB
Go
package geodb
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type trie_Node struct {
|
|
childrens [2]*trie_Node
|
|
ends bool
|
|
cc string
|
|
}
|
|
|
|
// Initializing the root of the trie
|
|
type trie struct {
|
|
root *trie_Node
|
|
}
|
|
|
|
func ipToBitString(ip string) string {
|
|
// Parse the IP address string into a net.IP object
|
|
parsedIP := net.ParseIP(ip)
|
|
|
|
// Convert the IP address to a 4-byte slice
|
|
ipBytes := parsedIP.To4()
|
|
|
|
// Convert each byte in the IP address to its 8-bit binary representation
|
|
var result []string
|
|
for _, b := range ipBytes {
|
|
result = append(result, fmt.Sprintf("%08b", b))
|
|
}
|
|
|
|
// Join the binary representation of each byte with dots to form the final bit string
|
|
return strings.Join(result, "")
|
|
}
|
|
|
|
func bitStringToIp(bitString string) string {
|
|
// Split the bit string into four 8-bit segments
|
|
segments := []string{
|
|
bitString[:8],
|
|
bitString[8:16],
|
|
bitString[16:24],
|
|
bitString[24:32],
|
|
}
|
|
|
|
// Convert each segment to its decimal equivalent
|
|
var decimalSegments []int
|
|
for _, s := range segments {
|
|
i, _ := strconv.ParseInt(s, 2, 64)
|
|
decimalSegments = append(decimalSegments, int(i))
|
|
}
|
|
|
|
// Join the decimal segments with dots to form the IP address string
|
|
return fmt.Sprintf("%d.%d.%d.%d", decimalSegments[0], decimalSegments[1], decimalSegments[2], decimalSegments[3])
|
|
}
|
|
|
|
// inititlaizing a new trie
|
|
func newTrie() *trie {
|
|
t := new(trie)
|
|
t.root = new(trie_Node)
|
|
return t
|
|
}
|
|
|
|
// Passing words to trie
|
|
func (t *trie) insert(ipAddr string, cc string) {
|
|
word := ipToBitString(ipAddr)
|
|
current := t.root
|
|
for _, wr := range word {
|
|
index := wr - '0'
|
|
if current.childrens[index] == nil {
|
|
current.childrens[index] = &trie_Node{
|
|
childrens: [2]*trie_Node{},
|
|
ends: false,
|
|
cc: cc,
|
|
}
|
|
}
|
|
current = current.childrens[index]
|
|
}
|
|
current.ends = true
|
|
}
|
|
|
|
func isReservedIP(ip string) bool {
|
|
parsedIP := net.ParseIP(ip)
|
|
if parsedIP == nil {
|
|
return false
|
|
}
|
|
// Check if the IP address is a loopback address
|
|
if parsedIP.IsLoopback() {
|
|
return true
|
|
}
|
|
// Check if the IP address is in the link-local address range
|
|
if parsedIP.IsLinkLocalUnicast() || parsedIP.IsLinkLocalMulticast() {
|
|
return true
|
|
}
|
|
// Check if the IP address is in the private address ranges
|
|
privateRanges := []*net.IPNet{
|
|
{IP: net.ParseIP("10.0.0.0"), Mask: net.CIDRMask(8, 32)},
|
|
{IP: net.ParseIP("172.16.0.0"), Mask: net.CIDRMask(12, 32)},
|
|
{IP: net.ParseIP("192.168.0.0"), Mask: net.CIDRMask(16, 32)},
|
|
}
|
|
for _, r := range privateRanges {
|
|
if r.Contains(parsedIP) {
|
|
return true
|
|
}
|
|
}
|
|
// If the IP address is not a reserved address, return false
|
|
return false
|
|
}
|
|
|
|
// Initializing the search for word in node
|
|
func (t *trie) search(ipAddr string) string {
|
|
if isReservedIP(ipAddr) {
|
|
return ""
|
|
}
|
|
word := ipToBitString(ipAddr)
|
|
current := t.root
|
|
for _, wr := range word {
|
|
index := wr - '0'
|
|
if current.childrens[index] == nil {
|
|
return current.cc
|
|
}
|
|
current = current.childrens[index]
|
|
}
|
|
if current.ends {
|
|
return current.cc
|
|
}
|
|
|
|
//Not found
|
|
return ""
|
|
}
|