func AddAToRegionCache(dst string, srcIP string, R []dns.RR, edns_h *dns.RR_Header, edns *dns.EDNS0_SUBNET) { var dn *DomainNode var domainNodeExist bool = false var retry = 0 var e *MyError.MyError for domainNodeExist = false; (domainNodeExist == false) && (retry < 5); { // wait for goroutine 'StoreDomainNodeToCache' in GetSOARecord to be finished dn, e = DomainRRCache.GetDomainNodeFromCacheWithName(dst) if e != nil { // here ,may be nil // error! need return //fmt.Println(utils.GetDebugLine(), // " GetARecord : have not got cache GetDomainNodeFromCacheWithName, need waite ", e) utils.ServerLogger.Error("GetARecord : have not got cache GetDomainNodeFromCacheWithName, need waite %s", e.Error()) time.Sleep(1 * time.Second) if e.ErrorNo == MyError.ERROR_NOTFOUND { retry++ } else { utils.ServerLogger.Critical("GetARecord error %s", e.Error()) //fmt.Println(utils.GetDebugLine(), e) // todo: need to log error } } else { domainNodeExist = true //fmt.Println(utils.GetDebugLine(), "GetARecord: ", dn) utils.ServerLogger.Debug("GetARecord dn: %s", dn.Domain.DomainName, dn.DomainRegionTree) } } if domainNodeExist == false && retry >= 5 { utils.ServerLogger.Warning("DomainRRCache.GetDomainNodeFromCacheWithName(dst) dst:", dst, " retry for ", retry, " times,but no result!") } else { //dn.InitRegionTree() utils.ServerLogger.Debug("Got dn :", dn) regiontree := dn.DomainRegionTree ////todo: Need to be combined with the go func within GetAFromMySQLBackend //var startIP, endIP uint32 //if config.RC.MySQLEnabled /** && config.RC.MySQLRegionEnabled **/ { // region, ee := RRMySQL.GetRegionWithIPFromMySQL(utils.Ip4ToInt32(utils.StrToIP(srcIP))) // if ee != nil { // //fmt.Println(utils.GetDebugLine(), "Error GetRegionWithIPFromMySQL:", ee) // utils.ServerLogger.Error("Error GetRegionWithIPFromMySQL: %s", ee.Error()) // } else { // startIP, endIP = region.Region.StarIP, region.Region.EndIP // //fmt.Println(utils.GetDebugLine(), region.Region, startIP, endIP) // } // //} else { // // startIP, endIP = iplookup.GetIpinfoStartEndWithIPString(srcIP) //} //cidrmask := utils.GetCIDRMaskWithUint32Range(startIP, endIP) //fmt.Println(utils.GetDebugLine(), "Search client region info with srcIP: ", // srcIP, " StartIP : ", startIP, "==", utils.Int32ToIP4(startIP).String(), // " EndIP: ", endIP, "==", utils.Int32ToIP4(endIP).String(), " cidrmask : ", cidrmask) if edns != nil { var ipnet *net.IPNet ipnet, e := utils.ParseEdnsIPNet(edns.Address, edns.SourceScope, edns.Family) if e != nil { utils.ServerLogger.Error("utils.ParseEdnsIPNet error:", edns) } netaddr, mask := utils.IpNetToInt32(ipnet) //fmt.Println(utils.GetDebugLine(), "Got Edns client subnet from ecs query, netaddr : ", netaddr, // " mask : ", mask) utils.ServerLogger.Debug("Got Edns client subnet from ecs query, netaddr : ", netaddr, " mask : ", mask) //if (netaddr != startIP) || (mask != cidrmask) { // //fmt.Println(utils.GetDebugLine(), "iplookup data dose not match edns query result , netaddr : ", // // netaddr, "<->", startIP, " mask: ", mask, "<->", cidrmask) // utils.ServerLogger.Debug("iplookup data dose not match edns query result , netaddr : ", netaddr, "<->", startIP, " mask: ", mask, "<->", cidrmask) //} //// if there is no region info in region table of mysql db or no info in ipdb //if cidrmask <= 0 || startIP <= 0 { // startIP = netaddr // cidrmask = mask //} r, _ := NewRegion(R, netaddr, mask) // Parse edns client subnet utils.ServerLogger.Debug("GetAFromDNSBackend: ", " edns_h: ", edns_h, " edns: ", edns) regiontree.AddRegionToCache(r) } else { //todo: get StartIP/EndIP from iplookup module // netaddr, mask := DefaultNetaddr, DefaultMask r, _ := NewRegion(R, DefaultRadixNetaddr, DefaultRadixNetMask) //todo: modify to go func,so you can cathe the result regiontree.AddRegionToCache(r) //fmt.Println(utils.GetDebugLine(), "GetAFromDNSBackend: AddRegionToCache: ", r) //fmt.Println(regionTree.GetRegionFromCacheWithAddr(startIP, cidrmask)) } //todo: modify to go func,so you can cathe the result //Add timer for auto refrech the RegionCache go func(dst, srcIP string, r dns.RR, regionTree *RegionTree) { //fmt.Println(utils.GetDebugLine(), " Refresh record after ", r.Header().Ttl-5, // " Second, dst: ", dst, " srcIP: ", srcIP, " ns_a: ", ns_a, "add timer ") time.AfterFunc((time.Duration(r.Header().Ttl-5))*time.Second, func() { GetAFromDNSBackend(dst, srcIP) //todo:add timer for update region cache utils.QueryLogger.Info("Need to refresh for domain:", dst, " srcIP: ", srcIP) }) }(dst, srcIP, R[0], regiontree) } }
func TestMubitRadix(t *testing.T) { cidrNet := []string{ "10.0.0.2/8", "10.20.0.0/14", "10.21.0.0/16", "192.168.0.0/16", "192.168.2.0/24", "8.0.0.0/9", "8.8.8.0/24", "0.0.0.0/0", // "128.0.0.0/1", } ip2Find := []string{ "10.20.1.2", "10.22.1.2", "10.19.0.1", "10.21.0.1", "192.168.2.3", "10.22.0.5", "202.106.0.20", "172.16.3.133", "8.8.8.8", "8.8.7.1", } RadixTree := NewDomainRegionTree() for _, x := range cidrNet { i, n, e := net.ParseCIDR(x) if e != nil { t.Log(e.Error()) t.Fail() continue } a, m := utils.IpNetToInt32(n) RadixTree.AddRegionToCache(&Region{ NetworkAddr: a, NetworkMask: m, RR: []dns.RR{ dns.RR(&dns.A{ A: i, Hdr: dns.RR_Header{ Rrtype: 1, Class: 1, Ttl: 60, }, }), }, }) } // For default route RadixTree.AddRegionToCache(&Region{ NetworkAddr: DefaultRadixNetaddr, NetworkMask: DefaultRadixNetMask, RR: []dns.RR{ dns.RR(&dns.A{ A: utils.Int32ToIP4(DefaultRadixNetaddr), Hdr: dns.RR_Header{ Rrtype: 1, Class: 1, Ttl: 60, }, }), }, }) for _, i := range ip2Find { ii := utils.Ip4ToInt32(utils.StrToIP(i)) r, e := RadixTree.GetRegionFromCacheWithAddr(ii, DefaultRadixSearchMask) if e != nil { t.Log(e) t.Log(i) t.Fail() } else { t.Log(r) } } RadixTree.Radix32.Do(func(r1 *bitradix.Radix32, i int) { t.Log(r1.Key(), r1.Value, r1.Bits()) }) }