-# Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2013-2014 Internet Systems Consortium, Inc. ("ISC")
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
entry removals have failed. The precise reason for the failure should be
documented in preceding log entries.
-% DHCP_DDNS_UPDATE_REQUEST_SENT for transaction key: %1 to server : %2
+% DHCP_DDNS_STARTING_TRANSACTION Transaction Key: %1
+
+% DHCP_DDNS_UPDATE_REQUEST_SENT for transaction key: %1 to server: %2
This is a debug message issued when DHCP_DDNS sends a DNS request to a DNS
server.
-% DHCP_DDNS_UPDATE_RESPONSE_RECEIVED for transaction key: %1 to server : %2 status: %3
+% DHCP_DDNS_UPDATE_RESPONSE_RECEIVED for transaction key: %1 to server: %2 status: %3
This is a debug message issued when DHCP_DDNS receives sends a DNS update
response from a DNS server.
forward_domain, reverse_domain));
} else {
trans.reset(new NameRemoveTransaction(io_service_, next_ncr,
- forward_domain, reverse_domain));
+ forward_domain, reverse_domain));
}
// Add the new transaction to the list.
public:
// A buffer holding response from a DNS.
util::OutputBufferPtr in_buf_;
- // A caller-supplied object holding a parsed response from DNS.
+ // A caller-supplied object which will hold the parsed response from DNS.
+ // The response object is (or descends from) isc::dns::Message and is
+ // populated using Message::fromWire(). This method may only be called
+ // once in the lifetime of a Message instance. Therefore, response_ is a
+ // pointer reference thus allowing this class to replace the object
+ // pointed to with a new Message instance each time a message is
+ // received. This allows a single DNSClientImpl instance to be used in
+ // for multiple, sequential IOFetch calls.
D2UpdateMessagePtr& response_;
// A caller-supplied external callback which is invoked when DNS message
// exchange is complete or interrupted.
: in_buf_(new OutputBuffer(DEFAULT_BUFFER_SIZE)),
response_(response_placeholder), callback_(callback), proto_(proto) {
+ // Response should be an empty pointer. It gets populated by the
+ // operator() method.
+ if (response_) {
+ isc_throw(isc::BadValue, "Response buffer pointer should be null");
+ }
+
// @todo Currently we only support UDP. The support for TCP is planned for
// the future release.
if (proto_ == DNSClient::TCP) {
/// @brief Constructor.
///
- /// @param response_placeholder Pointer to an object which will hold a
- /// DNS server's response. Caller is responsible for allocating this object.
+ /// @param response_placeholder Messge object pointer which will be updated
+ /// with dynamically allocated object holding the DNS server's response.
/// @param callback Pointer to an object implementing @c DNSClient::Callback
/// class. This object will be called when DNS message exchange completes or
/// if an error occurs. NULL value disables callback invocation.
void
NameChangeTransaction::startTransaction() {
+ LOG_DEBUG(dctl_logger, DBGLVL_TRACE_DETAIL,
+ DHCP_DDNS_STARTING_TRANSACTION)
+ .arg(getTransactionKey().toStr());
+
setNcrStatus(dhcp_ddns::ST_PENDING);
startModel(READY_ST);
}
if ((current_server_list_) &&
(next_server_pos_ < current_server_list_->size())) {
current_server_ = (*current_server_list_)[next_server_pos_];
- dns_update_response_.reset(new
- D2UpdateMessage(D2UpdateMessage::INBOUND));
+ // Toss out any previous response.
+ dns_update_response_.reset();
+
// @todo Protocol is set on DNSClient constructor. We need
// to propagate a configuration value downward, probably starting
// at global, then domain, then server
//@}
/// @brief Defualt time to assign to a single DNS udpate.
-#if 0
- /// @todo This value will be configurable in the near future, but
- /// until it is there is no way to replace its value. For now
- /// we will define it to be relatively short, so unit tests will
- /// run within reasonable amount of time.
- static const unsigned int DNS_UPDATE_DEFAULT_TIMEOUT = 5 * 1000;
-#else
+ /// @todo This value will be made configurable in the very near future
+ /// under trac3268. For now we will define it to 100 milliseconds
+ /// so unit tests will run within a reasonable amount of time.
static const unsigned int DNS_UPDATE_DEFAULT_TIMEOUT = 100;
-#endif
/// @brief Maximum times to attempt a single update on a given server.
static const unsigned int MAX_UPDATE_TRIES_PER_SERVER = 3;
void setDnsUpdateRequest(D2UpdateMessagePtr& request);
/// @brief Destroys the current update request packet and resets
- /// udpate attempts count..
+ /// udpate attempts count.
void clearDnsUpdateRequest();
/// @brief Sets the update status to the given status value.
namespace {
-/// @brief Wrapper class for D2UpdateMgr to provide access non-public methods.
+/// @brief Wrapper class for D2UpdateMgr providing access to non-public methods.
///
/// This class facilitates testing by making non-public methods accessible so
/// they can be invoked directly in test routines.
test_timer_(service_),
received_(0), expected_(0) {
asiodns::logger.setSeverity(isc::log::INFO);
- response_.reset(new D2UpdateMessage(D2UpdateMessage::INBOUND));
+ response_.reset();
dns_client_.reset(new DNSClient(response_, this));
// Set the test timeout to break any running tasks if they hang.
}
};
-class TimedIO {
+/// @brief Provides a means to process IOService IO for a finite amount of time.
+///
+/// This class instantiates an IOService provides a single method, runTimedIO
+/// which will run the IOService for no more than a finite amount of time,
+/// at least one event is executed or the IOService is stopped.
+/// It provides an overridable handler for timer expiration event. It is
+/// intended to be used as a base class for test fixtures that need to process
+/// IO by providing them a consistent way to do so while retaining a safety valve
+/// so tests do not hang.
+class TimedIO {
public:
IOServicePtr io_service_;
asiolink::IntervalTimer timer_;
// they are correct after each selection.
DnsServerInfoPtr prev_server = name_change->getCurrentServer();
DNSClientPtr prev_client = name_change->getDNSClient();
- D2UpdateMessagePtr prev_response = name_change->getDnsUpdateResponse();
+
+ // Verify response pointer is empty.
+ EXPECT_FALSE(name_change->getDnsUpdateResponse());
+
+ // Create dummy response so we can verify it is cleared at each
+ // new server select.
+ D2UpdateMessagePtr dummyResp;
+ dummyResp.reset(new D2UpdateMessage(D2UpdateMessage::INBOUND));
+ ASSERT_NO_THROW(name_change->setDnsUpdateResponse(dummyResp));
+ ASSERT_TRUE(name_change->getDnsUpdateResponse());
// Iteratively select through the list of servers.
int passes = 0;
// Verify that the new values are not empty.
EXPECT_TRUE(server);
EXPECT_TRUE(client);
- EXPECT_TRUE(response);
+
+ // Verify response pointer is now empty.
+ EXPECT_FALSE(name_change->getDnsUpdateResponse());
// Verify that the new values are indeed new.
EXPECT_NE(server, prev_server);
EXPECT_NE(client, prev_client);
- EXPECT_NE(response, prev_response);
// Remember the selected values for the next pass.
prev_server = server;
prev_client = client;
- prev_response = response;
+
+ // Create new dummy response.
+ dummyResp.reset(new D2UpdateMessage(D2UpdateMessage::INBOUND));
+ ASSERT_NO_THROW(name_change->setDnsUpdateResponse(dummyResp));
+ ASSERT_TRUE(name_change->getDnsUpdateResponse());
++passes;
}
ASSERT_NO_THROW(name_change->initServerSelection(domain));
// The server selection process determines the current server,
- // instantiates a new DNSClient, and a DNS response message buffer.
+ // instantiates a new DNSClient, and resets the DNS response message buffer.
// We need to save the values before each selection, so we can verify
// they are correct after each selection.
prev_server = name_change->getCurrentServer();
prev_client = name_change->getDNSClient();
- prev_response = name_change->getDnsUpdateResponse();
// Iteratively select through the list of servers.
passes = 0;
// Verify that the new values are not empty.
EXPECT_TRUE(server);
EXPECT_TRUE(client);
- EXPECT_TRUE(response);
+
+ // Verify response pointer is now empty.
+ EXPECT_FALSE(name_change->getDnsUpdateResponse());
// Verify that the new values are indeed new.
EXPECT_NE(server, prev_server);
EXPECT_NE(client, prev_client);
- EXPECT_NE(response, prev_response);
// Remember the selected values for the next pass.
prev_server = server;
prev_client = client;
- prev_response = response;
+
+ // Create new dummy response.
+ dummyResp.reset(new D2UpdateMessage(D2UpdateMessage::INBOUND));
+ ASSERT_NO_THROW(name_change->setDnsUpdateResponse(dummyResp));
+ ASSERT_TRUE(name_change->getDnsUpdateResponse());
++passes;
}