]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#4141] implemented select event handler
authorRazvan Becheriu <razvan@isc.org>
Wed, 29 Oct 2025 12:43:30 +0000 (14:43 +0200)
committerRazvan Becheriu <razvan@isc.org>
Mon, 3 Nov 2025 18:59:34 +0000 (18:59 +0000)
src/lib/dhcp/fd_event_handler.cc [new file with mode: 0644]
src/lib/dhcp/fd_event_handler.h [new file with mode: 0644]
src/lib/dhcp/meson.build
src/lib/dhcp/select_event_handler.cc [new file with mode: 0644]
src/lib/dhcp/select_event_handler.h [new file with mode: 0644]

diff --git a/src/lib/dhcp/fd_event_handler.cc b/src/lib/dhcp/fd_event_handler.cc
new file mode 100644 (file)
index 0000000..11ad335
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright (C) 2011-2025 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 <config.h>
+
+#include <fd_event_handler.h>
+
+namespace isc {
+namespace dhcp {
+
+FDEventHandler::FDEventHandler(HandlerType type) : type_(type) {
+}
+
+FDEventHandler::HandlerType FDEventHandler::type() {
+    return (type_);
+}
+
+} // end of namespace isc::dhcp
+} // end of namespace isc
diff --git a/src/lib/dhcp/fd_event_handler.h b/src/lib/dhcp/fd_event_handler.h
new file mode 100644 (file)
index 0000000..dd54240
--- /dev/null
@@ -0,0 +1,83 @@
+// Copyright (C) 2010-2024 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 FD_EVENT_HANDLER_H
+#define FD_EVENT_HANDLER_H
+
+#include <boost/shared_ptr.hpp>
+#include <stdint.h>
+
+namespace isc {
+namespace dhcp {
+
+/// @brief File descriptor event handler class handles events for registered
+/// file descriptors.
+class FDEventHandler {
+public:
+    enum HandlerType : uint16_t {
+        TYPE_UNKNOWN = 0,
+        TYPE_SELECT = 1,
+        TYPE_EPOLL = 2, // Linux OS (Linux like OS) only
+        TYPE_KQUEUE = 3, // BSD (BSD like OS) only
+    };
+
+    // @brief Constructor.
+    //
+    // @param type The file descriptor event handler type.
+    FDEventHandler(HandlerType type = TYPE_UNKNOWN);
+
+    // @brief Destructor.
+    virtual ~FDEventHandler() = default;
+
+    // @brief Add file descriptor to watch for events.
+    //
+    // @param fd The file descriptor.
+    // @param read The flag indicating if the file descriptor should be
+    // registered for read ready events.
+    // @param write The flag indicating if the file descriptor should be
+    // registered for write ready events.
+    virtual void addFD(int fd, bool read = true, bool write = false) = 0;
+
+    // @brief Wait for events on registered file descriptors.
+    //
+    // @param timeout_sec The wait timeout in seconds.
+    // @param timeout_usec The wait timeout in micro seconds
+    // @return -1 on error, 0 if no data is available (timeout expired),
+    // 1 if data is ready.
+    virtual int waitEvent(uint32_t timeout_sec, uint32_t timeout_usec = 0) = 0;
+
+    // @brief Check if file descriptor is ready for read operation.
+    //
+    // @param fd The file descriptor.
+    //
+    // @return True if file descriptor is ready for reading.
+    virtual bool readReadyFD(int fd) = 0;
+
+    // @brief Check if file descriptor is ready for write operation.
+    //
+    // @param fd The file descriptor.
+    //
+    // @return True if file descriptor is ready for writing.
+    virtual bool writeReady(int fd) = 0;
+
+    // @brief Clear registered file descriptors.
+    virtual void clear() = 0;
+
+    // @brief Return the event handler type.
+    HandlerType type();
+
+private:
+    // @brief The event handler type.
+    HandlerType type_;
+};
+
+/// @brief Shared pointer to an FD event handler.
+typedef boost::shared_ptr<FDEventHandler> FDEventHandlerPtr;
+
+}  // namespace isc::dhcp
+}  // namespace isc
+
+#endif  // FD_EVENT_HANDLER_H
index 6d2c0ab73316be52e8d075fdfa57cc05119bd4a1..7133b3f6e3cd7514fab3709600907e0733d5a4df 100644 (file)
@@ -15,6 +15,7 @@ kea_dhcp_lib = shared_library(
     'classify.cc',
     'duid.cc',
     'duid_factory.cc',
+    'fd_event_handler.cc',
     'hwaddr.cc',
     'iface_mgr.cc',
     iface_mgr,
@@ -54,6 +55,7 @@ kea_dhcp_lib = shared_library(
     'pkt_filter_inet6.cc',
     pkt_filter_cc,
     'protocol_util.cc',
+    'select_event_handler.cc',
     include_directories: [include_directories('.')] + INCLUDES,
     install: true,
     install_dir: LIBDIR,
@@ -72,6 +74,7 @@ kea_dhcp_headers = [
     'docsis3_option_defs.h',
     'duid.h',
     'duid_factory.h',
+    'fd_event_handler.h',
     'hwaddr.h',
     'iface_mgr.h',
     'iface_mgr_error_handler.h',
@@ -119,6 +122,7 @@ kea_dhcp_headers = [
     'pkt_filter_lpf.h',
     'pkt_template.h',
     'protocol_util.h',
+    'select_event_handler.h',
     'socket_info.h',
     'std_option_defs.h',
 ]
diff --git a/src/lib/dhcp/select_event_handler.cc b/src/lib/dhcp/select_event_handler.cc
new file mode 100644 (file)
index 0000000..41b8234
--- /dev/null
@@ -0,0 +1,75 @@
+// Copyright (C) 2011-2025 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 <config.h>
+
+#include <exceptions/exceptions.h>
+#include <select_event_handler.h>
+
+namespace isc {
+namespace dhcp {
+
+SelectEventHandler::SelectEventHandler() : FDEventHandler(TYPE_SELECT), max_fd_(0) {
+    clear();
+}
+
+void SelectEventHandler::add(int fd, bool read /* = true */, bool write /* = false */) {
+    if (fd < 0) {
+        isc_throw(BadValue, "invalid negative value for fd");
+    }
+    if (fd >= FD_SETSIZE) {
+        isc_throw(BadValue, "invalid value for fd exceeds maximum allowed " << FD_SETSIZE);
+    }
+    if (read) {
+        // Add this socket to read set
+        FD_SET(fd, &read_fd_set_);
+    }
+    if (write) {
+        // Add this socket to write set
+        FD_SET(fd, &write_fd_set_);
+    }
+}
+
+// @brief Wait for events on registered file descriptors.
+int SelectEventHandler::waitEvent(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
+    // Sanity check for microsecond timeout.
+    if (timeout_usec >= 1000000) {
+        isc_throw(BadValue, "fractional timeout must be shorter than"
+                  " one million microseconds");
+    }
+    struct timeval select_timeout;
+    select_timeout.tv_sec = timeout_sec;
+    select_timeout.tv_usec = timeout_usec;
+
+    return (select(max_fd_ + 1, &read_fd_set_, &write_fd_set_, 0, &select_timeout));
+}
+
+// @brief Check if file descriptor is ready for read operation.
+//
+// @param fd The file descriptor.
+//
+// @return True if file descriptor is ready for reading.
+bool SelectEventHandler::readReady(int fd) {
+    return (FD_ISSET(fd, &read_fd_set_));
+}
+
+// @brief Check if file descriptor is ready for write operation.
+//
+// @param fd The file descriptor.
+//
+// @return True if file descriptor is ready for writing.
+bool SelectEventHandler::writeReady(int fd) {
+    return (FD_ISSET(fd, &write_fd_set_));
+}
+
+void SelectEventHandler::clear() {
+    FD_ZERO(&read_fd_set_);
+    FD_ZERO(&write_fd_set_);
+    max_fd_ = 0;
+}
+
+} // end of namespace isc::dhcp
+} // end of namespace isc
diff --git a/src/lib/dhcp/select_event_handler.h b/src/lib/dhcp/select_event_handler.h
new file mode 100644 (file)
index 0000000..2a5cd06
--- /dev/null
@@ -0,0 +1,75 @@
+// Copyright (C) 2010-2024 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 SELECT_EVENT_HANDLER_H
+#define SELECT_EVENT_HANDLER_H
+
+#include <fd_event_handler.h>
+
+#include <sys/select.h>
+
+namespace isc {
+namespace dhcp {
+
+/// @brief File descriptor event handler class handles events for registered
+/// file descriptors. This class uses the OS select syscall for event handling.
+class SelectEventHandler : public FDEventHandler {
+public:
+    // @brief Constructor.
+    SelectEventHandler();
+
+    // @brief Destructor.
+    virtual ~SelectEventHandler() = default;
+
+    // @brief Add file descriptor to watch for events.
+    //
+    // @param fd The file descriptor.
+    // @param read The flag indicating if the file descriptor should be
+    // registered for read ready events.
+    // @param write The flag indicating if the file descriptor should be
+    // registered for write ready events.
+    void add(int fd, bool read = true, bool write = false);
+
+    // @brief Wait for events on registered file descriptors.
+    //
+    // @param timeout_sec The wait timeout in seconds.
+    // @param timeout_usec The wait timeout in micro seconds
+    // @return -1 on error, 0 if no data is available (timeout expired),
+    // 1 if data is ready.
+    int waitEvent(uint32_t timeout_sec, uint32_t timeout_usec = 0);
+
+    // @brief Check if file descriptor is ready for read operation.
+    //
+    // @param fd The file descriptor.
+    //
+    // @return True if file descriptor is ready for reading.
+    bool readReady(int fd);
+
+    // @brief Check if file descriptor is ready for write operation.
+    //
+    // @param fd The file descriptor.
+    //
+    // @return True if file descriptor is ready for writing.
+    bool writeReady(int fd);
+
+    // @brief Clear registered file descriptors.
+    void clear();
+
+private:
+    // @brief The maximum value of registered file descriptors.
+    int max_fd_;
+
+    // @brief The read event FD set.
+    fd_set read_fd_set_;
+
+    // @brief The write event FD set.
+    fd_set write_fd_set_;
+};
+
+}  // namespace isc::dhcp
+}  // namespace isc
+
+#endif  // SELECT_EVENT_HANDLER_H