diff --git a/framework/transport/ieee1905_transport/ieee1905_transport.cpp b/framework/transport/ieee1905_transport/ieee1905_transport.cpp index 527b556512..a15c41414d 100644 --- a/framework/transport/ieee1905_transport/ieee1905_transport.cpp +++ b/framework/transport/ieee1905_transport/ieee1905_transport.cpp @@ -31,13 +31,20 @@ static constexpr int listen_buffer_size = 10; /////////////////////////////// Implementation /////////////////////////////// ////////////////////////////////////////////////////////////////////////////// -Ieee1905Transport::Ieee1905Transport(const std::shared_ptr &event_loop) - : m_event_loop(event_loop) +Ieee1905Transport::Ieee1905Transport( + const std::shared_ptr &interface_state_monitor, + const std::shared_ptr &event_loop) + : m_interface_state_monitor(interface_state_monitor), m_event_loop(event_loop) { } -void Ieee1905Transport::run() +bool Ieee1905Transport::start() { + if (m_broker) { + LOG(ERROR) << "Failed to start 1905 transport: already started"; + return false; + } + // Broker server UDS socket auto server_socket = std::make_shared( std::string(TMP_PATH "/" BEEROCKS_BROKER_UDS), listen_buffer_size); @@ -63,47 +70,23 @@ void Ieee1905Transport::run() return true; }); - // init netlink socket - if (!open_netlink_socket()) { - MAPF_ERR("cannot open netlink socket."); - return; + m_interface_state_monitor->set_handler([&](uint32_t iface_index, bool iface_state) { + handle_interface_status_change(iface_index, iface_state); + }); + + return true; +} + +bool Ieee1905Transport::stop() +{ + if (!m_broker) { + LOG(ERROR) << "Failed to stop 1905 transport: not started"; + return false; } - // Create a shared_ptr socket wrapper for the netlink socket - auto netlink_socket = std::shared_ptr(new Socket(netlink_fd_), [](Socket *socket) { - // Close the socket file descriptor - if (socket) { - close(socket->getSocketFd()); - } - }); + m_interface_state_monitor->set_handler(nullptr); - // Add the netlink socket into the broker's event loop - m_event_loop->register_handlers(netlink_socket->getSocketFd(), - { - // Accept incoming connections - .on_read = - [&](int fd, EventLoop &loop) { - LOG(DEBUG) - << "incoming message on the netlink socket"; - handle_netlink_pollin_event(); - return true; - }, - - // Not implemented - .on_write = nullptr, - - // Fail on server socket disconnections or errors - .on_disconnect = - [&](int fd, EventLoop &loop) { - LOG(ERROR) << "netlink socket disconnected"; - return false; - }, - .on_error = - [&](int fd, EventLoop &loop) { - LOG(ERROR) << "netlink socket error"; - return false; - }, - }); + return true; } } // namespace transport diff --git a/framework/transport/ieee1905_transport/ieee1905_transport.h b/framework/transport/ieee1905_transport/ieee1905_transport.h index a7e04cd764..8babe8be22 100644 --- a/framework/transport/ieee1905_transport/ieee1905_transport.h +++ b/framework/transport/ieee1905_transport/ieee1905_transport.h @@ -13,6 +13,7 @@ #include #include +#include #include "ieee1905_transport_broker.h" @@ -58,12 +59,35 @@ class Ieee1905Transport { /** * Class constructor * + * @param interface_state_monitor Interface state monitor to detect changes in the state of + * network interfaces (transitions to and from the up-and-running state). * @param event_loop Event loop to wait for I/O events. */ - explicit Ieee1905Transport(const std::shared_ptr &event_loop); - void run(); + Ieee1905Transport( + const std::shared_ptr &interface_state_monitor, + const std::shared_ptr &event_loop); + + /** + * @brief Starts the transport process. + * + * @return True on success and false otherwise. + */ + bool start(); + + /** + * @brief Stops the transport process. + * + * @return True on success and false otherwise. + */ + bool stop(); private: + /** + * Interface state monitor used by the process to detect changes in the state of network + * interfaces (transitions to and from the up-and-running state). + */ + std::shared_ptr m_interface_state_monitor; + /** * Application event loop used by the process to wait for I/O events. */ diff --git a/framework/transport/ieee1905_transport/main.cpp b/framework/transport/ieee1905_transport/main.cpp index 5dbdec1d91..039222d4ca 100644 --- a/framework/transport/ieee1905_transport/main.cpp +++ b/framework/transport/ieee1905_transport/main.cpp @@ -9,32 +9,93 @@ #include "ieee1905_transport.h" #include +#include +#include #include #include using namespace beerocks; +using namespace beerocks::net; using namespace beerocks::transport; int main(int argc, char *argv[]) { mapf::Logger::Instance().LoggerInit("transport"); + /** + * Create NETLINK_ROUTE netlink socket for kernel/user-space communication. + */ + auto socket = std::make_shared(); + + /** + * Create client socket. + * Bind it to route netlink multicast group to listen for multicast packets sent from the + * kernel containing network interface create/delete/up/down events. + */ + ClientSocketImpl client(socket); + client.bind(NetlinkAddress(RTMGRP_LINK)); + + /** + * Create connection to send/receive data using this socket + */ + auto connection = std::make_shared(socket); + + /** + * Create application event loop to wait for blocking I/O operations. + */ auto event_loop = std::make_shared(); - Ieee1905Transport ieee1905_transport(event_loop); + /** + * Create the interface state monitor. + */ + auto interface_state_monitor = + std::make_shared(connection, event_loop); + + /** + * Application exit code: 0 on success and -1 on failure. + * From this point on, there's a single exit point to allow for start/stop methods to be + * cleanly called in pairs. + */ + int exit_code = 0; + + /** + * Start the interface state monitor + */ + if (interface_state_monitor->start()) { + /** + * Create the IEEE1905 transport process. + */ + Ieee1905Transport ieee1905_transport(interface_state_monitor, event_loop); - ieee1905_transport.run(); + /** + * Start the IEEE1905 transport process + */ + if (ieee1905_transport.start()) { - // Run the application event loop - MAPF_INFO("starting main loop..."); - for (;;) { - if (event_loop->run() < 0) { - LOG(ERROR) << "Broker event loop failure!"; - return -1; + // Run the application event loop + MAPF_INFO("starting main loop..."); + while (0 == exit_code) { + if (event_loop->run() < 0) { + LOG(ERROR) << "Broker event loop failure!"; + exit_code = -1; + } + } + MAPF_INFO("done"); + + ieee1905_transport.stop(); + + } else { + LOG(ERROR) << "Unable to start IEEE1905 transport process!"; + exit_code = -1; } + + interface_state_monitor->stop(); + + } else { + LOG(ERROR) << "Unable to start interface state monitor!"; + exit_code = -1; } - MAPF_INFO("done"); - return 0; + return exit_code; }