diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 12:15:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 12:15:43 +0000 |
commit | f5f56e1a1c4d9e9496fcb9d81131066a964ccd23 (patch) | |
tree | 49e44c6f87febed37efb953ab5485aa49f6481a7 /src/bin/dhcp4/client_handler.h | |
parent | Initial commit. (diff) | |
download | isc-kea-f5f56e1a1c4d9e9496fcb9d81131066a964ccd23.tar.xz isc-kea-f5f56e1a1c4d9e9496fcb9d81131066a964ccd23.zip |
Adding upstream version 2.4.1.upstream/2.4.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/bin/dhcp4/client_handler.h')
-rw-r--r-- | src/bin/dhcp4/client_handler.h | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/src/bin/dhcp4/client_handler.h b/src/bin/dhcp4/client_handler.h new file mode 100644 index 0000000..384fba9 --- /dev/null +++ b/src/bin/dhcp4/client_handler.h @@ -0,0 +1,248 @@ +// Copyright (C) 2020-2023 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_HANDLER_H +#define CLIENT_HANDLER_H + +#include <dhcp/pkt4.h> +#include <boost/noncopyable.hpp> +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/composite_key.hpp> +#include <boost/multi_index/hashed_index.hpp> +#include <boost/multi_index/member.hpp> +#include <boost/shared_ptr.hpp> +#include <functional> +#include <mutex> +#include <thread> + +namespace isc { +namespace dhcp { + +/// @brief Define the type of packet processing continuation. +typedef std::function<void()> Continuation; + +/// @brief Define the type of shared pointers to continuations. +typedef boost::shared_ptr<Continuation> ContinuationPtr; + +/// @brief Continuation factory. +/// +/// @param cont Continuation rvalue. +inline ContinuationPtr makeContinuation(Continuation&& cont) { + return (boost::make_shared<Continuation>(cont)); +} + +/// @brief Client race avoidance RAII handler. +class ClientHandler : public boost::noncopyable { +private: + + /// Class (aka static) types, methods and members. + + /// @brief Structure representing a client. + struct Client { + + /// @brief Constructor. + /// + /// @param query The query. + /// @param client_id The client ID. + /// @param hwaddr The hardware address. + /// @throw if the query is null or client_id and hwaddr are null. + Client(Pkt4Ptr query, ClientIdPtr client_id, HWAddrPtr hwaddr); + + /// @brief The query being processed. + Pkt4Ptr query_; + + /// @brief Cached binary client ID. + std::vector<uint8_t> client_id_; + + /// @brief Cached hardware type. + uint16_t htype_; + + /// @brief Cached binary hardware address. + std::vector<uint8_t> hwaddr_; + + /// @brief The ID of the thread processing the query. + std::thread::id thread_; + + /// @brief The next query. + /// + /// @note This field can be modified from another handler + /// holding the mutex. + Pkt4Ptr next_query_; + + /// @brief The continuation to process next query for the client. + /// + /// @note This field can be modified from another handler + /// holding the mutex. + ContinuationPtr cont_; + }; + + /// @brief The type of shared pointers to clients. + typedef boost::shared_ptr<Client> ClientPtr; + + /// @brief The type of the client-by-id container. + typedef boost::multi_index_container< + + // This container stores pointers to client-by-id objects. + ClientPtr, + + // Start specification of indexes here. + boost::multi_index::indexed_by< + + // First index is used to search by Duid. + boost::multi_index::hashed_unique< + + // Client ID binary content as a member of the Client object. + boost::multi_index::member< + Client, std::vector<uint8_t>, &Client::client_id_ + > + > + > + > ClientByIdContainer; + + /// @brief The type of the client-by-hwaddr container. + typedef boost::multi_index_container< + + // This container stores pointers to client-by-hwaddr objects. + ClientPtr, + + // Start specification of indexes here. + boost::multi_index::indexed_by< + + // First index is used to search by HWAddr. + boost::multi_index::hashed_unique< + + // This is a composite index for type and binary components. + boost::multi_index::composite_key< + Client, + boost::multi_index::member< + Client, uint16_t, &Client::htype_ + >, + boost::multi_index::member< + Client, std::vector<uint8_t>, &Client::hwaddr_ + > + > + > + > + > ClientByHWAddrContainer; + + /// @brief Lookup a client by id. + /// + /// The mutex must be held by the caller. + /// + /// @param client_id The duid of the query from the client. + /// @return The client found in the by client id container or null. + static ClientPtr lookup(const ClientIdPtr& client_id); + + /// @brief Lookup a client by hwaddr. + /// + /// The mutex must be held by the caller. + /// + /// @param hwaddr The hardware address of the query from the client. + /// @return The client found in the by hardware address container or null. + static ClientPtr lookup(const HWAddrPtr& hwaddr); + + /// @brief Add a client by id. + /// + /// The mutex must be held by the caller. + /// + /// @param client The client to insert into the by id client container. + static void addById(const ClientPtr& client); + + /// @brief Add a client by hwaddr. + /// + /// The mutex must be held by the caller. + /// + /// @param client The client to insert into the by hwaddr client container. + static void addByHWAddr(const ClientPtr& client); + + /// @brief Delete a client by id. + /// + /// The mutex must be held by the caller. + /// + /// @param client_id The duid to delete from the by id client container. + static void del(const ClientIdPtr& client_id); + + /// @brief Delete a client by hwaddr. + /// + /// The mutex must be held by the caller. + /// + /// @param hwaddr The hwaddr to delete from the by hwaddr client container. + static void del(const HWAddrPtr& hwaddr); + + /// @brief Mutex to protect client containers. + /// + /// The mutex is used only by public methods for guards. + static std::mutex mutex_; + + /// @brief The client-by-id container. + static ClientByIdContainer clients_client_id_; + + /// @brief The client-by-hwaddr container. + static ClientByHWAddrContainer clients_hwaddr_; + +public: + + /// Public interface. + + /// @brief Constructor. + ClientHandler(); + + /// @brief Destructor. + /// + /// Releases the client if it was acquired. + virtual ~ClientHandler(); + + /// @brief Tries to acquires a client. + /// + /// Lookup the client: + /// - if not found insert the client in the clients map and return true + /// - if found, if has a continuation put it in the holder, + /// and return false + /// + /// @param query The query from the client. + /// @param cont The continuation in the case the client was held. + /// @return true if the client was acquired, false if there is already + /// a query from the same client. + bool tryLock(Pkt4Ptr query, ContinuationPtr cont = ContinuationPtr()); + +private: + + /// Instance methods and members. + + /// @brief Acquire a client by client ID option. + /// + /// The mutex must be held by the caller. + void lockById(); + + /// @brief Acquire a client by hardware address. + /// + /// The mutex must be held by the caller. + void lockByHWAddr(); + + /// @brief Release a client by client ID option. + /// + /// The mutex must be held by the caller. + void unLockById(); + + /// @brief Release a client by hardware address. + /// + /// The mutex must be held by the caller. + void unLockByHWAddr(); + + /// @brief Local client. + ClientPtr client_; + + /// @brief Client ID locked by this handler. + ClientIdPtr locked_client_id_; + + /// @brief Hardware address locked by this handler. + HWAddrPtr locked_hwaddr_; +}; + +} // namespace isc +} // namespace dhcp + +#endif // CLIENT_HANDLER_H |