improved simple_wml error exception handling and error logging
This commit is contained in:
parent
da6efafc48
commit
31fa18d219
3 changed files with 74 additions and 61 deletions
|
@ -35,6 +35,8 @@ static lg::log_domain log_server("server");
|
|||
#define WRN_GAME LOG_STREAM(warn, log_server)
|
||||
#define LOG_GAME LOG_STREAM(info, log_server)
|
||||
#define DBG_GAME LOG_STREAM(debug, log_server)
|
||||
static lg::log_domain log_config("config");
|
||||
#define WRN_CONFIG LOG_STREAM(warn, log_config)
|
||||
|
||||
namespace wesnothd {
|
||||
int game::id_num = 1;
|
||||
|
@ -79,18 +81,13 @@ game::game(player_map& players, const network::connection host,
|
|||
|
||||
game::~game()
|
||||
{
|
||||
try {
|
||||
save_replay();
|
||||
save_replay();
|
||||
|
||||
user_vector users = all_game_users();
|
||||
for (user_vector::const_iterator u = users.begin(); u != users.end(); ++u) {
|
||||
remove_player(*u, false, true);
|
||||
}
|
||||
clear_history();
|
||||
} catch (...) {
|
||||
LOG_GAME << "Caught unknown error while destructing game:\t\""
|
||||
<< name_ << "\" (" << id_ << ")\n";
|
||||
user_vector users = all_game_users();
|
||||
for (user_vector::const_iterator u = users.begin(); u != users.end(); ++u) {
|
||||
remove_player(*u, false, true);
|
||||
}
|
||||
clear_history();
|
||||
}
|
||||
|
||||
bool game::allow_observers() const {
|
||||
|
@ -1213,12 +1210,17 @@ void game::send_history(const network::connection sock) const
|
|||
delete *i;
|
||||
}
|
||||
|
||||
simple_wml::document* doc = new simple_wml::document(buf.c_str(), simple_wml::INIT_STATIC);
|
||||
const simple_wml::string_span& data = doc->output_compressed();
|
||||
doc->compress();
|
||||
network::send_raw_data(data.begin(), data.size(), sock,"game_history");
|
||||
history_.clear();
|
||||
history_.push_back(doc);
|
||||
try {
|
||||
simple_wml::document* doc = new simple_wml::document(buf.c_str(), simple_wml::INIT_STATIC);
|
||||
const simple_wml::string_span& data = doc->output_compressed();
|
||||
doc->compress();
|
||||
network::send_raw_data(data.begin(), data.size(), sock,"game_history");
|
||||
history_.clear();
|
||||
history_.push_back(doc);
|
||||
} catch (simple_wml::error& e) {
|
||||
WRN_CONFIG << "simple_wml error: " << e.message << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static bool is_invalid_filename_char(char c) {
|
||||
|
@ -1260,16 +1262,21 @@ void game::save_replay() {
|
|||
name << " (" << id_ << ").gz";
|
||||
|
||||
std::string replay_data_str = replay_data.str();
|
||||
simple_wml::document replay(replay_data_str.c_str(), simple_wml::INIT_STATIC);
|
||||
try {
|
||||
simple_wml::document replay(replay_data_str.c_str(), simple_wml::INIT_STATIC);
|
||||
|
||||
std::string filename(name.str());
|
||||
std::replace(filename.begin(), filename.end(), ' ', '_');
|
||||
filename.erase(std::remove_if(filename.begin(), filename.end(), is_invalid_filename_char), filename.end());
|
||||
DBG_GAME << "saving replay: " << filename << std::endl;
|
||||
scoped_ostream os(ostream_file(replay_save_path_ + filename));
|
||||
(*os) << replay.output_compressed();
|
||||
if (!os->good()) {
|
||||
LOG_GAME << "Could not save replay! (" << filename << ")\n";
|
||||
std::string filename(name.str());
|
||||
std::replace(filename.begin(), filename.end(), ' ', '_');
|
||||
filename.erase(std::remove_if(filename.begin(), filename.end(), is_invalid_filename_char), filename.end());
|
||||
DBG_GAME << "saving replay: " << filename << std::endl;
|
||||
scoped_ostream os(ostream_file(replay_save_path_ + filename));
|
||||
(*os) << replay.output_compressed();
|
||||
|
||||
if (!os->good()) {
|
||||
ERR_GAME << "Could not save replay! (" << filename << ")\n";
|
||||
}
|
||||
} catch (simple_wml::error& e) {
|
||||
WRN_CONFIG << "simple_wml error: " << e.message << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -685,7 +685,7 @@ void server::run() {
|
|||
metrics_.service_request();
|
||||
|
||||
if(buf.empty()) {
|
||||
std::cerr << "received empty packet\n";
|
||||
WRN_SERVER << "received empty packet\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -702,6 +702,7 @@ void server::run() {
|
|||
data_ptr->take_ownership_of_buffer(buf_ptr);
|
||||
|
||||
} catch (simple_wml::error& e) {
|
||||
WRN_CONFIG << "simple_wml error in received data: " << e.message << std::endl;
|
||||
send_error(sock, ("Invalid WML received: " + e.message).c_str());
|
||||
delete [] buf_ptr;
|
||||
continue;
|
||||
|
@ -729,8 +730,6 @@ void server::run() {
|
|||
|
||||
metrics_.no_requests();
|
||||
|
||||
} catch(config::error& e) {
|
||||
WRN_CONFIG << "Warning: error in received data: " << e.message << "\n";
|
||||
} catch(simple_wml::error& e) {
|
||||
WRN_CONFIG << "Warning: error in received data: " << e.message << "\n";
|
||||
} catch(network::error& e) {
|
||||
|
@ -1187,7 +1186,7 @@ void server::process_query(const network::connection sock,
|
|||
<< "\tIP: "<< network::ip_address(sock)
|
||||
<< "\tnick: "<< pl->second.name() << std::endl;
|
||||
response << process_command(command.to_string(), pl->second.name());
|
||||
LOG_SERVER << response.str();
|
||||
LOG_SERVER << response.str() << std::endl;
|
||||
}
|
||||
} else if (command == "help" || command.empty()) {
|
||||
response << help_msg;
|
||||
|
@ -2081,8 +2080,8 @@ void server::process_data_game(const network::connection sock,
|
|||
return;
|
||||
// Everything below should only be processed if the game is already intialized.
|
||||
} else if (!g->level_init()) {
|
||||
WRN_SERVER << "Received unknown data from: " << pl->second.name()
|
||||
<< " (socket:" << sock
|
||||
WRN_SERVER << network::ip_address(sock) << "\tReceived unknown data from: "
|
||||
<< pl->second.name() << " (socket:" << sock
|
||||
<< ") while the scenario wasn't yet initialized.\n" << data.output();
|
||||
return;
|
||||
// If the host is sending the next scenario data.
|
||||
|
@ -2306,8 +2305,9 @@ void server::process_data_game(const network::connection sock,
|
|||
return;
|
||||
}
|
||||
|
||||
WRN_SERVER << "Received unknown data from: " << pl->second.name()
|
||||
<< ". (socket:" << sock << ")\n" << data.output();
|
||||
WRN_SERVER << network::ip_address(sock) << "\tReceived unknown data from: "
|
||||
<< pl->second.name() << " (socket:" << sock << ") in game: \""
|
||||
<< g->name() << "\" (" << g->id() << ")\n" << data.output();
|
||||
}
|
||||
|
||||
void server::delete_game(std::vector<wesnothd::game*>::iterator game_it) {
|
||||
|
|
|
@ -6,6 +6,11 @@
|
|||
|
||||
#include "simple_wml.hpp"
|
||||
|
||||
#include "../log.hpp"
|
||||
|
||||
static lg::log_domain log_config("config");
|
||||
#define ERR_SWML LOG_STREAM(err, log_config)
|
||||
|
||||
namespace simple_wml {
|
||||
|
||||
namespace {
|
||||
|
@ -54,33 +59,33 @@ char* uncompress_buffer(const string_span& input, string_span* span)
|
|||
|
||||
char* compress_buffer(const char* input, string_span* span)
|
||||
{
|
||||
std::string in(input);
|
||||
std::istringstream stream(in);
|
||||
boost::iostreams::filtering_stream<boost::iostreams::input> filter;
|
||||
filter.push(boost::iostreams::gzip_compressor());
|
||||
filter.push(stream);
|
||||
|
||||
std::vector<char> buf(in.size()*2 + 80);
|
||||
const int len = filter.read(&buf[0], buf.size()).gcount();
|
||||
assert(len < 128*1024*1024);
|
||||
if((!filter.eof() && !filter.good()) || len == static_cast<int>(buf.size())) {
|
||||
throw error("failed to compress");
|
||||
}
|
||||
|
||||
buf.resize(len);
|
||||
|
||||
char* small_out;
|
||||
try {
|
||||
small_out = new char[len];
|
||||
std::string in(input);
|
||||
std::istringstream stream(in);
|
||||
boost::iostreams::filtering_stream<boost::iostreams::input> filter;
|
||||
filter.push(boost::iostreams::gzip_compressor());
|
||||
filter.push(stream);
|
||||
|
||||
std::vector<char> buf(in.size()*2 + 80);
|
||||
const int len = filter.read(&buf[0], buf.size()).gcount();
|
||||
assert(len < 128*1024*1024);
|
||||
if((!filter.eof() && !filter.good()) || len == static_cast<int>(buf.size())) {
|
||||
throw error("failed to compress");
|
||||
}
|
||||
|
||||
buf.resize(len);
|
||||
|
||||
char* small_out = new char[len];
|
||||
memcpy(small_out, &buf[0], len);
|
||||
|
||||
*span = string_span(small_out, len);
|
||||
assert(*small_out == 31);
|
||||
return small_out;
|
||||
} catch (std::bad_alloc& e) {
|
||||
std::cerr << "ERROR: Trying to allocate " << len << " bytes.";
|
||||
ERR_SWML << "ERROR: bad_alloc caught in compress_buffer() with input: '"
|
||||
<< *input << "' " << e.what() << std::endl;
|
||||
throw error("Bad allocation request in compress_buffer().");
|
||||
}
|
||||
|
||||
*span = string_span(small_out, len);
|
||||
assert(*small_out == 31);
|
||||
return small_out;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -122,7 +127,7 @@ char* string_span::duplicate() const
|
|||
error::error(const char* msg)
|
||||
: message(msg)
|
||||
{
|
||||
std::cerr << "ERROR: '" << msg << "'\n";
|
||||
ERR_SWML << "ERROR: '" << msg << "'\n";
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& o, const string_span& s)
|
||||
|
@ -201,7 +206,7 @@ node::node(document& doc, node* parent, const char** str, int depth) :
|
|||
default: {
|
||||
const char* end = strchr(s, '=');
|
||||
if(end == NULL) {
|
||||
std::cerr << "attribute: " << s << "\n";
|
||||
ERR_SWML << "attribute: " << s << "\n";
|
||||
throw error("could not find '=' after attribute");
|
||||
}
|
||||
|
||||
|
@ -215,7 +220,7 @@ node::node(document& doc, node* parent, const char** str, int depth) :
|
|||
}
|
||||
|
||||
if(*s != '"') {
|
||||
std::cerr << "no quotes for attribute '" << name << "'\n";
|
||||
ERR_SWML << "no quotes for attribute '" << name << "'\n";
|
||||
throw error("did not find quotes around attribute");
|
||||
}
|
||||
|
||||
|
@ -227,7 +232,7 @@ node::node(document& doc, node* parent, const char** str, int depth) :
|
|||
}
|
||||
|
||||
if(end == NULL) {
|
||||
std::cerr << "ATTR: '" << name << "' (((" << s << ")))\n";
|
||||
ERR_SWML << "ATTR: '" << name << "' (((" << s << ")))\n";
|
||||
throw error("did not find end of attribute");
|
||||
}
|
||||
|
||||
|
@ -250,7 +255,7 @@ node::node(document& doc, node* parent, const char** str, int depth) :
|
|||
|
||||
string_span value(s, end - s);
|
||||
if(attr_.empty() == false && !(attr_.back().first < name)) {
|
||||
std::cerr << "attributes: '" << attr_.back().first << "' < '" << name << "'\n";
|
||||
ERR_SWML << "attributes: '" << attr_.back().first << "' < '" << name << "'\n";
|
||||
throw error("attributes not in order");
|
||||
}
|
||||
|
||||
|
@ -956,7 +961,8 @@ const char* document::output()
|
|||
try {
|
||||
buf = new char[buf_size];
|
||||
} catch (std::bad_alloc& e) {
|
||||
std::cerr << "ERROR: Trying to allocate " << buf_size << " bytes.";
|
||||
ERR_SWML << "ERROR: Trying to allocate " << buf_size << " bytes. "
|
||||
<< e.what() << std::endl;
|
||||
throw error("Bad allocation request in output().");
|
||||
}
|
||||
buffers_.push_back(buf);
|
||||
|
|
Loading…
Add table
Reference in a new issue