LCOV - code coverage report
Current view: top level - nsas - nameserver_entry.cc (source / functions) Hit Total Coverage
Test: report.info Lines: 142 159 89.3 %
Date: 2012-05-15 Functions: 15 15 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 195 324 60.2 %

           Branch data     Line data    Source code
       1                 :            : // Copyright (C) 2010-2011  Internet Systems Consortium, Inc. ("ISC")
       2                 :            : //
       3                 :            : // Permission to use, copy, modify, and/or distribute this software for any
       4                 :            : // purpose with or without fee is hereby granted, provided that the above
       5                 :            : // copyright notice and this permission notice appear in all copies.
       6                 :            : //
       7                 :            : // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
       8                 :            : // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
       9                 :            : // AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
      10                 :            : // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
      11                 :            : // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
      12                 :            : // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
      13                 :            : // PERFORMANCE OF THIS SOFTWARE.
      14                 :            : 
      15                 :            : #include <config.h>
      16                 :            : 
      17                 :            : #include <algorithm>
      18                 :            : #include <functional>
      19                 :            : #include <cassert>
      20                 :            : #include <iostream>
      21                 :            : #include <boost/bind.hpp>
      22                 :            : #include <boost/foreach.hpp>
      23                 :            : 
      24                 :            : #include <ctype.h>
      25                 :            : #include <strings.h>
      26                 :            : 
      27                 :            : #include <config.h>
      28                 :            : 
      29                 :            : #include <exceptions/exceptions.h>
      30                 :            : #include <dns/name.h>
      31                 :            : #include <dns/rrclass.h>
      32                 :            : #include <dns/rrttl.h>
      33                 :            : #include <dns/rcode.h>
      34                 :            : #include <dns/opcode.h>
      35                 :            : #include <dns/question.h>
      36                 :            : #include <resolve/resolver_interface.h>
      37                 :            : 
      38                 :            : #include <asiolink/io_address.h>
      39                 :            : 
      40                 :            : #include "address_entry.h"
      41                 :            : #include "nameserver_address.h"
      42                 :            : #include "nameserver_entry.h"
      43                 :            : #include "nsas_log.h"
      44                 :            : 
      45                 :            : using namespace isc::asiolink;
      46                 :            : using namespace isc::nsas;
      47                 :            : using namespace isc::dns;
      48                 :            : using namespace std;
      49                 :            : 
      50                 :            : namespace isc {
      51                 :            : namespace nsas {
      52                 :            : 
      53                 :            : namespace {
      54                 :            : 
      55                 :            : // Just shorter type alias
      56                 :            : typedef isc::util::locks::scoped_lock<isc::util::locks::recursive_mutex> Lock;
      57                 :            : 
      58                 :            : }
      59                 :            : 
      60                 :            : // Returns the list of addresses matching the given family
      61                 :            : Fetchable::State
      62                 :     802132 : NameserverEntry::getAddresses(AddressVector& addresses,
      63                 :            :     AddressFamily family, bool expired_ok)
      64                 :            : {
      65                 :            :     Lock lock(mutex_);
      66                 :            : 
      67                 :            :     // Check TTL
      68                 :     802132 :     time_t now(time(NULL));
      69                 :            :     // We take = as well, so we catch TTL 0 correctly
      70                 :            :     // expiration_ == 0 means not set, the reason is we are UNREACHABLE or
      71                 :            :     // NOT_ASKED or IN_PROGRESS
      72 [ +  + ][ +  + ]:     802132 :     if (getState() != NOT_ASKED && expiration_ && expiration_ <= now) {
         [ +  + ][ +  + ]
      73                 :         11 :         setState(EXPIRED);
      74                 :            :     }
      75                 :            : 
      76 [ +  + ][ +  + ]:     802132 :     if (getState() == EXPIRED && !expired_ok) {
                 [ +  + ]
      77                 :            :         return EXPIRED;
      78                 :            :     }
      79                 :            : 
      80   [ +  +  +  - ]:     802128 :     switch (getState()) {
      81                 :            :         case IN_PROGRESS:
      82                 :            :             /*
      83                 :            :              * Did we receive the address already?
      84                 :            :              *
      85                 :            :              * We might have already received the addresses for this family
      86                 :            :              * and still wait for the other (in which case has_address_[family]
      87                 :            :              * will be true). We might already received a negative answer,
      88                 :            :              * in which case expect_address_[family] is false and
      89                 :            :              * has_address_[family] is false as well.
      90                 :            :              */
      91 [ +  + ][ +  + ]:       2068 :             if (!has_address_[family] && expect_address_[family]) {
      92                 :            :                 return IN_PROGRESS;
      93                 :            :             }
      94                 :            :             // If we do not expect the address, then fall trough to READY
      95                 :            :         case EXPIRED: // If expired_ok, we pretend to be ready
      96                 :            :         case READY:
      97         [ +  + ]:     802059 :             if (!has_address_[family]) {
      98                 :            :                 return UNREACHABLE;
      99                 :            :             }
     100                 :            :             break; // OK, we give some answers
     101                 :            :         case NOT_ASKED:
     102                 :            :         case UNREACHABLE:
     103                 :            :             // Reject giving any data
     104                 :         29 :             return (getState());
     105                 :            :     }
     106                 :            : 
     107                 :     802052 :     boost::shared_ptr<NameserverEntry> self(shared_from_this());
     108                 :            :     // If any address is OK, just pass everything we have
     109         [ +  + ]:     802052 :     if (family == ANY_OK) {
     110 [ +  + ][ +  - ]:    1602083 :         BOOST_FOREACH(const AddressEntry& entry, addresses_[V6_ONLY]) {
         [ +  - ][ +  + ]
                 [ +  + ]
     111 [ +  - ][ +  - ]:     400023 :             addresses.push_back(NameserverAddress(self, entry, V6_ONLY));
     112                 :            :         }
     113 [ +  + ][ +  - ]:    2410177 :         BOOST_FOREACH(const AddressEntry& entry, addresses_[V4_ONLY]) {
         [ +  - ][ +  + ]
                 [ +  + ]
     114 [ +  - ][ +  - ]:     804070 :             addresses.push_back(NameserverAddress(self, entry, V4_ONLY));
     115                 :            :         }
     116                 :            :     } else {
     117 [ +  + ][ +  - ]:         45 :         BOOST_FOREACH(const AddressEntry& entry, addresses_[family]) {
         [ +  - ][ +  + ]
                 [ +  + ]
     118 [ +  - ][ +  - ]:         15 :             addresses.push_back(NameserverAddress(self, entry, family));
     119                 :            :         }
     120                 :            :     }
     121 [ +  + ][ -  + ]:     802052 :     if (getState() == EXPIRED && expired_ok) {
                 [ +  + ]
     122                 :            :         return READY;
     123                 :            :     }
     124                 :     802045 :     return getState();
     125                 :            : }
     126                 :            : 
     127                 :            : // Return the address corresponding to the family
     128                 :            : asiolink::IOAddress
     129                 :          3 : NameserverEntry::getAddressAtIndex(size_t index, AddressFamily family) const {
     130                 :            :     Lock lock(mutex_);
     131                 :            : 
     132         [ -  + ]:          3 :     assert(index < addresses_[family].size());
     133                 :            : 
     134                 :          3 :     return (addresses_[family][index].getAddress());
     135                 :            : }
     136                 :            : 
     137                 :            : // Set the address RTT to a specific value
     138                 :            : void
     139                 :         14 : NameserverEntry::setAddressRTT(const IOAddress& address, uint32_t rtt) {
     140                 :            :     Lock lock(mutex_);
     141                 :            : 
     142                 :            :     // Search through the list of addresses for a match
     143                 :         14 :     AddressFamily family(V4_ONLY);
     144                 :            :     for (;;) {
     145 [ +  + ][ +  - ]:         74 :         BOOST_FOREACH(AddressEntry& entry, addresses_[family]) {
         [ +  - ][ +  + ]
                 [ +  + ]
     146         [ +  + ]:         27 :             if (entry.getAddress().equals(address)) {
     147                 :            :                 entry.setRTT(rtt);
     148                 :            :                 return;
     149                 :            :             }
     150                 :            :         }
     151                 :            : 
     152                 :            :         // Hack. C++ does not allow ++ on enums, enumerating trough them is pain
     153         [ +  - ]:         21 :         switch (family) {
     154                 :            :             case V4_ONLY: family = V6_ONLY; break;
     155                 :            :             default: return;
     156                 :            :         }
     157                 :            :     }
     158                 :            : }
     159                 :            : 
     160                 :            : // Update the address's rtt
     161                 :            : #define UPDATE_RTT_ALPHA 0.7
     162                 :            : void
     163                 :      22003 : NameserverEntry::updateAddressRTTAtIndex(uint32_t rtt, size_t index,
     164                 :            :     AddressFamily family)
     165                 :            : {
     166                 :            :     Lock lock(mutex_);
     167                 :            : 
     168                 :            :     //make sure it is a valid index
     169         [ +  - ]:      44006 :     if(index >= addresses_[family].size()) return;
     170                 :            : 
     171                 :            :     // Smoothly update the rtt
     172                 :            :     // The algorithm is as the same as bind8/bind9:
     173                 :            :     //    new_rtt = old_rtt * alpha + new_rtt * (1 - alpha), where alpha is a float number in [0, 1.0]
     174                 :            :     // The default value for alpha is 0.7
     175                 :      44006 :     uint32_t old_rtt = addresses_[family][index].getRTT();
     176                 :            :     uint32_t new_rtt = (uint32_t)(old_rtt * UPDATE_RTT_ALPHA + rtt *
     177                 :      22003 :         (1 - UPDATE_RTT_ALPHA));
     178         [ +  + ]:      22003 :     if (new_rtt == 0) {
     179                 :       2000 :         new_rtt = 1;
     180                 :            :     }
     181                 :      22003 :     addresses_[family][index].setRTT(new_rtt);
     182 [ +  - ][ +  - ]:      44006 :     LOG_DEBUG(nsas_logger, NSAS_DBG_RTT, NSAS_UPDATE_RTT)
     183 [ +  - ][ +  - ]:      44006 :               .arg(addresses_[family][index].getAddress().toText())
     184 [ +  - ][ +  - ]:      22003 :               .arg(old_rtt).arg(new_rtt);
     185                 :            : }
     186                 :            : 
     187                 :            : void
     188                 :      22008 : NameserverEntry::updateAddressRTT(uint32_t rtt,
     189                 :            :     const asiolink::IOAddress& address, AddressFamily family)
     190                 :            : {
     191                 :            :     Lock lock(mutex_);
     192         [ +  + ]:      32009 :     for (size_t i(0); i < addresses_[family].size(); ++ i) {
     193         [ +  + ]:      32004 :         if (addresses_[family][i].getAddress().equals(address)) {
     194                 :      22003 :             updateAddressRTTAtIndex(rtt, i, family);
     195                 :      22008 :             return;
     196                 :            :         }
     197                 :            :     }
     198                 :            : }
     199                 :            : 
     200                 :            : // Sets the address to be unreachable
     201                 :            : void
     202                 :          5 : NameserverEntry::setAddressUnreachable(const IOAddress& address) {
     203                 :          5 :     setAddressRTT(address, AddressEntry::UNREACHABLE);
     204                 :          5 : }
     205                 :            : 
     206                 :            : /**
     207                 :            :  * \short A callback into the resolver.
     208                 :            :  *
     209                 :            :  * Whenever we ask the resolver something, this is created and the answer is
     210                 :            :  * fed back through this. It holds a shared pointer to the entry so it is not
     211                 :            :  * destroyed too soon.
     212                 :            :  */
     213                 :        176 : class NameserverEntry::ResolverCallback :
     214                 :            :         public isc::resolve::ResolverInterface::Callback {
     215                 :            :     public:
     216                 :            :         ResolverCallback(boost::shared_ptr<NameserverEntry> entry,
     217                 :            :             AddressFamily family, const RRType& type) :
     218                 :            :             entry_(entry),
     219                 :            :             family_(family),
     220                 :        264 :             type_(type)
     221                 :            :         { }
     222                 :            :         /**
     223                 :            :          * \short We received the address successfully.
     224                 :            :          *
     225                 :            :          * This extracts the addresses out from the response and puts them
     226                 :            :          * inside the entry. It tries to reuse the address entries from before
     227                 :            :          * (if there were any), to keep their RTTs.
     228                 :            :          */
     229                 :         58 :         virtual void success(MessagePtr response_message) {
     230                 :         58 :             time_t now = time(NULL);
     231                 :            : 
     232                 :         58 :             Lock lock(entry_->mutex_);
     233                 :            : 
     234                 :            :             // TODO: find the correct RRset, not simply the first
     235         [ -  + ]:         58 :             if (!response_message) {
     236 [ #  # ][ #  # ]:          0 :                 LOG_ERROR(nsas_logger, NSAS_NULL_RESPONSE).arg(entry_->getName());
         [ #  # ][ #  # ]
     237                 :          0 :                 failureInternal(lock);
     238                 :          0 :                 return;
     239                 :            : 
     240         [ -  + ]:         58 :             } else if (response_message->getRcode() != isc::dns::Rcode::NOERROR()) {
     241 [ #  # ][ #  # ]:          0 :                 LOG_DEBUG(nsas_logger, NSAS_DBG_RESULTS, NSAS_ERROR_RESPONSE).
     242 [ #  # ][ #  # ]:          0 :                           arg(response_message->getRcode()).arg(entry_->getName());
         [ #  # ][ #  # ]
     243                 :          0 :                 failureInternal(lock);
     244                 :          0 :                 return;
     245                 :            : 
     246         [ -  + ]:         58 :             } else if (
     247                 :         58 :                 response_message->getRRCount(isc::dns::Message::SECTION_ANSWER) == 0) {
     248 [ #  # ][ #  # ]:          0 :                 LOG_DEBUG(nsas_logger, NSAS_DBG_RESULTS, NSAS_EMPTY_RESPONSE).
     249 [ #  # ][ #  # ]:          0 :                           arg(entry_->getName());
     250                 :          0 :                 failureInternal(lock);
     251                 :          0 :                 return;
     252                 :            :             }
     253                 :            :             
     254                 :            :             isc::dns::RRsetIterator rrsi =
     255                 :        116 :                 response_message->beginSection(isc::dns::Message::SECTION_ANSWER);
     256         [ +  - ]:         58 :             const isc::dns::RRsetPtr response = *rrsi;
     257                 :            :             
     258                 :         58 :             vector<AddressEntry> entries;
     259                 :            : 
     260 [ +  - ][ +  - ]:        116 :             if (response->getType() != type_ ||
         [ -  + ][ -  + ]
     261         [ +  - ]:         58 :                 response->getClass() != RRClass(entry_->getClass()))
     262                 :            :             {
     263                 :            :                 // Invalid response type or class
     264 [ #  # ][ #  # ]:          0 :                 LOG_ERROR(nsas_logger, NSAS_WRONG_ANSWER)
                 [ #  # ]
     265 [ #  # ][ #  # ]:          0 :                           .arg(entry_->getName()).arg(type_)
                 [ #  # ]
     266 [ #  # ][ #  # ]:          0 :                           .arg(entry_->getClass()).arg(response->getType())
                 [ #  # ]
     267 [ #  # ][ #  # ]:          0 :                           .arg(response->getClass());
     268                 :            : 
     269         [ #  # ]:          0 :                 failureInternal(lock);
     270                 :            :                 return;
     271                 :            :             }
     272                 :            : 
     273 [ +  - ][ +  + ]:        205 :             for (RdataIteratorPtr i(response->getRdataIterator());
     274 [ +  - ][ +  - ]:        147 :                 !i->isLast(); i->next())
     275                 :            :             {
     276                 :            :                 // Try to find the original value and reuse it
     277 [ +  - ][ +  - ]:        178 :                 string address(i->getCurrent().toText());
     278                 :         89 :                 AddressEntry *found(NULL);
     279 [ +  + ][ +  + ]:        110 :                 BOOST_FOREACH(AddressEntry& entry,
         [ +  + ][ +  + ]
                 [ +  + ]
     280                 :            :                     entry_->previous_addresses_[family_])
     281                 :            :                 {
     282 [ +  - ][ +  + ]:         21 :                     if (entry.getAddress().toText() == address) {
     283                 :            :                         // Good, found it.
     284                 :            :                         found = &entry;
     285                 :            :                         break;
     286                 :            :                     }
     287                 :            :                 }
     288                 :            :                 // If we found it, use it. If not, create a new one.
     289                 :            :                 entries.push_back(found ? *found : AddressEntry(
     290 [ +  + ][ +  - ]:         89 :                                                    IOAddress(address), 1));
     291 [ +  - ][ +  - ]:        178 :                 LOG_DEBUG(nsas_logger, NSAS_DBG_RESULTS, NSAS_FOUND_ADDRESS)
                 [ +  - ]
     292 [ +  - ][ +  - ]:        267 :                           .arg(address).arg(entry_->getName());
                 [ +  - ]
     293                 :            :             }
     294                 :            : 
     295                 :            :             // We no longer need the previous set of addresses, we have
     296                 :            :             // the current ones now.
     297                 :         58 :             entry_->previous_addresses_[family_].clear();
     298                 :            : 
     299         [ -  + ]:         58 :             if (entries.empty()) {
     300                 :            :                 // No data there, count it as a failure
     301         [ #  # ]:          0 :                 failureInternal(lock);
     302                 :            :             } else {
     303                 :            :                 // We received the data, so mark it
     304                 :         58 :                 entry_->expect_address_[family_] = false;
     305                 :         58 :                 entry_->expect_address_[ANY_OK] =
     306                 :         58 :                     entry_->expect_address_[V4_ONLY] ||
     307 [ +  - ][ +  + ]:         58 :                     entry_->expect_address_[V6_ONLY];
     308                 :            :                 // Everything is here (all address families)
     309         [ +  + ]:         58 :                 if (!entry_->expect_address_[ANY_OK]) {
     310                 :         25 :                     entry_->setState(READY);
     311                 :            :                 }
     312                 :            :                 // We have some address
     313                 :         58 :                 entry_->has_address_[ANY_OK] =
     314                 :         58 :                     entry_->has_address_[family_] = true;
     315                 :            :                 // Insert the entries inside
     316                 :         58 :                 entry_->addresses_[family_].swap(entries);
     317                 :            :                 // Update the expiration time. If it is 0, it means we
     318                 :            :                 // did not set it yet, so reset
     319         [ +  - ]:         58 :                 time_t expiration(now + response->getTTL().getValue());
     320         [ +  + ]:         58 :                 if (entry_->expiration_) {
     321                 :            :                     // We expire at the time first address expires
     322                 :         44 :                     entry_->expiration_ = min(entry_->expiration_, expiration);
     323                 :            :                 } else {
     324                 :            :                     // We have no expiration time set, use this one
     325                 :         36 :                     entry_->expiration_ = expiration;
     326                 :            :                 }
     327                 :            :                 // Run the right callbacks
     328         [ +  - ]:         58 :                 dispatchCallbacks(lock);
     329                 :            :             }
     330                 :            :         }
     331                 :            :         /**
     332                 :            :          * \short The resolver failed to retrieve the data.
     333                 :            :          *
     334                 :            :          * So mark the current address family as unreachable.
     335                 :            :          */
     336                 :         95 :         virtual void failure() {
     337 [ +  - ][ +  - ]:        190 :             LOG_DEBUG(nsas_logger, NSAS_DBG_RESULTS, NSAS_NS_LOOKUP_FAIL)
     338 [ +  - ][ +  - ]:        285 :                       .arg(type_).arg(entry_->getName());
                 [ +  - ]
     339                 :         95 :             Lock lock(entry_->mutex_);
     340                 :         95 :             failureInternal(lock);
     341                 :         95 :         }
     342                 :            :     private:
     343                 :            :         boost::shared_ptr<NameserverEntry> entry_;
     344                 :            :         AddressFamily family_;
     345                 :            :         RRType type_;
     346                 :            : 
     347                 :            :         // Dispatches all relevant callbacks. Keeps lock unlocked afterwards.
     348                 :            :         // TODO: We might want to use recursive lock and get rid of this
     349                 :        153 :         void dispatchCallbacks(Lock& lock)
     350                 :            :         {
     351                 :            :             // We dispatch ANY addresses if there is at last one address or
     352                 :            :             // there's no chance we'll get some in future
     353                 :        153 :             bool dispatch_any = entry_->has_address_[ANY_OK] ||
     354 [ +  + ][ +  + ]:        153 :                 !entry_->expect_address_[ANY_OK];
     355                 :            :             // Sort out the callbacks we want
     356                 :        153 :             vector<CallbackPair> keep;
     357         [ +  - ]:        153 :             vector<boost::shared_ptr<NameserverEntry::Callback> > dispatch;
     358 [ +  + ][ +  - ]:        449 :             BOOST_FOREACH(const CallbackPair &callback, entry_->callbacks_)
         [ +  - ][ +  + ]
                 [ +  + ]
     359                 :            :             {
     360 [ +  + ][ +  + ]:        148 :                 if (callback.first == family_ || (dispatch_any &&
                 [ +  + ]
     361                 :            :                     callback.first == ANY_OK))
     362                 :            :                 {
     363                 :         99 :                     dispatch.push_back(callback.second);
     364                 :            :                 } else {
     365         [ +  - ]:        148 :                     keep.push_back(callback);
     366                 :            :                 }
     367                 :            :             }
     368                 :            :             // Put there only the ones that we do not want, drop the rest
     369                 :        153 :             keep.swap(entry_->callbacks_);
     370                 :            :             keep.clear();
     371                 :            : 
     372                 :            :             // We can't keep the lock while we execute callbacks
     373                 :            :             lock.unlock();
     374                 :            :             // Run all the callbacks
     375                 :            :             /*
     376                 :            :              * FIXME: This is not completely exception safe. If there's an
     377                 :            :              * exception in a callback, we lose the rest of them.
     378                 :            :              */
     379 [ +  + ][ +  - ]:        351 :             BOOST_FOREACH(const boost::shared_ptr<NameserverEntry::Callback>&
         [ +  - ][ +  + ]
                 [ +  + ]
     380                 :            :                 callback, dispatch)
     381                 :            :             {
     382         [ +  - ]:         99 :                 (*callback)(entry_);
     383                 :            :             }
     384                 :        153 :         }
     385                 :            : 
     386                 :            :         // Handle a failure to obtain data. Dispatches callbacks and leaves
     387                 :            :         // lock unlocked
     388                 :         95 :         void failureInternal(Lock &lock) {
     389                 :            :             // Set state of the addresses
     390                 :         95 :             entry_->expect_address_[family_] = false;
     391                 :         95 :             entry_->expect_address_[ANY_OK] =
     392                 :         95 :                 entry_->expect_address_[V4_ONLY] ||
     393 [ +  + ][ +  + ]:         95 :                 entry_->expect_address_[V6_ONLY];
     394                 :            :             // When we do not expect any more addresses, decide the state
     395         [ +  + ]:         95 :             if (!entry_->expect_address_[ANY_OK]) {
     396         [ +  + ]:         75 :                 if (entry_->has_address_[ANY_OK]) {
     397                 :            :                     // We have at last one kind of address, so OK
     398                 :         61 :                     entry_->setState(READY);
     399                 :            :                 } else {
     400                 :            :                     // No addresses :-(
     401                 :         14 :                     entry_->setState(UNREACHABLE);
     402                 :            :                 }
     403                 :            :             }
     404                 :            :             // Drop the previous addresses, no use of them now
     405                 :         95 :             entry_->previous_addresses_[family_].clear();
     406                 :            :             // Dispatch any relevant callbacks
     407                 :         95 :             dispatchCallbacks(lock);
     408                 :         95 :         }
     409                 :            : };
     410                 :            : 
     411                 :            : void
     412                 :         88 : NameserverEntry::askIP(isc::resolve::ResolverInterface* resolver,
     413                 :            :     const RRType& type, AddressFamily family)
     414                 :            : {
     415                 :         88 :     QuestionPtr question(new Question(Name(getName()), RRClass(getClass()),
     416 [ +  - ][ +  - ]:         88 :         type));
     417                 :            :     boost::shared_ptr<ResolverCallback> callback(new ResolverCallback(
     418 [ +  - ][ +  - ]:         88 :         shared_from_this(), family, type));
     419         [ +  - ]:         88 :     resolver->resolve(question, callback);
     420                 :         88 : }
     421                 :            : 
     422                 :            : void
     423                 :        103 : NameserverEntry::askIP(isc::resolve::ResolverInterface* resolver,
     424                 :            :     boost::shared_ptr<Callback> callback, AddressFamily family)
     425                 :            : {
     426                 :            :     Lock lock(mutex_);
     427                 :            : 
     428 [ +  + ][ +  + ]:        103 :     if (getState() == EXPIRED || getState() == NOT_ASKED) {
                 [ +  + ]
     429                 :            :         // We will request the addresses
     430                 :            : 
     431                 :            :         // Set internal state first
     432                 :            :         // We store the old addresses so we can pick their RTT when
     433                 :            :         // we get the same addresses again (most probably)
     434                 :         44 :         previous_addresses_[V4_ONLY].clear();
     435                 :         44 :         previous_addresses_[V6_ONLY].clear();
     436                 :         44 :         addresses_[V4_ONLY].swap(previous_addresses_[V4_ONLY]);
     437                 :         44 :         addresses_[V6_ONLY].swap(previous_addresses_[V6_ONLY]);
     438                 :         44 :         setState(IN_PROGRESS);
     439                 :         88 :         has_address_[V4_ONLY] = has_address_[V6_ONLY] = has_address_[ANY_OK] =
     440                 :        132 :             false;
     441                 :         44 :         expect_address_[V4_ONLY] = expect_address_[V6_ONLY] =
     442                 :         88 :             expect_address_[ANY_OK] = true;
     443                 :         44 :         expiration_ = 0;
     444                 :            : 
     445                 :            :         // Store the callback
     446         [ +  - ]:         44 :         callbacks_.push_back(CallbackPair(family, callback));
     447                 :            : 
     448                 :            :         // Ask for both types of addresses
     449                 :            :         // We are unlocked here, as the callback from that might want to lock
     450                 :            :         lock.unlock();
     451                 :            : 
     452   [ +  -  +  - ]:         88 :         LOG_DEBUG(nsas_logger, NSAS_DBG_TRACE, NSAS_FIND_NS_ADDRESS).arg(getName());
         [ +  - ][ +  - ]
     453                 :         44 :         askIP(resolver, RRType::A(), V4_ONLY);
     454                 :         44 :         askIP(resolver, RRType::AAAA(), V6_ONLY);
     455                 :            :         // Make sure we end the routine when we are not locked
     456                 :         44 :         return;
     457                 :            :     } else {
     458                 :            :         // We already asked. Do we expect this address type still to come?
     459         [ +  + ]:         59 :         if (!expect_address_[family]) {
     460                 :            :             // We do not expect it to come, dispatch right away
     461                 :            :             lock.unlock();
     462         [ +  - ]:          4 :             (*callback)(shared_from_this());
     463                 :            :             return;
     464                 :            :         } else {
     465                 :            :             // It will come in future, store the callback until then
     466         [ +  - ]:         55 :             callbacks_.push_back(CallbackPair(family, callback));
     467                 :            :         }
     468                 :            :     }
     469                 :            : }
     470                 :            : 
     471                 :            : } // namespace dns
     472                 :          4 : } // namespace isc

Generated by: LCOV version 1.9