From: Stephen Morris Date: Thu, 20 Jul 2017 15:39:07 +0000 (+0200) Subject: [client] Intermediate commit X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=41463398d0107d4a01f40c0d51f4aa59abde9bd9;p=thirdparty%2Fkea.git [client] Intermediate commit --- diff --git a/src/bin/client/Makefile.am b/src/bin/client/Makefile.am index 246d740fae..6f2a70391b 100644 --- a/src/bin/client/Makefile.am +++ b/src/bin/client/Makefile.am @@ -34,13 +34,13 @@ endif noinst_LTLIBRARIES = libclient.la -libclnt_la_SOURCES = -libclnt_la_SOURCES += main.cc -libclnt_la_SOURCES += client_interface.h client_interface.cc -libclnt_la_SOURCES += executor.cc executor.h -libclnt_la_SOURCES += clnt_process.cc clnt_process.h -libclnt_la_SOURCES += clnt_cfg_mgr.cc clnt_cfg_mgr.h -libclnt_la_SOURCES += clnt_config.cc clnt_config.h +libclient_la_SOURCES = +libclient_la_SOURCES += main.cc +libclient_la_SOURCES += client_interface.h client_interface.cc +libclient_la_SOURCES += executor.cc executor.h +libclient_la_SOURCES += clnt_process.cc clnt_process.h +libclient_la_SOURCES += clnt_cfg_mgr.cc clnt_cfg_mgr.h +libclient_la_SOURCES += clnt_config.cc clnt_config.h sbin_PROGRAMS = kea-client diff --git a/src/bin/client/client_interface.cc b/src/bin/client/client6_interface.cc similarity index 50% rename from src/bin/client/client_interface.cc rename to src/bin/client/client6_interface.cc index ad0e80ba89..9e1375c41a 100644 --- a/src/bin/client/client_interface.cc +++ b/src/bin/client/client6_interface.cc @@ -5,17 +5,30 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #include +#include #include +#include using namespace isc::util; namespace isc { namespace client { +// Define the constants +const int ClientInterface::ST_BEGIN; +const int ClientInterface::ST_SERVER_DISCOVERY; +const int ClientInterface::ST_AWAITING_RECOGNITION; + +const int ClientInterface::EVT_SEND_SOLICIT; +const int ClientInterface::EVT_SOLICIT_RESPONSE_RECEIVED; +const int ClientInterface::EVT_SOLICIT_TIMEOUT; +const int ClientInterface::EVT_SEND_REQUEST; + + // Constructor. -ClientInterface(const str::string& name, int ifindex, - IOServicePtr& io_service) : - isc::dhcp::Iface(string, ifindex), io_service_(io_service) +ClientInterface::ClientInterface(const std::string& name, int ifindex, + isc::asiolink::IOServicePtr& io_service) : + isc::dhcp::Iface(name, ifindex), io_service_(io_service) { } @@ -30,7 +43,7 @@ ClientInterface::defineEvents() { // Define NCT events. defineEvent(EVT_SEND_SOLICIT, "EVT_SEND_SOLICIT"); defineEvent(EVT_SOLICIT_RESPONSE_RECEIVED, "EVT_SOLICIT_RESPONSE_RECEIVED"); - defineEvent(EVT_SOLICIT_RESPONSE_TIMEOUT, "EVT_SOLICIT_RESPONSE_TIMEOUT"); + defineEvent(EVT_SOLICIT_TIMEOUT, "EVT_SOLICIT_TIMEOUT"); defineEvent(EVT_SEND_REQUEST, "EVT_SEND_REQUEST"); defineEvent(EVT_REQUEST_RESPONSE_RECEIVED, "EVT_REQUEST_RESPONSE_RECEIVED"); defineEvent(EVT_REQUEST_RESPONSE_TIMEOUT, "EVT_REQUEST_RESPONSE_TIMEOUT"); @@ -50,7 +63,7 @@ ClientInterface::verifyEvents() { // Verify events by trying to get them. getEvent(EVT_SEND_SOLICIT); getEvent(EVT_SOLICIT_RESPONSE_RECEIVED); - getEvent(EVT_SOLICIT_RESPONSE_TIMEOUT); + getEvent(EVT_SOLICIT_TIMEOUT); getEvent(EVT_SEND_REQUEST); getEvent(EVT_REQUEST_RESPONSE_RECEIVED); getEvent(EVT_REQUEST_RESPONSE_TIMEOUT); @@ -75,6 +88,69 @@ ClientInterface::defineStates() { defineState(ST_SERVER_DISCOVERY, "ST_SERVER_DISCOVERY", boost::bind(&ClientInterface::serverDiscoveryHandler, this)); + defineState(ST_AWAITING_RECOGNITION, "ST_AWAITING_RECOGNITION", + boost::bind(&ClientInterface::awaitingRecognitionHandler, + this)); + +} + +void +ClientInterface::verifyStates() { + // Call the superclass implementation first + StateModel::verifyStates(); + + // Verify ClientInterface states by attempting to fetch them. + getState(ST_BEGIN); + getState(ST_SERVER_DISCOVERY); + getState(ST_AWAITING_RECOGNITION); +} + + +// Asynchronous operation completion handler. Justs post the appropriate +// event and enters the given state. + +void +ClientInterface::asynchCompletion(const boost::system::error_code&, int event) { +// TODO: Check error code + runModel(event); +} + + +// Begin handler. Initialise, then transition to SERVER_DISCOVERY + +void +ClientInterface::beginHandler() { + std::cout << "beginHandler()\n"; + // TODO: Initialization + + // Move to the server discovery stage. + transition(ST_SERVER_DISCOVERY, EVT_SEND_SOLICIT); +} + +// Server discovery handler. Broadcast a SOLICT message, then start a timer +// and issue a read for a response. + +void +ClientInterface::serverDiscoveryHandler() { + if (doOnEntry()) { + std::cout << "serverDiscoveryHandler()\n"; + postNextEvent(NOP_EVT); + + } else { + // All events (the completion of the I/O or the expiry of the timer) + // cause a transition to the AWAITING_RECOGNITION state. + transition(ST_AWAITING_RECOGNITION, getNextEvent()); + } +} + +// Awaiting recognition state. Process the response and timer handlers. + +void +ClientInterface::awaitingRecognitionHandler() { + std::cout << "awaitingRecognitionHandler()\n"; + + // Stay in the AWAITING_RECOGNITION state. + transition(ST_AWAITING_RECOGNITION, NOP_EVT); } } // namespace isc::client diff --git a/src/bin/client/client6_interface.h b/src/bin/client/client6_interface.h new file mode 100644 index 0000000000..068287a58d --- /dev/null +++ b/src/bin/client/client6_interface.h @@ -0,0 +1,307 @@ +// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef CLIENT6_INTERFACE_H +#define CLIENT6_INTERFACE_H + +#include +#include +#include +#include + +#include + +namespace isc { +namespace client { + +/// @brief Thrown if the some error is encountered +class Client6InterfaceError : public isc::Exception { +public: + Client6InterfaceError(const char* file, size_t line, const char* what) : + isc::Exception(file, line, what) {}; +}; + +/// @brief DHCPv6 Client Interface +/// +/// This is the class that represents an interface that the client is managing. +/// It has a dual inheritance: +/// +/// The first parent is the Iface class, representing a physical interface. It +/// contains all information, e.g. name, MAC address etc. +/// +/// The other parent is the StateModel, which defines the state the interface +/// is in and handles the logic for the process of acquring an address. Each +/// state has an associate method that handles the processing of the state. +/// Transitions between states are mainly (not always) triggered by the +/// completion of an asynchronous operation. +/// +/// To illustrate the flow of control in such a situation, assume the following: +/// The Client Interface moves from state A to state B. In state B, it queues +/// an asynchronous operation, the completion of which causes it to move to +/// state C. The processing is as follows: +/// +/// 1. State A is entered from state B. Any processing required on entry to +/// state B is done in the state B's handler at that time: either +/// the state is entered via a unique event, when a check on the event is +/// sufficient to determine that the state has been entered from state A, +/// or the single-shot doOnEntry() flag is checked. +/// +/// 2. State B's handler queues an asynchronous I/O operation, passing to it +/// as a parameter the event to invoke when the operation completes. +/// +/// 3. The handler calls postNextEvent(NOP_EVT) then exits, causing the +/// runModel() call that invoked the state machine processing to exit. +/// The process goes back to waiting on the IOService object. +/// +/// 4. The asynchronous event completes, and the completion handler calls +/// the state machine's runModel() method, passing to it the event that +/// was associated with the operation. +/// +/// 5. The state machine calls state B's handler again, passing to it the +/// event associated with the asynchronous operation. The handler calls +/// the state machine's "transition" method to move to state C. +/// +/// The upshot of this is that if an asynchronous operation is triggered, the +/// Client Interface will wait for completion in the state that triggered the +/// operation, transitioning to the new state when the operation completes. + +class Client6Interface : public isc::util::StateModel, + public isc::dhcp::Iface { +public: + + /// @brief State list + /// + /// See http://kea.isc.org/wiki/ClientDesign for the definitions of each + /// state. + enum { + ST_BEGIN = SM_DERIVED_STATE_MIN + 1, + ST_SERVER_DISCOVERY, + ST_SEND_SOLICIT, + ST_SOLICIT_TIMEOUT, + ST_ADVERTISE_RECEIVED, + ST_SEND_REQUEST, + ST_REQUEST_TIMEOUT, + ST_REPLY_RECEIVED, + ST_DUPLICATE_CHECK, + ST_DUPLICATE_TIMEOUT, + ST_CONFIGURED, + ST_START_RENEW, + ST_RESENT_RENEW, + ST_RENEW_COMPLETE, + ST_REBINDING, + ST_PROCESS_REBINDING, + ST_REBINDING_TIMEOUT + }; + + /// @brief Event List + /// + /// List of events. Effectively these are the list of states, as each + /// event indicates the target of the transition. + enum { + EVT_SERVER_DISCOVERY = SM_DERIVED_EVENT_MIN + 1, + EVT_SEND_SOLICIT, + EVT_ADVERTISE_RECEIVED, + EVT_SOLICIT_TIMEOUT, + EVT_SEND_REQUEST + EVT_REQUEST_TIMEOUT, + EVT_REPLY_RECEIVED, + EVT_DUPLICATE_CHECK, + EVT_DUPLICATE_TIMEOUT, + EVT_CONFIGURED, + EVT_START_RENEW, + EVT_RESEND_RENEW, + EVT_REBINDING, + EVT_PROCESS_REBINDING, + EVT_REBINDING_TIMEOUT + }; + + /// @brief Constructor + /// + /// @param name Name of the interface + /// @param index Index of the interface + /// @param io_service Pointer to the IOService object used to keep track of + /// all asynchronous operations. + Client6Interface(const std::string& name, int ifindex, + isc::asiolink::IOServicePtr& io_service); + + /// @brief Destructor + virtual ~Client6Interface(); + + /// @brief Adds events defined by Client6Interface to the event set. + /// + /// This method adds the events defined for this state machine to the set + /// of defined events. It invokes the superclass's implementation + /// first to maintain the hierarchical chain of event definition. + /// + /// @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 + /// then this implementation to verify events defined by + /// NameChangeTransaction. + /// + /// @throw StateModelError if an event value is undefined. + virtual void verifyEvents(); + + /// @brief Adds states defined by Client6Interface to the state set. + /// + /// This method adds the states associated with the Client6Interface to + /// the dictionary of states. It invokes the superclass's implementation + /// first to maintain the hierarchical chain of state definition. + /// + /// @throw StateModelError if an state definition is invalid or a duplicate. + virtual void defineStates(); + + /// @brief Validates the contents of the set of states. + /// + /// 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 Client6Interface. + /// + /// @throw StateModelError if an event value is undefined. + virtual void verifyStates(); + + + //@{ State Methods + + /// @brief State handler for BEGIN + /// + /// BEGIN is the state the model transitions into when the method + /// startTransaction is called, It is the entry point into the state + /// machine. It performs all the initialization then unconditionally + /// transitions to the SEND_SOLICIT state. + void beginHandler(); + + /// @brief State handler for SEND_SOLICIT + /// + /// SEND_SOLICIT is the state that initiates the discovery of servers. + /// It initializes the list of servers, then broadcasts the SOLICIT message. + /// It then kicks off an asynchronous read, as well as a read timer. + void serverDiscoveryHandler(); + + /// @brief State handler for ADVERTISE_RECEIVED + /// + /// The client enters this state when an ADVERTISE is received from the + /// server. If the SOLICIT has not timed out, it will - unless the + /// server is one with the maximum preference value - loop round and + /// wait for more responses until teh solicit timer times out. + void advertiseReceivedHandler(); + + /// @brief State handler for SEND_REQUEST + /// + /// Starts a timer and sends the REQUEST to the server at the top of the + /// servers list. + void sendRequestHandler(); + + /// @brief State handler for REQUEST_TIMEOUT + /// + /// Called when the timer associated with waiting for a REPLY from the + /// server has timed out, this either sends another request (to the same + /// or a different server) or goes back to looking for servers. + void requestTimeoutHandler()l + + /// @brief State handler for REPLY_RECEIVED + /// + /// When the server responds with a REPLY message, the client enters this + /// state. Depending on the response, it will either look for duplicate + /// addresses or try to contact another server. + void replyReceivedTimer(); + + /// @brief State handler for DUPLICATE_CHECK + /// + /// The client enters this state to look for duplicates. It waits here + /// for a fixed period of time to see if the kernel realises that there + /// are duplicate addresses. + void duplicateCheckHandler(); + + /// @brief State handler for DUPLICATE_TIMEOUT + /// + /// This state is entered when the duplicate wait period expires. The + /// client consults the kernel to see if duplicate addresses were found. + void duplicateTimeoutHandler(); + + /// @brief State handler for CONFIGURED + /// + /// The CONFIGURED state is the state where the client should spend most of + /// its time. It only leaves this state when the T1 timer expires, + /// telling it that it should renew its lease. + void configuredHandler(); + + /// @brief State handler for START_RENEW + /// + /// The client enters this state when the T1 timer expires. From here, it + /// tries to renew its lease. + void startRenewHandler(); + + /// @brief State handler for RESEND_RENEW + /// + /// Entered when the iretransmission timer associated with receiving a + /// response to the renewal request times out, the renew request is resent + /// to the server. + void resendRenewHandler(); + + /// @brief State handler for RENEW_COMPLETE + /// + /// Entered when a response is received to the renew request, in this state + /// the client decides whether it can accept the answer or has to start + /// the process of acquiring a new lease. + void renewCompleteHandler(); + + /// @brief State handler for REBINDING + /// + /// If the T2 timer times out (this is started when a renewal request is + /// made), the client will start the process of rebinding to a new address. + void rebindingHandler(); + + /// @brief State handler for PROCESS_REBINDING + /// + /// Entered when a rebinding response has been received, in this state + /// the client decides whether to acept the response of take some other + /// action. + void processRebdingingHandler(); + + /// @brief State handler for REBINDING_TIMEOUT + /// + /// Enters when the timer assoiated with the rebinding request expires, + /// the client tidies up and starts the server discovery process again. + void rebindingTimeoutHandler(); + + //@} + + /// @brief Asynchronous Operation Completion Handler + /// + /// Called when any asynchronous option completes, it causes the state + /// machine to transition to the next state. + /// + /// @param ec System error code + /// @param event Event that causes the transition + void asynchCompletion(const boost::system::error_code& ec, int event); + + + /// @brief Fetches the IOService the transaction uses for IO processing. + /// + /// @return returns a const pointer to the IOService. + const asiolink::IOServicePtr& getIOService() { + return (io_service_); + } + +private: + /// @brief The IOService which should be used to for IO processing. + asiolink::IOServicePtr io_service_; +}; + +/// @brief Defines a pointer to a Client6Interface +typedef boost::shared_ptr Client6InterfacePtr; + +} // namespace isc::client +} // namespace isc + +#endif // CLIENT6_INTERFACE_H diff --git a/src/bin/client/client_interface.h b/src/bin/client/client_interface.h deleted file mode 100644 index aed212021f..0000000000 --- a/src/bin/client/client_interface.h +++ /dev/null @@ -1,281 +0,0 @@ -// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef CLIENT_INTERFACE_H -#define CLIENT_INTERFACE_H - -#include -#include -#include - -#include - -namespace isc { -namespace client { - -/// @brief Thrown if the some error is encountered -class ClientInterfaceError : public isc::Exception { -public: - ClientInterfaceError(const char* file, size_t line, const char* what) : - isc::Exception(file, line, what) {}; -}; - -/// @brief Client Interface -/// -/// This is the class that represents an interface that the client is managing. -/// It has a dual inheritance: the first parent is the Iface class, -/// representing a physical interface. It contains all information, e.g. -/// name, MAC address etc. -/// -/// The other parent is the StateModel, which defines the state the interface -/// is in and handles the logic for the process of acquring an address. Each -/// state has an associate method, which is invoked when the state is entered. -/// This will usually carry out a certain amount of processing before -/// initiating an asynchronous operation (either an I/O or setting a timer). -/// The callback handlers on these operations are methods in this class and -/// after performing the necessary processing, cause a transition to some other -/// state. -/// -/// The processing required for the client is quite lengthy and is described in -/// http://kea.isc.org/wiki/ClientDesign. - -class ClientInterface : public isc::util::StateModel, isc::dhcp::Iface { -public: - - //@{ States - - /// @brief ST_BEGIN - Initialization - /// - /// The entry point into the state machine. The relevant sockets are - /// opened, and the timer interval initialzied. - static const int ST_BEGIN = SM_DERIVED_STATE_MIN + 1; - - /// @brief ST_SERVER_DISCOVERY - Initiate I/O to find servers - /// - /// Sends a SOLICIT meassage on the relevant interface and starts a timer. - /// A wait state is then entered until the timer expires. - static const int ST_ SERVER_DISCOVERY = SM_DERIVED_STATE_MIN + 2; - - /// @brief ST_AWAITING_RECOGNITION - Wait for server to respond - /// - /// A request has been broadcast, so we are now waiting for a server to - /// respond. - static const int ST_AWAITING_RECOGNITION = SM_DERIVED_STATE_MIN + 3; - - /// @brief ST_SEND_REQUEST - Send REQUEST to server - /// - /// One or more servers have responded, so select a server and send it - /// a REQUEST. - static const int ST_SEND_REQUEST = SM_DERIVED_STATE_MIN +4; - - /// @brief ST_AWAITING_RESPONSE - Await response from chosen server - /// - /// After a request has been sent to the selected server, the client must - /// wait for a response. - static const int ST_AWAITING_RESPONSE = SM_DERIVED_STATE_MIN + 5; - - /// @brief ST_DUPLICATE_CHECK - Look for address already in use - /// - /// Before starting to use the address, we need to wait for a bit to ensure - /// that the address is not already in use. - static const int ST_DUPLICATE_CHECK = SM_DERIVED_STATE_MIN + 6; - - /// @brief ST_DUPLICATE_CHECK_TIMEOUT - Duplicate check period has ended - /// - /// The waiting period for the duplicate check has ended, so now process - /// the results. - static const int ST_DUPLICATE_CHECK_TIMEOUT = SM_DERIVED_STATE_MIN + 7; - - /// @brief ST_CONFIGURED - Successful configuration - /// - /// The client has now been successfully configured, so now prepare it for - /// renewing its configuration. - static const int ST_CONFIGURED = SM_DERIVED_STATE_MIN + 8; - - /// @brief ST_START_RENEW - Start renewal process - /// - /// Send a RENEW message to the server from which we originally got our - /// configuration and start all the relavnt timers associated with this - /// process - static const int ST_START_RENEW = SM_DERIVED_STATE_MIN + 9; - - /// @brief ST_RESEND_RENEW - Resend RENEW request - static const int ST_RENEW_COMPLETE = SM_DERIVED_STATE_MIN + 10; - - /// @brief ST_RESEND_RENEW - Response to RENEW request received - static const int ST_RENEW_COMPLETE = SM_DERIVED_STATE_MIN + 11; - - /// @brief ST_REBINDING - Handle rebinding - /// - /// The client was unable to renew its configuration, so move to the - /// rebinding processing. - static const int REBINDING = SM_DERIVED_STATE_MIN + 12; - - //@} - - //@{ Events - - /// @brief EVT_SEND_SOLICT - Trigger sending of SOLICIT message to server - static const int EVT_SEND_SOLICIT = SM_DERIVED_EVENT_MIN + 1; - - /// @brief EVT_SOLICIT_RESPONSE_RECEIVED - Received response to SOLICT - /// - /// The server has responded with a message (that should be an ADVERTISE - /// message). - static const int EVT_SOLICIT_RESPONSE_RECEIVED = SM_DERIVED_EVENT_MIN + 2; - - /// @brief EVT_SOLICIT_TIMEOUT - No response to SOLICIT message - static const int EVT_SOLICIT_TIMEOUT = SM_DERIVED_EVENT_MIN + 3; - - /// @brief - EVT_SEND_REQUEST - Initiate sending of REQUEST to server - static const int EVT_SEND_REQUEST = SM_DERIVED_EVENT_MIN + 4; - - /// @brief EVT_REQUEST_RESPONSE_RECEIVED - Received response to REQUEST - /// - /// The server has responded to the client's REQUEST message with a response - /// that should be a REPLY message. - static const int EVT_REQUEST_RESPONSE_RECEIVED = SM_DERIVED_EVENT_MIN + 5; - - /// @brief EVT_REQUEST_RESPONSE_TIMEOUT - No response to REQUEST message - static const int EVT_REQUEST_RESPONSE_TIMEOUT = SM_DERIVED_EVENT_MIN + 6; - - /// @brief EVT_DUPLICATE_TIMEOUT - Duplicate check timer has expired - static const int EVT_DUPLICATE_TIMEOUT = SM_DERIVED_EVENT_MIN + 7; - - /// @brief EVT_T1_TIMEOUT - Timeout of T1 Timer - static const int EVT_T1_TIMEOUT = SM_DERIVED_EVENT_MIN + 8; - - /// @brief EVT_RENEW_RESPONSE_RECEIVED - Received response to RENEW request - static const int EVT_RENEW_RESPONSE_RECEIVED = SM_DERIVED_EVENT_MIN + 9; - - /// @brief EVT_RENEW_RESPONSE_TIMEOUT - RENEW response request timed out - static const int EVT_RENEW_RESPONSE_TIMEOUT = SM_DERIVED_EVENT_MIN + 10; - - /// @brief EVT_T2_TIMEOUT - Timeout of T2 Timer - static const int EVT_T2_TIMEOUT = SM_DERIVED_EVENT_MIN + 11; - - /// @brief EVT_RETRANSMISSION_TIMEOUT - Timeout of RETRANSMISSION Timer - static const int EVT_RETRANSMISSION_TIMEOUT = SM_DERIVED_EVENT_MIN + 12; - - //@} - - - /// @brief Constructor - /// - /// @param name Name of the interface - /// @param index Index of the interface - /// @param io_service Pointer to the IOService object used to keep track of - /// all asynchronous operations. - ClientInterface(const std::string& name, int ifindex, - IOServicePtr& io_service); - - /// @brief Destructor - virtual ~ClientInterface(); - - /// @brief Adds events defined by ClientInterface to the event set. - /// - /// This method adds the events defined for this state machine to the set - /// of defined events. It invokes the superclass's implementation - /// first to maintain the hierarchical chain of event definition. - /// - /// @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 - /// then this implementation to verify events defined by - /// NameChangeTransaction. - /// - /// @throw StateModelError if an event value is undefined. - virtual void verifyEvents(); - - /// @brief Adds states defined by ClientInterface to the state set. - /// - /// This method adds the states associated with the ClientInterface to - /// the dictionary of states. It invokes the superclass's implementation - /// first to maintain the hierarchical chain of state definition. - /// - /// @throw StateModelError if an state definition is invalid or a duplicate. - virtual void defineStates(); - - /// @brief Validates the contents of the set of states. - /// - /// 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 ClientInterface. - /// - /// @throw StateModelError if an event value is undefined. - virtual void verifyStates(); - - - //@{ State Methods - - /// @brief State handler for BEGIN - /// - /// Entered from: - /// INIT_ST with next event of START_EVT - /// - /// BEGIN is the state the model transitions into when the method - /// startTransaction is called, It is the entry point into the state - /// machine. It performs all the initialization. - /// - /// Transitions to: - /// - SERVER_DISCOVERY with the next event of EVT_SEND_SOLICIT. This is an - /// unconditional transition. - void beginHandler(); - - /// @brief State handler for SERVER_DISCOVERY - /// - /// Entered from: - /// BEGIN with next event of EVT_SEND_SOLICIT - /// AWAITING_RECOGNITION with next event of EVT_SEND_SOLICIT - /// SEND_REQUEST with next event of EVT_SEND_SOLICIT - /// - /// SERVER_DISCOVERY is the state that initiates the discovery of servers. - /// It initializes the list of servers, then broadcasts the SOLICIT message. - /// It then kicks off an asynchronous read, as well as a read timer. - /// - /// Transitions to: - /// - AWAITING_RECOGNITION with next event of EVT_SOLICIT_RESPONSE RECEIVED - /// - AWAITING_RECOGNITION with next event of EVT_SOLICIT_TIMEOUT - void serverDiscoveryHandler(); - - //@} - - /// @brief Asynchronous Operation Completion Handler - /// - /// Called when any asynchronous option completes, it causes the state - /// machine to transition to the next state. - /// - /// @param ec System error code - /// @param next_state State to which a transition should be made - /// @param event Event that causes the transition - void asynchCompletion(const boost::system::error_code& ec, - int next_state, int event); - - - /// @brief Fetches the IOService the transaction uses for IO processing. - /// - /// @return returns a const pointer to the IOService. - const asiolink::IOServicePtr& getIOService() { - return (io_service_); - } - -private: - /// @brief The IOService which should be used to for IO processing. - asiolink::IOServicePtr io_service_; -}; - -/// @brief Defines a pointer to a ClientInterface -typedef boost::shared_ptr ClientInterfacePtr; - -} // namespace isc::client -} // namespace isc -#endif diff --git a/src/bin/client/tests/Makefile.am b/src/bin/client/tests/Makefile.am index 4fb3148a6b..c2ba504ad0 100644 --- a/src/bin/client/tests/Makefile.am +++ b/src/bin/client/tests/Makefile.am @@ -1,20 +1,5 @@ -SHTESTS = # The test of dynamic reconfiguration based on signals will work only # if we are using file based configuration approach. -SHTESTS += clnt_process_tests.sh - -noinst_SCRIPTS = clnt_process_tests.sh - -EXTRA_DIST = clnt_process_tests.sh.in - -# test using command-line arguments, so use check-local target instead of TESTS -check-local: - for shtest in $(SHTESTS) ; do \ - echo Running test: $$shtest ; \ - export KEA_LOCKFILE_DIR=$(abs_top_builddir); \ - export KEA_PIDFILE_DIR=$(abs_top_builddir); \ - ${SHELL} $(abs_builddir)/$$shtest || exit ; \ - done AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib AM_CPPFLAGS += -I$(top_builddir)/src/bin # for generated spec_config.h header @@ -24,8 +9,6 @@ AM_CPPFLAGS += -DTEST_DATA_BUILDDIR=\"$(abs_top_builddir)/src/bin/client/tests\" AM_CPPFLAGS += -DINSTALL_PROG=\"$(abs_top_srcdir)/install-sh\" AM_CPPFLAGS += -DCFG_EXAMPLES=\"$(abs_top_srcdir)/doc/examples/client\" -DISTCLEANFILES = clnt_process_tests.sh - AM_CXXFLAGS = $(KEA_CXXFLAGS) if USE_STATIC_LINK @@ -38,28 +21,31 @@ TESTS_ENVIRONMENT = \ TESTS = if HAVE_GTEST -TESTS += clnt_unittests - -clnt_unittests_SOURCES = clnt_unittests.cc - -clnt_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) -clnt_unittests_LDFLAGS = $(AM_LDFLAGS) $(CRYPTO_LDFLAGS) -clnt_unittests_LDFLAGS += $(GTEST_LDFLAGS) - -clnt_unittests_LDADD = $(top_builddir)/src/bin/client/libclnt.la -clnt_unittests_LDADD += $(top_builddir)/src/lib/process/testutils/libprocesstest.la -clnt_unittests_LDADD += $(top_builddir)/src/lib/process/libkea-process.la -clnt_unittests_LDADD += $(top_builddir)/src/lib/testutils/libkea-testutils.la -clnt_unittests_LDADD += $(top_builddir)/src/lib/asiodns/libkea-asiodns.la -clnt_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la -clnt_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la -clnt_unittests_LDADD += $(top_builddir)/src/lib/cc/libkea-cc.la -clnt_unittests_LDADD += $(top_builddir)/src/lib/hooks/libkea-hooks.la -clnt_unittests_LDADD += $(top_builddir)/src/lib/util/threads/libkea-threads.la -clnt_unittests_LDADD += $(top_builddir)/src/lib/util/libkea-util.la -clnt_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la -clnt_unittests_LDADD += $(LOG4CPLUS_LIBS) $(CRYPTO_LIBS) -clnt_unittests_LDADD += $(BOOST_LIBS) $(GTEST_LDADD) +TESTS += client_unittests + +client_unittests_SOURCES = client_unittests.cc +client_unittests_SOURCES += state_machine_unittest.cc + +client_unittests_SOURCES += ../client_interface.cc + +client_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) +client_unittests_LDFLAGS = $(AM_LDFLAGS) $(CRYPTO_LDFLAGS) +client_unittests_LDFLAGS += $(GTEST_LDFLAGS) + +#client_unittests_LDADD = $(top_builddir)/src/bin/client/libclient.la +client_unittests_LDADD = $(top_builddir)/src/lib/process/testutils/libprocesstest.la +client_unittests_LDADD += $(top_builddir)/src/lib/process/libkea-process.la +client_unittests_LDADD += $(top_builddir)/src/lib/testutils/libkea-testutils.la +client_unittests_LDADD += $(top_builddir)/src/lib/asiodns/libkea-asiodns.la +client_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la +client_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la +client_unittests_LDADD += $(top_builddir)/src/lib/cc/libkea-cc.la +client_unittests_LDADD += $(top_builddir)/src/lib/hooks/libkea-hooks.la +client_unittests_LDADD += $(top_builddir)/src/lib/util/threads/libkea-threads.la +client_unittests_LDADD += $(top_builddir)/src/lib/util/libkea-util.la +client_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la +client_unittests_LDADD += $(LOG4CPLUS_LIBS) $(CRYPTO_LIBS) +client_unittests_LDADD += $(BOOST_LIBS) $(GTEST_LDADD) endif diff --git a/src/bin/client/tests/client_unittests.cc b/src/bin/client/tests/client_unittests.cc new file mode 100644 index 0000000000..57446fa0e6 --- /dev/null +++ b/src/bin/client/tests/client_unittests.cc @@ -0,0 +1,25 @@ +// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include +#include + +int +main(int argc, char* argv[]) { + + ::testing::InitGoogleTest(&argc, argv); + + // See the documentation of the KEA_* environment variables in + // src/lib/log/README for info on how to tweak logging + isc::log::initLogger(); + + // Override --localstatedir value for PID files + setenv("KEA_PIDFILE_DIR", TEST_DATA_BUILDDIR, 1); + + int result = RUN_ALL_TESTS(); + + return (result); +}