Skip to content
This repository has been archived by the owner on Sep 7, 2020. It is now read-only.

Create interface state monitor #1579

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion common/beerocks/bcl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ if (BUILD_TESTS)
set(unit_tests_sources
${bcl_sources}
${MODULE_PATH}/unit_tests/network_utils_test.cpp
${MODULE_PATH}/unit_tests/socket_event_loop_test.cpp
${MODULE_PATH}/unit_tests/event_loop_impl_test.cpp
${MODULE_PATH}/unit_tests/interface_state_manager_impl_test.cpp
${MODULE_PATH}/unit_tests/wireless_utils_test.cpp
)
add_executable(${TEST_PROJECT_NAME}
Expand Down
79 changes: 19 additions & 60 deletions common/beerocks/bcl/include/bcl/beerocks_event_loop.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@
#ifndef _BEEROCKS_EVENT_LOOP_H_
#define _BEEROCKS_EVENT_LOOP_H_

#include "beerocks_backport.h"

#include <chrono>
#include <functional>

namespace beerocks {
Expand All @@ -33,37 +30,19 @@ namespace beerocks {
* event loop is at the highest level of control within the program.
*/

template <typename E, typename T> class EventLoop {
// Fail the build if T (timeout type) is not derived from std::chrono::duration
static_assert(is_chrono_duration<T>::value, "T must be derived from std::chrono::duration");

class EventLoop {
public:
/**
* The type of the event source (e.g. file descriptor).
*/
using EventType = E;

/**
* The type of the event loop.
*/
using EventLoopType = EventLoop<E, T>;

/**
* The type of the timeout units for the event loop.
*/
using TimeoutType = T;

/**
* @brief Event handler function definition.
*
* Parameters to the event handler function are:
* @param[in] event The resource where the event was originated at.
* @param[in] fd The file descriptor of the OS resource where the event was originated at.
* @param[in] loop The event loop where the event was caught. Event handler can install new handlers,
* remove existing handlers and even ask for loop termination.
*
* @returns True on success or false otherwise
*/
using EventHandler = std::function<bool(EventType event, EventLoopType &loop)>;
using EventHandler = std::function<bool(int fd, EventLoop &loop)>;

/**
* Set of event handler functions, one function to handle each possible event happened.
Expand All @@ -75,45 +54,28 @@ template <typename E, typename T> class EventLoop {
struct EventHandlers {
/**
* Hook method that is called back by the event loop to handle read events.
* Read events are dispatched when the socket is ready for a read operation (a read
* operation will not block).
* @param socket Socket the event was originated at.
* @param loop Event loop where the event was caught on.
* Read events are dispatched for example when a socket is ready for a read operation (a
* read operation will not block).
*/
EventHandler on_read;

/**
* Hook method that is called back by the event loop to handle write events.
* Write events are dispatched when the socket is ready for a write operation (a write
* operation will not block).
* @param socket Socket the event was originated at.
* @param loop Event loop where the event was caught on.
* Write events are dispatched for example when a socket is ready for a write operation (a
* write operation will not block).
*/
EventHandler on_write;

/**
* Hook method that is called back by the event loop to handle timeout events.
* Timeout events are dispatched when timeout expires while waiting for the socket to
* be ready for a read or write operation.
* @param socket Socket the event was originated at.
* @param loop Event loop where the event was caught on.
*/
EventHandler on_timeout;

/**
* Hook method that is called back by the event loop to handle disconnect events.
* Disconnect events are dispatched when the remote socket is closed.
* @param socket Socket the event was originated at.
* @param loop Event loop where the event was caught on.
* Disconnect events are dispatched for example when the remote socket is closed.
*/
EventHandler on_disconnect;

/**
* Hook method that is called back by the event loop to handle error events.
* Error events are dispatched when an error occurs while waiting for the socket to
* be ready for a read or write operation.
* @param socket Socket the event was originated at.
* @param loop Event loop where the event was caught on.
* Error events are dispatched for example when an error occurs while waiting for a socket
* to be ready for a read or write operation.
*/
EventHandler on_error;
};
Expand All @@ -127,35 +89,32 @@ template <typename E, typename T> class EventLoop {
* @brief Registers a set of event handlers for the given event source (e.g. socket).
*
* Event handler for the event that occurred will be called back when the event source is
* ready for a read/write operation, when a disconnect/error occurs or when given timeout expires.
* ready for a read/write operation, when a disconnect/error occurs.
*
* @param event Event source object.
* @param fd File descriptor of the event source object.
* @param handlers Set of event handlers: class with the methods to be called back when an
* event occurs.
* @param timeout Time to wait in milliseconds (-1 to wait indefinitely) for a read/write
* event to occur.
* @return True on success and false otherwise.
*/
virtual bool add_event(EventType event, EventHandlers handlers,
TimeoutType timeout = TimeoutType::min()) = 0;
virtual bool register_handlers(int fd, const EventHandlers &handlers) = 0;

/**
* @brief Removes previously registered event handlers for the given event source.
*
* @param event Event source object.
* @param fd File descriptor of the event source object.
* @return True on success and false otherwise.
*/
virtual bool del_event(EventType socket) = 0;
virtual bool remove_handlers(int fd) = 0;

/**
* @brief Runs message loop.
*
* Performs a single loop iteration and returns after processing IO events
* or when an error or timeout occurs.
* Performs a single loop iteration and returns after processing IO events or when an error
* or timeout occurs.
*
* @return -1 on critical errors
* @return 0 on timeout without any socket events
* @return >0 number of socket events processed during the class to this method.
* @return 0 on timeout waiting for events on all file descriptors.
* @return >0 number of events processed during the call to this method.
*/
virtual int run() = 0;
};
Expand Down
81 changes: 81 additions & 0 deletions common/beerocks/bcl/include/bcl/beerocks_event_loop_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/* SPDX-License-Identifier: BSD-2-Clause-Patent
*
* SPDX-FileCopyrightText: 2016-2020 the prplMesh contributors (see AUTHORS.md)
*
* This code is subject to the terms of the BSD+Patent license.
* See LICENSE file for more details.
*/

#ifndef _BEEROCKS_EVENT_LOOP_IMPL_H_
#define _BEEROCKS_EVENT_LOOP_IMPL_H_

#include "beerocks_event_loop.h"

#include <chrono>
#include <unordered_map>

namespace beerocks {

/**
* @brief ePoll based implementation of the EventLoop interface.
* @see EventLoop
*
* This class uses the Linux epoll APIs for monitoring the provided file descriptors for I/O
* operations.
*/
class EventLoopImpl : public EventLoop {
public:
/**
* @brief Class constructor.
*
* Initializes an epoll file descriptor.
*
* @param [in] timeout Sets the master timeout (in milliseconds) for the event loop.
*/
explicit EventLoopImpl(std::chrono::milliseconds timeout = std::chrono::milliseconds::min());

/**
* @brief Class destructor.
*/
~EventLoopImpl() override;

/**
* @see EventLoop::register_handlers
*/
bool register_handlers(int fd, const EventHandlers &handlers) override;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have to register all handlers at once?
Do we need ability to register/remove a single handler? Does underlying interface prevent us from doing that?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EventHandlers is a struct containing several EventHandler functions (on_read, on_write, on_error, ...). Method register_handlers registers all of them at once. This way the method can check if handlers have already been installed or not.

I cannot think of a situation where we would want to register/remove a single handler but that's possible by passing a EventHandlers struct with its members set accordingly. You can call register_handlers as many times as you want, provided you call remove_handlers in between.


/**
* @see EventLoop::remove_handlers
*/
bool remove_handlers(int fd) override;

/**
* @brief Main event loop method.
* @see EventLoop::run
*
* Executes the epoll_wait() function and processes occurred events.
*/
int run() override;

private:
/**
* epoll file descriptor.
*/
int m_epoll_fd = -1;

/**
* Event loop master timeout (used for the epoll_wait function).
*/
std::chrono::milliseconds m_timeout = std::chrono::milliseconds::min();

/**
* Map of registered event handlers.
* Key value is the file descriptor and value is the EventHandlers structure containing the
* event handlers to deall with events occurred on that file descriptor.
*/
std::unordered_map<int, EventHandlers> m_fd_to_event_handlers;
};

} // namespace beerocks

#endif // _BEEROCKS_EVENT_LOOP_IMPL_H_
108 changes: 0 additions & 108 deletions common/beerocks/bcl/include/bcl/beerocks_socket_event_loop.h

This file was deleted.

37 changes: 37 additions & 0 deletions common/beerocks/bcl/include/bcl/network/file_descriptor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/* SPDX-License-Identifier: BSD-2-Clause-Patent
*
* SPDX-FileCopyrightText: 2020 the prplMesh contributors (see AUTHORS.md)
*
* This code is subject to the terms of the BSD+Patent license.
* See LICENSE file for more details.
*/

#ifndef BCL_NETWORK_FILE_DESCRIPTOR_H_
#define BCL_NETWORK_FILE_DESCRIPTOR_H_

namespace beerocks {
namespace net {

/**
* This interface models OS resources implementing the file descriptor interface.
*/
class FileDescriptor {
public:
static constexpr int invalid_descriptor = -1;

virtual ~FileDescriptor() = default;

/**
* @brief Returns the file descriptor.
*
* A file descriptor is a number that uniquely identifies an open file in the OS.
*
* @return File descriptor.
*/
virtual int fd() = 0;
};

} // namespace net
} // namespace beerocks

#endif /* BCL_NETWORK_FILE_DESCRIPTOR_H_ */
Loading