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.
This commit is contained in:
Sergey Popov 2012-10-04 02:23:15 +00:00
parent 98a9b7ad9d
commit 136f42bd4f
5 changed files with 44 additions and 6 deletions

View File

@ -36,6 +36,7 @@
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/iostreams/filter/gzip.hpp> #include <boost/iostreams/filter/gzip.hpp>
#include <boost/exception/get_error_info.hpp>
// the fork execute is unix specific only tested on Linux quite sure it won't // 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. // 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"; LOG_CS << "client disconnect: " << e.message << " " << network::ip_address(e.socket) << "\n";
e.disconnect(); e.disconnect();
} }
} catch(config::error& /*e*/) { } catch(const config::error& e) {
LOG_CS << "error in receiving data...\n"; network::connection err_sock = 0;
network::disconnect(sock); network::connection const * err_connection = boost::get_error_info<network::connection_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); SDL_Delay(20);

View File

@ -35,6 +35,7 @@
#include <iosfwd> #include <iosfwd>
#include <vector> #include <vector>
#include <boost/variant/variant.hpp> #include <boost/variant/variant.hpp>
#include <boost/exception/exception.hpp>
#include "game_errors.hpp" #include "game_errors.hpp"
#include "tstring.hpp" #include "tstring.hpp"
@ -397,7 +398,7 @@ public:
std::string debug() const; std::string debug() const;
std::string hash() 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) {} error(const std::string& message) : game::error(message) {}
}; };

View File

@ -38,6 +38,9 @@
#include <cstring> #include <cstring>
#include <stdexcept> #include <stdexcept>
#include <boost/exception/get_error_info.hpp>
#include <boost/exception/info.hpp>
#include <signal.h> #include <signal.h>
#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
#undef INADDR_ANY #undef INADDR_ANY
@ -795,7 +798,23 @@ connection receive_data(config& cfg, connection connection_num, bandwidth_in_ptr
{ {
bandwidth_in = &temp; 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<tcpsocket_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 (sock == NULL) {
if (!is_server() && last_ping != 0 && ping_timeout != 0) if (!is_server() && last_ping != 0 && ping_timeout != 0)
{ {

View File

@ -30,6 +30,7 @@ class config;
#include <vector> #include <vector>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/exception/error_info.hpp>
namespace threading namespace threading
{ {
@ -267,6 +268,9 @@ struct error : public game::error
void disconnect(); void disconnect();
}; };
typedef boost::error_info<struct tag_tcpsocket,TCPsocket> tcpsocket_info;
typedef boost::error_info<struct tag_connum,connection> connection_info;
struct statistics struct statistics
{ {
statistics() : total(0), current(0), current_max(0) {} statistics() : total(0), current(0), current_max(0) {}

View File

@ -34,6 +34,7 @@
#include "wesconfig.h" #include "wesconfig.h"
#include <boost/iostreams/filter/gzip.hpp> #include <boost/iostreams/filter/gzip.hpp>
#include <boost/exception/info.hpp>
#include <cerrno> #include <cerrno>
#include <deque> #include <deque>
@ -918,9 +919,10 @@ TCPsocket get_received_data(TCPsocket sock, config& cfg, network::bandwidth_in_p
// throw the error in parent thread // throw the error in parent thread
std::string error = (*itor)->config_error; std::string error = (*itor)->config_error;
buffer* buf = *itor; buffer* buf = *itor;
TCPsocket err_sock = (*itor)->sock;
received_data_queue.erase(itor); received_data_queue.erase(itor);
delete buf; delete buf;
throw config::error(error); throw config::error(error) << network::tcpsocket_info(err_sock);
} else { } else {
cfg.swap((*itor)->config_buf); cfg.swap((*itor)->config_buf);
const TCPsocket res = (*itor)->sock; const TCPsocket res = (*itor)->sock;