2024-08-26 19:10:40 +03:00
|
|
|
package main
|
2024-08-24 19:47:10 +03:00
|
|
|
|
|
|
|
import (
|
|
|
|
"net"
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Records struct {
|
2024-08-25 00:18:15 +03:00
|
|
|
mutex sync.RWMutex
|
|
|
|
aRecords map[string]map[string]time.Time
|
|
|
|
cnameRecords map[string]map[string]time.Time
|
2024-08-24 19:47:10 +03:00
|
|
|
}
|
|
|
|
|
2024-08-25 00:18:15 +03:00
|
|
|
func (r *Records) getCNames(domainName string, recursive bool) []string {
|
|
|
|
cNameList := make([]string, 0)
|
|
|
|
for cname, ttl := range r.cnameRecords[domainName] {
|
|
|
|
if time.Now().Sub(ttl).Nanoseconds() > 0 {
|
|
|
|
delete(r.cnameRecords[domainName], cname)
|
2024-08-25 00:28:34 +03:00
|
|
|
if len(r.cnameRecords[domainName]) == 0 {
|
|
|
|
delete(r.cnameRecords, domainName)
|
|
|
|
return nil
|
|
|
|
}
|
2024-08-25 00:18:15 +03:00
|
|
|
continue
|
2024-08-24 19:47:10 +03:00
|
|
|
}
|
2024-08-25 00:18:15 +03:00
|
|
|
cNameList = append(cNameList, cname)
|
2024-08-24 19:47:10 +03:00
|
|
|
}
|
|
|
|
|
2024-08-25 00:18:15 +03:00
|
|
|
if recursive {
|
|
|
|
origCNameLen := len(cNameList)
|
|
|
|
for i := 0; i < origCNameLen; i++ {
|
|
|
|
parentList := r.getCNames(cNameList[i], true)
|
|
|
|
if parentList != nil {
|
|
|
|
cNameList = append(cNameList, parentList...)
|
|
|
|
}
|
2024-08-24 19:47:10 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return cNameList
|
|
|
|
}
|
|
|
|
|
2024-08-25 00:18:15 +03:00
|
|
|
func (r *Records) GetCNameRecords(domainName string, recursive bool) []string {
|
2024-08-24 19:47:10 +03:00
|
|
|
r.mutex.RLock()
|
|
|
|
defer r.mutex.RUnlock()
|
|
|
|
|
2024-08-25 00:18:15 +03:00
|
|
|
return r.getCNames(domainName, recursive)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *Records) GetARecords(domainName string, recursive bool) []net.IP {
|
|
|
|
r.mutex.RLock()
|
|
|
|
defer r.mutex.RUnlock()
|
2024-08-24 19:47:10 +03:00
|
|
|
|
2024-08-25 00:18:15 +03:00
|
|
|
cNameList := []string{domainName}
|
|
|
|
if recursive {
|
|
|
|
cNameList = append(cNameList, r.getCNames(domainName, true)...)
|
|
|
|
}
|
|
|
|
|
|
|
|
aRecords := make([]net.IP, 0)
|
|
|
|
for _, cName := range cNameList {
|
|
|
|
for addr, ttl := range r.aRecords[cName] {
|
|
|
|
if time.Now().Sub(ttl).Nanoseconds() > 0 {
|
|
|
|
delete(r.aRecords[cName], addr)
|
2024-08-25 00:28:34 +03:00
|
|
|
if len(r.aRecords[cName]) == 0 {
|
|
|
|
delete(r.aRecords, cName)
|
|
|
|
break
|
|
|
|
}
|
2024-08-25 00:18:15 +03:00
|
|
|
continue
|
2024-08-24 19:47:10 +03:00
|
|
|
}
|
2024-08-25 00:18:15 +03:00
|
|
|
aRecords = append(aRecords, []byte(addr))
|
2024-08-24 19:47:10 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-25 00:18:15 +03:00
|
|
|
return aRecords
|
2024-08-24 19:47:10 +03:00
|
|
|
}
|
|
|
|
|
2024-08-26 19:10:40 +03:00
|
|
|
func (r *Records) PutCNameRecord(domainName string, cName string, ttl time.Duration) {
|
2024-08-24 19:47:10 +03:00
|
|
|
r.mutex.Lock()
|
|
|
|
defer r.mutex.Unlock()
|
|
|
|
|
2024-08-25 00:18:15 +03:00
|
|
|
if r.cnameRecords[domainName] == nil {
|
|
|
|
r.cnameRecords[domainName] = make(map[string]time.Time)
|
2024-08-24 19:47:10 +03:00
|
|
|
}
|
|
|
|
|
2024-08-26 19:10:40 +03:00
|
|
|
r.cnameRecords[domainName][cName] = time.Now().Add(ttl)
|
2024-08-24 19:47:10 +03:00
|
|
|
}
|
|
|
|
|
2024-08-26 19:10:40 +03:00
|
|
|
func (r *Records) PutARecord(domainName string, addr net.IP, ttl time.Duration) {
|
2024-08-24 19:47:10 +03:00
|
|
|
r.mutex.Lock()
|
|
|
|
defer r.mutex.Unlock()
|
|
|
|
|
2024-08-25 00:18:15 +03:00
|
|
|
if r.aRecords[domainName] == nil {
|
|
|
|
r.aRecords[domainName] = make(map[string]time.Time)
|
2024-08-24 19:47:10 +03:00
|
|
|
}
|
|
|
|
|
2024-08-26 19:10:40 +03:00
|
|
|
r.aRecords[domainName][string(addr)] = time.Now().Add(ttl)
|
2024-08-24 19:47:10 +03:00
|
|
|
}
|
|
|
|
|
2024-08-25 00:28:34 +03:00
|
|
|
func (r *Records) Cleanup() {
|
|
|
|
r.mutex.Lock()
|
|
|
|
defer r.mutex.Unlock()
|
|
|
|
|
|
|
|
for domainName, _ := range r.aRecords {
|
|
|
|
for aRecord, ttl := range r.aRecords[domainName] {
|
|
|
|
if time.Now().Sub(ttl).Nanoseconds() <= 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
delete(r.aRecords[domainName], aRecord)
|
|
|
|
if len(r.aRecords[domainName]) == 0 {
|
|
|
|
delete(r.aRecords, domainName)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for domainName, _ := range r.cnameRecords {
|
|
|
|
for cname, ttl := range r.cnameRecords[domainName] {
|
|
|
|
if time.Now().Sub(ttl).Nanoseconds() <= 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
delete(r.cnameRecords[domainName], cname)
|
|
|
|
if len(r.cnameRecords[domainName]) == 0 {
|
|
|
|
delete(r.cnameRecords, domainName)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-24 19:47:10 +03:00
|
|
|
func NewRecords() *Records {
|
|
|
|
return &Records{
|
2024-08-25 00:18:15 +03:00
|
|
|
aRecords: make(map[string]map[string]time.Time),
|
|
|
|
cnameRecords: make(map[string]map[string]time.Time),
|
2024-08-24 19:47:10 +03:00
|
|
|
}
|
|
|
|
}
|