From 4f3df6d91030db23253936ef041b8d9a0e896a5b Mon Sep 17 00:00:00 2001 From: Mikhail Katliar Date: Mon, 1 Mar 2021 13:00:59 +0100 Subject: [PATCH 1/2] Exception-based error handling in egm::UDPServer --- include/abb_libegm/egm_udp_server.h | 21 +++------- src/egm_base_interface.cpp | 4 +- src/egm_udp_server.cpp | 62 ++++++++--------------------- 3 files changed, 24 insertions(+), 63 deletions(-) diff --git a/include/abb_libegm/egm_udp_server.h b/include/abb_libegm/egm_udp_server.h index 329aacd..e4c87fc 100644 --- a/include/abb_libegm/egm_udp_server.h +++ b/include/abb_libegm/egm_udp_server.h @@ -107,23 +107,19 @@ class UDPServer * * \param io_service for operating boost asio's asynchronous functions. * \param port_number for the server's UDP socket. - * \param p_interface that processes the received messages. + * \param interface UDP server that processes the received messages. + * + * \throw \a std::exception if an error occurs. */ UDPServer(boost::asio::io_service& io_service, unsigned short port_number, - AbstractUDPServerInterface* p_interface); + AbstractUDPServerInterface& interface); /** * \brief A destructor. */ ~UDPServer(); - /** - * \brief Checks if the server was successfully initialized or not. - * - * \return bool true if and only if the server was initialized correctly. - */ - bool isInitialized() const; private: /** @@ -155,7 +151,7 @@ class UDPServer /** * \brief The server's UDP socket. */ - boost::shared_ptr p_socket_; + boost::asio::ip::udp::socket socket_; /** * \brief The address of the calling computer (e.g. an ABB robot controller or a virtual controller in RobotStudio). @@ -170,17 +166,12 @@ class UDPServer /** * \brief Pointer to an object that is derived from AbstractUDPSeverInterface, which processes the received messages. */ - AbstractUDPServerInterface* p_interface_; + AbstractUDPServerInterface& interface_; /** * \brief Container for server data. */ UDPServerData server_data_; - - /** - * \brief Flag indicating if the server was initialized successfully or not. - */ - bool initialized_; }; } // end namespace egm diff --git a/src/egm_base_interface.cpp b/src/egm_base_interface.cpp index 0219754..b355cb2 100644 --- a/src/egm_base_interface.cpp +++ b/src/egm_base_interface.cpp @@ -772,7 +772,7 @@ EGMBaseInterface::EGMBaseInterface(boost::asio::io_service& io_service, const unsigned short port_number, const BaseConfiguration& configuration) : -udp_server_(io_service, port_number, this), +udp_server_(io_service, port_number, *this), configuration_(configuration) { if (configuration_.active.use_logging) @@ -913,7 +913,7 @@ bool EGMBaseInterface::initializeCallback(const UDPServerData& server_data) bool EGMBaseInterface::isInitialized() { - return udp_server_.isInitialized(); + return true; } bool EGMBaseInterface::isConnected() diff --git a/src/egm_udp_server.cpp b/src/egm_udp_server.cpp index c966c24..918c453 100644 --- a/src/egm_udp_server.cpp +++ b/src/egm_udp_server.cpp @@ -48,57 +48,27 @@ namespace egm UDPServer::UDPServer(boost::asio::io_service& io_service, unsigned short port_number, - AbstractUDPServerInterface* p_interface) -: -initialized_(false), -p_interface_(p_interface) + AbstractUDPServerInterface& interface) +: socket_ {io_service, boost::asio::ip::udp::endpoint {boost::asio::ip::udp::v4(), port_number}} +, interface_ {interface} { - bool success = true; - - try - { - server_data_.port_number = port_number; - p_socket_.reset(new boost::asio::ip::udp::socket(io_service, - boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), - port_number))); - } - catch (std::exception e) - { - success = false; - } - - if (success) - { - initialized_ = true; - startAsynchronousReceive(); - } + server_data_.port_number = port_number; + startAsynchronousReceive(); } UDPServer::~UDPServer() { - if (p_socket_) - { - p_socket_->close(); - p_socket_.reset(); - } -} - -bool UDPServer::isInitialized() const -{ - return initialized_; + socket_.close(); } void UDPServer::startAsynchronousReceive() { - if (p_socket_) - { - p_socket_->async_receive_from(boost::asio::buffer(receive_buffer_), - remote_endpoint_, - boost::bind(&UDPServer::receiveCallback, - this, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } + socket_.async_receive_from(boost::asio::buffer(receive_buffer_), + remote_endpoint_, + boost::bind(&UDPServer::receiveCallback, + this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); } void UDPServer::receiveCallback(const boost::system::error_code& error, const std::size_t bytes_transferred) @@ -106,15 +76,15 @@ void UDPServer::receiveCallback(const boost::system::error_code& error, const st server_data_.p_data = receive_buffer_; server_data_.bytes_transferred = (int) bytes_transferred; - if (error == boost::system::errc::success && p_interface_) + if (error == boost::system::errc::success) { // Process the received data via the callback method (creates the reply message). - const std::string& reply = p_interface_->callback(server_data_); + const std::string& reply = interface_.callback(server_data_); - if (!reply.empty() && p_socket_) + if (!reply.empty()) { // Send the response message to the robot controller. - p_socket_->async_send_to(boost::asio::buffer(reply), + socket_.async_send_to(boost::asio::buffer(reply), remote_endpoint_, boost::bind(&UDPServer::sendCallback, this, From fea4654f35ec9879a8075f1da5329421737647ef Mon Sep 17 00:00:00 2001 From: Mikhail Katliar Date: Mon, 8 Mar 2021 19:42:48 +0100 Subject: [PATCH 2/2] Added a UDPServer ctor that taken an udp::endpoint and not just port, s.t. the network interface can be specified. --- include/abb_libegm/egm_udp_server.h | 15 +++++++++++++++ src/egm_udp_server.cpp | 13 +++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/include/abb_libegm/egm_udp_server.h b/include/abb_libegm/egm_udp_server.h index e4c87fc..c926230 100644 --- a/include/abb_libegm/egm_udp_server.h +++ b/include/abb_libegm/egm_udp_server.h @@ -115,6 +115,21 @@ class UDPServer unsigned short port_number, AbstractUDPServerInterface& interface); + + /** + * \brief Start UDP server on a specified address and port. + * + * \param io_service for operating boost asio's asynchronous functions. + * \param server_endpoint server's UDP endpoint. + * \param interface UDP server that processes the received messages. + * + * \throw \a std::exception if an error occurs. + */ + UDPServer(boost::asio::io_service& io_service, + boost::asio::ip::udp::endpoint const& server_endpoint, + AbstractUDPServerInterface& interface); + + /** * \brief A destructor. */ diff --git a/src/egm_udp_server.cpp b/src/egm_udp_server.cpp index 918c453..1f74666 100644 --- a/src/egm_udp_server.cpp +++ b/src/egm_udp_server.cpp @@ -49,13 +49,22 @@ namespace egm UDPServer::UDPServer(boost::asio::io_service& io_service, unsigned short port_number, AbstractUDPServerInterface& interface) -: socket_ {io_service, boost::asio::ip::udp::endpoint {boost::asio::ip::udp::v4(), port_number}} +: UDPServer {io_service, boost::asio::ip::udp::endpoint {boost::asio::ip::udp::v4(), port_number}, interface} +{ +} + + +UDPServer::UDPServer(boost::asio::io_service& io_service, + boost::asio::ip::udp::endpoint const& server_endpoint, + AbstractUDPServerInterface& interface) +: socket_ {io_service, server_endpoint} , interface_ {interface} { - server_data_.port_number = port_number; + server_data_.port_number = server_endpoint.port(); startAsynchronousReceive(); } + UDPServer::~UDPServer() { socket_.close();