// 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 }