From 136f42bd4f264c0e933af9fcf6860d2a0a69bdb7 Mon Sep 17 00:00:00 2001 From: Sergey Popov Date: Thu, 4 Oct 2012 02:23:15 +0000 Subject: [PATCH] Fix bug #20205 Malformed data caused config::error exception to be thrown. Unfortunately campaignd on catching such an exception had no way to close the right connection, instead all connections were closed because the local variable that was supposed to contain connection number wasn't updated. This is fixed by using boost.exception to attach the necessary data to config::error objects so it can be used at the catch site. --- src/campaign_server/campaign_server.cpp | 18 +++++++++++++++--- src/config.hpp | 3 ++- src/network.cpp | 21 ++++++++++++++++++++- src/network.hpp | 4 ++++ src/network_worker.cpp | 4 +++- 5 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/campaign_server/campaign_server.cpp b/src/campaign_server/campaign_server.cpp index 25f73965962..446fdac08c9 100644 --- a/src/campaign_server/campaign_server.cpp +++ b/src/campaign_server/campaign_server.cpp @@ -36,6 +36,7 @@ #include #include +#include // the fork execute is unix specific only tested on Linux quite sure it won't // work on Windows not sure which other platforms have a problem with it. @@ -571,9 +572,20 @@ namespace { LOG_CS << "client disconnect: " << e.message << " " << network::ip_address(e.socket) << "\n"; e.disconnect(); } - } catch(config::error& /*e*/) { - LOG_CS << "error in receiving data...\n"; - network::disconnect(sock); + } catch(const config::error& e) { + network::connection err_sock = 0; + network::connection const * err_connection = boost::get_error_info(e); + if(err_connection != NULL) { + err_sock = *err_connection; + } + if(err_sock == 0 && sock > 0) + err_sock = sock; + if(err_sock) { + LOG_CS << "client disconnect due to exception: " << e.what() << " " << network::ip_address(*err_connection) << "\n"; + network::disconnect(*err_connection); + } else { + throw; + } } SDL_Delay(20); diff --git a/src/config.hpp b/src/config.hpp index ed6384fd670..31657419ef1 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -35,6 +35,7 @@ #include #include #include +#include #include "game_errors.hpp" #include "tstring.hpp" @@ -397,7 +398,7 @@ public: std::string debug() const; std::string hash() const; - struct error : public game::error { + struct error : public game::error, public boost::exception { error(const std::string& message) : game::error(message) {} }; diff --git a/src/network.cpp b/src/network.cpp index f87111832c2..a9a4fdd5e41 100644 --- a/src/network.cpp +++ b/src/network.cpp @@ -38,6 +38,9 @@ #include #include +#include +#include + #include #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) #undef INADDR_ANY @@ -795,7 +798,23 @@ connection receive_data(config& cfg, connection connection_num, bandwidth_in_ptr { bandwidth_in = &temp; } - sock = network_worker_pool::get_received_data(sock,cfg, *bandwidth_in); + try { + sock = network_worker_pool::get_received_data(sock,cfg, *bandwidth_in); + } catch(const config::error& e) { + TCPsocket const * err_sock = boost::get_error_info(e); + if(err_sock == NULL) + throw; + connection err_connection = 0; + for(connection_map::const_iterator i = connections.begin(); i != connections.end(); ++i) { + if(i->second.sock == *err_sock) { + err_connection = i->first; + } + } + if(err_connection) { + throw e << connection_info(err_connection); + } + throw; + } if (sock == NULL) { if (!is_server() && last_ping != 0 && ping_timeout != 0) { diff --git a/src/network.hpp b/src/network.hpp index ef2e2b116f5..27dd7f842a4 100644 --- a/src/network.hpp +++ b/src/network.hpp @@ -30,6 +30,7 @@ class config; #include #include +#include namespace threading { @@ -267,6 +268,9 @@ struct error : public game::error void disconnect(); }; +typedef boost::error_info tcpsocket_info; +typedef boost::error_info connection_info; + struct statistics { statistics() : total(0), current(0), current_max(0) {} diff --git a/src/network_worker.cpp b/src/network_worker.cpp index d382f0447cf..360af5a87bd 100644 --- a/src/network_worker.cpp +++ b/src/network_worker.cpp @@ -34,6 +34,7 @@ #include "wesconfig.h" #include +#include #include #include @@ -918,9 +919,10 @@ TCPsocket get_received_data(TCPsocket sock, config& cfg, network::bandwidth_in_p // throw the error in parent thread std::string error = (*itor)->config_error; buffer* buf = *itor; + TCPsocket err_sock = (*itor)->sock; received_data_queue.erase(itor); delete buf; - throw config::error(error); + throw config::error(error) << network::tcpsocket_info(err_sock); } else { cfg.swap((*itor)->config_buf); const TCPsocket res = (*itor)->sock;