reSIProcate/rutil  9694
RRCache.cxx
Go to the documentation of this file.
00001 #if defined(HAVE_CONFIG_H)
00002 #include "config.h"
00003 #endif
00004 
00005 #include "AresCompat.hxx"
00006 
00007 #ifndef WIN32
00008 #include <sys/types.h>
00009 #include <sys/socket.h>
00010 #include <arpa/inet.h>
00011 #ifndef __CYGWIN__
00012 #  include <netinet/in.h>
00013 #  include <arpa/nameser.h>
00014 #  include <resolv.h>
00015 #endif
00016 #include <netdb.h>
00017 #include <netinet/in.h>
00018 #else
00019 #include <Winsock2.h>
00020 #include <svcguid.h>
00021 #ifdef USE_IPV6
00022 #include <ws2tcpip.h>
00023 #endif
00024 #endif
00025 
00026 #include <set>
00027 #include <vector>
00028 #include <list>
00029 #include <map>
00030 #include <cassert>
00031 #include "rutil/BaseException.hxx"
00032 #include "rutil/Data.hxx"
00033 #include "rutil/Timer.hxx"
00034 #include "rutil/dns/RRFactory.hxx"
00035 #include "rutil/dns/RROverlay.hxx"
00036 #include "rutil/dns/RRFactory.hxx"
00037 #include "rutil/dns/DnsResourceRecord.hxx"
00038 #include "rutil/dns/DnsAAAARecord.hxx"
00039 #include "rutil/dns/DnsHostRecord.hxx"
00040 #include "rutil/dns/DnsNaptrRecord.hxx"
00041 #include "rutil/dns/DnsSrvRecord.hxx"
00042 #include "rutil/dns/DnsCnameRecord.hxx"
00043 #include "rutil/dns/RRCache.hxx"
00044 #include "rutil/WinLeakCheck.hxx"
00045 
00046 using namespace resip;
00047 using namespace std;
00048 
00049 RRCache::RRCache() 
00050    : mHead(),
00051      mLruHead(LruListType::makeList(&mHead)),
00052      mUserDefinedTTL(DEFAULT_USER_DEFINED_TTL),
00053      mSize(DEFAULT_SIZE)
00054 {
00055    mFactoryMap[T_CNAME] = &mCnameRecordFactory;
00056    mFactoryMap[T_NAPTR] = &mNaptrRecordFacotry;
00057    mFactoryMap[T_SRV] = &mSrvRecordFactory;
00058 #ifdef USE_IPV6
00059    mFactoryMap[T_AAAA] = &mAAAARecordFactory;
00060 #endif
00061    mFactoryMap[T_A] = &mHostRecordFactory;
00062 }
00063 
00064 RRCache::~RRCache()
00065 {
00066    cleanup();
00067 }
00068 
00069 void 
00070 RRCache::updateCacheFromHostFile(const DnsHostRecord &record)
00071 {
00072    //FactoryMap::iterator it = mFactoryMap.find(T_A);
00073    RRList* key = new RRList(record, 3600);         
00074    RRSet::iterator lb = mRRSet.lower_bound(key);
00075    if (lb != mRRSet.end() &&
00076        !(mRRSet.key_comp()(key, *lb)))
00077    {
00078       (*lb)->update(record, 3600);
00079       touch(*lb);
00080    }
00081    else
00082    {
00083       RRList* val = new RRList(record, 3600);
00084       mRRSet.insert(val);
00085       mLruHead->push_back(val);
00086       purge();
00087    }
00088    delete key;
00089 }
00090 
00091 void 
00092 RRCache::updateCache(const Data& target,
00093                      const int rrType,
00094                      Itr begin, 
00095                      Itr end)
00096 {
00097    Data domain = (*begin).domain();
00098    FactoryMap::iterator it = mFactoryMap.find(rrType);
00099    assert(it != mFactoryMap.end());
00100    RRList* key = new RRList(domain, rrType);         
00101    RRSet::iterator lb = mRRSet.lower_bound(key);
00102    if (lb != mRRSet.end() &&
00103        !(mRRSet.key_comp()(key, *lb)))
00104    {
00105       (*lb)->update(it->second, begin, end, mUserDefinedTTL);
00106       touch(*lb);
00107    }
00108    else
00109    {
00110       RRList* val = new RRList(it->second, domain, rrType, begin, end, mUserDefinedTTL);
00111       mRRSet.insert(val);
00112       mLruHead->push_back(val);
00113       purge();
00114    }
00115    delete key;
00116 }
00117 
00118 void 
00119 RRCache::cacheTTL(const Data& target,
00120                   const int rrType,
00121                   const int status,
00122                   RROverlay overlay)
00123 {
00124    int ttl = getTTL(overlay);
00125 
00126    if (ttl < 0) 
00127    {
00128       return;
00129    }
00130 
00131    if (ttl < mUserDefinedTTL)
00132    {
00133       ttl = mUserDefinedTTL;
00134    }
00135 
00136    RRList* val = new RRList(target, rrType, ttl, status);
00137    RRSet::iterator it = mRRSet.find(val);
00138    if (it != mRRSet.end())
00139    {
00140       (*it)->remove();
00141       delete *it;
00142       mRRSet.erase(it);
00143    }
00144    mRRSet.insert(val);
00145    mLruHead->push_back(val);
00146    purge();
00147 }
00148 
00149 bool 
00150 RRCache::lookup(const Data& target, 
00151                 const int type, 
00152                 const int protocol,
00153                 Result& records, 
00154                 int& status)
00155 {
00156    records.empty();
00157    status = 0;
00158    RRList* key = new RRList(target, type);
00159    RRSet::iterator it = mRRSet.find(key);
00160    delete key;
00161    if (it == mRRSet.end())
00162    {
00163       return false;
00164    }
00165    else
00166    {
00167       if (Timer::getTimeSecs() >= (*it)->absoluteExpiry())
00168       {
00169          delete *it;
00170          mRRSet.erase(it);
00171          return false;
00172       }
00173       else
00174       {
00175          records = (*it)->records(protocol);
00176          status = (*it)->status();
00177          touch(*it);
00178          return true;
00179       }
00180    }
00181 }
00182 
00183 void 
00184 RRCache::clearCache()
00185 {
00186     cleanup();
00187 }
00188 
00189 void 
00190 RRCache::touch(RRList* node)
00191 {
00192    node->remove();
00193    mLruHead->push_back(node);
00194 }
00195 
00196 void 
00197 RRCache::cleanup()
00198 {
00199    for (std::set<RRList*, CompareT>::iterator it = mRRSet.begin(); it != mRRSet.end(); it++)
00200    {
00201       (*it)->remove();
00202       delete *it;
00203    }
00204    mRRSet.clear();
00205 }
00206 
00207 int 
00208 RRCache::getTTL(const RROverlay& overlay)
00209 {
00210    // overlay is a soa answer.
00211    if (overlay.type() != T_SOA) return -1;
00212    char* name = 0;
00213    long len = 0;
00214    int status = ares_expand_name(overlay.data(), overlay.msg(), overlay.msgLength(), &name, &len);
00215    assert( status == ARES_SUCCESS );
00216    const unsigned char* pPos = overlay.data() + len;
00217    free(name); name = 0;
00218    status = ares_expand_name(pPos, overlay.msg(), overlay.msgLength(), &name, &len);
00219    assert( status == ARES_SUCCESS );
00220    free(name);
00221    pPos += len;
00222    pPos += 16; // skip four 32 bit entities.
00223    return DNS__32BIT(pPos);         
00224 }
00225 
00226 void 
00227 RRCache::purge()
00228 {
00229    if (mRRSet.size() < mSize) return;
00230    RRList* lst = *(mLruHead->begin());
00231    RRSet::iterator it = mRRSet.find(lst);
00232    assert(it != mRRSet.end());
00233    lst->remove();
00234    delete *it;
00235    mRRSet.erase(it);
00236 }
00237 
00238 void 
00239 RRCache::logCache()
00240 {
00241    for (std::set<RRList*, CompareT>::iterator it = mRRSet.begin(); it != mRRSet.end(); it++)
00242    {
00243       (*it)->log();
00244    }
00245 }
00246 
00247 void 
00248 RRCache::getCacheDump(Data& dnsCacheDump)
00249 {
00250    DataStream strm(dnsCacheDump);
00251    for (std::set<RRList*, CompareT>::iterator it = mRRSet.begin(); it != mRRSet.end(); it++)
00252    {
00253       (*it)->encodeRRList(strm);
00254    }
00255    strm.flush();
00256 }
00257 
00258 /* ====================================================================
00259  * The Vovida Software License, Version 1.0 
00260  * 
00261  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00262  * Copyright (c) 2010 SIP Spectrum, Inc.  All rights reserved.
00263  * 
00264  * Redistribution and use in source and binary forms, with or without
00265  * modification, are permitted provided that the following conditions
00266  * are met:
00267  * 
00268  * 1. Redistributions of source code must retain the above copyright
00269  *    notice, this list of conditions and the following disclaimer.
00270  * 
00271  * 2. Redistributions in binary form must reproduce the above copyright
00272  *    notice, this list of conditions and the following disclaimer in
00273  *    the documentation and/or other materials provided with the
00274  *    distribution.
00275  * 
00276  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00277  *    and "Vovida Open Communication Application Library (VOCAL)" must
00278  *    not be used to endorse or promote products derived from this
00279  *    software without prior written permission. For written
00280  *    permission, please contact vocal@vovida.org.
00281  *
00282  * 4. Products derived from this software may not be called "VOCAL", nor
00283  *    may "VOCAL" appear in their name, without prior written
00284  *    permission of Vovida Networks, Inc.
00285  * 
00286  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00287  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00288  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00289  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00290  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00291  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00292  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00293  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00294  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00295  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00296  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00297  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00298  * DAMAGE.
00299  * 
00300  * ====================================================================
00301  * 
00302  * This software consists of voluntary contributions made by Vovida
00303  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00304  * Inc.  For more information on Vovida Networks, Inc., please see
00305  * <http://www.vovida.org/>.
00306  *
00307  */