Example #1
0
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())
	})
}