]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[client] Intermediate commit
authorStephen Morris <stephen@isc.org>
Thu, 20 Jul 2017 15:39:07 +0000 (17:39 +0200)
committerTomek Mrugalski <tomasz@isc.org>
Mon, 18 Nov 2019 19:26:54 +0000 (03:26 +0800)
src/bin/client/Makefile.am
src/bin/client/client6_interface.cc [moved from src/bin/client/client_interface.cc with 50% similarity]
src/bin/client/client6_interface.h [new file with mode: 0644]
src/bin/client/client_interface.h [deleted file]
src/bin/client/tests/Makefile.am
src/bin/client/tests/client_unittests.cc [new file with mode: 0644]

index 246d740fae31c46d26fc54012b4f5ab418afcc4c..6f2a70391bfbf0980f13a8da2fcb5293edd620d3 100644 (file)
@@ -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
 
similarity index 50%
rename from src/bin/client/client_interface.cc
rename to src/bin/client/client6_interface.cc
index ad0e80ba8974d8271e3e3d3e55c92f9e8d3eb46f..9e1375c41a3189c2da5cb1baf5d01b33ccda1ed2 100644 (file)
@@ -5,17 +5,30 @@
 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 #include <config.h>
+#include <boost/bind.hpp>
 #include <client/client_interface.h>
+#include <iostream>
 
 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 (file)
index 0000000..068287a
--- /dev/null
@@ -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 <asiolink/io_service.h>
+#include <dhcp/iface_mgr.h>
+#include <exceptions/exceptions.h>
+#include <util/state_model.h>
+
+#include <string>
+
+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<Client6Interface> 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 (file)
index aed2120..0000000
+++ /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 <asiolink/io_service.h>
-#include <exceptions/exceptions.h>
-#include <util/state_model.h>
-
-#include <string>
-
-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<ClientInterface> ClientInterfacePtr;
-
-} // namespace isc::client
-} // namespace isc
-#endif
index 4fb3148a6b0e9821dbedccd536a999db9a19a284..c2ba504ad063003cbc2bdfa8bf1c4575d3d2b63e 100644 (file)
@@ -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 (file)
index 0000000..57446fa
--- /dev/null
@@ -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 <log/logger_support.h>
+#include <gtest/gtest.h>
+
+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);
+}