nc_trans.h 25 KB
Newer Older
1
// Copyright (C) 2013-2014 Internet Systems Consortium, Inc. ("ISC")
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

#ifndef NC_TRANS_H
#define NC_TRANS_H

/// @file nc_trans.h This file defines the class NameChangeTransaction.

#include <exceptions/exceptions.h>
21
#include <d2/d2_asio.h>
22 23
#include <d2/d2_config.h>
#include <d2/dns_client.h>
24
#include <d2/state_model.h>
25
#include <dhcp_ddns/ncr_msg.h>
26
#include <dns/tsig.h>
27 28 29 30 31 32 33

#include <boost/shared_ptr.hpp>
#include <map>

namespace isc {
namespace d2 {

34
/// @brief Thrown if the transaction encounters a general error.
35 36 37 38 39 40 41 42 43 44 45 46 47 48
class NameChangeTransactionError : public isc::Exception {
public:
    NameChangeTransactionError(const char* file, size_t line,
                               const char* what) :
        isc::Exception(file, line, what) { };
};

/// @brief Defines the type used as the unique key for transactions.
typedef isc::dhcp_ddns::D2Dhcid TransactionKey;

/// @brief Embodies the "life-cycle" required to carry out a DDNS update.
///
/// NameChangeTransaction is the base class that provides the common state
/// model mechanics and services performing the DNS updates needed to carry out
49 50
/// a DHCP_DDNS request as described by a NameChangeRequest.  It is derived
/// from StateModel which supplies a simple, general purpose FSM implementation.
51 52 53 54 55 56
///
/// Upon construction, each transaction has all of the information and
/// resources required to carry out its assigned request, including the list(s)
/// of DNS server(s) needed. It is responsible for knowing what conversations
/// it must have with which servers and in the order necessary to fulfill the
/// request. Upon fulfillment of the request, the transaction's work is complete
57
/// and it is destroyed.
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
///
/// Fulfillment of the request is carried out through the performance of the
/// transaction's state model.  Using a state driven implementation accounts
/// for the conditional processing flow necessary to meet the DDNS RFCs as well
/// as the asynchronous nature of IO with DNS servers.
///
/// Derivations of the class are responsible for defining the state model and
/// conversations necessary to carry out the specific of request.
///
/// Conversations with DNS servers are done through the use of the DNSClient
/// class.  The DNSClient provides a IOService-based means a service which
/// performs a single, packet exchange with a given DNS server.  It sends a
/// single update to the server and returns the response, asynchronously,
/// through a callback.  At each point in a transaction's state model, where
/// an update is to be sent, the model "suspends" until notified by the
73
/// DNSClient via the callback.  Suspension is done by posting a
74
/// StateModel::NOP_EVT as the next event, stopping the state model execution.
75
///
76 77 78
/// Resuming state model execution when a DNS update completes is done by a
/// call to StateModel::runStateModel() from within the DNSClient callback,
/// with an event value of IO_COMPLETED_EVT (described below).
79 80 81 82 83 84
///
/// This class defines a set of events and states that are a common to all
/// transactions. Each derivation may add define additional states and events
/// as needed, but it must support the common set.  NameChangeTransaction
/// does not supply any state handlers.  These are the sole responsibility of
/// derivations.
85
class NameChangeTransaction : public DNSClient::Callback, public StateModel {
86 87 88
public:

    //@{ States common to all transactions.
89

90
    /// @brief State from which a transaction is started.
91
    static const int READY_ST = SM_DERIVED_STATE_MIN + 1;
92

93 94 95 96 97 98
    /// @brief State in which forward DNS server selection is done.
    ///
    /// Within this state, the actual selection of the next forward server
    /// to use is conducted.  Upon conclusion of this state the next server
    /// is either selected or it should transition out with NO_MORE_SERVERS_EVT
    /// event.
99
    static const int SELECTING_FWD_SERVER_ST = SM_DERIVED_STATE_MIN + 2;
100

101
    /// @brief State in which reverse DNS server  selection is done.
102 103 104 105 106
    ///
    /// Within this state, the actual selection of the next reverse server
    /// to use is conducted.  Upon conclusion of this state the next server
    /// is either selected or it should transition out with NO_MORE_SERVERS_EVT
    /// event.
107
    static const int SELECTING_REV_SERVER_ST = SM_DERIVED_STATE_MIN + 3;
108

109 110
    /// @brief State which processes successful transaction conclusion.
    static const int PROCESS_TRANS_OK_ST = SM_DERIVED_STATE_MIN + 4;
111

112 113
    /// @brief State which processes an unsuccessful transaction conclusion.
    static const int PROCESS_TRANS_FAILED_ST = SM_DERIVED_STATE_MIN + 5;
114

115
    /// @brief Value at which custom states in a derived class should begin.
116
    static const int NCT_DERIVED_STATE_MIN = SM_DERIVED_STATE_MIN + 101;
117 118 119 120
    //@}

    //@{ Events common to all transactions.
    /// @brief Issued when a server needs to be selected.
121 122
    static const int SELECT_SERVER_EVT = SM_DERIVED_EVENT_MIN + 1;

123
    /// @brief Issued when a server  has been selected.
124 125
    static const int SERVER_SELECTED_EVT = SM_DERIVED_EVENT_MIN + 2;

126
    /// @brief Issued when an update fails due to an IO error.
127 128
    static const int SERVER_IO_ERROR_EVT = SM_DERIVED_EVENT_MIN + 3;

129 130 131
    /// @brief Issued when there are no more servers from which to select.
    /// This occurs when none of the servers in the list can be reached to
    /// perform the update.
132 133

    static const int NO_MORE_SERVERS_EVT =SM_DERIVED_EVENT_MIN +  4;
134 135 136
    /// @brief Issued when a DNS update packet exchange has completed.
    /// This occurs whenever the DNSClient callback is invoked whether the
    /// exchange was successful or not.
137 138

    static const int IO_COMPLETED_EVT = SM_DERIVED_EVENT_MIN + 5;
139 140 141
    /// @brief Issued when the attempted update successfully completed.
    /// This occurs when an DNS update packet was successfully processed
    /// by the server.
142 143 144

    static const int UPDATE_OK_EVT = SM_DERIVED_EVENT_MIN + 6;

145 146 147 148
    /// @brief Issued when the attempted update fails to complete.
    /// This occurs when an DNS update packet fails to process. The nature of
    /// the failure is given by the DNSClient return status and the response
    /// packet (if one was received).
149
    static const int UPDATE_FAILED_EVT = SM_DERIVED_EVENT_MIN + 7;
150

151
    /// @brief Value at which custom events in a derived class should begin.
152
    static const int NCT_DERIVED_EVENT_MIN = SM_DERIVED_EVENT_MIN + 101;
153 154
    //@}

155
    /// @brief Defualt time to assign to a single DNS udpate.
156 157 158
    /// @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.
159
    static const unsigned int DNS_UPDATE_DEFAULT_TIMEOUT = 100;
160 161 162 163

    /// @brief Maximum times to attempt a single update on a given server.
    static const unsigned int MAX_UPDATE_TRIES_PER_SERVER = 3;

164 165 166 167 168 169 170 171 172
    /// @brief Constructor
    ///
    /// Instantiates a transaction that is ready to be started.
    ///
    /// @param io_service IO service to be used for IO processing
    /// @param ncr is the NameChangeRequest to fulfill
    /// @param forward_domain is the domain to use for forward DNS updates
    /// @param reverse_domain is the domain to use for reverse DNS updates
    ///
173
    /// @throw NameChangeTransactionError if given an null request,
174 175
    /// if forward change is enabled but forward domain is null, if
    /// reverse change is enabled but reverse domain is null.
176
    NameChangeTransaction(IOServicePtr& io_service,
177
                          dhcp_ddns::NameChangeRequestPtr& ncr,
178 179
                          DdnsDomainPtr& forward_domain,
                          DdnsDomainPtr& reverse_domain);
180

181
    /// @brief Destructor
182 183 184 185
    virtual ~NameChangeTransaction();

    /// @brief Begins execution of the transaction.
    ///
186 187 188
    /// This method invokes StateModel::startModel() with a value of READY_ST.
    /// This causes transaction's state model to attempt to begin execution
    /// with the state handler for READY_ST.
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
    void startTransaction();

    /// @brief Serves as the DNSClient IO completion event handler.
    ///
    /// This is the implementation of the method inherited by our derivation
    /// from DNSClient::Callback.  When the DNSClient completes an update it
    /// invokes this method as the completion handler.  This method stores
    /// the given status and invokes runStateModel() with an event value of
    /// IO_COMPLETED_EVT.
    ///
    /// @param status is the outcome of the DNS update packet exchange.
    /// This method is exception safe.
    virtual void operator()(DNSClient::Status status);

protected:
204 205 206 207 208 209 210
    /// @brief Send the update request to the current server.
    ///
    /// This method increments the update attempt count and then passes the
    /// current update request to the DNSClient instance to be sent to the
    /// currently selected server.  Since the send is asynchronous, the method
    /// posts NOP_EVT as the next event and then returns.
    ///
211 212 213 214
    /// If tsig_key_ is not NULL, then the update will be conducted using
    /// the key to sign the request and verify the response, otherwise it
    /// will be conducted without TSIG.
    ///
215
    /// @param comment text to include in log detail
216
    ///
217 218
    /// If an exception occurs it will be logged and and the transaction will
    /// be failed.
219
    virtual void sendUpdate(const std::string& comment = "");
220

221
    /// @brief Adds events defined by NameChangeTransaction to the event set.
222 223 224
    ///
    /// This method adds the events common to NCR transaction processing to
    /// the set of define events.  It invokes the superclass's implementation
225
    /// first to maintain the hierarchical chain of event definition.
226
    /// Derivations of NameChangeTransaction must invoke its implementation
227 228 229 230 231 232 233 234 235 236
    /// in like fashion.
    ///
    /// @throw StateModelError if an event definition is invalid or a duplicate.
    virtual void defineEvents();

    /// @brief Validates the contents of the set of events.
    ///
    /// This method verifies that the events defined by both the superclass and
    /// this class are defined.  As with defineEvents, this method calls the
    /// superclass's implementation first, to verify events defined by it and
237
    /// then this implementation to verify events defined by
238 239
    /// NameChangeTransaction.
    ///
240
    /// @throw StateModelError if an event value is undefined.
241 242
    virtual void verifyEvents();

243
    /// @brief Adds states defined by NameChangeTransaction to the state set.
244
    ///
245 246
    /// This method adds the states common to NCR transaction processing to
    /// the dictionary of states.  It invokes the superclass's implementation
247
    /// first to maintain the hierarchical chain of state definition.
248 249
    /// Derivations of NameChangeTransaction must invoke its implementation
    /// in like fashion.
250
    ///
251 252
    /// @throw StateModelError if an state definition is invalid or a duplicate.
    virtual void defineStates();
253

254
    /// @brief Validates the contents of the set of states.
255
    ///
256 257 258 259 260
    /// This method verifies that the states defined by both the superclass and
    /// this class are defined.  As with defineStates, this method calls the
    /// superclass's implementation first, to verify states defined by it and
    /// then this implementation to verify states defined by
    /// NameChangeTransaction.
261
    ///
262 263
    /// @throw StateModelError if an event value is undefined.
    virtual void verifyStates();
264

265
    /// @brief Handler for fatal model execution errors.
266
    ///
267 268 269 270
    /// This handler is called by the StateModel implementation when the model
    /// execution encounters a model violation:  attempt to call an unmapped
    /// state, an event not valid for the current state, or an uncaught
    /// exception thrown during a state handler invocation.  When such an
271
    /// error occurs the transaction is deemed inoperable, and further model
272 273
    /// execution cannot be performed.  It marks the transaction as failed by
    /// setting the NCR status to dhcp_ddns::ST_FAILED
274 275 276
    ///
    /// @param explanation is text detailing the error
    virtual void onModelFailure(const std::string& explanation);
277

278 279 280
    /// @brief Determines the state and next event based on update attempts.
    ///
    /// This method will post a next event of SERVER_SELECTED_EVT to the
281
    /// current state if the number of update attempts has not reached the
282 283 284 285 286
    /// maximum allowed.
    ///
    /// If the maximum number of attempts has been reached, it will transition
    /// to the given state with a next event of SERVER_IO_ERROR_EVT.
    ///
287
    /// @param fail_to_state  State to transition to if maximum attempts
288 289
    /// have been tried.
    ///
290
    void retryTransition(const int fail_to_state);
291 292 293 294 295 296

    /// @brief Sets the update request packet to the given packet.
    ///
    /// @param request is the new request packet to assign.
    void setDnsUpdateRequest(D2UpdateMessagePtr& request);

297
    /// @brief Destroys the current update request packet and resets
298
    /// udpate attempts count.
299 300
    void clearDnsUpdateRequest();

301 302 303 304 305 306 307 308 309 310
    /// @brief Sets the update status to the given status value.
    ///
    /// @param status is the new value for the update status.
    void setDnsUpdateStatus(const DNSClient::Status& status);

    /// @brief Sets the update response packet to the given packet.
    ///
    /// @param response is the new response packet to assign.
    void setDnsUpdateResponse(D2UpdateMessagePtr& response);

311
    /// @brief Destroys the current update response packet.
312 313
    void clearDnsUpdateResponse();

314 315 316 317 318 319 320 321 322 323
    /// @brief Sets the forward change completion flag to the given value.
    ///
    /// @param value is the new value to assign to the flag.
    void setForwardChangeCompleted(const bool value);

    /// @brief Sets the reverse change completion flag to the given value.
    ///
    /// @param value is the new value to assign to the flag.
    void setReverseChangeCompleted(const bool value);

324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
    /// @brief Sets the status of the transaction's NameChangeRequest
    ///
    /// @param status is the new value to assign to the NCR status.
    void setNcrStatus(const dhcp_ddns::NameChangeStatus& status);

    /// @brief Initializes server selection from the given DDNS domain.
    ///
    /// Method prepares internal data to conduct server selection from the
    /// list of servers supplied by the given domain.  This method should be
    /// called when a transaction is ready to begin selecting servers from
    /// a new list.  Typically this will be prior to starting the updates for
    /// a given DNS direction.
    ///
    /// @param domain is the domain from which server selection is to be
    /// conducted.
339
    void initServerSelection(const DdnsDomainPtr& domain);
340 341 342 343 344

    /// @brief Selects the next server in the current server list.
    ///
    /// This method is used to iterate over the list of servers.  If there are
    /// no more servers in the list, it returns false.  Otherwise it sets the
345
    /// current server to the next server and creates a new DNSClient
346 347 348 349 350 351
    /// instance.
    ///
    /// @return True if a server has been selected, false if there are no more
    /// servers from which to select.
    bool selectNextServer();

352 353 354 355 356 357
    /// @brief Sets the TSIG key to be used.
    ///
    /// @param tsig_key TSIG Key value to be used for signing and verifying
    /// messages.  If set to an emtpy pointer, TSIG will not be used.
    void setTSIGKey(const dns::TSIGKeyPtr& tsig_key);

358 359 360
    /// @brief Sets the update attempt count to the given value.
    ///
    /// @param value is the new value to assign.
361 362
    void setUpdateAttempts(const size_t value);

363 364 365
    /// @brief Fetches the IOService the transaction uses for IO processing.
    ///
    /// @return returns a const pointer to the IOService.
366 367 368 369
    const IOServicePtr& getIOService() {
        return (io_service_);
    }

370 371 372 373
    /// @brief Creates a new DNS update request based on the given domain.
    ///
    /// Constructs a new "empty", OUTBOUND, request with the message id set
    /// and zone section populated based on the given domain.
374
    /// It is declared virtual for test purposes.
375 376 377 378
    ///
    /// @return A D2UpdateMessagePtr to the new request.
    ///
    /// @throw NameChangeTransactionError if request cannot be constructed.
379
    virtual D2UpdateMessagePtr prepNewRequest(DdnsDomainPtr domain);
380 381 382 383 384 385

    /// @brief Adds an RData for the lease address to the given RRset.
    ///
    /// Creates an in::A() or in:AAAA() RData instance from the NCR
    /// lease address and adds it to the given RRset.
    ///
386
    /// @param rrset RRset to which to add the RData
387 388 389 390 391 392 393 394 395 396
    ///
    /// @throw NameChangeTransactionError if RData cannot be constructed or
    /// the RData cannot be added to the given RRset.
    void addLeaseAddressRdata(dns::RRsetPtr& rrset);

    /// @brief Adds an RData for the lease client's DHCID to the given RRset.
    ///
    /// Creates an in::DHCID() RData instance from the NCR DHCID and adds
    /// it to the given RRset.
    ///
397
    /// @param rrset RRset to which to add the RData
398 399 400 401 402 403 404 405 406 407
    ///
    /// @throw NameChangeTransactionError if RData cannot be constructed or
    /// the RData cannot be added to the given RRset.
    void addDhcidRdata(dns::RRsetPtr& rrset);

    /// @brief Adds an RData for the lease FQDN to the given RRset.
    ///
    /// Creates an in::PTR() RData instance from the NCR FQDN and adds
    /// it to the given RRset.
    ///
408
    /// @param rrset RRset to which to add the RData
409 410 411 412
    ///
    /// @throw NameChangeTransactionError if RData cannot be constructed or
    /// the RData cannot be added to the given RRset.
    void addPtrRdata(dns::RRsetPtr& rrset);
413

414 415 416 417 418 419
    /// @brief Returns a string version of the current response status and rcode
    ///
    /// Renders a string containing the a text label current DNS update status
    /// and RCODE (if status is DNSClient::SUCCESS)
    ///
    /// @return std::string containing constructed text
420 421 422 423 424 425 426 427 428 429 430
    std::string responseString() const;

    /// @brief Returns a string version of transaction outcome.
    ///
    /// Renders a string containing summarizes the outcome of the
    /// transaction. The information includes the overall status,
    /// the last event, whether not forward and reverse changes were
    /// done, as well as the NCR serviced.
    ///
    /// @return std::string containing constructed text
    std::string transactionOutcomeString() const;
431

432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449
public:
    /// @brief Fetches the NameChangeRequest for this transaction.
    ///
    /// @return A const pointer reference to the NameChangeRequest.
    const dhcp_ddns::NameChangeRequestPtr& getNcr() const;

    /// @brief Fetches the unique key that identifies this transaction.
    ///
    /// Transactions are uniquely identified by a TransactionKey. Currently
    /// this is wrapper around a D2Dhcid.
    ///
    /// @return A const reference to the TransactionKey.
    const TransactionKey& getTransactionKey() const;

    /// @brief Fetches the NameChangeRequest status of the transaction.
    ///
    /// This is the current status of the NameChangeRequest, not to
    /// be confused with the state of the transaction.  Once the transaction
450
    /// is reached its conclusion, the request will end up with a final
451 452 453 454 455 456
    /// status.
    ///
    /// @return A dhcp_ddns::NameChangeStatus representing the current
    /// status of the transaction.
    dhcp_ddns::NameChangeStatus getNcrStatus() const;

457
    /// @brief Fetches the forward DdnsDomain.
458
    ///
459
    /// @return A pointer reference to the forward DdnsDomain.  If
460
    /// the request does not include a forward change, the pointer will empty.
461 462 463 464
    DdnsDomainPtr& getForwardDomain();

    /// @brief Fetches the reverse DdnsDomain.
    ///
465
    /// @return A pointer reference to the reverse DdnsDomain.  If
466
    /// the request does not include a reverse change, the pointer will empty.
467
    DdnsDomainPtr& getReverseDomain();
468

469 470 471 472 473 474 475 476 477 478 479
    /// @brief Fetches the currently selected server.
    ///
    /// @return A const pointer reference to the DnsServerInfo of the current
    /// server.
    const DnsServerInfoPtr& getCurrentServer() const;

    /// @brief Fetches the DNSClient instance
    ///
    /// @return A const pointer reference to the DNSClient
    const DNSClientPtr& getDNSClient() const;

480 481 482 483 484 485
    /// @brief Pointer to the TSIG key which should be used (if any).
    ///
    /// @return A const pointer reference to the current TSIG key. Pointer
    /// will be empty if TSIG is not being used.
    const dns::TSIGKeyPtr& getTSIGKey() const;

486 487 488 489 490 491
    /// @brief Fetches the current DNS update request packet.
    ///
    /// @return A const pointer reference to the current D2UpdateMessage
    /// request.
    const D2UpdateMessagePtr& getDnsUpdateRequest() const;

492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521
    /// @brief Fetches the most recent DNS update status.
    ///
    /// @return A DNSClient::Status indicating the result of the most recent
    /// DNS update to complete.
    DNSClient::Status getDnsUpdateStatus() const;

    /// @brief Fetches the most recent DNS update response packet.
    ///
    /// @return A const pointer reference to the D2UpdateMessage most recently
    /// received.
    const D2UpdateMessagePtr& getDnsUpdateResponse() const;

    /// @brief Returns whether the forward change has completed or not.
    ///
    /// The value returned is only meaningful if the NameChangeRequest calls
    /// for a forward change to be done. The value returned indicates if
    /// forward change has been completed successfully.
    ///
    /// @return True if the forward change has been completed, false otherwise.
    bool getForwardChangeCompleted() const;

    /// @brief Returns whether the reverse change has completed or not.
    ///
    /// The value returned is only meaningful if the NameChangeRequest calls
    /// for a reverse change to be done. The value returned indicates if
    /// reverse change has been completed successfully.
    ///
    /// @return True if the reverse change has been completed, false otherwise.
    bool getReverseChangeCompleted() const;

522 523 524 525 526 527
    /// @brief Fetches the update attempt count for the current update.
    ///
    /// @return size_t which is the number of times the current request has
    /// been attempted against the current server.
    size_t getUpdateAttempts() const;

528 529 530 531 532 533
    /// @brief Returns the DHCP data type for the lease address
    ///
    /// @return constant reference to dns::RRType::A() if the lease address
    /// is IPv4 or dns::RRType::AAAA() if the lease address is IPv6.
    const dns::RRType& getAddressRRType() const;

534
private:
535
    /// @brief The IOService which should be used to for IO processing.
536
    IOServicePtr io_service_;
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557

    /// @brief The NameChangeRequest that the transaction is to fulfill.
    dhcp_ddns::NameChangeRequestPtr ncr_;

    /// @brief The forward domain that matches the request.
    ///
    /// The forward "domain" is DdnsDomain which contains all of the information
    /// necessary, including the list of DNS servers to be used for a forward
    /// change.
    DdnsDomainPtr forward_domain_;

    /// @brief The reverse domain that matches the request.
    ///
    /// The reverse "domain" is DdnsDomain which contains all of the information
    /// necessary, including the list of DNS servers to be used for a reverse
    /// change.
    DdnsDomainPtr reverse_domain_;

    /// @brief The DNSClient instance that will carry out DNS packet exchanges.
    DNSClientPtr dns_client_;

558 559 560
    /// @brief The DNS current update request packet.
    D2UpdateMessagePtr dns_update_request_;

561 562 563 564 565 566 567 568 569 570 571
    /// @brief The outcome of the most recently completed DNS packet exchange.
    DNSClient::Status dns_update_status_;

    /// @brief The DNS update response packet most recently received.
    D2UpdateMessagePtr dns_update_response_;

    /// @brief Indicator for whether or not the forward change completed ok.
    bool forward_change_completed_;

    /// @brief Indicator for whether or not the reverse change completed ok.
    bool reverse_change_completed_;
572 573 574 575 576 577 578 579 580 581 582 583

    /// @brief Pointer to the current server selection list.
    DnsServerInfoStoragePtr current_server_list_;

    /// @brief Pointer to the currently selected server.
    DnsServerInfoPtr current_server_;

    /// @brief Next server position in the list.
    ///
    /// This value is always the position of the next selection in the server
    /// list, which may be beyond the end of the list.
    size_t next_server_pos_;
584

585
    /// @brief Number of transmit attempts for the current request.
586
    size_t update_attempts_;
587 588 589

    /// @brief Pointer to the TSIG key which should be used (if any).
    dns::TSIGKeyPtr tsig_key_;
590 591 592 593 594 595 596 597
};

/// @brief Defines a pointer to a NameChangeTransaction.
typedef boost::shared_ptr<NameChangeTransaction> NameChangeTransactionPtr;

} // namespace isc::d2
} // namespace isc
#endif