don't check team names on serverside
http://gna.org/bugs/?23028 previously clients could add a "team_name" to specific packages which should only be redirect to sides in this team. But the serversided code which calculated in which team a side was had some bugs: 1) It did not correctly handle sides that were in multiple teams ([side] team_name="team1,team2"...) 2) The serversided data about teams was not updated when wml changed the teams, also the calculation which side was controlled by a human used posssibly oudated information. This commit moves this calculation to the sending client so that the clients now must specify a list of sides to which the package should be sended.
This commit is contained in:
parent
15698bbea6
commit
6aa3b3bc9a
7 changed files with 93 additions and 53 deletions
|
@ -2550,9 +2550,9 @@ void menu_handler::send_chat_message(const std::string& message, bool allies_onl
|
||||||
|
|
||||||
if(private_message) {
|
if(private_message) {
|
||||||
if (board().is_observer()) {
|
if (board().is_observer()) {
|
||||||
cfg["team_name"] = game_config::observer_team_name;
|
cfg["to_sides"] = game_config::observer_team_name;
|
||||||
} else {
|
} else {
|
||||||
cfg["team_name"] = teams()[gui_->viewing_team()].team_name();
|
cfg["to_sides"] = teams()[gui_->viewing_team()].allied_human_teams();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
static lg::log_domain log_server("server");
|
static lg::log_domain log_server("server");
|
||||||
#define ERR_GAME LOG_STREAM(err, log_server)
|
#define ERR_GAME LOG_STREAM(err, log_server)
|
||||||
|
@ -34,6 +35,38 @@ static lg::log_domain log_server("server");
|
||||||
static lg::log_domain log_config("config");
|
static lg::log_domain log_config("config");
|
||||||
#define WRN_CONFIG LOG_STREAM(warn, log_config)
|
#define WRN_CONFIG LOG_STREAM(warn, log_config)
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
struct split_conv_impl
|
||||||
|
{
|
||||||
|
void operator()(std::vector<int> res, const simple_wml::string_span& span)
|
||||||
|
{
|
||||||
|
if(!span.empty()) {
|
||||||
|
res.push_back(span.to_int());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template<typename TResult, typename TConvert>
|
||||||
|
std::vector<TResult> split(const simple_wml::string_span& val, TConvert conv, const char c = ',')
|
||||||
|
{
|
||||||
|
std::vector<TResult> res;
|
||||||
|
simple_wml::string_span::const_iterator i1 = val.begin();
|
||||||
|
simple_wml::string_span::const_iterator i2 = i1;
|
||||||
|
|
||||||
|
while (i2 != val.end()) {
|
||||||
|
if (*i2 == c) {
|
||||||
|
conv(res, simple_wml::string_span(i1, i2));
|
||||||
|
++i2;
|
||||||
|
i1 = i2;
|
||||||
|
} else {
|
||||||
|
++i2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
conv(res, simple_wml::string_span(i1, i2));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace wesnothd {
|
namespace wesnothd {
|
||||||
int game::id_num = 1;
|
int game::id_num = 1;
|
||||||
|
|
||||||
|
@ -898,7 +931,7 @@ bool game::process_turn(simple_wml::document& data, const player_map::const_iter
|
||||||
marked.push_back(index - marked.size());
|
marked.push_back(index - marked.size());
|
||||||
} else if ((**command).child("speak")) {
|
} else if ((**command).child("speak")) {
|
||||||
simple_wml::node& speak = *(**command).child("speak");
|
simple_wml::node& speak = *(**command).child("speak");
|
||||||
if (speak["team_name"] != "" || is_muted_observer(user->first)) {
|
if (speak["to_sides"] != "" || is_muted_observer(user->first)) {
|
||||||
DBG_GAME << "repackaging..." << std::endl;
|
DBG_GAME << "repackaging..." << std::endl;
|
||||||
repackage = true;
|
repackage = true;
|
||||||
}
|
}
|
||||||
|
@ -950,35 +983,25 @@ bool game::process_turn(simple_wml::document& data, const player_map::const_iter
|
||||||
record_data(mdata);
|
record_data(mdata);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const simple_wml::string_span& team_name = (*speak)["team_name"];
|
const simple_wml::string_span& to_sides = (*speak)["to_sides"];
|
||||||
// Anyone can send to the observer team.
|
// Anyone can send to the observer team.
|
||||||
if (team_name == game_config::observer_team_name.c_str()) {
|
if (is_muted_observer(user->first) && to_sides != game_config::observer_team_name.c_str()) {
|
||||||
// Don't send if the member is muted.
|
|
||||||
} else if (is_muted_observer(user->first)) {
|
|
||||||
send_server_message("You have been muted, others can't see your message!", user->first);
|
send_server_message("You have been muted, others can't see your message!", user->first);
|
||||||
continue;
|
continue;
|
||||||
// Don't send if the player addresses a different team.
|
|
||||||
} else if (!is_on_team(team_name, user->first)) {
|
|
||||||
std::ostringstream msg;
|
|
||||||
msg << "Removing illegal message from " << user->second.name() << " to " << std::string(team_name.begin(), team_name.end()) << ".";
|
|
||||||
const std::string& msg_str = msg.str();
|
|
||||||
LOG_GAME << msg_str << std::endl;
|
|
||||||
send_and_record_server_message(msg_str);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::auto_ptr<simple_wml::document> message(new simple_wml::document);
|
std::auto_ptr<simple_wml::document> message(new simple_wml::document);
|
||||||
simple_wml::node& turn = message->root().add_child("turn");
|
simple_wml::node& turn = message->root().add_child("turn");
|
||||||
simple_wml::node& command = turn.add_child("command");
|
simple_wml::node& command = turn.add_child("command");
|
||||||
speak->copy_into(command.add_child("speak"));
|
speak->copy_into(command.add_child("speak"));
|
||||||
if (team_name == "") {
|
if (to_sides == "") {
|
||||||
send_data(*message, user->first, "game message");
|
send_data(*message, user->first, "game message");
|
||||||
record_data(message.release());
|
record_data(message.release());
|
||||||
} else if (team_name == game_config::observer_team_name) {
|
} else if (to_sides == game_config::observer_team_name) {
|
||||||
wesnothd::send_to_many(*message, observers_, user->first, "game message");
|
wesnothd::send_to_many(*message, observers_, user->first, "game message");
|
||||||
record_data(message.release());
|
record_data(message.release());
|
||||||
} else {
|
} else {
|
||||||
send_data_team(*message, team_name, user->first, "game message");
|
send_data_sides(*message, to_sides, user->first, "game message");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return turn_ended;
|
return turn_ended;
|
||||||
|
@ -1041,23 +1064,22 @@ void game::process_whiteboard(simple_wml::document& data, const player_map::cons
|
||||||
|
|
||||||
simple_wml::node const& wb_node = *data.child("whiteboard");
|
simple_wml::node const& wb_node = *data.child("whiteboard");
|
||||||
|
|
||||||
// Ensure "side" and "team_name" attributes match with user
|
// Ensure "side" attribute match with user
|
||||||
simple_wml::string_span const& team_name = wb_node["team_name"];
|
simple_wml::string_span const& to_sides = wb_node["to_sides"];
|
||||||
size_t const side_index = wb_node["side"].to_int() - 1;
|
size_t const side_index = wb_node["side"].to_int() - 1;
|
||||||
if(!is_on_team(team_name, user->first)
|
if(side_index >= sides_.size()
|
||||||
|| side_index >= sides_.size()
|
|
||||||
|| sides_[side_index] != user->first)
|
|| sides_[side_index] != user->first)
|
||||||
{
|
{
|
||||||
std::ostringstream msg;
|
std::ostringstream msg;
|
||||||
msg << "Ignoring illegal whiteboard data, sent from user '" << user->second.name()
|
msg << "Ignoring illegal whiteboard data, sent from user '" << user->second.name()
|
||||||
<< "' to team '" << std::string(team_name.begin(), team_name.end()) << "'." << std::endl;
|
<< "' which had an invalid side '" << side_index + 1 << "' specified" << std::endl;
|
||||||
const std::string& msg_str = msg.str();
|
const std::string& msg_str = msg.str();
|
||||||
LOG_GAME << msg_str << std::endl;
|
LOG_GAME << msg_str << std::endl;
|
||||||
send_and_record_server_message(msg_str);
|
send_and_record_server_message(msg_str);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
send_data_team(data,team_name,user->first,"whiteboard");
|
send_data_sides(data, to_sides, user->first, "whiteboard");
|
||||||
}
|
}
|
||||||
|
|
||||||
void game::process_change_controller_wml(simple_wml::document& data, const player_map::const_iterator user)
|
void game::process_change_controller_wml(simple_wml::document& data, const player_map::const_iterator user)
|
||||||
|
@ -1105,7 +1127,7 @@ bool game::end_turn() {
|
||||||
if (description_ == NULL) {
|
if (description_ == NULL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
//FIXME: this "turn" attribute migth be outdated if teh number of turns was changed by wml.
|
||||||
description_->set_attr_dup("turn", describe_turns(current_turn(), level_["turns"]).c_str());
|
description_->set_attr_dup("turn", describe_turns(current_turn(), level_["turns"]).c_str());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -1355,49 +1377,42 @@ void game::send_data(simple_wml::document& data,
|
||||||
wesnothd::send_to_many(data, all_game_users(), exclude, packet_type);
|
wesnothd::send_to_many(data, all_game_users(), exclude, packet_type);
|
||||||
}
|
}
|
||||||
namespace {
|
namespace {
|
||||||
struct is_on_team_helper
|
struct controls_side_helper
|
||||||
{
|
{
|
||||||
const wesnothd::game& game_;
|
const wesnothd::game& game_;
|
||||||
const simple_wml::string_span& team_;
|
const std::vector<int>& sides_;
|
||||||
is_on_team_helper(const wesnothd::game& game, const simple_wml::string_span& team)
|
controls_side_helper(const wesnothd::game& game, const std::vector<int>& sides)
|
||||||
: game_(game)
|
: game_(game)
|
||||||
, team_(team)
|
, sides_(sides)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
bool operator ()(network::connection user) const
|
bool operator ()(network::connection user) const
|
||||||
{
|
{
|
||||||
return game_.is_on_team(team_, user);
|
return game_.controls_side(sides_, user);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
void game::send_data_team(simple_wml::document& data,
|
|
||||||
const simple_wml::string_span& team,
|
void game::send_data_sides(simple_wml::document& data,
|
||||||
|
const simple_wml::string_span& sides,
|
||||||
const network::connection exclude,
|
const network::connection exclude,
|
||||||
std::string packet_type) const
|
std::string packet_type) const
|
||||||
{
|
{
|
||||||
|
std::vector<int> sides_vec = ::split<int>(sides, ::split_conv_impl());
|
||||||
DBG_GAME << __func__ << "...\n";
|
DBG_GAME << __func__ << "...\n";
|
||||||
wesnothd::send_to_many(data, players_, is_on_team_helper(*this, team), exclude, packet_type);
|
wesnothd::send_to_many(data, players_, controls_side_helper(*this, sides_vec), exclude, packet_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool game::controls_side(const std::vector<int>& sides, const network::connection player) const
|
||||||
bool game::is_on_team(const simple_wml::string_span& team, const network::connection player) const {
|
{
|
||||||
const simple_wml::node::child_list& side_list = get_sides_list();
|
BOOST_FOREACH(int side, sides)
|
||||||
for (side_vector::const_iterator side = sides_.begin(); side != sides_.end(); ++side) {
|
{
|
||||||
if (*side != player) continue;
|
size_t side_index = side - 1;
|
||||||
for (simple_wml::node::child_list::const_iterator i = side_list.begin();
|
if(side_index < sides_.size() && sides_[side_index] == player) {
|
||||||
i != side_list.end(); ++i) {
|
|
||||||
if ((**i)["side"].to_int() != side - sides_.begin() + 1) continue;
|
|
||||||
if ((**i)["team_name"] != team) continue;
|
|
||||||
// Don't consider ai sides on a team.
|
|
||||||
if ((**i)["controller"] == "ai") continue;
|
|
||||||
if (side_controllers_[side - sides_.begin()] == "ai") continue;
|
|
||||||
DBG_GAME << "side: " << (**i)["side"].to_int() << " with team_name: " << (**i)["team_name"]
|
|
||||||
<< " belongs to player: " << player << std::endl;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -227,10 +227,9 @@ public:
|
||||||
|
|
||||||
void reset_last_synced_context_id() { last_synced_context_id_ = -1; }
|
void reset_last_synced_context_id() { last_synced_context_id_ = -1; }
|
||||||
/**
|
/**
|
||||||
* Function which returns true iff 'player' is on 'team'.
|
* Function which returns true iff 'player' controls any of the sides spcified in 'sides'.
|
||||||
* AI controlled sides are not considered on a team.
|
|
||||||
*/
|
*/
|
||||||
bool is_on_team(const simple_wml::string_span& team, const network::connection player) const;
|
bool controls_side(const std::vector<int>& sides, const network::connection player) const;
|
||||||
private:
|
private:
|
||||||
//forbidden operations
|
//forbidden operations
|
||||||
game(const game&);
|
game(const game&);
|
||||||
|
@ -268,7 +267,10 @@ private:
|
||||||
const std::string& controller = "");
|
const std::string& controller = "");
|
||||||
void transfer_ai_sides(const network::connection player);
|
void transfer_ai_sides(const network::connection player);
|
||||||
void send_leave_game(network::connection user) const;
|
void send_leave_game(network::connection user) const;
|
||||||
void send_data_team(simple_wml::document& data, const simple_wml::string_span& team,
|
/**
|
||||||
|
@param sides: a comma sperated list of side numbers to which the package should be sent,
|
||||||
|
*/
|
||||||
|
void send_data_sides(simple_wml::document& data, const simple_wml::string_span& sides,
|
||||||
const network::connection exclude=0, std::string packet_type = "") const;
|
const network::connection exclude=0, std::string packet_type = "") const;
|
||||||
void send_data_observers(simple_wml::document& data, const network::connection exclude=0, std::string packet_type = "") const;
|
void send_data_observers(simple_wml::document& data, const network::connection exclude=0, std::string packet_type = "") const;
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,12 @@ public:
|
||||||
{}
|
{}
|
||||||
string_span(const char* str) : str_(str), size_(strlen(str))
|
string_span(const char* str) : str_(str), size_(strlen(str))
|
||||||
{}
|
{}
|
||||||
|
string_span(const char* begin, const char* end) : str_(begin), size_(end - begin)
|
||||||
|
{}
|
||||||
|
|
||||||
|
typedef const char* const_iterator;
|
||||||
|
typedef const char* iterator;
|
||||||
|
typedef const char value_type;
|
||||||
|
|
||||||
bool operator==(const char* o) const {
|
bool operator==(const char* o) const {
|
||||||
const char* i1 = str_;
|
const char* i1 = str_;
|
||||||
|
|
13
src/team.cpp
13
src/team.cpp
|
@ -33,6 +33,7 @@
|
||||||
#include "whiteboard/side_actions.hpp"
|
#include "whiteboard/side_actions.hpp"
|
||||||
#include "network.hpp"
|
#include "network.hpp"
|
||||||
#include "config_assign.hpp"
|
#include "config_assign.hpp"
|
||||||
|
#include "serialization/string_utils.hpp"
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
#include <boost/assign/list_of.hpp>
|
#include <boost/assign/list_of.hpp>
|
||||||
|
@ -851,3 +852,15 @@ config team::to_config() const
|
||||||
write(result);
|
write(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string team::allied_human_teams() const
|
||||||
|
{
|
||||||
|
std::vector<int> res;
|
||||||
|
BOOST_FOREACH(const team& t, *teams)
|
||||||
|
{
|
||||||
|
if(!t.is_enemy(this->side()) && t.is_human()) {
|
||||||
|
res.push_back(t.side());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return utils::join(res);
|
||||||
|
}
|
||||||
|
|
|
@ -258,6 +258,8 @@ public:
|
||||||
bool is_local() const { return is_local_human() || is_local_ai(); }
|
bool is_local() const { return is_local_human() || is_local_ai(); }
|
||||||
bool is_network() const { return is_network_human() || is_network_ai(); }
|
bool is_network() const { return is_network_human() || is_network_ai(); }
|
||||||
|
|
||||||
|
bool is_human() const { return is_local_human() || is_network_human(); }
|
||||||
|
|
||||||
bool is_local_human() const { return info_.controller == CONTROLLER::HUMAN; }
|
bool is_local_human() const { return info_.controller == CONTROLLER::HUMAN; }
|
||||||
bool is_local_ai() const { return info_.controller == CONTROLLER::AI; }
|
bool is_local_ai() const { return info_.controller == CONTROLLER::AI; }
|
||||||
bool is_network_human() const { return info_.controller == CONTROLLER::NETWORK; }
|
bool is_network_human() const { return info_.controller == CONTROLLER::NETWORK; }
|
||||||
|
@ -376,6 +378,8 @@ public:
|
||||||
|
|
||||||
bool share_maps() const { return info_.share_maps; }
|
bool share_maps() const { return info_.share_maps; }
|
||||||
bool share_view() const { return info_.share_view; }
|
bool share_view() const { return info_.share_view; }
|
||||||
|
|
||||||
|
std::string allied_human_teams() const;
|
||||||
private:
|
private:
|
||||||
|
|
||||||
const std::vector<const shroud_map*>& ally_shroud(const std::vector<team>& teams) const;
|
const std::vector<const shroud_map*>& ally_shroud(const std::vector<team>& teams) const;
|
||||||
|
|
|
@ -609,7 +609,7 @@ void manager::send_network_data()
|
||||||
config packet;
|
config packet;
|
||||||
config& wb_cfg = packet.add_child("whiteboard",buf_cfg);
|
config& wb_cfg = packet.add_child("whiteboard",buf_cfg);
|
||||||
wb_cfg["side"] = static_cast<int>(team_index+1);
|
wb_cfg["side"] = static_cast<int>(team_index+1);
|
||||||
wb_cfg["team_name"] = resources::teams->at(team_index).team_name();
|
wb_cfg["to_sides"] = resources::teams->at(team_index).allied_human_teams();
|
||||||
|
|
||||||
buf_cfg = config();
|
buf_cfg = config();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue