mirror of
				https://github.com/gnss-sdr/gnss-sdr
				synced 2025-10-30 23:03:05 +00:00 
			
		
		
		
	Improve error handling of UDP connections
This commit is contained in:
		| @@ -14,6 +14,10 @@ All notable changes to GNSS-SDR will be documented in this file. | ||||
|  | ||||
| ## [Unreleased](https://github.com/gnss-sdr/gnss-sdr/tree/next) | ||||
|  | ||||
| ### Improvements in Interoperability: | ||||
|  | ||||
| - Improved error handling in UDP connections. | ||||
|  | ||||
| ### Improvements in Portability: | ||||
|  | ||||
| - Fix building against google-glog 0.7.0. | ||||
|   | ||||
| @@ -55,22 +55,24 @@ bool Monitor_Ephemeris_Udp_Sink::write_galileo_ephemeris(const std::shared_ptr<G | ||||
|             outbound_data.append(serdes_gal.createProtobuffer(monitor_gal_eph)); | ||||
|         } | ||||
|  | ||||
|     for (const auto& endpoint : endpoints) | ||||
|         { | ||||
|             socket.open(endpoint.protocol(), error); | ||||
|  | ||||
|     try | ||||
|         { | ||||
|                     if (socket.send_to(boost::asio::buffer(outbound_data), endpoint) == 0) | ||||
|             for (const auto& endpoint : endpoints) | ||||
|                 { | ||||
|                     socket.open(endpoint.protocol(), error);  // NOLINT(bugprone-unused-return-value) | ||||
|  | ||||
|                     if (socket.send_to(boost::asio::buffer(outbound_data), endpoint) == 0)  // this can throw | ||||
|                         { | ||||
|                             return false; | ||||
|                         } | ||||
|                 } | ||||
|             catch (boost::system::system_error const& e) | ||||
|         } | ||||
|     catch (const boost::system::system_error& e) | ||||
|         { | ||||
|             std::cerr << "Error sending Galileo ephemeris: " << e.what() << '\n'; | ||||
|             return false; | ||||
|         } | ||||
|         } | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| @@ -91,21 +93,23 @@ bool Monitor_Ephemeris_Udp_Sink::write_gps_ephemeris(const std::shared_ptr<Gps_E | ||||
|             outbound_data.append(serdes_gps.createProtobuffer(monitor_gps_eph)); | ||||
|         } | ||||
|  | ||||
|     for (const auto& endpoint : endpoints) | ||||
|         { | ||||
|             socket.open(endpoint.protocol(), error); | ||||
|  | ||||
|     try | ||||
|         { | ||||
|                     if (socket.send_to(boost::asio::buffer(outbound_data), endpoint) == 0) | ||||
|             for (const auto& endpoint : endpoints) | ||||
|                 { | ||||
|                     socket.open(endpoint.protocol(), error);  // NOLINT(bugprone-unused-return-value) | ||||
|  | ||||
|                     if (socket.send_to(boost::asio::buffer(outbound_data), endpoint) == 0)  // this can throw | ||||
|                         { | ||||
|                             return false; | ||||
|                         } | ||||
|                 } | ||||
|             catch (boost::system::system_error const& e) | ||||
|         } | ||||
|     catch (const boost::system::system_error& e) | ||||
|         { | ||||
|             std::cerr << "Error sending GPS ephemeris: " << e.what() << '\n'; | ||||
|             return false; | ||||
|         } | ||||
|         } | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|   | ||||
| @@ -54,21 +54,23 @@ bool Monitor_Pvt_Udp_Sink::write_monitor_pvt(const Monitor_Pvt* const monitor_pv | ||||
|             outbound_data = serdes.createProtobuffer(monitor_pvt); | ||||
|         } | ||||
|  | ||||
|     for (const auto& endpoint : endpoints) | ||||
|         { | ||||
|             socket.open(endpoint.protocol(), error); | ||||
|  | ||||
|     try | ||||
|         { | ||||
|                     if (socket.send_to(boost::asio::buffer(outbound_data), endpoint) == 0) | ||||
|             for (const auto& endpoint : endpoints) | ||||
|                 { | ||||
|                     socket.open(endpoint.protocol(), error);  // NOLINT(bugprone-unused-return-value) | ||||
|  | ||||
|                     if (socket.send_to(boost::asio::buffer(outbound_data), endpoint) == 0)  // this can throw | ||||
|                         { | ||||
|                             return false; | ||||
|                         } | ||||
|                 } | ||||
|         } | ||||
|     catch (boost::system::system_error const& e) | ||||
|         { | ||||
|             std::cerr << "Error sending PVT data: " << e.what() << '\n'; | ||||
|             return false; | ||||
|         } | ||||
|         } | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|   | ||||
| @@ -78,20 +78,20 @@ rtl_tcp_signal_source_c::rtl_tcp_signal_source_c(const std::string &address, | ||||
|             return; | ||||
|         } | ||||
|     ip::tcp::endpoint ep(addr, port); | ||||
|     socket_.open(ep.protocol(), ec); | ||||
|     socket_.open(ep.protocol(), ec);  // NOLINT(bugprone-unused-return-value) | ||||
|     if (ec) | ||||
|         { | ||||
|             std::cout << "Failed to open socket.\n"; | ||||
|             LOG(ERROR) << "Failed to open socket."; | ||||
|         } | ||||
|  | ||||
|     socket_.set_option(boost::asio::socket_base::reuse_address(true), ec); | ||||
|     socket_.set_option(boost::asio::socket_base::reuse_address(true), ec);  // NOLINT(bugprone-unused-return-value) | ||||
|     if (ec) | ||||
|         { | ||||
|             std::cout << "Failed to set reuse address option: " << ec << '\n'; | ||||
|             LOG(WARNING) << "Failed to set reuse address option"; | ||||
|         } | ||||
|     socket_.set_option(boost::asio::socket_base::linger(true, 0), ec); | ||||
|     socket_.set_option(boost::asio::socket_base::linger(true, 0), ec);  // NOLINT(bugprone-unused-return-value) | ||||
|     if (ec) | ||||
|         { | ||||
|             std::cout << "Failed to set linger option: " << ec << '\n'; | ||||
| @@ -99,8 +99,7 @@ rtl_tcp_signal_source_c::rtl_tcp_signal_source_c(const std::string &address, | ||||
|         } | ||||
|  | ||||
|     // 3. Connect socket | ||||
|  | ||||
|     socket_.connect(ep, ec); | ||||
|     socket_.connect(ep, ec);  // NOLINT(bugprone-unused-return-value) | ||||
|     if (ec) | ||||
|         { | ||||
|             std::cout << "Failed to connect to " << addr << ":" << port | ||||
| @@ -113,7 +112,7 @@ rtl_tcp_signal_source_c::rtl_tcp_signal_source_c(const std::string &address, | ||||
|     LOG(INFO) << "Connected to " << addr << ":" << port; | ||||
|  | ||||
|     // 4. Set nodelay | ||||
|     socket_.set_option(ip::tcp::no_delay(true), ec); | ||||
|     socket_.set_option(ip::tcp::no_delay(true), ec);  // NOLINT(bugprone-unused-return-value) | ||||
|     if (ec) | ||||
|         { | ||||
|             std::cout << "Failed to set no delay option.\n"; | ||||
|   | ||||
| @@ -18,9 +18,15 @@ | ||||
| #include "nav_message_udp_sink.h" | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #if USE_GLOG_AND_GFLAGS | ||||
| #include <glog/logging.h> | ||||
| #else | ||||
| #include <absl/log/log.h> | ||||
| #endif | ||||
|  | ||||
|  | ||||
| Nav_Message_Udp_Sink::Nav_Message_Udp_Sink(const std::vector<std::string>& addresses, const uint16_t& port) : socket{io_context} | ||||
| Nav_Message_Udp_Sink::Nav_Message_Udp_Sink(const std::vector<std::string>& addresses, const uint16_t& port) | ||||
|     : socket{io_context} | ||||
| { | ||||
|     for (const auto& address : addresses) | ||||
|         { | ||||
| @@ -35,22 +41,30 @@ bool Nav_Message_Udp_Sink::write_nav_message(const std::shared_ptr<Nav_Message_P | ||||
| { | ||||
|     std::string outbound_data = serdes_nav.createProtobuffer(nav_meg_packet); | ||||
|  | ||||
|     for (const auto& endpoint : endpoints) | ||||
|         { | ||||
|             socket.open(endpoint.protocol(), error); | ||||
|             socket.connect(endpoint, error); | ||||
|  | ||||
|     try | ||||
|         { | ||||
|                     if (socket.send(boost::asio::buffer(outbound_data)) == 0) | ||||
|             for (const auto& endpoint : endpoints) | ||||
|                 { | ||||
|                     socket.open(endpoint.protocol(), error);  // NOLINT(bugprone-unused-return-value) | ||||
|                     socket.connect(endpoint, error);          // NOLINT(bugprone-unused-return-value) | ||||
|                     if (error) | ||||
|                         { | ||||
|                             LOG(WARNING) << "Error connecting to IP address " << endpoint.address() | ||||
|                                          << ", port " << static_cast<int>(endpoint.port()) << ": " << error.message(); | ||||
|                             return false; | ||||
|                         } | ||||
|  | ||||
|                     if (socket.send(boost::asio::buffer(outbound_data)) == 0)  // this can throw | ||||
|                         { | ||||
|                             return false; | ||||
|                         } | ||||
|                 } | ||||
|             catch (boost::system::system_error const& e) | ||||
|         } | ||||
|     catch (const boost::system::system_error& e) | ||||
|         { | ||||
|             std::cerr << "Error sending navigation data: " << e.what() << '\n'; | ||||
|             return false; | ||||
|         } | ||||
|         } | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|   | ||||
| @@ -53,22 +53,24 @@ bool Gnss_Synchro_Udp_Sink::write_gnss_synchro(const std::vector<Gnss_Synchro>& | ||||
|         { | ||||
|             outbound_data = serdes.createProtobuffer(stocks); | ||||
|         } | ||||
|     for (const auto& endpoint : endpoints) | ||||
|         { | ||||
|             socket.open(endpoint.protocol(), error); | ||||
|  | ||||
|     try | ||||
|         { | ||||
|                     if (socket.send_to(boost::asio::buffer(outbound_data), endpoint) == 0) | ||||
|             for (const auto& endpoint : endpoints) | ||||
|                 { | ||||
|                             std::cerr << "Gnss_Synchro_Udp_Sink sent 0 bytes\n"; | ||||
|                         } | ||||
|                 } | ||||
|             catch (boost::system::system_error const& e) | ||||
|                     socket.open(endpoint.protocol(), error);  // NOLINT(bugprone-unused-return-value) | ||||
|  | ||||
|                     if (socket.send_to(boost::asio::buffer(outbound_data), endpoint) == 0)  // this can throw | ||||
|                         { | ||||
|                     std::cerr << e.what() << '\n'; | ||||
|                             return false; | ||||
|                         } | ||||
|                 } | ||||
|         } | ||||
|     catch (const boost::system::system_error& e) | ||||
|         { | ||||
|             std::cerr << "Error sending data: " << e.what() << '\n'; | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|   | ||||
| @@ -323,10 +323,10 @@ void TcpCmdInterface::run_cmd_server(int tcp_port) | ||||
|                             std::cout << "TcpCmdInterface: Telecommand TCP interface listening on port " << tcp_port << '\n'; | ||||
|  | ||||
|                             boost::asio::ip::tcp::socket socket(context); | ||||
|                             acceptor.accept(socket, not_throw); | ||||
|                             acceptor.accept(socket, not_throw);  // NOLINT(bugprone-unused-return-value) | ||||
|                             if (not_throw) | ||||
|                                 { | ||||
|                                     std::cerr << "TcpCmdInterface: Error when binding the port in the socket\n"; | ||||
|                                     std::cerr << "TcpCmdInterface: Error when binding the port to the socket: " << not_throw.message() << '\n'; | ||||
|                                     continue; | ||||
|                                 } | ||||
|  | ||||
|   | ||||
| @@ -31,6 +31,7 @@ int main(int argc, char *argv[]) | ||||
|  | ||||
|             unsigned short port = boost::lexical_cast<unsigned short>(argv[1]); | ||||
|             Nav_Msg_Udp_Listener udp_listener(port); | ||||
|             std::cout << "Listening on port " << static_cast<int>(port) << ", press Control+C to exit ...\n"; | ||||
|  | ||||
|             while (true) | ||||
|                 { | ||||
| @@ -45,9 +46,15 @@ int main(int argc, char *argv[]) | ||||
|                         } | ||||
|                 } | ||||
|         } | ||||
|     catch (boost::bad_lexical_cast &) | ||||
|         { | ||||
|             std::cerr << "Error: the argument " << argv[1] << " is not a valid port number.\n"; | ||||
|             return 1; | ||||
|         } | ||||
|     catch (std::exception &e) | ||||
|         { | ||||
|             std::cerr << e.what() << '\n'; | ||||
|             return 1; | ||||
|         } | ||||
|  | ||||
|     return 0; | ||||
|   | ||||
| @@ -19,18 +19,33 @@ | ||||
| #include <string> | ||||
|  | ||||
| Nav_Msg_Udp_Listener::Nav_Msg_Udp_Listener(unsigned short port) | ||||
|     : socket{io_service}, endpoint{boost::asio::ip::udp::v4(), port} | ||||
|     : socket{io_service}, endpoint{boost::asio::ip::udp::v4(), port}, connected_socket(true) | ||||
| { | ||||
|     socket.open(endpoint.protocol(), error);  // Open socket | ||||
|     if (error) | ||||
|         { | ||||
|             std::cerr << "Error opening socket: " << error.message() << '\n'; | ||||
|             connected_socket = false; | ||||
|         } | ||||
|     if (connected_socket) | ||||
|         { | ||||
|     socket.open(endpoint.protocol(), error);  // Open socket. | ||||
|             socket.bind(endpoint, error);  // Bind the socket to the given local endpoint. | ||||
|             if (error) | ||||
|                 { | ||||
|                     std::cerr << "Error binding socket: " << error.message() << '\n'; | ||||
|                     connected_socket = false; | ||||
|                 } | ||||
|         } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * !\brief blocking call to read nav_message from UDP port | ||||
|  * \param[out] message navigation message class to contain parsed output | ||||
|  * \return true if message parsed succesfully, false ow | ||||
|  | ||||
| /* | ||||
|  * Blocking call to read nav_message from UDP port | ||||
|  * return true if message parsed succesfully, false ow | ||||
|  */ | ||||
| bool Nav_Msg_Udp_Listener::receive_and_parse_nav_message(gnss_sdr::navMsg &message) | ||||
| { | ||||
|     if (connected_socket) | ||||
|         { | ||||
|             char buff[8192];  // Buffer for storing the received data. | ||||
|  | ||||
| @@ -41,12 +56,17 @@ bool Nav_Msg_Udp_Listener::receive_and_parse_nav_message(gnss_sdr::navMsg &messa | ||||
|             // Deserialize a stock of Nav_Msg objects from the binary string. | ||||
|             return message.ParseFromString(data); | ||||
|         } | ||||
|     return false; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * !\brief prints navigation message content | ||||
|  * \param[in] message nav message to be printed | ||||
|  * Prints navigation message content | ||||
|  * param[in] message nav message to be printed | ||||
|  */ | ||||
| void Nav_Msg_Udp_Listener::print_message(gnss_sdr::navMsg &message) const | ||||
| { | ||||
|     if (connected_socket) | ||||
|         { | ||||
|             std::string system = message.system(); | ||||
|             std::string signal = message.signal(); | ||||
| @@ -54,7 +74,7 @@ void Nav_Msg_Udp_Listener::print_message(gnss_sdr::navMsg &message) const | ||||
|             int tow_at_current_symbol_ms = message.tow_at_current_symbol_ms(); | ||||
|             std::string nav_message = message.nav_message(); | ||||
|  | ||||
|     std::cout << "\nNew Data received:\n"; | ||||
|             std::cout << "\nNew data received:\n"; | ||||
|             std::cout << "System: " << system << '\n'; | ||||
|             std::cout << "Signal: " << signal << '\n'; | ||||
|             std::cout << "PRN: " << prn << '\n'; | ||||
| @@ -62,3 +82,4 @@ void Nav_Msg_Udp_Listener::print_message(gnss_sdr::navMsg &message) const | ||||
|                       << tow_at_current_symbol_ms << '\n'; | ||||
|             std::cout << "Nav message: " << nav_message << "\n\n"; | ||||
|         } | ||||
| } | ||||
|   | ||||
| @@ -31,6 +31,7 @@ private: | ||||
|     boost::asio::ip::udp::socket socket; | ||||
|     boost::system::error_code error; | ||||
|     boost::asio::ip::udp::endpoint endpoint; | ||||
|     bool connected_socket; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Carles Fernandez
					Carles Fernandez