reSIProcate/stack  9694
testDnsCache.cxx
Go to the documentation of this file.
00001 #if defined(HAVE_CONFIG_H)
00002 #include "config.h"
00003 #endif
00004 
00005 #if defined (HAVE_POPT_H) 
00006 #include <popt.h>
00007 #else
00008 #ifndef WIN32
00009 #warning "will not work very well without libpopt"
00010 #endif
00011 #endif
00012 
00013 #include <sys/types.h>
00014 #include <iostream>
00015 #include <memory>
00016 
00017 #include <fstream>
00018 
00019 #include "rutil/socket.hxx"
00020 #include "rutil/Data.hxx"
00021 #include "rutil/DnsUtil.hxx"
00022 #include "resip/stack/DnsInterface.hxx"
00023 #include "rutil/dns/QueryTypes.hxx"
00024 #include "rutil/dns/RROverlay.hxx"
00025 #include "rutil/dns/RRList.hxx"
00026 #include "rutil/dns/RRCache.hxx"
00027 #include "rutil/dns/DnsStub.hxx"
00028 
00029 using namespace resip;
00030 using namespace std;
00031 
00032 class MyDnsSink : public DnsResultSink
00033 {
00034    void onDnsResult(const DNSResult<DnsHostRecord>&);
00035 #ifdef USE_IPV6
00036    void onDnsResult(const DNSResult<DnsAAAARecord>&); 
00037 #endif
00038    void onDnsResult(const DNSResult<DnsSrvRecord>&);
00039    void onDnsResult(const DNSResult<DnsNaptrRecord>&) {}
00040    void onDnsResult(const DNSResult<DnsCnameRecord>&);
00041 };
00042 
00043 void MyDnsSink::onDnsResult(const DNSResult<DnsHostRecord>& result)
00044 {
00045    cout << "A records" << endl;
00046    cout << "Status: " << result.status << endl;
00047    cout << "Domain: " << result.domain << endl;
00048    if (result.status == 0)
00049    {
00050       for (vector<DnsHostRecord>::const_iterator it = result.records.begin(); it != result.records.end(); ++it)
00051       {
00052          cout << (*it).host() << endl;
00053       }
00054    }
00055    cout << endl;
00056 }
00057 
00058 void MyDnsSink::onDnsResult(const DNSResult<DnsCnameRecord>& result)
00059 {
00060    cout << "CNAME records" << endl;
00061    cout << "Status: " << result.status << endl;
00062    cout << "Domain: " << result.domain << endl;
00063    if (result.status == 0)
00064    {
00065       for (vector<DnsCnameRecord>::const_iterator it = result.records.begin(); it != result.records.end(); ++it)
00066       {
00067          cout << (*it).cname() << endl;
00068       }
00069    }
00070    cout << endl;
00071 }
00072 
00073 void MyDnsSink::onDnsResult(const DNSResult<DnsSrvRecord>& result)
00074 {
00075    cout << "SRV records" << endl;
00076    cout << "Status: " << result.status << endl;
00077    cout << "Domain: " << result.domain << endl;
00078    if (result.status == 0)
00079    {
00080       for (vector<DnsSrvRecord>::const_iterator it = result.records.begin(); it != result.records.end(); ++it)
00081       {
00082          cout << "Name: " << (*it).name() << endl;
00083          cout << "Priority: " << (*it).priority() << endl;
00084          cout << "Weight: " << (*it).weight() << endl;
00085          cout << "Port: " << (*it).port() << endl;
00086          cout << "Target: " << (*it).target() << endl;
00087       }
00088    }
00089    cout << endl;
00090 }
00091 
00092 
00093 // adopted from DnsUtil.
00094 const int NS_INT16SZ = 2;
00095 const int NS_INADDRSZ = 4;
00096 const int NS_IN6ADDRSZ = 16;
00097 
00098 static const char*
00099 MyInet_ntop4(const u_char *src, char *dst, size_t size)
00100 {
00101    static const char fmt[] = "%u.%u.%u.%u";
00102 #ifdef WIN32
00103    if ( _snprintf(dst, size, fmt, src[0], src[1], src[2], src[3]) < 0)
00104 #else
00105    if ( snprintf(dst, size, fmt, src[0], src[1], src[2], src[3]) < 0)
00106 #endif
00107    {
00108       errno = ENOSPC;
00109       dst[size-1] = 0;
00110       return NULL;
00111    }
00112    return (dst);
00113 }
00114 
00115 static const char *
00116 MyInet_ntop6(const u_char *src, char *dst, size_t size)
00117 {
00118    /*
00119     * Note that int32_t and int16_t need only be "at least" large enough
00120     * to contain a value of the specified size.  On some systems, like
00121     * Crays, there is no such thing as an integer variable with 16 bits.
00122     * Keep this in mind if you think this function should have been coded
00123     * to use pointer overlays.  All the world's not a VAX.
00124     */
00125    char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
00126    struct { int base, len; } best, cur;
00127    u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
00128    int i;
00129 
00130    /*
00131     * Preprocess:
00132     *   Copy the input (bytewise) array into a wordwise array.
00133     *   Find the longest run of 0x00's in src[] for :: shorthanding.
00134     */
00135    memset(words, '\0', sizeof words);
00136    for (i = 0; i < NS_IN6ADDRSZ; i++)
00137       words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
00138    best.base = -1;
00139    cur.base = -1;
00140    for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
00141       if (words[i] == 0) {
00142          if (cur.base == -1)
00143             cur.base = i, cur.len = 1;
00144          else
00145             cur.len++;
00146       } else {
00147          if (cur.base != -1) {
00148             if (best.base == -1 || cur.len > best.len)
00149                best = cur;
00150             cur.base = -1;
00151          }
00152       }
00153    }
00154    if (cur.base != -1) {
00155       if (best.base == -1 || cur.len > best.len)
00156          best = cur;
00157    }
00158    if (best.base != -1 && best.len < 2)
00159       best.base = -1;
00160 
00161    /*
00162     * Format the result.
00163     */
00164    tp = tmp;
00165    for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
00166       /* Are we inside the best run of 0x00's? */
00167       if (best.base != -1 && i >= best.base &&
00168           i < (best.base + best.len)) {
00169          if (i == best.base)
00170             *tp++ = ':';
00171          continue;
00172       }
00173       /* Are we following an initial run of 0x00s or any real hex? */
00174       if (i != 0)
00175          *tp++ = ':';
00176       /* Is this address an encapsulated IPv4? */
00177       if (i == 6 && best.base == 0 &&
00178           (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
00179          if (!MyInet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
00180             return (NULL);
00181          tp += strlen(tp);
00182          break;
00183       }
00184       tp += sprintf(tp, "%x", words[i]);
00185    }
00186    /* Was it a trailing run of 0x00's? */
00187    if (best.base != -1 && (best.base + best.len) ==
00188        (NS_IN6ADDRSZ / NS_INT16SZ))
00189       *tp++ = ':';
00190    *tp++ = '\0';
00191 
00192    /*
00193     * Check for overflow, copy, and we're done.
00194     */
00195    if ((size_t)(tp - tmp) > size) {
00196       errno = ENOSPC;
00197       return (NULL);
00198    }
00199    strcpy(dst, tmp);
00200    return (dst);
00201 }
00202 
00203 #ifdef USE_IPV6
00204 void MyDnsSink::onDnsResult(const DNSResult<DnsAAAARecord>& result)
00205 {
00206    cout << "AAAA records" << endl;
00207    cout << "Status: " << result.status << endl;
00208    cout << "Domain: " << result.domain << endl;
00209    if (result.status == 0)
00210    {
00211       for (vector<DnsAAAARecord>::const_iterator it = result.records.begin(); it != result.records.end(); ++it)
00212       {
00213          char str[256];
00214          cout << MyInet_ntop6((const u_char*)&(*it).v6Address(), str, sizeof(str)) << endl;
00215       }
00216    }
00217    cout << endl;
00218 }
00219 #endif
00220 
00221 
00222 // NOTE: In order to run this test, you need to uncomment out the USE_LOCAL_DNS define in
00223 // ExternalDnsFactory.cxx.
00224 main(int argc, char* argv[])
00225 {
00226    {
00227       const char* const key = "yahoo.com";
00228       MyDnsSink sink;
00229       DnsStub stub;
00230       DnsInterface dns(stub);
00231       stub.lookup<RR_A>(key, Protocol::Sip, &sink);
00232    }
00233 
00234    {
00235       const char* const key = "_ldap._tcp.openldap.org";
00236       MyDnsSink sink;
00237       DnsStub stub;
00238       DnsInterface dns(stub);
00239       stub.lookup<RR_SRV>(key, Protocol::Sip, &sink);
00240    }
00241 
00242    {
00243 #ifdef USE_IPV6
00244       const char* const key = "quartz";
00245       MyDnsSink sink;
00246       DnsStub stub;
00247       DnsInterface dns(stub);
00248       stub.lookup<RR_AAAA>(key, Protocol::Sip, &sink);
00249 #endif
00250    }
00251 
00252    {
00253       const char* const key = "www.google.com";
00254       MyDnsSink sink;
00255       DnsStub stub;
00256       DnsInterface dns(stub);
00257       stub.lookup<RR_CNAME>(key, Protocol::Sip, &sink);
00258    }
00259 
00260    return 0;
00261 }
00262 /* ====================================================================
00263  * The Vovida Software License, Version 1.0 
00264  * 
00265  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00266  * 
00267  * Redistribution and use in source and binary forms, with or without
00268  * modification, are permitted provided that the following conditions
00269  * are met:
00270  * 
00271  * 1. Redistributions of source code must retain the above copyright
00272  *    notice, this list of conditions and the following disclaimer.
00273  * 
00274  * 2. Redistributions in binary form must reproduce the above copyright
00275  *    notice, this list of conditions and the following disclaimer in
00276  *    the documentation and/or other materials provided with the
00277  *    distribution.
00278  * 
00279  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00280  *    and "Vovida Open Communication Application Library (VOCAL)" must
00281  *    not be used to endorse or promote products derived from this
00282  *    software without prior written permission. For written
00283  *    permission, please contact vocal@vovida.org.
00284  *
00285  * 4. Products derived from this software may not be called "VOCAL", nor
00286  *    may "VOCAL" appear in their name, without prior written
00287  *    permission of Vovida Networks, Inc.
00288  * 
00289  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00290  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00291  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00292  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00293  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00294  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00295  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00296  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00297  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00298  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00299  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00300  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00301  * DAMAGE.
00302  * 
00303  * ====================================================================
00304  * 
00305  * This software consists of voluntary contributions made by Vovida
00306  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00307  * Inc.  For more information on Vovida Networks, Inc., please see
00308  * <http://www.vovida.org/>.
00309  *
00310  */
00311