#include <sstream>
#include <thread>
-#include <sys/select.h>
#include <sys/stat.h>
-#include <sys/ioctl.h>
#include <cstdlib>
#include <unistd.h>
#include <sstream>
#include <thread>
-#include <sys/select.h>
#include <sys/stat.h>
-#include <sys/ioctl.h>
#include <cstdlib>
#include <unistd.h>
}
struct timeval tm;
tm.tv_sec = tm.tv_usec = 0;
- // r4z: should move to epoll/kqueue?
+ // @todo implement this using SelectEventHandler
+ // @todo: should move to epoll/kqueue?
int n = select(nfd + 1, &fds, 0, 0, &tm);
if ((n < 0) && (errno == EINTR)) {
cerr << "interrupted" << endl;
-// Copyright (C) 2011-2025 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 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
-// Copyright (C) 2010-2024 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 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
TYPE_UNKNOWN = 0,
TYPE_SELECT = 1,
TYPE_EPOLL = 2, // Linux OS (Linux like OS) only
- TYPE_KQUEUE = 3, // BSD (BSD like OS) only
+ TYPE_KQUEUE = 3, // BSD OS (BSD like OS) only
};
- // @brief Constructor.
- //
- // @param type The file descriptor event handler type.
+ /// @brief Constructor.
+ ///
+ /// @param type The file descriptor event handler type.
FDEventHandler(HandlerType type = TYPE_UNKNOWN);
- // @brief Destructor.
+ /// @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.
+ /// @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 add(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.
+ /// @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 readReady(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.
+ /// @brief Clear registered file descriptors.
virtual void clear() = 0;
- // @brief Return the event handler type.
+ /// @brief Return the event handler type.
HandlerType type();
private:
- // @brief The event handler type.
+ /// @brief The event handler type.
HandlerType type_;
};
--- /dev/null
+// Copyright (C) 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 <dhcp/fd_event_handler_factory.h>
+#include <dhcp/select_event_handler.h>
+
+namespace isc {
+namespace dhcp {
+
+FDEventHandlerPtr FDEventHandlerFactory::factoryFDEventHandler() {
+ // todo: use configuration to initialize the FDEventHandler.
+ return (FDEventHandlerPtr(new SelectEventHandler()));
+}
+
+} // end of namespace isc::dhcp
+} // end of namespace isc
--- /dev/null
+// Copyright (C) 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/.
+
+#ifndef FD_EVENT_HANDLER_FACTORY_H
+#define FD_EVENT_HANDLER_FACTORY_H
+
+#include <dhcp/fd_event_handler.h>
+
+namespace isc {
+namespace dhcp {
+
+/// @brief File descriptor event handler factory class handles the creation of
+/// the FDEventHangler instance according to configuration and OS supported
+/// syscalls.
+class FDEventHandlerFactory {
+public:
+
+ /// @brief Constructor.
+ FDEventHandlerFactory() = default;
+
+ /// @brief Destructor.
+ virtual ~FDEventHandlerFactory() = default;
+
+ /// @brief Return an FDEventhandler.
+ static FDEventHandlerPtr factoryFDEventHandler();
+};
+
+} // namespace isc::dhcp
+} // namespace isc
+
+#endif // FD_EVENT_HANDLER_FACTORY_H
#include <dhcp/iface_mgr_error_handler.h>
#include <dhcp/pkt_filter_inet.h>
#include <dhcp/pkt_filter_inet6.h>
+#include <dhcp/fd_event_handler_factory.h>
#include <exceptions/exceptions.h>
#include <util/io/pktinfo_utilities.h>
#include <util/multi_threading_mgr.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/select.h>
-
-#ifndef FD_COPY
-#define FD_COPY(orig, copy) \
- do { \
- memmove(copy, orig, sizeof(fd_set)); \
- } while (0)
-#endif
using namespace std;
using namespace isc::asiolink;
} catch (const std::exception& ex) {
isc_throw(IfaceDetectError, ex.what());
}
+
+ initializeFDEventHandler();
+}
+
+void IfaceMgr::initializeFDEventHandler() {
+ fd_event_handler_ = FDEventHandlerFactory::factoryFDEventHandler();
+ receiver_fd_event_handler_ = FDEventHandlerFactory::factoryFDEventHandler();
}
void Iface::addUnicast(const isc::asiolink::IOAddress& addr) {
" one million microseconds");
}
- fd_set sockets;
- int maxfd = 0;
-
- FD_ZERO(&sockets);
+ fd_event_handler_->clear();
// if there are any callbacks for external sockets registered...
{
if (!callbacks_.empty()) {
for (const SocketCallbackInfo& s : callbacks_) {
// Add this socket to listening set
- addFDtoSet(s.socket_, maxfd, &sockets);
+ fd_event_handler_->add(s.socket_);
}
}
}
// Add Receiver ready watch socket
- addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::READY), maxfd, &sockets);
+ fd_event_handler_->add(dhcp_receiver_->getWatchFd(WatchedThread::READY));
// Add Receiver error watch socket
- addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::ERROR), maxfd, &sockets);
+ fd_event_handler_->add(dhcp_receiver_->getWatchFd(WatchedThread::ERROR));
// Set timeout for our next select() call. If there are
// no DHCP packets to read, then we'll wait for a finite
// poll (timeout = 0 secs). We need to poll, even if
// DHCP packets are waiting so we don't starve external
// sockets under heavy DHCP load.
- struct timeval select_timeout;
- if (getPacketQueue4()->empty()) {
- select_timeout.tv_sec = timeout_sec;
- select_timeout.tv_usec = timeout_usec;
- } else {
- select_timeout.tv_sec = 0;
- select_timeout.tv_usec = 0;
+ if (!getPacketQueue4()->empty()) {
+ timeout_sec = 0;
+ timeout_usec = 0;
}
// zero out the errno to be safe
errno = 0;
- int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
+ int result = fd_event_handler_->waitEvent(timeout_sec, timeout_usec);
if ((result == 0) && getPacketQueue4()->empty()) {
// nothing received and timeout has been reached
{
std::lock_guard<std::mutex> lock(callbacks_mutex_);
for (const SocketCallbackInfo& s : callbacks_) {
- if (!FD_ISSET(s.socket_, &sockets)) {
+ if (!fd_event_handler_->readReady(s.socket_)) {
continue;
}
found = true;
isc_throw(BadValue, "fractional timeout must be shorter than"
" one million microseconds");
}
+
boost::scoped_ptr<SocketInfo> candidate;
- fd_set sockets;
- int maxfd = 0;
- FD_ZERO(&sockets);
+ fd_event_handler_->clear();
/// @todo: marginal performance optimization. We could create the set once
/// and then use its copy for select(). Please note that select() modifies
// Only deal with IPv4 addresses.
if (s.addr_.isV4()) {
// Add this socket to listening set
- addFDtoSet(s.sockfd_, maxfd, &sockets);
+ fd_event_handler_->add(s.sockfd_);
}
}
}
if (!callbacks_.empty()) {
for (const SocketCallbackInfo& s : callbacks_) {
// Add this socket to listening set
- addFDtoSet(s.socket_, maxfd, &sockets);
+ fd_event_handler_->add(s.socket_);
}
}
}
- struct timeval select_timeout;
- select_timeout.tv_sec = timeout_sec;
- select_timeout.tv_usec = timeout_usec;
-
// zero out the errno to be safe
errno = 0;
- int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
+ int result = fd_event_handler_->waitEvent(timeout_sec, timeout_usec);
if (result == 0) {
// nothing received and timeout has been reached
{
std::lock_guard<std::mutex> lock(callbacks_mutex_);
for (const SocketCallbackInfo& s : callbacks_) {
- if (!FD_ISSET(s.socket_, &sockets)) {
+ if (!fd_event_handler_->readReady(s.socket_)) {
continue;
}
found = true;
IfacePtr recv_if;
for (const IfacePtr& iface : ifaces_) {
for (const SocketInfo& s : iface->getSockets()) {
- if (FD_ISSET(s.sockfd_, &sockets)) {
+ if (fd_event_handler_->readReady(s.sockfd_)) {
candidate.reset(new SocketInfo(s));
break;
}
return (receive6Direct(timeout_sec, timeout_usec));
}
-void
-IfaceMgr::addFDtoSet(int fd, int& maxfd, fd_set* sockets) {
- if (!sockets) {
- isc_throw(BadValue, "addFDtoSet: sockets can't be null");
- }
-
- if (fd >= FD_SETSIZE) {
- isc_throw(BadValue, "addFDtoSet: sockets fd too large: " << fd << " >= " << FD_SETSIZE);
- }
-
- FD_SET(fd, sockets);
- if (maxfd < fd) {
- maxfd = fd;
- }
-}
-
Pkt6Ptr
IfaceMgr::receive6Direct(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */ ) {
// Sanity check for microsecond timeout.
}
boost::scoped_ptr<SocketInfo> candidate;
- fd_set sockets;
- int maxfd = 0;
- FD_ZERO(&sockets);
+ fd_event_handler_->clear();
/// @todo: marginal performance optimization. We could create the set once
/// and then use its copy for select(). Please note that select() modifies
// Only deal with IPv6 addresses.
if (s.addr_.isV6()) {
// Add this socket to listening set
- addFDtoSet(s.sockfd_, maxfd, &sockets);
+ fd_event_handler_->add(s.sockfd_);
}
}
}
if (!callbacks_.empty()) {
for (const SocketCallbackInfo& s : callbacks_) {
// Add this socket to listening set
- addFDtoSet(s.socket_, maxfd, &sockets);
+ fd_event_handler_->add(s.socket_);
}
}
}
- struct timeval select_timeout;
- select_timeout.tv_sec = timeout_sec;
- select_timeout.tv_usec = timeout_usec;
-
// zero out the errno to be safe
errno = 0;
- int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
+ int result = fd_event_handler_->waitEvent(timeout_sec, timeout_usec);
if (result == 0) {
// nothing received and timeout has been reached
{
std::lock_guard<std::mutex> lock(callbacks_mutex_);
for (const SocketCallbackInfo& s : callbacks_) {
- if (!FD_ISSET(s.socket_, &sockets)) {
+ if (!fd_event_handler_->readReady(s.socket_)) {
continue;
}
found = true;
// Let's find out which interface/socket has the data
for (const IfacePtr& iface : ifaces_) {
for (const SocketInfo& s : iface->getSockets()) {
- if (FD_ISSET(s.sockfd_, &sockets)) {
+ if (fd_event_handler_->readReady(s.sockfd_)) {
candidate.reset(new SocketInfo(s));
break;
}
" one million microseconds");
}
- fd_set sockets;
- int maxfd = 0;
-
- FD_ZERO(&sockets);
+ fd_event_handler_->clear();
// if there are any callbacks for external sockets registered...
{
if (!callbacks_.empty()) {
for (const SocketCallbackInfo& s : callbacks_) {
// Add this socket to listening set
- addFDtoSet(s.socket_, maxfd, &sockets);
+ fd_event_handler_->add(s.socket_);
}
}
}
// Add Receiver ready watch socket
- addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::READY), maxfd, &sockets);
+ fd_event_handler_->add(dhcp_receiver_->getWatchFd(WatchedThread::READY));
// Add Receiver error watch socket
- addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::ERROR), maxfd, &sockets);
+ fd_event_handler_->add(dhcp_receiver_->getWatchFd(WatchedThread::ERROR));
// Set timeout for our next select() call. If there are
// no DHCP packets to read, then we'll wait for a finite
// poll (timeout = 0 secs). We need to poll, even if
// DHCP packets are waiting so we don't starve external
// sockets under heavy DHCP load.
- struct timeval select_timeout;
- if (getPacketQueue6()->empty()) {
- select_timeout.tv_sec = timeout_sec;
- select_timeout.tv_usec = timeout_usec;
- } else {
- select_timeout.tv_sec = 0;
- select_timeout.tv_usec = 0;
+ if (!getPacketQueue6()->empty()) {
+ timeout_sec = 0;
+ timeout_usec = 0;
}
// zero out the errno to be safe
errno = 0;
- int result = select(maxfd + 1, &sockets, 0, 0, &select_timeout);
+ int result = fd_event_handler_->waitEvent(timeout_sec, timeout_usec);
if ((result == 0) && getPacketQueue6()->empty()) {
// nothing received and timeout has been reached
{
std::lock_guard<std::mutex> lock(callbacks_mutex_);
for (const SocketCallbackInfo& s : callbacks_) {
- if (!FD_ISSET(s.socket_, &sockets)) {
+ if (!fd_event_handler_->readReady(s.socket_)) {
continue;
}
found = true;
void
IfaceMgr::receiveDHCP4Packets() {
- fd_set sockets;
- int maxfd = 0;
-
- FD_ZERO(&sockets);
+ receiver_fd_event_handler_->clear();
// Add terminate watch socket.
- addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::TERMINATE), maxfd, &sockets);
+ receiver_fd_event_handler_->add(dhcp_receiver_->getWatchFd(WatchedThread::TERMINATE));
// Add Interface sockets.
for (const IfacePtr& iface : ifaces_) {
// Only deal with IPv4 addresses.
if (s.addr_.isV4()) {
// Add this socket to listening set.
- addFDtoSet(s.sockfd_, maxfd, &sockets);
+ receiver_fd_event_handler_->add(s.sockfd_);
}
}
}
return;
}
- fd_set rd_set;
- FD_COPY(&sockets, &rd_set);
-
// zero out the errno to be safe.
errno = 0;
// Select with null timeouts to wait indefinitely an event
- int result = select(maxfd + 1, &rd_set, 0, 0, 0);
+ int result = receiver_fd_event_handler_->waitEvent(0, 0);
// Re-check the watch socket.
if (dhcp_receiver_->shouldTerminate()) {
// Let's find out which interface/socket has data.
for (const IfacePtr& iface : ifaces_) {
for (const SocketInfo& s : iface->getSockets()) {
- if (FD_ISSET(s.sockfd_, &sockets)) {
+ if (receiver_fd_event_handler_->readReady(s.sockfd_)) {
receiveDHCP4Packet(*iface, s);
// Can take time so check one more time the watch socket.
if (dhcp_receiver_->shouldTerminate()) {
}
}
}
-
}
void
IfaceMgr::receiveDHCP6Packets() {
- fd_set sockets;
- int maxfd = 0;
-
- FD_ZERO(&sockets);
+ receiver_fd_event_handler_->clear();
// Add terminate watch socket.
- addFDtoSet(dhcp_receiver_->getWatchFd(WatchedThread::TERMINATE), maxfd, &sockets);
+ receiver_fd_event_handler_->add(dhcp_receiver_->getWatchFd(WatchedThread::TERMINATE));
// Add Interface sockets.
for (const IfacePtr& iface : ifaces_) {
// Only deal with IPv6 addresses.
if (s.addr_.isV6()) {
// Add this socket to listening set.
- addFDtoSet(s.sockfd_ , maxfd, &sockets);
+ receiver_fd_event_handler_->add(s.sockfd_);
}
}
}
return;
}
- fd_set rd_set;
- FD_COPY(&sockets, &rd_set);
-
// zero out the errno to be safe.
errno = 0;
- // Note we wait until something happen.
- int result = select(maxfd + 1, &rd_set, 0, 0, 0);
+ // Select with null timeouts to wait indefinitely an event
+ int result = receiver_fd_event_handler_->waitEvent(0, 0);
// Re-check the watch socket.
if (dhcp_receiver_->shouldTerminate()) {
// Let's find out which interface/socket has data.
for (const IfacePtr& iface : ifaces_) {
for (const SocketInfo& s : iface->getSockets()) {
- if (FD_ISSET(s.sockfd_, &sockets)) {
+ if (receiver_fd_event_handler_->readReady(s.sockfd_)) {
receiveDHCP6Packet(s);
// Can take time so check one more time the watch socket.
if (dhcp_receiver_->shouldTerminate()) {
#include <asiolink/io_address.h>
#include <dhcp/dhcp4.h>
#include <dhcp/dhcp6.h>
+#include <dhcp/fd_event_handler_factory.h>
#include <dhcp/pkt4.h>
#include <dhcp/pkt6.h>
#include <dhcp/packet_queue_mgr4.h>
/// Closes open sockets.
virtual ~IfaceMgr();
+ /// @brief Initialize the FD event handler;
+ void initializeFDEventHandler();
+
/// @brief Sets or clears the test mode for @c IfaceMgr.
///
/// Various unit test may set this flag to true, to indicate that the
bool configureDHCPPacketQueue(const uint16_t family,
data::ConstElementPtr queue_control);
- /// @brief Convenience method for adding an descriptor to a set
- ///
- /// @param fd descriptor to add
- /// @param[out] maxfd maximum fd value in the set. If the new fd is
- /// larger than it's current value, it will be updated to new fd value
- /// @param sockets pointer to the set of sockets
- /// @throw BadValue if sockets is null
- static void addFDtoSet(int fd, int& maxfd, fd_set* sockets);
-
// don't use private, we need derived classes in tests
protected:
/// @brief DHCP packet receiver.
isc::util::WatchedThreadPtr dhcp_receiver_;
+
+ /// @brief The FDEventHandler instance.
+ FDEventHandlerPtr fd_event_handler_;
+
+ /// @brief The receiver FDEventHandler instance.
+ FDEventHandlerPtr receiver_fd_event_handler_;
};
} // namespace isc::dhcp
'duid.cc',
'duid_factory.cc',
'fd_event_handler.cc',
+ 'fd_event_handler_factory.cc',
'hwaddr.cc',
'iface_mgr.cc',
iface_mgr,
'duid.h',
'duid_factory.h',
'fd_event_handler.h',
+ 'fd_event_handler_factory.h',
'hwaddr.h',
'iface_mgr.h',
'iface_mgr_error_handler.h',
/// @brief local HW address (dst if receiving packet, src if sending packet)
HWAddrPtr local_hwaddr_;
- // @brief List of deferred option codes
+ /// @brief List of deferred option codes
std::list<uint16_t> deferred_options_;
/// @brief message operation code
-// Copyright (C) 2011-2025 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 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
#include <exceptions/exceptions.h>
#include <select_event_handler.h>
+#ifndef FD_COPY
+#define FD_COPY(orig, copy) \
+ do { \
+ memcpy(copy, orig, sizeof(fd_set)); \
+ } while (0)
+#endif
+
namespace isc {
namespace dhcp {
// Add this socket to write set
FD_SET(fd, &write_fd_set_);
}
+ if (fd > max_fd_) {
+ max_fd_ = fd;
+ }
}
// @brief Wait for events on registered file descriptors.
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));
+ FD_COPY(&read_fd_set_, &ready_read_fd_set_);
+ FD_COPY(&write_fd_set_, &ready_write_fd_set_);
+
+ return (select(max_fd_ + 1, &ready_read_fd_set_, &ready_write_fd_set_, 0, &select_timeout));
}
// @brief Check if file descriptor is ready for read operation.
//
// @return True if file descriptor is ready for reading.
bool SelectEventHandler::readReady(int fd) {
- return (FD_ISSET(fd, &read_fd_set_));
+ return (FD_ISSET(fd, &ready_read_fd_set_));
}
// @brief Check if file descriptor is ready for write operation.
//
// @return True if file descriptor is ready for writing.
bool SelectEventHandler::writeReady(int fd) {
- return (FD_ISSET(fd, &write_fd_set_));
+ return (FD_ISSET(fd, &ready_write_fd_set_));
}
void SelectEventHandler::clear() {
-// Copyright (C) 2010-2024 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 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 descriptors. This class uses the OS select syscall for event handling.
class SelectEventHandler : public FDEventHandler {
public:
- // @brief Constructor.
+ /// @brief Constructor.
SelectEventHandler();
- // @brief Destructor.
+ /// @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.
+ /// @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.
+ /// @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.
+ /// @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.
+ /// @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.
+ /// @brief Clear registered file descriptors.
void clear();
private:
- // @brief The maximum value of registered file descriptors.
+ /// @brief The maximum value of registered file descriptors.
int max_fd_;
- // @brief The read event FD set.
+ /// @brief The read event FD set.
fd_set read_fd_set_;
- // @brief The write event FD set.
+ /// @brief The write event FD set.
fd_set write_fd_set_;
+
+ /// @brief The read event FD set.
+ fd_set ready_read_fd_set_;
+
+ /// @brief The write event FD set.
+ fd_set ready_write_fd_set_;
};
} // namespace isc::dhcp
#include <functional>
#include <algorithm>
-#include <sys/select.h>
-
using namespace std;
using namespace isc;
using namespace isc::asiolink;
IfaceMgr& iface_mgr = IfaceMgr::instance();
// Remove selection of unicast addresses from all interfaces.
iface_mgr.clearUnicasts();
+ // Initialize IfaceMgr FDEventHandler.
+ iface_mgr.initializeFDEventHandler();
// Allow the loopback interface when required.
iface_mgr.setAllowLoopBack(loopback_used_);
// For the DHCPv4 server, if the user has selected that raw sockets
#include <gtest/gtest.h>
#include <functional>
-#include <sys/select.h>
using namespace std;
using namespace isc::asiolink;
#include <string>
#include <fstream>
-//#include <config.h>
-
#include <log/logger_manager.h>
#include <log/logger_name.h>
#include <log/logger_support.h>
-//#include <boost/shared_ptr.hpp>
-//#include <boost/scoped_ptr.hpp>
#include <gtest/gtest.h>
using namespace std;
#include <config.h>
#include <sys/select.h>
-#include <sys/ioctl.h>
namespace isc {
namespace util {
int selectCheck(const int fd_to_check, const unsigned int timeout_sec,
bool read_check, bool write_check) {
+ // @todo implement this using SelectEventHandler
+ // @todo: should move to epoll/kqueue?
if (fd_to_check < 0) {
return (-1);
}
#include <config.h>
-//#include <dhcp_ddns/dhcp_ddns_log.h>
#include <util/watch_socket.h>
#include <fcntl.h>