zoraxy/src/mod/geodb/trie.go
Toby Chui 54475e4b99 Fixed #271
- Fixed implementation in geoip resolver trie tree
2024-07-31 21:57:59 +08:00

106 lines
2.0 KiB
Go

package geodb
import (
"net"
)
type trie_Node struct {
childrens [2]*trie_Node
cc string
}
// Initializing the root of the trie
type trie struct {
root *trie_Node
}
func ipToBytes(ip string) []byte {
// 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()
if ipBytes == nil {
//This is an IPv6 address
ipBytes = parsedIP.To16()
}
return ipBytes
}
// 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) {
ipBytes := ipToBytes(ipAddr)
current := t.root
for _, b := range ipBytes {
//For each byte in the ip address (4 / 16 bytes)
//each byte is 8 bit
for j := 7; j >= 0; j-- {
bit := int(b >> j & 1)
if current.childrens[bit] == nil {
current.childrens[bit] = &trie_Node{
childrens: [2]*trie_Node{},
cc: cc,
}
}
current = current.childrens[bit]
}
}
}
// isReservedIP check if the given ip address is NOT a public ip address
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 is in the reserved private range
if parsedIP.IsPrivate() {
return true
}
return false
}
// Initializing the search for word in node
func (t *trie) search(ipAddr string) string {
if isReservedIP(ipAddr) {
return ""
}
ipBytes := ipToBytes(ipAddr)
current := t.root
for _, b := range ipBytes {
//For each byte in the ip address
//each byte is 8 bit
for j := 7; j >= 0; j-- {
bit := int(b >> j & 1)
if current.childrens[bit] == nil {
return current.cc
}
current = current.childrens[bit]
}
}
if len(current.childrens) == 0 {
return current.cc
}
//Not found
return ""
}