@@ -802,10 +802,41 @@ runLoopMode: runLoopMode]; [sock asyncReceiveIntoBuffer: _buffer length: bufferLength runLoopMode: runLoopMode]; } + +- (void)of_cleanUpCache +{ + void *pool = objc_autoreleasePoolPush(); + OFTimeInterval now = [OFDate date].timeIntervalSince1970; + OFMutableArray *removeList; + + if (now - _lastCacheCleanup < 1) + return; + + _lastCacheCleanup = now; + removeList = [OFMutableArray arrayWithCapacity: _cache.count]; + + for (OFDNSQuery *query in _cache) { + OFPair OF_GENERIC(OFDate *, OFDNSResponse *) *entry = + [_cache objectForKey: query]; + uint32_t age = + (uint32_t)now - [entry.firstObject timeIntervalSince1970]; + OFDNSResponse *response = entry.secondObject; + + if (containsExpiredRecord(response.answerRecords, age) || + containsExpiredRecord(response.authorityRecords, age) || + containsExpiredRecord(response.additionalRecords, age)) + [removeList addObject: query]; + } + + for (OFDNSQuery *query in removeList) + [_cache removeObjectForKey: query]; + + objc_autoreleasePoolPop(pool); +} - (void)asyncPerformQuery: (OFDNSQuery *)query delegate: (id )delegate { [self asyncPerformQuery: query @@ -819,10 +850,12 @@ { void *pool = objc_autoreleasePoolPush(); OFNumber *ID; OFDNSResolverContext *context; OFPair OF_GENERIC(OFDate *, OFDNSResponse *) *cacheEntry; + + [self of_cleanUpCache]; if ((cacheEntry = [_cache objectForKey: query]) != nil) { uint32_t age = (uint32_t)-[cacheEntry.firstObject timeIntervalSinceNow]; OFDNSResponse *response = cacheEntry.secondObject; @@ -1079,10 +1112,12 @@ [_cache setObject: [OFPair pairWithFirstObject: [OFDate date] secondObject: response] forKey: context->_query]; else [_cache removeObjectForKey: context->_query]; + + [self of_cleanUpCache]; [context->_delegate resolver: self didPerformQuery: context->_query response: response exception: exception];