nc_trans.h 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. // Copyright (C) 2013-2014 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. #ifndef NC_TRANS_H
  15. #define NC_TRANS_H
  16. /// @file nc_trans.h This file defines the class NameChangeTransaction.
  17. #include <exceptions/exceptions.h>
  18. #include <d2/d2_asio.h>
  19. #include <d2/d2_config.h>
  20. #include <d2/dns_client.h>
  21. #include <d2/state_model.h>
  22. #include <dhcp_ddns/ncr_msg.h>
  23. #include <boost/shared_ptr.hpp>
  24. #include <map>
  25. namespace isc {
  26. namespace d2 {
  27. /// @brief Thrown if the transaction encounters a general error.
  28. class NameChangeTransactionError : public isc::Exception {
  29. public:
  30. NameChangeTransactionError(const char* file, size_t line,
  31. const char* what) :
  32. isc::Exception(file, line, what) { };
  33. };
  34. /// @brief Defines the type used as the unique key for transactions.
  35. typedef isc::dhcp_ddns::D2Dhcid TransactionKey;
  36. /// @brief Embodies the "life-cycle" required to carry out a DDNS update.
  37. ///
  38. /// NameChangeTransaction is the base class that provides the common state
  39. /// model mechanics and services performing the DNS updates needed to carry out
  40. /// a DHCP_DDNS request as described by a NameChangeRequest. It is derived
  41. /// from StateModel which supplies a simple, general purpose FSM implementation.
  42. ///
  43. /// Upon construction, each transaction has all of the information and
  44. /// resources required to carry out its assigned request, including the list(s)
  45. /// of DNS server(s) needed. It is responsible for knowing what conversations
  46. /// it must have with which servers and in the order necessary to fulfill the
  47. /// request. Upon fulfillment of the request, the transaction's work is complete
  48. /// and it is destroyed.
  49. ///
  50. /// Fulfillment of the request is carried out through the performance of the
  51. /// transaction's state model. Using a state driven implementation accounts
  52. /// for the conditional processing flow necessary to meet the DDNS RFCs as well
  53. /// as the asynchronous nature of IO with DNS servers.
  54. ///
  55. /// Derivations of the class are responsible for defining the state model and
  56. /// conversations necessary to carry out the specific of request.
  57. ///
  58. /// Conversations with DNS servers are done through the use of the DNSClient
  59. /// class. The DNSClient provides a IOService-based means a service which
  60. /// performs a single, packet exchange with a given DNS server. It sends a
  61. /// single update to the server and returns the response, asynchronously,
  62. /// through a callback. At each point in a transaction's state model, where
  63. /// an update is to be sent, the model "suspends" until notified by the
  64. /// DNSClient via the callback. Suspension is done by posting a
  65. /// StateModel::NOP_EVT as the next event, stopping the state model execution.
  66. ///
  67. /// Resuming state model execution when a DNS update completes is done by a
  68. /// call to StateModel::runStateModel() from within the DNSClient callback,
  69. /// with an event value of IO_COMPLETED_EVT (described below).
  70. ///
  71. /// This class defines a set of events and states that are a common to all
  72. /// transactions. Each derivation may add define additional states and events
  73. /// as needed, but it must support the common set. NameChangeTransaction
  74. /// does not supply any state handlers. These are the sole responsibility of
  75. /// derivations.
  76. class NameChangeTransaction : public DNSClient::Callback, public StateModel {
  77. public:
  78. //@{ States common to all transactions.
  79. /// @brief State from which a transaction is started.
  80. static const int READY_ST = SM_DERIVED_STATE_MIN + 1;
  81. /// @brief State in which forward DNS server selection is done.
  82. ///
  83. /// Within this state, the actual selection of the next forward server
  84. /// to use is conducted. Upon conclusion of this state the next server
  85. /// is either selected or it should transition out with NO_MORE_SERVERS_EVT
  86. /// event.
  87. static const int SELECTING_FWD_SERVER_ST = SM_DERIVED_STATE_MIN + 2;
  88. /// @brief State in which reverse DNS server selection is done.
  89. ///
  90. /// Within this state, the actual selection of the next reverse server
  91. /// to use is conducted. Upon conclusion of this state the next server
  92. /// is either selected or it should transition out with NO_MORE_SERVERS_EVT
  93. /// event.
  94. static const int SELECTING_REV_SERVER_ST = SM_DERIVED_STATE_MIN + 3;
  95. /// @brief State which processes successful transaction conclusion.
  96. static const int PROCESS_TRANS_OK_ST = SM_DERIVED_STATE_MIN + 4;
  97. /// @brief State which processes an unsuccessful transaction conclusion.
  98. static const int PROCESS_TRANS_FAILED_ST = SM_DERIVED_STATE_MIN + 5;
  99. /// @brief Value at which custom states in a derived class should begin.
  100. static const int NCT_DERIVED_STATE_MIN = SM_DERIVED_STATE_MIN + 101;
  101. //@}
  102. //@{ Events common to all transactions.
  103. /// @brief Issued when a server needs to be selected.
  104. static const int SELECT_SERVER_EVT = SM_DERIVED_EVENT_MIN + 1;
  105. /// @brief Issued when a server has been selected.
  106. static const int SERVER_SELECTED_EVT = SM_DERIVED_EVENT_MIN + 2;
  107. /// @brief Issued when an update fails due to an IO error.
  108. static const int SERVER_IO_ERROR_EVT = SM_DERIVED_EVENT_MIN + 3;
  109. /// @brief Issued when there are no more servers from which to select.
  110. /// This occurs when none of the servers in the list can be reached to
  111. /// perform the update.
  112. static const int NO_MORE_SERVERS_EVT =SM_DERIVED_EVENT_MIN + 4;
  113. /// @brief Issued when a DNS update packet exchange has completed.
  114. /// This occurs whenever the DNSClient callback is invoked whether the
  115. /// exchange was successful or not.
  116. static const int IO_COMPLETED_EVT = SM_DERIVED_EVENT_MIN + 5;
  117. /// @brief Issued when the attempted update successfully completed.
  118. /// This occurs when an DNS update packet was successfully processed
  119. /// by the server.
  120. static const int UPDATE_OK_EVT = SM_DERIVED_EVENT_MIN + 6;
  121. /// @brief Issued when the attempted update fails to complete.
  122. /// This occurs when an DNS update packet fails to process. The nature of
  123. /// the failure is given by the DNSClient return status and the response
  124. /// packet (if one was received).
  125. static const int UPDATE_FAILED_EVT = SM_DERIVED_EVENT_MIN + 7;
  126. /// @brief Value at which custom events in a derived class should begin.
  127. static const int NCT_DERIVED_EVENT_MIN = SM_DERIVED_EVENT_MIN + 101;
  128. //@}
  129. /// @brief Defualt time to assign to a single DNS udpate.
  130. /// @todo This value will be made configurable in the very near future
  131. /// under trac3268. For now we will define it to 100 milliseconds
  132. /// so unit tests will run within a reasonable amount of time.
  133. static const unsigned int DNS_UPDATE_DEFAULT_TIMEOUT = 100;
  134. /// @brief Maximum times to attempt a single update on a given server.
  135. static const unsigned int MAX_UPDATE_TRIES_PER_SERVER = 3;
  136. /// @brief Constructor
  137. ///
  138. /// Instantiates a transaction that is ready to be started.
  139. ///
  140. /// @param io_service IO service to be used for IO processing
  141. /// @param ncr is the NameChangeRequest to fulfill
  142. /// @param forward_domain is the domain to use for forward DNS updates
  143. /// @param reverse_domain is the domain to use for reverse DNS updates
  144. ///
  145. /// @throw NameChangeTransactionError if given an null request,
  146. /// if forward change is enabled but forward domain is null, if
  147. /// reverse change is enabled but reverse domain is null.
  148. NameChangeTransaction(IOServicePtr& io_service,
  149. dhcp_ddns::NameChangeRequestPtr& ncr,
  150. DdnsDomainPtr& forward_domain,
  151. DdnsDomainPtr& reverse_domain);
  152. /// @brief Destructor
  153. virtual ~NameChangeTransaction();
  154. /// @brief Begins execution of the transaction.
  155. ///
  156. /// This method invokes StateModel::startModel() with a value of READY_ST.
  157. /// This causes transaction's state model to attempt to begin execution
  158. /// with the state handler for READY_ST.
  159. void startTransaction();
  160. /// @brief Serves as the DNSClient IO completion event handler.
  161. ///
  162. /// This is the implementation of the method inherited by our derivation
  163. /// from DNSClient::Callback. When the DNSClient completes an update it
  164. /// invokes this method as the completion handler. This method stores
  165. /// the given status and invokes runStateModel() with an event value of
  166. /// IO_COMPLETED_EVT.
  167. ///
  168. /// @param status is the outcome of the DNS update packet exchange.
  169. /// This method is exception safe.
  170. virtual void operator()(DNSClient::Status status);
  171. protected:
  172. /// @brief Send the update request to the current server.
  173. ///
  174. /// This method increments the update attempt count and then passes the
  175. /// current update request to the DNSClient instance to be sent to the
  176. /// currently selected server. Since the send is asynchronous, the method
  177. /// posts NOP_EVT as the next event and then returns.
  178. ///
  179. /// @param use_tsig True if the update should be include a TSIG key. This
  180. /// is not yet implemented.
  181. ///
  182. /// If an exception occurs it will be logged and and the transaction will
  183. /// be failed.
  184. virtual void sendUpdate(bool use_tsig = false);
  185. /// @brief Adds events defined by NameChangeTransaction to the event set.
  186. ///
  187. /// This method adds the events common to NCR transaction processing to
  188. /// the set of define events. It invokes the superclass's implementation
  189. /// first to maintain the hierarchical chain of event definition.
  190. /// Derivations of NameChangeTransaction must invoke its implementation
  191. /// in like fashion.
  192. ///
  193. /// @throw StateModelError if an event definition is invalid or a duplicate.
  194. virtual void defineEvents();
  195. /// @brief Validates the contents of the set of events.
  196. ///
  197. /// This method verifies that the events defined by both the superclass and
  198. /// this class are defined. As with defineEvents, this method calls the
  199. /// superclass's implementation first, to verify events defined by it and
  200. /// then this implementation to verify events defined by
  201. /// NameChangeTransaction.
  202. ///
  203. /// @throw StateModelError if an event value is undefined.
  204. virtual void verifyEvents();
  205. /// @brief Adds states defined by NameChangeTransaction to the state set.
  206. ///
  207. /// This method adds the states common to NCR transaction processing to
  208. /// the dictionary of states. It invokes the superclass's implementation
  209. /// first to maintain the hierarchical chain of state definition.
  210. /// Derivations of NameChangeTransaction must invoke its implementation
  211. /// in like fashion.
  212. ///
  213. /// @throw StateModelError if an state definition is invalid or a duplicate.
  214. virtual void defineStates();
  215. /// @brief Validates the contents of the set of states.
  216. ///
  217. /// This method verifies that the states defined by both the superclass and
  218. /// this class are defined. As with defineStates, this method calls the
  219. /// superclass's implementation first, to verify states defined by it and
  220. /// then this implementation to verify states defined by
  221. /// NameChangeTransaction.
  222. ///
  223. /// @throw StateModelError if an event value is undefined.
  224. virtual void verifyStates();
  225. /// @brief Handler for fatal model execution errors.
  226. ///
  227. /// This handler is called by the StateModel implementation when the model
  228. /// execution encounters a model violation: attempt to call an unmapped
  229. /// state, an event not valid for the current state, or an uncaught
  230. /// exception thrown during a state handler invocation. When such an
  231. /// error occurs the transaction is deemed inoperable, and further model
  232. /// execution cannot be performed. It marks the transaction as failed by
  233. /// setting the NCR status to dhcp_ddns::ST_FAILED
  234. ///
  235. /// @param explanation is text detailing the error
  236. virtual void onModelFailure(const std::string& explanation);
  237. /// @brief Determines the state and next event based on update attempts.
  238. ///
  239. /// This method will post a next event of SERVER_SELECTED_EVT to the
  240. /// current state if the number of update attempts has not reached the
  241. /// maximum allowed.
  242. ///
  243. /// If the maximum number of attempts has been reached, it will transition
  244. /// to the given state with a next event of SERVER_IO_ERROR_EVT.
  245. ///
  246. /// @param fail_to_state State to transition to if maximum attempts
  247. /// have been tried.
  248. ///
  249. void retryTransition(const int fail_to_state);
  250. /// @brief Sets the update request packet to the given packet.
  251. ///
  252. /// @param request is the new request packet to assign.
  253. void setDnsUpdateRequest(D2UpdateMessagePtr& request);
  254. /// @brief Destroys the current update request packet and resets
  255. /// udpate attempts count.
  256. void clearDnsUpdateRequest();
  257. /// @brief Sets the update status to the given status value.
  258. ///
  259. /// @param status is the new value for the update status.
  260. void setDnsUpdateStatus(const DNSClient::Status& status);
  261. /// @brief Sets the update response packet to the given packet.
  262. ///
  263. /// @param response is the new response packet to assign.
  264. void setDnsUpdateResponse(D2UpdateMessagePtr& response);
  265. /// @brief Destroys the current update response packet.
  266. void clearDnsUpdateResponse();
  267. /// @brief Sets the forward change completion flag to the given value.
  268. ///
  269. /// @param value is the new value to assign to the flag.
  270. void setForwardChangeCompleted(const bool value);
  271. /// @brief Sets the reverse change completion flag to the given value.
  272. ///
  273. /// @param value is the new value to assign to the flag.
  274. void setReverseChangeCompleted(const bool value);
  275. /// @brief Sets the status of the transaction's NameChangeRequest
  276. ///
  277. /// @param status is the new value to assign to the NCR status.
  278. void setNcrStatus(const dhcp_ddns::NameChangeStatus& status);
  279. /// @brief Initializes server selection from the given DDNS domain.
  280. ///
  281. /// Method prepares internal data to conduct server selection from the
  282. /// list of servers supplied by the given domain. This method should be
  283. /// called when a transaction is ready to begin selecting servers from
  284. /// a new list. Typically this will be prior to starting the updates for
  285. /// a given DNS direction.
  286. ///
  287. /// @param domain is the domain from which server selection is to be
  288. /// conducted.
  289. void initServerSelection(const DdnsDomainPtr& domain);
  290. /// @brief Selects the next server in the current server list.
  291. ///
  292. /// This method is used to iterate over the list of servers. If there are
  293. /// no more servers in the list, it returns false. Otherwise it sets the
  294. /// current server to the next server and creates a new DNSClient
  295. /// instance.
  296. ///
  297. /// @return True if a server has been selected, false if there are no more
  298. /// servers from which to select.
  299. bool selectNextServer();
  300. /// @brief Sets the update attempt count to the given value.
  301. ///
  302. /// @param value is the new value to assign.
  303. void setUpdateAttempts(const size_t value);
  304. /// @brief Fetches the IOService the transaction uses for IO processing.
  305. ///
  306. /// @return returns a const pointer to the IOService.
  307. const IOServicePtr& getIOService() {
  308. return (io_service_);
  309. }
  310. /// @brief Creates a new DNS update request based on the given domain.
  311. ///
  312. /// Constructs a new "empty", OUTBOUND, request with the message id set
  313. /// and zone section populated based on the given domain.
  314. /// It is declared virtual for test purposes.
  315. ///
  316. /// @return A D2UpdateMessagePtr to the new request.
  317. ///
  318. /// @throw NameChangeTransactionError if request cannot be constructed.
  319. virtual D2UpdateMessagePtr prepNewRequest(DdnsDomainPtr domain);
  320. /// @brief Adds an RData for the lease address to the given RRset.
  321. ///
  322. /// Creates an in::A() or in:AAAA() RData instance from the NCR
  323. /// lease address and adds it to the given RRset.
  324. ///
  325. /// @param rrset RRset to which to add the RData
  326. ///
  327. /// @throw NameChangeTransactionError if RData cannot be constructed or
  328. /// the RData cannot be added to the given RRset.
  329. void addLeaseAddressRdata(dns::RRsetPtr& rrset);
  330. /// @brief Adds an RData for the lease client's DHCID to the given RRset.
  331. ///
  332. /// Creates an in::DHCID() RData instance from the NCR DHCID and adds
  333. /// it to the given RRset.
  334. ///
  335. /// @param rrset RRset to which to add the RData
  336. ///
  337. /// @throw NameChangeTransactionError if RData cannot be constructed or
  338. /// the RData cannot be added to the given RRset.
  339. void addDhcidRdata(dns::RRsetPtr& rrset);
  340. /// @brief Adds an RData for the lease FQDN to the given RRset.
  341. ///
  342. /// Creates an in::PTR() RData instance from the NCR FQDN and adds
  343. /// it to the given RRset.
  344. ///
  345. /// @param rrset RRset to which to add the RData
  346. ///
  347. /// @throw NameChangeTransactionError if RData cannot be constructed or
  348. /// the RData cannot be added to the given RRset.
  349. void addPtrRdata(dns::RRsetPtr& rrset);
  350. public:
  351. /// @brief Fetches the NameChangeRequest for this transaction.
  352. ///
  353. /// @return A const pointer reference to the NameChangeRequest.
  354. const dhcp_ddns::NameChangeRequestPtr& getNcr() const;
  355. /// @brief Fetches the unique key that identifies this transaction.
  356. ///
  357. /// Transactions are uniquely identified by a TransactionKey. Currently
  358. /// this is wrapper around a D2Dhcid.
  359. ///
  360. /// @return A const reference to the TransactionKey.
  361. const TransactionKey& getTransactionKey() const;
  362. /// @brief Fetches the NameChangeRequest status of the transaction.
  363. ///
  364. /// This is the current status of the NameChangeRequest, not to
  365. /// be confused with the state of the transaction. Once the transaction
  366. /// is reached its conclusion, the request will end up with a final
  367. /// status.
  368. ///
  369. /// @return A dhcp_ddns::NameChangeStatus representing the current
  370. /// status of the transaction.
  371. dhcp_ddns::NameChangeStatus getNcrStatus() const;
  372. /// @brief Fetches the forward DdnsDomain.
  373. ///
  374. /// @return A pointer reference to the forward DdnsDomain. If
  375. /// the request does not include a forward change, the pointer will empty.
  376. DdnsDomainPtr& getForwardDomain();
  377. /// @brief Fetches the reverse DdnsDomain.
  378. ///
  379. /// @return A pointer reference to the reverse DdnsDomain. If
  380. /// the request does not include a reverse change, the pointer will empty.
  381. DdnsDomainPtr& getReverseDomain();
  382. /// @brief Fetches the currently selected server.
  383. ///
  384. /// @return A const pointer reference to the DnsServerInfo of the current
  385. /// server.
  386. const DnsServerInfoPtr& getCurrentServer() const;
  387. /// @brief Fetches the DNSClient instance
  388. ///
  389. /// @return A const pointer reference to the DNSClient
  390. const DNSClientPtr& getDNSClient() const;
  391. /// @brief Fetches the current DNS update request packet.
  392. ///
  393. /// @return A const pointer reference to the current D2UpdateMessage
  394. /// request.
  395. const D2UpdateMessagePtr& getDnsUpdateRequest() const;
  396. /// @brief Fetches the most recent DNS update status.
  397. ///
  398. /// @return A DNSClient::Status indicating the result of the most recent
  399. /// DNS update to complete.
  400. DNSClient::Status getDnsUpdateStatus() const;
  401. /// @brief Fetches the most recent DNS update response packet.
  402. ///
  403. /// @return A const pointer reference to the D2UpdateMessage most recently
  404. /// received.
  405. const D2UpdateMessagePtr& getDnsUpdateResponse() const;
  406. /// @brief Returns whether the forward change has completed or not.
  407. ///
  408. /// The value returned is only meaningful if the NameChangeRequest calls
  409. /// for a forward change to be done. The value returned indicates if
  410. /// forward change has been completed successfully.
  411. ///
  412. /// @return True if the forward change has been completed, false otherwise.
  413. bool getForwardChangeCompleted() const;
  414. /// @brief Returns whether the reverse change has completed or not.
  415. ///
  416. /// The value returned is only meaningful if the NameChangeRequest calls
  417. /// for a reverse change to be done. The value returned indicates if
  418. /// reverse change has been completed successfully.
  419. ///
  420. /// @return True if the reverse change has been completed, false otherwise.
  421. bool getReverseChangeCompleted() const;
  422. /// @brief Fetches the update attempt count for the current update.
  423. ///
  424. /// @return size_t which is the number of times the current request has
  425. /// been attempted against the current server.
  426. size_t getUpdateAttempts() const;
  427. /// @brief Returns the DHCP data type for the lease address
  428. ///
  429. /// @return constant reference to dns::RRType::A() if the lease address
  430. /// is IPv4 or dns::RRType::AAAA() if the lease address is IPv6.
  431. const dns::RRType& getAddressRRType() const;
  432. private:
  433. /// @brief The IOService which should be used to for IO processing.
  434. IOServicePtr io_service_;
  435. /// @brief The NameChangeRequest that the transaction is to fulfill.
  436. dhcp_ddns::NameChangeRequestPtr ncr_;
  437. /// @brief The forward domain that matches the request.
  438. ///
  439. /// The forward "domain" is DdnsDomain which contains all of the information
  440. /// necessary, including the list of DNS servers to be used for a forward
  441. /// change.
  442. DdnsDomainPtr forward_domain_;
  443. /// @brief The reverse domain that matches the request.
  444. ///
  445. /// The reverse "domain" is DdnsDomain which contains all of the information
  446. /// necessary, including the list of DNS servers to be used for a reverse
  447. /// change.
  448. DdnsDomainPtr reverse_domain_;
  449. /// @brief The DNSClient instance that will carry out DNS packet exchanges.
  450. DNSClientPtr dns_client_;
  451. /// @brief The DNS current update request packet.
  452. D2UpdateMessagePtr dns_update_request_;
  453. /// @brief The outcome of the most recently completed DNS packet exchange.
  454. DNSClient::Status dns_update_status_;
  455. /// @brief The DNS update response packet most recently received.
  456. D2UpdateMessagePtr dns_update_response_;
  457. /// @brief Indicator for whether or not the forward change completed ok.
  458. bool forward_change_completed_;
  459. /// @brief Indicator for whether or not the reverse change completed ok.
  460. bool reverse_change_completed_;
  461. /// @brief Pointer to the current server selection list.
  462. DnsServerInfoStoragePtr current_server_list_;
  463. /// @brief Pointer to the currently selected server.
  464. DnsServerInfoPtr current_server_;
  465. /// @brief Next server position in the list.
  466. ///
  467. /// This value is always the position of the next selection in the server
  468. /// list, which may be beyond the end of the list.
  469. size_t next_server_pos_;
  470. /// @brief Number of transmit attempts for the current request.
  471. size_t update_attempts_;
  472. };
  473. /// @brief Defines a pointer to a NameChangeTransaction.
  474. typedef boost::shared_ptr<NameChangeTransaction> NameChangeTransactionPtr;
  475. } // namespace isc::d2
  476. } // namespace isc
  477. #endif