Пример #1
0
// Lookup returns the CacheResult of given Namelabel and Type combination
// rr will be nil if there was no positive match
// re will be nil if there was no negative match
// rr == re == nil if the entry is completely unknown
func (c *Cache) Lookup(label packet.Namelabel, t uint16) (rr *CacheResult, re *CacheResult) {
	key := label.ToKey()
	now := time.Now()

	c.Lock()
	defer c.Unlock()

	if c.CacheMap[key] != nil {
		qtypes := []uint16{t}                         // the types we are going to query from the cache
		ent := make([]packet.ResourceRecordFormat, 0) // the final response

		if t == constants.QTYPE_ALL && len(c.CacheMap[key]) > 0 {
			// special case: This was an ANY query and we DO have some data.
			// As QTYPE_ALL is not a valid type, we are just going to return all rr's we got data for
			qtypes = []uint16{}
			for k, _ := range c.CacheMap[key] {
				qtypes = append(qtypes, k)
			}
		}

		for _, qtype := range qtypes {
			if c.CacheMap[key][qtype] != nil {
				for _, item := range c.CacheMap[key][qtype] {
					if now.Before(item.deadline) {
						ttl := uint32(item.deadline.Sub(now).Seconds())
						ent = append(ent, packet.ResourceRecordFormat{Name: label, Class: constants.CLASS_IN, Type: qtype, Ttl: ttl, Data: item.data})
					}
				}
			}
		}

		if len(ent) > 0 { // ensure to return a null pointer if ent is empty
			rr = &CacheResult{ResourceRecord: ent, ResponseCode: constants.RC_NO_ERR}
		}
	}

	// rr will be nil on cache miss, check if we have a negative cache entry
	if rr == nil && c.MissMap[key] != nil {
		mtype := t
		if c.MissMap[key][constants.TYPE_SOA] != nil {
			// we do have a negative soa entry, so the domain simply does not exist
			// and there is no point in looking up 't'
			mtype = constants.TYPE_SOA
		}
		if c.MissMap[key][mtype] != nil {
			for _, item := range c.MissMap[key][mtype] {
				if now.Before(item.deadline) {
					ttl := uint32(item.deadline.Sub(now).Seconds())
					// unparse fiddled-in soa label
					rend := item.data[0] + 1
					rlabel := item.data[1:rend]
					plabel, _ := packet.ParseName(rlabel)
					ent := make([]packet.ResourceRecordFormat, 0)
					ent = append(ent, packet.ResourceRecordFormat{Name: plabel, Class: constants.CLASS_IN, Type: constants.TYPE_SOA, Ttl: ttl, Data: item.data[rend:]})
					re = &CacheResult{ResourceRecord: ent, ResponseCode: item.rcode}
				}
			}
		}
	}
	return
}