#include "dns/dnsresolver.h"
#include <stdint.h>
+#include <sstream>
#include <boost/foreach.hpp>
#include <boost/bind.hpp>
const DnsCacheItem cache,
const boost::asio::ip::address &name_server)
: ResolverBase( io_serv, hostname, cache )
- , Socket( *io_serv )
+ , Socket( *io_serv, ip::udp::endpoint(ip::udp::v4(), 0))
+ // just connect to anything, will specify sender/receiver later
, ReceiveBuffer()
, Protocol( protocol )
, NameServer( name_server, Config::DNS_PORT )
, NextIpIndex( 0 )
, RetryCount( 0 )
, IsResolving( false )
-{ }
+ , LogPrefix( "DnsResolver" )
+{
+ std::stringstream temp;
+ temp << "Dns(" << ResolverBase::Hostname << "): ";
+ LogPrefix = temp.str();
+}
DnsResolver::~DnsResolver()
{
boost::system::error_code error;
- Socket.shutdown(boost::asio::ip::udp::socket::shutdown_both, error); //both=send&receive
+ Socket.shutdown(boost::asio::ip::udp::socket::shutdown_both, error);
if ( error )
- GlobalLogger.warning() << "Received error " << error
+ GlobalLogger.warning() << LogPrefix << "Received error " << error
<< " when shutting down socket for DNS";
// in IcmpPinger always gave an error system:9
// (probably EBADF: Bad file descriptor)
Socket.close(error);
if ( error )
- GlobalLogger.warning() << "Received error " << error
+ GlobalLogger.warning() << LogPrefix << "Received error " << error
<< " when closing socket for DNS";
}
// check if resolving already
if (IsResolving)
{
- GlobalLogger.info()
+ GlobalLogger.info() << LogPrefix
<< "Call to do_resolve ignored since resolving already";
return;
}
+ GlobalLogger.info() << LogPrefix << "start resolving";
+
// just to be sure: cancel timers
ResolveTimeoutTimer.cancel();
PauseBeforeRetryTimer.cancel();
this, boost::asio::placeholders::error) );
// send dns request
- Socket.send_to( boost::asio::buffer(request_buffer.get_array()),
- NameServer );
+ size_t bytes_sent;
+ try
+ {
+ bytes_sent = Socket.send_to(
+ boost::asio::buffer(request_buffer.get_array()),
+ NameServer );
+ }
+ catch (boost::system::system_error &err)
+ {
+ GlobalLogger.warning() << LogPrefix
+ << "Sending of DNS request message failed: "
+ << err.what();
+ handle_unavailable();
+ return;
+ }
+
+ if ( bytes_sent == 0 )
+ {
+ GlobalLogger.warning() << LogPrefix << "Empty DNS request sent!";
+ handle_unavailable();
+ return;
+ }
+
+ GlobalLogger.info() << LogPrefix << "resolving under way";
}
{
if ( error == boost::asio::error::operation_aborted ) // cancelled
{
- GlobalLogger.info() << "DNS resolve operation was cancelled";
+ GlobalLogger.info() << LogPrefix
+ << "DNS resolve operation was cancelled";
bool was_success = false;
finalize_resolve(was_success);
}
else if (error)
{
- GlobalLogger.info() << "DNS resolve resulted in error " << error
- << " --> treat like unavailable";
+ GlobalLogger.info() << LogPrefix << "DNS resolve resulted in error "
+ << error << " --> treat like unavailable";
handle_unavailable();
return;
}
using boost::net::dns::resource_base_t;
BOOST_FOREACH( boost::shared_ptr<resource_base_t> rr_item, *answers )
{
- GlobalLogger.debug() << std::showbase << std::hex
+ GlobalLogger.debug() << LogPrefix << std::showbase << std::hex
<< static_cast<unsigned>(rr_item->rtype()) << ": ";
uint32_t ttl = rr_item->ttl();
boost::net::dns::type_t rr_type = rr_item->rtype();
{ // 'A' resource records carry IPv4 addresses
if (Protocol == DNS_IPv6)
{
- GlobalLogger.info() << "Ignoring IPv4 address because resolver "
- << "was configured to only use IPv6.";
+ GlobalLogger.info() << LogPrefix << "Ignoring IPv4 address "
+ << "because resolver was configured to only use IPv6.";
continue;
}
boost::asio::ip::address_v4 ip =
{ // 'AAAA' resource records carry IPv6 addresses
if (Protocol == DNS_IPv4)
{
- GlobalLogger.info() << "Ignoring IPv6 address because resolver "
- << "was configured to only use IPv4.";
+ GlobalLogger.info() << LogPrefix << "Ignoring IPv6 address "
+ << "because resolver was configured to only use IPv4.";
continue;
}
boost::asio::ip::address_v6 ip =
result_cnames.push_back( cname );
}
else if (rr_type == boost::net::dns::type_ns)
- GlobalLogger.debug() << "NS resource";
+ GlobalLogger.debug() << LogPrefix << "NS resource";
else if (rr_type == boost::net::dns::type_soa)
- GlobalLogger.debug() << "SOA resource";
+ GlobalLogger.debug() << LogPrefix << "SOA resource";
else if (rr_type == boost::net::dns::type_ptr)
- GlobalLogger.debug() << "ptr resource";
+ GlobalLogger.debug() << LogPrefix << "ptr resource";
else if (rr_type == boost::net::dns::type_hinfo)
- GlobalLogger.debug() << "hinfo resource";
+ GlobalLogger.debug() << LogPrefix << "hinfo resource";
else if (rr_type == boost::net::dns::type_mx)
- GlobalLogger.debug() << "mx resource";
+ GlobalLogger.debug() << LogPrefix << "mx resource";
else if (rr_type == boost::net::dns::type_txt)
- GlobalLogger.debug() << "txt resource";
+ GlobalLogger.debug() << LogPrefix << "txt resource";
else if (rr_type == boost::net::dns::type_srv)
- GlobalLogger.debug() << "srv resource";
+ GlobalLogger.debug() << LogPrefix << "srv resource";
else if (rr_type == boost::net::dns::type_axfr)
- GlobalLogger.debug() << "axfr resource";
+ GlobalLogger.debug() << LogPrefix << "axfr resource";
else
- GlobalLogger.debug() << "unknown resource type";
+ GlobalLogger.debug() << LogPrefix << "unknown resource type";
}
- GlobalLogger.info() << "Have " << result_ips.size() << " IPs and "
- << result_cnames.size() << " CNAMEs";
+ GlobalLogger.info() << LogPrefix << "Have " << result_ips.size()
+ << " IPs and " << result_cnames.size() << " CNAMEs";
// We expect either one single CNAME and no IPs or a list of IPs.
// But deal with other cases as well
if (result_ips.empty() && result_cnames.empty())
handle_unavailable(); // we just got crap, this is a dead end
else if ( !result_ips.empty() && !result_cnames.empty())
- GlobalLogger.warning() << "Have CNAMEs AND IPs --> deal with both!";
+ GlobalLogger.warning() << LogPrefix << "Have CNAMEs AND IPs "
+ << "--> deal with both!";
BOOST_FOREACH( const std::string &cname, result_cnames )
handle_cname(cname); // will schedule another DNS call
ResolverBase::update_cache(
ResolverBase::get_cached_results(canonical_name) );
else
- GlobalLogger.info() << "Cname resolution failed";
+ GlobalLogger.info() << LogPrefix << "Cname resolution failed";
finalize_resolve(was_success, cname_count+1);
}
ResolverBase::schedule_callbacks(was_success, cname_count);
// finalize
- GlobalLogger.notice() << "Done resolving"
+ GlobalLogger.notice() << LogPrefix << "Done resolving"
<< " with success = " << was_success
<< " and cname_count = " << cname_count;
IsResolving = false;
void DnsResolver::stop_trying()
{
// cancel timers
- GlobalLogger.debug() << "Cancelling timers";
+ GlobalLogger.debug() << LogPrefix << "Cancelling timers";
ResolveTimeoutTimer.cancel();
PauseBeforeRetryTimer.cancel();
StaleDataLongtermTimer.cancel();
{
if ( error == boost::asio::error::operation_aborted ) // cancelled
{
- GlobalLogger.warning() << "Resolve timeout timer was cancelled!";
+ GlobalLogger.warning() << LogPrefix
+ << "Resolve timeout timer was cancelled!";
return;
}
else if (error)
{
- GlobalLogger.warning() << "resolve timeout handler received error "
+ GlobalLogger.warning() << LogPrefix
+ << "resolve timeout handler received error "
<< error;
return;
}
- GlobalLogger.notice() << "DNS resolving timed out";
+ GlobalLogger.notice() << LogPrefix << "DNS resolving timed out";
// increment timer
++RetryCount;
const boost::system::error_code &error)
{
if ( error == boost::asio::error::operation_aborted ) // cancelled
- GlobalLogger.warning() << "Resolve timeout timer was cancelled!";
+ GlobalLogger.warning() << LogPrefix
+ << "Resolve timeout timer was cancelled!";
else if (error)
- GlobalLogger.warning() << "resolve timeout handler received error "
+ GlobalLogger.warning() << LogPrefix
+ << "resolve timeout handler received error "
<< error;
else
{
- GlobalLogger.info() << "Done waiting --> re-try resolve";
+ GlobalLogger.info() << LogPrefix << "Done waiting --> re-try resolve";
do_resolve();
}
}