Updated the network code to handle gzipped data instead of binary wml.

Nobody sends it yet, but the server can receive it, once the server
has been restarted there will be another commit to make the clients
send gzipped data to the server.

There's a config variable to change the server to send gzipped data as
well. On the trunk server this switch can be set once everybody had
some time to update their clients.

Once 1.3.12 is no longer allowed on the server this can also be set on
the 1.3 server. Once it's no longer allowed there the server will be
modified to only send gzipped data and the switch removed.

(The campaign server won't be modified at this moment.)

NOTE *campaign server and server need to be included
serialization/binary_or_text.cpp*
This commit is contained in:
Mark de Wever 2007-12-08 17:42:36 +00:00
parent e265e9f3a0
commit 7b12cffb91
22 changed files with 358 additions and 177 deletions

View file

@ -239,6 +239,7 @@ wesnothd_SOURCES = \
network.cpp \
network_worker.cpp \
loadscreen_empty.cpp \
serialization/binary_or_text.cpp \
serialization/parser.cpp
wesnothd_LDADD = -L. -lwesnoth-core @SDL_NET_LIBS@ @SDL_LIBS@ $(LIBINTL)
@ -254,6 +255,7 @@ campaignd_SOURCES = \
network_worker.cpp \
publish_campaign.cpp \
loadscreen_empty.cpp \
serialization/binary_or_text.cpp \
serialization/parser.cpp
campaignd_LDADD = -L. -lwesnoth-core @SDL_NET_LIBS@ @SDL_LIBS@ $(LIBINTL)

View file

@ -311,18 +311,21 @@ namespace {
config response;
response.add_child("campaigns",campaign_list);
network::send_data(response,sock);
//! @todo, maybe we should let the server send gzipped data.
network::send_data(response, sock, false);
} else if(const config* req = data.child("request_campaign")) {
LOG_CS << "sending campaign " << (*req)["name"] << " to " << network::ip_address(sock) << "\n";
config* const campaign = campaigns().find_child("campaign","name",(*req)["name"]);
if(campaign == NULL) {
network::send_data(construct_error("Add-on '" + (*req)["name"] + "'not found."), sock);
//! @todo, maybe we should let the server send gzipped data.
network::send_data(construct_error("Add-on '" + (*req)["name"] + "'not found."), sock, false);
} else {
config cfg;
scoped_istream stream = istream_file((*campaign)["filename"]);
read_compressed(cfg, *stream);
add_license(cfg);
network::send_data(cfg,sock);
//! @todo, maybe we should let the server send gzipped data.
network::send_data(cfg, sock, false);
const int downloads = lexical_cast_default<int>((*campaign)["downloads"],0)+1;
(*campaign)["downloads"] = lexical_cast<std::string>(downloads);
@ -330,18 +333,22 @@ namespace {
} else if(data.child("request_terms") != NULL) {
LOG_CS << "sending terms " << network::ip_address(sock) << "\n";
network::send_data(construct_message("All add-ons uploaded to this server must be licensed under the terms of the GNU General Public License (GPL). By uploading content to this server, you certify that you have the right to place the content under the conditions of the GPL, and choose to do so."),sock);
//! @todo, maybe we should let the server send gzipped data.
network::send_data(construct_message("All add-ons uploaded to this server must be licensed under the terms of the GNU General Public License (GPL). By uploading content to this server, you certify that you have the right to place the content under the conditions of the GPL, and choose to do so."), sock, false);
LOG_CS << " Done\n";
} else if(config* upload = data.child("upload")) {
LOG_CS << "uploading campaign " << network::ip_address(sock) << "\n";
config* data = upload->child("data");
config* campaign = campaigns().find_child("campaign","name",(*upload)["name"]);
if(data == NULL) {
network::send_data(construct_error("No add-on data was supplied."),sock);
//! @todo, maybe we should let the server send gzipped data.
network::send_data(construct_error("No add-on data was supplied."), sock, false);
} else if(campaign_name_legal((*upload)["name"]) == false) {
network::send_data(construct_error("The name of the add-on is invalid"),sock);
//! @todo, maybe we should let the server send gzipped data.
network::send_data(construct_error("The name of the add-on is invalid"), sock, false);
} else if(check_names_legal(*data) == false) {
network::send_data(construct_error("The add-on contains an illegal file or directory name."),sock);
//! @todo, maybe we should let the server send gzipped data.
network::send_data(construct_error("The add-on contains an illegal file or directory name."), sock, false);
} else if(campaign != NULL && (*campaign)["passphrase"] != (*upload)["passphrase"]) {
// the user password failed, now test for the master password, in master password
// mode the upload behaves different since it's only intended to update translations.
@ -371,10 +378,12 @@ namespace {
file_size(filename));
scoped_ostream cfgfile = ostream_file(file_);
write(*cfgfile, cfg_);
network::send_data(construct_message(message),sock);
//! @todo, maybe we should let the server send gzipped data.
network::send_data(construct_message(message), sock, false);
} else {
network::send_data(construct_error("The add-on already exists, and your passphrase was incorrect."),sock);
//! @todo, maybe we should let the server send gzipped data.
network::send_data(construct_error("The add-on already exists, and your passphrase was incorrect."), sock, false);
}
} else {
std::string message = "Add-on accepted.";
@ -424,7 +433,8 @@ namespace {
file_size(filename));
scoped_ostream cfgfile = ostream_file(file_);
write(*cfgfile, cfg_);
network::send_data(construct_message(message),sock);
//! @todo, maybe we should let the server send gzipped data.
network::send_data(construct_message(message), sock, false);
fire("hook_post_upload", (*upload)["name"]);
}
@ -432,7 +442,8 @@ namespace {
LOG_CS << "deleting campaign " << network::ip_address(sock) << "\n";
config* const campaign = campaigns().find_child("campaign","name",(*erase)["name"]);
if(campaign == NULL) {
network::send_data(construct_error("The add-on does not exist."),sock);
//! @todo, maybe we should let the server send gzipped data.
network::send_data(construct_error("The add-on does not exist."), sock, false);
continue;
}
@ -440,7 +451,8 @@ namespace {
&& (campaigns()["master_password"] == ""
|| campaigns()["master_password"] != (*erase)["passphrase"])) {
network::send_data(construct_error("The passphrase is incorrect."),sock);
//! @todo, maybe we should let the server send gzipped data.
network::send_data(construct_error("The passphrase is incorrect."), sock, false);
continue;
}
@ -453,35 +465,43 @@ namespace {
campaigns().remove_child("campaign",index);
scoped_ostream cfgfile = ostream_file(file_);
write(*cfgfile, cfg_);
network::send_data(construct_message("Add-on deleted."),sock);
//! @todo, maybe we should let the server send gzipped data.
network::send_data(construct_message("Add-on deleted."), sock, false);
fire("hook_post_erase", (*erase)["name"]);
} else if(const config* cpass = data.child("change_passphrase")) {
config* campaign = campaigns().find_child("campaign","name",(*cpass)["name"]);
if(campaign == NULL) {
network::send_data(construct_error("No add-on with that name exists."),sock);
//! @todo, maybe we should let the server send gzipped data.
network::send_data(construct_error("No add-on with that name exists."), sock, false);
} else if((*campaign)["passphrase"] != (*cpass)["passphrase"]) {
network::send_data(construct_error("Your old passphrase was incorrect."),sock);
//! @todo, maybe we should let the server send gzipped data.
network::send_data(construct_error("Your old passphrase was incorrect."), sock, false);
} else if((const t_string)(*cpass)["new_passphrase"] == "") {
network::send_data(construct_error("No new passphrase was supplied."),sock);
//! @todo, maybe we should let the server send gzipped data.
network::send_data(construct_error("No new passphrase was supplied."), sock, false);
} else {
(*campaign)["passphrase"] = (*cpass)["new_passphrase"];
scoped_ostream cfgfile = ostream_file(file_);
write(*cfgfile, cfg_);
network::send_data(construct_message("Passphrase changed."),sock);
//! @todo, maybe we should let the server send gzipped data.
network::send_data(construct_message("Passphrase changed."), sock, false);
}
} else if(const config* cvalidate = data.child("validate_scripts")) {
config* campaign = campaigns().find_child("campaign","name",(*cvalidate)["name"]);
if(campaign == NULL) {
//! @todo, maybe we should let the server send gzipped data.
network::send_data(construct_error(
"No add-on with that name exists."),sock);
"No add-on with that name exists."), sock, false);
} else if(campaigns()["master_password"] == "") {
//! @todo, maybe we should let the server send gzipped data.
network::send_data(construct_error(
"Sever does not allow scripts."),sock);
"Sever does not allow scripts."), sock, false);
} else if (campaigns()["master_password"] != (*cvalidate)["master_password"]) {
//! @todo, maybe we should let the server send gzipped data.
network::send_data(construct_error(
"Password was incorrect."),sock);
"Password was incorrect."), sock, false);
} else {
// Read the campaign from disk.
config campaign_file;
@ -493,10 +513,12 @@ namespace {
scoped_ostream ostream = ostream_file((*campaign)["filename"]);
write_compressed(*ostream, campaign_file);
//! @todo, maybe we should let the server send gzipped data.
network::send_data(construct_message("The following scripts have been validated: " +
scripts), sock);
scripts), sock, false);
} else {
network::send_data(construct_message("No unchecked scripts found!"), sock);
//! @todo, maybe we should let the server send gzipped data.
network::send_data(construct_message("No unchecked scripts found!"), sock, false);
}
}
}

View file

@ -1077,7 +1077,8 @@ void game_controller::download_campaigns(std::string host)
config cfg;
cfg.add_child("request_campaign_list");
network::send_data(cfg,sock);
// @todo Should be enabled once the campaign server can be recompiled.
network::send_data(cfg, sock, false);
network::connection res = dialogs::network_receive_dialog(disp(),_("Asking for list of add-ons"),cfg,sock);
if(!res) {
@ -1223,7 +1224,8 @@ void game_controller::download_campaigns(std::string host)
config request;
request.add_child("request_campaign")["name"] = campaigns[index];
network::send_data(request,sock);
// @todo Should be enabled once the campaign server can be recompiled.
network::send_data(request, sock, false);
res = dialogs::network_receive_dialog(disp(),_("Downloading add-on..."),cfg,sock);
if(!res) {
@ -1300,7 +1302,8 @@ void game_controller::upload_campaign(const std::string& campaign, network::conn
{
config request_terms;
request_terms.add_child("request_terms");
network::send_data(request_terms,sock);
// @todo Should be enabled once the campaign server can be recompiled.
network::send_data(request_terms, sock, false);
config data;
sock = network::receive_data(data,sock,5000);
if(!sock) {
@ -1342,7 +1345,8 @@ void game_controller::upload_campaign(const std::string& campaign, network::conn
data.add_child("upload",cfg).add_child("data",campaign_data);
LOG_NET << "uploading campaign...\n";
network::send_data(data,sock);
// @todo Should be enabled once the campaign server can be recompiled.
network::send_data(data, sock, false);
sock = dialogs::network_send_dialog(disp(),_("Sending add-on"),data,sock);
if(!sock) {
@ -1369,7 +1373,8 @@ void game_controller::delete_campaign(const std::string& campaign, network::conn
config data;
data.add_child("delete",msg);
network::send_data(data,sock);
// @todo Should be enabled once the campaign server can be recompiled.
network::send_data(data, sock, false);
sock = network::receive_data(data,sock,5000);
if(!sock) {

View file

@ -1852,7 +1852,9 @@ private:
cwhisper["receiver"] = arg1;
data.add_child("whisper", cwhisper);
add_chat_message("whisper to "+cwhisper["receiver"],0,cwhisper["message"], game_display::MESSAGE_PRIVATE);
network::send_data(data);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(data, 0, false);
} else if (cmd == help) {
@ -2109,7 +2111,9 @@ private:
config& ban = cfg.add_child(cmd);
ban["username"] = data;
network::send_data(cfg);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(cfg, 0, false);
} else if (cmd == "mute" && network::nconnections() != 0) {
config cfg;
config& mute = cfg.add_child(cmd);
@ -2117,9 +2121,13 @@ private:
mute["username"] = data;
}
network::send_data(cfg);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(cfg, 0, false);
} else if (cmd == "muteall" && network::nconnections() != 0) {
network::send_data(config(cmd));
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(config(cmd), 0, false);
} else if(cmd == "control" && network::nconnections() != 0) {
const std::string::const_iterator j = std::find(data.begin(),data.end(),' ');
if(j == data.end())
@ -2285,7 +2293,9 @@ private:
change["own_side"] = "yes";
}
network::send_data(cfg);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(cfg, 0, false);
}
} // end namespace events

View file

@ -54,7 +54,9 @@ public:
LOG_NW << "sending leave_game\n";
config cfg;
cfg.add_child("leave_game");
network::send_data(cfg);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(cfg, 0, false);
LOG_NW << "sent leave_game\n";
}
};
@ -211,7 +213,9 @@ static server_type open_connection(game_display& disp, const std::string& origin
config res;
cfg["version"] = game_config::version;
res.add_child("version", cfg);
network::send_data(res);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(res, 0, false);
}
//if we got a direction to login
@ -240,7 +244,9 @@ static server_type open_connection(game_display& disp, const std::string& origin
config response;
response.add_child("login")["username"] = login;
network::send_data(response);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(response, 0, false);
network::connection data_res = network::receive_data(data, 0, 3000);
if(!data_res) {
@ -383,7 +389,9 @@ static void enter_create_mode(game_display& disp, const config& game_config, gam
case mp::ui::QUIT:
default:
//update lobby content
network::send_data(config("refresh_lobby"));
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(config("refresh_lobby"), 0, false);
break;
}
}
@ -408,7 +416,9 @@ static void enter_lobby_mode(game_display& disp, const config& game_config, game
gui::show_error_message(disp, error.message);
}
//update lobby content
network::send_data(config("refresh_lobby"));
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(config("refresh_lobby"), 0, false);
}
break;
case mp::ui::OBSERVE:
@ -418,7 +428,9 @@ static void enter_lobby_mode(game_display& disp, const config& game_config, game
if(!error.message.empty()) {
gui::show_error_message(disp, error.message);
//update lobby content
network::send_data(config("refresh_lobby"));
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(config("refresh_lobby"), 0, false);
}
}
break;
@ -429,7 +441,9 @@ static void enter_lobby_mode(game_display& disp, const config& game_config, game
if (!error.message.empty())
gui::show_error_message(disp, error.message);
//update lobby content
network::send_data(config("refresh_lobby"));
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(config("refresh_lobby"), 0, false);
}
break;
case mp::ui::QUIT:
@ -439,7 +453,9 @@ static void enter_lobby_mode(game_display& disp, const config& game_config, game
const preferences::display_manager disp_manager(&disp);
preferences::show_preferences_dialog(disp,game_config);
//update lobby content
network::send_data(config("refresh_lobby"));
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(config("refresh_lobby"), 0, false);
}
break;
default:

View file

@ -898,7 +898,9 @@ connect::connect(game_display& disp, const config& game_config, const game_data&
}
}
create_game["human_sides"] = lexical_cast<std::string>(human_sides);*/
network::send_data(response);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(response, 0, false);
// Adds the current user as default user.
users_.push_back(connected_user(preferences::login(), CNTR_LOCAL, 0));
@ -926,7 +928,9 @@ connect::connect(game_display& disp, const config& game_config, const game_data&
gamelist_updated(true);
// If we are connected, send data to the connected host
network::send_data(level_);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(level_, 0, false);
}
void connect::process_event()
@ -943,7 +947,7 @@ void connect::process_event()
if(network::nconnections() > 0) {
config cfg;
cfg.add_child("leave_game");
network::send_data(cfg);
network::send_data(cfg, 0, false);
}
set_result(QUIT);
@ -979,13 +983,17 @@ void connect::start_game()
// Make other clients not show the results of resolve_random().
config lock;
lock.add_child("stop_updates");
network::send_data(lock);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(lock, 0, false);
update_and_send_diff(true);
// Build the gamestate object after updating the level
level_to_gamestate(level_, state_, params_.saved_game);
network::send_data(config("start_game"));
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(config("start_game"), 0, false);
}
void connect::hide_children(bool hide)
@ -1041,7 +1049,9 @@ void connect::process_network_data(const config& data, const network::connection
if(name.empty()) {
config response;
response.values["failed"] = "yes";
network::send_data(response,sock);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(response, sock, false);
ERR_CF << "ERROR: No username provided with the side.\n";
return;
}
@ -1052,13 +1062,17 @@ void connect::process_network_data(const config& data, const network::connection
config response;
response.values["failed"] = "yes";
response["message"] = "The nick '" + name + "' is already in use.";
network::send_data(response,sock);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(response, sock, false);
return;
} else {
users_.erase(player);
config observer_quit;
observer_quit.add_child("observer_quit").values["name"] = name;
network::send_data(observer_quit);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(observer_quit, 0, false);
update_user_combos();
}
}
@ -1079,12 +1093,16 @@ void connect::process_network_data(const config& data, const network::connection
if(itor == sides_.end()) {
config response;
response.values["failed"] = "yes";
network::send_data(response, sock);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(response, sock, false);
config kick;
kick["username"] = data["name"];
config res;
res.add_child("kick", kick);
network::send_data(res);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(res, 0, false);
update_user_combos();
update_and_send_diff();
ERR_CF << "ERROR: Couldn't assign a side to '" << name << "'\n";
@ -1109,7 +1127,9 @@ void connect::process_network_data(const config& data, const network::connection
ERR_CF << "tried to take illegal side: " << side_taken << '\n';
config response;
response.values["failed"] = "yes";
network::send_data(response, sock);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(response, sock, false);
}
}
@ -1202,9 +1222,13 @@ void connect::process_network_connection(const network::connection sock)
{
ui::process_network_connection(sock);
network::send_data(config("join_game"));
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(config("join_game"), 0, false);
network::send_data(level_, sock);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(level_, sock, false);
}
void connect::layout_children(const SDL_Rect& rect)
@ -1521,7 +1545,9 @@ void connect::update_and_send_diff(bool update_time_of_day)
config diff;
diff.add_child("scenario_diff",level_.get_diff(old_level));
network::send_data(diff);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(diff, 0, false);
}
bool connect::sides_available()
@ -1605,7 +1631,9 @@ void connect::kick_player(const std::string& name)
kick["username"] = name;
config res;
res.add_child("kick", kick);
network::send_data(res);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(res, 0, false);
}
int side = find_player_side(name);

View file

@ -721,7 +721,9 @@ void lobby::process_event()
else{
join["observe"] = "no";
}
network::send_data(response);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(response, 0, false);
if(observe) {
if (game.started){

View file

@ -372,7 +372,9 @@ void ui::handle_event(const SDL_Event& event)
//if the dialog has been open for a long time, refresh the lobby
config request;
request.add_child("refresh_lobby");
network::send_data(request);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(request, 0, false);
}
}
}
@ -381,7 +383,9 @@ void ui::send_chat_query(const std::string& args)
{
config data;
data.add_child("query")["type"] = args;
network::send_data(data);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(data, 0, false);
}
void ui::add_chat_message(const std::string& speaker, int /*side*/, const std::string& message, game_display::MESSAGE_TYPE /*type*/)
@ -398,7 +402,9 @@ void ui::send_chat_message(const std::string& message, bool /*allies_only*/)
data.add_child("message", msg);
add_chat_message(preferences::login(),0, message); //local echo
network::send_data(data);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(data, 0, false);
}

View file

@ -258,7 +258,9 @@ void wait::join_game(bool observe)
cfg["faction"] = "random";
cfg["leader"] = "random";
cfg["gender"] = "random";
network::send_data(cfg);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(cfg, 0, false);
if(allow_changes) {
events::event_context context;
@ -304,7 +306,9 @@ void wait::join_game(bool observe)
change["faction"] = lexical_cast<std::string>(faction_choice);
change["leader"] = leader_choice;
change["gender"] = gender_choice;
network::send_data(faction);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(faction, 0, false);
}
}

View file

@ -686,7 +686,10 @@ connection receive_data(config& cfg, connection connection_num)
return result;
}
void send_data(const config& cfg, connection connection_num)
//! @todo Note the gzipped parameter should be removed later, we want to send
//! all data gzipped. This can be done once the campaign server is also updated
//! to work with gzipped data.
void send_data(const config& cfg, connection connection_num, const bool gzipped)
{
DBG_NW << "in send_data()...\n";
@ -704,7 +707,7 @@ void send_data(const config& cfg, connection connection_num)
for(sockets_list::const_iterator i = sockets.begin();
i != sockets.end(); ++i) {
DBG_NW << "server socket: " << server_socket << "\ncurrent socket: " << *i << "\n";
send_data(cfg,*i);
send_data(cfg,*i, gzipped);
}
return;
}
@ -717,7 +720,7 @@ void send_data(const config& cfg, connection connection_num)
}
LOG_NW << "SENDING to: " << connection_num << ": " << cfg.debug();
network_worker_pool::queue_data(info->second.sock,cfg);
network_worker_pool::queue_data(info->second.sock, cfg, gzipped);
}
void process_send_queue(connection, size_t)
@ -725,14 +728,15 @@ void process_send_queue(connection, size_t)
check_error();
}
void send_data_all_except(const config& cfg, connection connection_num)
//! @todo Note the gzipped parameter should be removed later.
void send_data_all_except(const config& cfg, connection connection_num, const bool gzipped)
{
for(sockets_list::const_iterator i = sockets.begin(); i != sockets.end(); ++i) {
if(*i == connection_num) {
continue;
}
send_data(cfg,*i);
send_data(cfg,*i, gzipped);
}
}

View file

@ -124,7 +124,7 @@ connection receive_data(config& cfg, connection connection_num, int timeout);
//! Function to send data down a given connection,
//! or broadcast to all peers if connection_num is 0.
//! Throws error.
void send_data(const config& cfg, connection connection_num=0);
void send_data(const config& cfg, connection connection_num /*= 0*/, const bool gzipped);
//! Function to send any data that is in a connection's send_queue,
//! up to a maximum of 'max_size' bytes --
@ -132,7 +132,7 @@ void send_data(const config& cfg, connection connection_num=0);
void process_send_queue(connection connection_num=0, size_t max_size=0);
//! Function to send data to all peers except 'connection_num'.
void send_data_all_except(const config& cfg, connection connection_num);
void send_data_all_except(const config& cfg, connection connection_num, const bool gzipped);
//! Function to get the remote ip address of a socket.
std::string ip_address(connection connection_num);

View file

@ -20,7 +20,9 @@
#include "thread.hpp"
#include "wassert.hpp"
//#include "wesconfig.h"
#include "serialization/binary_or_text.hpp"
#include "serialization/binary_wml.hpp"
#include "serialization/parser.hpp"
#include <algorithm>
#include <cerrno>
@ -30,6 +32,8 @@
#include <map>
#include <vector>
#include <boost/iostreams/filter/gzip.hpp>
#ifdef __AMIGAOS4__
#include <unistd.h>
//#include <sys/clib2_net.h>
@ -86,11 +90,20 @@ size_t min_threads = 0;
size_t max_threads = 0;
struct buffer {
explicit buffer(TCPsocket sock) : sock(sock),config_error("") {}
explicit buffer(TCPsocket sock) :
sock(sock),
config_buf(),
config_error(""),
gzipped(false)
{}
TCPsocket sock;
mutable config config_buf;
std::string config_error;
//! Do we wish to send the data gzipped, if not use binary wml.
//! This needs to stay until the last user of binary_wml has
//! been removed.
bool gzipped;
};
@ -214,14 +227,21 @@ bool receive_with_timeout(TCPsocket s, char* buf, size_t nbytes,
return true;
}
static SOCKET_STATE send_buf(TCPsocket sock, config& config_in) {
static SOCKET_STATE send_buffer(TCPsocket sock, config& config_in, const bool gzipped) {
#ifdef __BEOS__
int timeout = 15000;
#endif
size_t upto = 0;
compression_schema &compress = schemas.insert(std::pair<TCPsocket,schema_pair>(sock,schema_pair())).first->second.outgoing;
std::ostringstream compressor;
write_compressed(compressor, config_in, compress);
if(gzipped) {
// std::cerr << "send gzipped\n.";
config_writer writer(compressor, true, "");
writer.write(config_in);
} else {
// std::cerr << "send binary wml\n.";
write_compressed(compressor, config_in, compress);
}
std::string const &value = compressor.str();
std::vector<char> buf(4 + value.size() + 1);
SDLNet_Write32(value.size()+1,&buf[0]);
@ -427,7 +447,7 @@ static int process_queue(void*)
std::vector<char> buf;
if(sent_buf != NULL) {
result = send_buf(sent_buf->sock, sent_buf->config_buf);
result = send_buffer(sent_buf->sock, sent_buf->config_buf, sent_buf->gzipped);
delete sent_buf;
sent_buf = NULL;
} else {
@ -449,12 +469,26 @@ static int process_queue(void*)
std::string buffer(buf.begin(), buf.end());
std::istringstream stream(buffer);
compression_schema &compress = schemas.insert(std::pair<TCPsocket,schema_pair>(sock,schema_pair())).first->second.incoming;
try {
read_compressed(received_data_queue.back().config_buf, stream, compress);
} catch(config::error &e) {
//throw back the error in the parent thread
received_data_queue.back().config_error = e.message;
// Binary wml starts with a char < 4, the first char of a gzip header is 31
// so test that here and use the proper reader.
// std::cerr << "front of buffer " << stream.peek() << " ";
if(stream.peek() == 31) {
try {
// std::cerr << "recieve gzipped\n.";
read_gz(received_data_queue.back().config_buf, stream);
} catch(boost::iostreams::gzip_error& e) {
//throw back the error in the parent thread
// std::cerr << "error in gzipped data\n";
received_data_queue.back().config_error = e.error();
}
} else {
try {
// std::cerr << "recieve binary_wml\n.";
read_compressed(received_data_queue.back().config_buf, stream, compress);
} catch(config::error &e) {
//throw back the error in the parent thread
received_data_queue.back().config_error = e.message;
}
}
}
}
@ -559,7 +593,7 @@ TCPsocket get_received_data(TCPsocket sock, config& cfg)
}
}
void queue_data(TCPsocket sock,const config& buf)
void queue_data(TCPsocket sock,const config& buf, const bool gzipped)
{
DBG_NW << "queuing data...\n";
@ -568,6 +602,7 @@ void queue_data(TCPsocket sock,const config& buf)
buffer *queued_buf = new buffer(sock);
queued_buf->config_buf = buf;
queued_buf->gzipped = gzipped;
bufs.push_back(queued_buf);
sockets_locked.insert(std::pair<TCPsocket,SOCKET_STATE>(sock,SOCKET_READY));

View file

@ -46,7 +46,7 @@ void receive_data(TCPsocket sock);
TCPsocket get_received_data(TCPsocket sock, config& cfg);
void queue_data(TCPsocket sock, const config& buf);
void queue_data(TCPsocket sock, const config& buf, const bool gzipped);
bool socket_locked(TCPsocket sock);
bool close_socket(TCPsocket sock);
std::pair<unsigned int,size_t> thread_state();

View file

@ -191,7 +191,9 @@ void notify_next_scenario(const io_type_t io_type){
cfg_notify["is_host"] = "1";
else
cfg_notify["is_host"] = "0";
network::send_data(cfg);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(cfg, 0, false);
}
LEVEL_RESULT play_game(display& disp, game_state& gamestate, const config& game_config,
@ -455,7 +457,9 @@ LEVEL_RESULT play_game(display& disp, game_state& gamestate, const config& game_
config cfg;
std::string msg = _("Downloading next scenario...");
config cfg_load = cfg.add_child("load_next_scenario");
network::send_data(cfg);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(cfg, 0, false);
do {
cfg.clear();
@ -518,7 +522,9 @@ LEVEL_RESULT play_game(display& disp, game_state& gamestate, const config& game_
// information, to the configuration object
wassert(cfg.child("store_next_scenario") != NULL);
write_game(gamestate, *cfg.child("store_next_scenario"), WRITE_SNAPSHOT_ONLY);
network::send_data(cfg);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(cfg, 0, false);
//notifies the clients that the host advanced to the next scenario
notify_next_scenario(IO_SERVER);

View file

@ -292,7 +292,9 @@ LEVEL_RESULT playsingle_controller::play_scenario(const std::vector<config*>& st
info["type"] = "termination";
info["condition"] = "game over";
info["result"] = gamestate_.completion;
network::send_data(cfg);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(cfg, 0, false);
} else {
gui::message_dialog(*gui_,_("Game Over"),
_("The game is over.")).show();

View file

@ -100,7 +100,9 @@ turn_info::PROCESS_DATA_RESULT turn_info::process_network_data(const config& cfg
const config::child_list& turns = cfg.get_children("turn");
if(turns.empty() == false && from != network::null_connection) {
//forward the data to other peers
network::send_data_all_except(cfg,from);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data_all_except(cfg, from, false);
}
for(config::child_list::const_iterator t = turns.begin(); t != turns.end(); ++t) {
@ -120,7 +122,9 @@ turn_info::PROCESS_DATA_RESULT turn_info::process_network_data(const config& cfg
config& info = cfg.add_child("info");
info["type"] = "termination";
info["condition"] = "out of sync";
network::send_data(cfg);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(cfg, 0, false);
replay::last_replay_error = e.message; //FIXME: some better way to pass this?
replay_error_.notify_observers();
@ -311,7 +315,9 @@ void turn_info::change_side_controller(const std::string& side, const std::strin
change["own_side"] = "yes";
}
network::send_data(cfg);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(cfg, 0, false);
}
void turn_info::take_side(const std::string& side, const std::string& controller)
@ -320,5 +326,7 @@ void turn_info::take_side(const std::string& side, const std::string& controller
cfg.values["side"] = side;
cfg.values["controller"] = controller;
cfg.values["name"] = controller+side;
network::send_data(cfg);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(cfg, 0, false);
}

View file

@ -1144,7 +1144,9 @@ void replay_network_sender::sync_non_undoable()
config cfg;
const config& data = cfg.add_child("turn",obj_.get_data_range(upto_,obj_.ncommands(),replay::NON_UNDO_DATA));
if(data.empty() == false) {
network::send_data(cfg);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(cfg, 0, false);
}
}
}
@ -1155,7 +1157,9 @@ void replay_network_sender::commit_and_sync()
config cfg;
const config& data = cfg.add_child("turn",obj_.get_data_range(upto_,obj_.ncommands()));
if(data.empty() == false) {
network::send_data(cfg);
//! @todo To avoid chicken and egg first enable the server to receive
//! gzipped data.
network::send_data(cfg, 0, false);
}
upto_ = obj_.ncommands();

View file

@ -27,6 +27,8 @@
#define DBG_GAME LOG_STREAM(debug, mp_server)
int game::id_num = 1;
//! @todo remove after 1.3.12 is no longer allowed on the server.
bool game::send_gzipped = false;
game::game(player_map& players, const network::connection host, const std::string name)
: player_info_(&players), id_(id_num++), name_(name), owner_(host),
@ -181,7 +183,7 @@ bool game::take_side(network::connection player, const config& cfg)
sides_taken_[side_num - 1] = true;
config new_cfg = cfg;
new_cfg["side"] = (**i)["side"];
network::send_data(new_cfg, owner_);
network::send_data(new_cfg, owner_, send_gzipped);
return true;
}
}
@ -214,7 +216,7 @@ bool game::take_side(network::connection player, const config& cfg)
sides_[side_num - 1] = player;
sides_taken_[side_num - 1] = true;
// Send the taken side to the host.
network::send_data(cfg, owner_);
network::send_data(cfg, owner_, send_gzipped);
return true;
}
@ -315,7 +317,7 @@ void game::transfer_side_control(const network::connection sock, const config& c
}
// Is he in this game?
if (newplayer == player_info_->end() || !is_member(newplayer->first)) {
network::send_data(construct_server_message("Player/Observer not in this game."), sock);
network::send_data(construct_server_message("Player/Observer not in this game."), sock, send_gzipped);
return;
}
// Check the side number.
@ -327,16 +329,16 @@ void game::transfer_side_control(const network::connection sock, const config& c
std::ostringstream msg;
msg << "The side number has to be between 1 and "
<< gamemap::MAX_PLAYERS << ".";
network::send_data(construct_server_message(msg.str()),sock);
network::send_data(construct_server_message(msg.str()), sock, send_gzipped);
return;
}
}
catch(bad_lexical_cast&) {
network::send_data(construct_server_message("Not a side number."), sock);
network::send_data(construct_server_message("Not a side number."), sock, send_gzipped);
return;
}
if (side_num > level_.get_children("side").size()) {
network::send_data(construct_server_message("Invalid side number."), sock);
network::send_data(construct_server_message("Invalid side number."), sock, send_gzipped);
return;
}
@ -344,18 +346,18 @@ void game::transfer_side_control(const network::connection sock, const config& c
&& cfg["own_side"] != "yes")
{
network::send_data(construct_server_message(
"This side is already controlled by a player."), sock);
"This side is already controlled by a player."), sock, send_gzipped);
return;
}
// Check if the sender actually owns the side he gives away or is the host.
if (!(sides_[side_num - 1] == sock || (sock == owner_))) {
DBG_GAME << "Side belongs to: " << sides_[side_num - 1] << "\n";
network::send_data(construct_server_message("Not your side."), sock);
network::send_data(construct_server_message("Not your side."), sock, send_gzipped);
return;
}
if (newplayer->first == sock) {
network::send_data(construct_server_message(
"That's already your side, silly."), sock);
"That's already your side, silly."), sock, send_gzipped);
return;
}
sides_[side_num - 1] = 0;
@ -401,7 +403,7 @@ void game::transfer_side_control(const network::connection sock, const config& c
send_data(response, newplayer->first);
// Tell the new player that he controls this side now.
change["controller"] = "human";
network::send_data(response, newplayer->first);
network::send_data(response, newplayer->first, send_gzipped);
// Update the level so observer who join get the new name.
config::child_itors it = level_.child_range("side");
@ -416,7 +418,7 @@ void game::transfer_side_control(const network::connection sock, const config& c
if (side_controllers_[i] == "ai") {
change["side"] = lexical_cast<std::string, unsigned int>(i + 1);
change["controller"] = "ai";
network::send_data(response, owner_);
network::send_data(response, owner_, send_gzipped);
sides_[side_num - 1] = owner_;
}
}
@ -446,7 +448,7 @@ void game::notify_new_host(){
config& cfg_host_transfer = cfg.add_child("host_transfer");
cfg_host_transfer["name"] = it_host->second.name();
cfg_host_transfer["value"] = "1";
network::send_data(cfg, owner_);
network::send_data(cfg, owner_, send_gzipped);
}
}
@ -509,19 +511,19 @@ void game::mute_observer(const config& mute) {
//! and also allow muting of usernames not in the game.
if (pl == player_info_->end() || !is_observer(pl->first)) {
network::send_data(construct_server_message(
"Observer not found."), owner_);
"Observer not found."), owner_, send_gzipped);
return;
}
if (is_muted_observer(pl->first)) {
network::send_data(construct_server_message(pl->second.name()
+ " is already muted."), owner_);
+ " is already muted."), owner_, send_gzipped);
return;
}
//! Prevent muting ourselves.
if (pl->first != owner_) {
muted_observers_.push_back(pl->first);
network::send_data(construct_server_message(
"You have been muted."), pl->first);
"You have been muted."), pl->first, send_gzipped);
send_data(construct_server_message(pl->second.name()
+ " has been muted."), pl->first);
}
@ -534,24 +536,24 @@ network::connection game::kick_member(const config& kick) {
const player_map::const_iterator user = find_user(name);
if (user == player_info_->end() || !is_member(user->first)) {
network::send_data(construct_server_message(
"Not a member of this game."), owner_);
"Not a member of this game."), owner_, send_gzipped);
return 0;
}
if (user->first == owner_) {
network::send_data(construct_server_message(
"Don't kick yourself, silly."), owner_);
"Don't kick yourself, silly."), owner_, send_gzipped);
return 0;
}
LOG_GAME << network::ip_address(owner_) << "\t"
<< owner_ << "\tkicked: " << user->second.name() << "\tfrom game:\t"
<< name_ << "\" (" << id_ << ")\n";
network::send_data(construct_server_message("You have been kicked."),
user->first);
user->first, send_gzipped);
const config msg = construct_server_message(name + " has been kicked.");
send_data(msg, user->first);
record_data(msg);
// Tell the user to leave the game.
network::send_data(config("leave_game"), user->first);
network::send_data(config("leave_game"), user->first, send_gzipped);
remove_player(user->first);
return user->first;
}
@ -565,17 +567,17 @@ network::connection game::ban_user(const config& ban) {
const player_map::const_iterator user = find_user(name);
if (user == player_info_->end()) {
network::send_data(construct_server_message(
"User not found."), owner_);
"User not found."), owner_, send_gzipped);
return 0;
}
if (user->first == owner_) {
network::send_data(construct_server_message(
"Don't ban yourself, silly."), owner_);
"Don't ban yourself, silly."), owner_, send_gzipped);
return 0;
}
if (player_is_banned(user->first)) {
network::send_data(construct_server_message(name
+ " is already banned."), owner_);
+ " is already banned."), owner_, send_gzipped);
return 0;
}
LOG_GAME << network::ip_address(owner_) << "\t"
@ -587,9 +589,9 @@ network::connection game::ban_user(const config& ban) {
record_data(msg);
if (is_member(user->first)) {
network::send_data(construct_server_message("You have been banned."),
user->first);
user->first, send_gzipped);
// Tell the user to leave the game.
network::send_data(config("leave_game"), user->first);
network::send_data(config("leave_game"), user->first, send_gzipped);
remove_player(user->first);
return user->first;
}
@ -675,13 +677,13 @@ void game::add_player(const network::connection player, const bool observer) {
DBG_GAME << debug_player_info();
send_user_list();
// Send the user the game data.
network::send_data(level_, player);
network::send_data(level_, player, send_gzipped);
//if the game has already started, we add the player as an observer
if(started_) {
//tell this player that the game has started
network::send_data(config("start_game"), player);
network::send_data(config("start_game"), player, send_gzipped);
// Send the player the history of the game to-date.
network::send_data(history_,player);
network::send_data(history_, player, send_gzipped);
// Send observer join of all the observers in the game to the new player
// only once the game started. The client forgets about it anyway
// otherwise.
@ -691,7 +693,7 @@ void game::add_player(const network::connection player, const bool observer) {
if(obs != player_info_->end()) {
config cfg;
cfg.add_child("observer").values["name"] = obs->second.name();
network::send_data(cfg, player);
network::send_data(cfg, player, send_gzipped);
}
}
}
@ -784,7 +786,7 @@ void game::remove_player(const network::connection player, const bool notify_cre
config drop;
drop["side_drop"] = lexical_cast<std::string, size_t>(side + 1);
drop["controller"] = "ai";
network::send_data(drop, owner_);
network::send_data(drop, owner_, send_gzipped);
sides_taken_[side] = false;
}
}
@ -802,7 +804,7 @@ void game::remove_player(const network::connection player, const bool notify_cre
config drop;
drop["side_drop"] = lexical_cast<std::string, size_t>(side - sides_.begin() + 1);
drop["controller"] = side_controllers_[side - sides_.begin()];
network::send_data(drop, owner_);
network::send_data(drop, owner_, send_gzipped);
}
side_controllers_[side - sides_.begin()] = "null";
sides_taken_[side - sides_.begin()] = false;
@ -837,7 +839,7 @@ void game::send_data(const config& data, const network::connection exclude) cons
const user_vector users = all_game_users();
for(user_vector::const_iterator i = users.begin(); i != users.end(); ++i) {
if (*i != exclude) {
network::send_data(data,*i);
network::send_data(data, *i, send_gzipped);
}
}
}
@ -860,7 +862,7 @@ void game::send_data_team(const config& data, const std::string& team,
{
for(user_vector::const_iterator i = players_.begin(); i != players_.end(); ++i) {
if(*i != exclude && player_on_team(team,*i)) {
network::send_data(data,*i);
network::send_data(data, *i, send_gzipped);
}
}
}
@ -868,7 +870,7 @@ void game::send_data_team(const config& data, const std::string& team,
void game::send_data_observers(const config& data, const network::connection exclude) const {
for(user_vector::const_iterator i = observers_.begin(); i != observers_.end(); ++i) {
if (*i != exclude) {
network::send_data(data,*i);
network::send_data(data, *i, send_gzipped);
}
}
}

View file

@ -119,6 +119,11 @@ public:
if (termination_.empty()) { termination_ = reason; }
}
//! This is a tempory variable to have a flag to switch between
//! gzipped data and not.
//! @todo remove after 1.3.12 is no longer allowed on the server.
static bool send_gzipped;
private:
//! Adds players and observers into one vector and returns that.
const user_vector all_game_users() const;

View file

@ -75,14 +75,15 @@ void disconnect(network::connection sock)
network::disconnect(peer);
}
void received_data(network::connection sock, const config& data)
//! @todo remove gzip param after 1.3.12 is no longer allowed on the server.
void received_data(network::connection sock, const config& data, const bool send_gzipped)
{
const network::connection peer = find_peer(sock);
if(!peer) {
return;
}
network::send_data(data,peer);
network::send_data(data, peer, send_gzipped);
}
}

View file

@ -27,7 +27,8 @@ void create_proxy(network::connection sock, const std::string& host, int port);
bool is_proxy(network::connection sock);
void disconnect(network::connection sock);
void received_data(network::connection sock, const config& data);
//! @todo remove gzip param after 1.3.12 is no longer allowed on the server.
void received_data(network::connection sock, const config& data, const bool send_gzipped);
}

View file

@ -141,6 +141,11 @@ private:
time_t last_stats_;
void dump_stats(const time_t& now);
//! This is a tempory variable to have a flag to switch between
//! gzipped data and not.
//! @todo remove after 1.3.12 is no longer allowed on the server.
bool send_gzipped_;
void process_data(const network::connection sock, const config& data);
void process_login(const network::connection sock, const config& data);
//! Handle queries from clients.
@ -155,12 +160,21 @@ private:
};
server::server(int port, input_stream& input, const std::string& config_file, size_t min_threads,size_t max_threads)
: net_manager_(min_threads,max_threads), server_(port), not_logged_in_(players_),
lobby_(players_), input_(input), config_file_(config_file),
cfg_(read_config()), version_query_response_("version"),
login_response_("mustlogin"), join_lobby_response_("join_lobby"),
games_and_users_list_("gamelist"), old_games_and_users_list_(games_and_users_list_),
last_ping_(time(NULL)), last_stats_(last_ping_)
: net_manager_(min_threads,max_threads),
server_(port),
not_logged_in_(players_),
lobby_(players_),
input_(input),
config_file_(config_file),
cfg_(read_config()),
version_query_response_("version"),
login_response_("mustlogin"),
join_lobby_response_("join_lobby"),
games_and_users_list_("gamelist"),
old_games_and_users_list_(games_and_users_list_),
last_ping_(time(NULL)),
last_stats_(last_ping_),
send_gzipped_(false)
{
load_config();
signal(SIGHUP, reload_config);
@ -190,6 +204,10 @@ config server::read_config() const {
void server::load_config() {
admin_passwd_ = cfg_["passwd"];
motd_ = cfg_["motd"];
// Note this option will not be documented since it's only needed
// for a short transition phase.
send_gzipped_ = utils::string_bool(cfg_["gzipped"], false);
game::send_gzipped = send_gzipped_;
disallowed_names_.clear();
if (cfg_["disallow_names"] == "") {
@ -311,7 +329,7 @@ void server::run() {
for (player_map::const_iterator i = players_.begin();
i != players_.end(); ++i)
{
network::send_data(ping, i->first);
network::send_data(ping, i->first, send_gzipped_);
}
last_ping_ = now;
}
@ -323,16 +341,16 @@ void server::run() {
const std::string& ip = network::ip_address(sock);
if (is_ip_banned(ip)) {
LOG_SERVER << ip << "\trejected banned user.\n";
network::send_data(construct_error("You are banned."),sock);
network::send_data(construct_error("You are banned."), sock, send_gzipped_);
network::disconnect(sock);
} else if (ip_exceeds_connection_limit(ip)) {
LOG_SERVER << ip << "\trejected ip due to excessive connections\n";
network::send_data(construct_error("Too many connections from your IP."),sock);
network::send_data(construct_error("Too many connections from your IP."), sock, send_gzipped_);
network::disconnect(sock);
} else {
DBG_SERVER << ip << "\tnew connection accepted. (socket: "
<< sock << ")\n";
network::send_data(version_query_response_,sock);
network::send_data(version_query_response_, sock, send_gzipped_);
not_logged_in_.add_player(sock, true);
}
}
@ -433,7 +451,7 @@ void server::run() {
void server::process_data(const network::connection sock, const config& data) {
if (proxy::is_proxy(sock)) {
proxy::received_data(sock, data);
proxy::received_data(sock, data, send_gzipped_);
}
// Ignore client side pings for now.
const string_map::const_iterator ping = data.values.find("ping");
@ -470,7 +488,7 @@ void server::process_login(const network::connection sock, const config& data) {
LOG_SERVER << network::ip_address(sock)
<< "\tplayer joined using accepted version " << version_str
<< ":\ttelling them to log in.\n";
network::send_data(login_response_,sock);
network::send_data(login_response_, sock, send_gzipped_);
return;
}
std::map<std::string,config>::const_iterator config_it;
@ -488,7 +506,7 @@ void server::process_login(const network::connection sock, const config& data) {
<< ":" << config_it->second["port"] << "\n";
config response;
response.add_child("redirect",config_it->second);
network::send_data(response,sock);
network::send_data(response, sock, send_gzipped_);
return;
}
// Check if it's a version we should start a proxy for.
@ -520,13 +538,13 @@ void server::process_login(const network::connection sock, const config& data) {
ERR_SERVER << "ERROR: This server doesn't accept any versions at all.\n";
response["version"] = "null";
}
network::send_data(response,sock);
network::send_data(response, sock, send_gzipped_);
return;
}
const config* const login = data.child("login");
// Client must send a login first.
if (login == NULL) {
network::send_data(construct_error("You must login first"),sock);
network::send_data(construct_error("You must login first"), sock, send_gzipped_);
return;
}
// Check if the username is valid (all alpha-numeric plus underscore and hyphen)
@ -534,11 +552,11 @@ void server::process_login(const network::connection sock, const config& data) {
if (!utils::isvalid_username(username)) {
network::send_data(construct_error("This username contains invalid "
"characters. Only alpha-numeric characters, underscores and hyphens"
"are allowed."), sock);
"are allowed."), sock, send_gzipped_);
return;
}
if (username.size() > 18) {
network::send_data(construct_error("This username is too long"),sock);
network::send_data(construct_error("This username is too long"), sock, send_gzipped_);
return;
}
// Check if the uername is allowed.
@ -549,7 +567,7 @@ void server::process_login(const network::connection sock, const config& data) {
utils::lowercase(*d_it)))
{
network::send_data(construct_error("The nick '" + username
+ "' is reserved and can not be used by players"), sock);
+ "' is reserved and can not be used by players"), sock, send_gzipped_);
return;
}
}
@ -557,11 +575,11 @@ void server::process_login(const network::connection sock, const config& data) {
player_map::const_iterator p;
for (p = players_.begin(); p != players_.end(); ++p) {
if (p->second.name() == username) {
network::send_data(construct_error("This username is already taken"), sock);
network::send_data(construct_error("This username is already taken"), sock, send_gzipped_);
return;
}
}
network::send_data(join_lobby_response_, sock);
network::send_data(join_lobby_response_, sock, send_gzipped_);
config* const player_cfg = &games_and_users_list_.add_child("user");
const player new_player(username, *player_cfg, default_max_messages_,
@ -572,14 +590,14 @@ void server::process_login(const network::connection sock, const config& data) {
lobby_.add_player(sock, true);
// Send the new player the entire list of games and players
network::send_data(games_and_users_list_,sock);
network::send_data(games_and_users_list_, sock, send_gzipped_);
if (motd_ != "") {
network::send_data(lobby_.construct_server_message(motd_),sock);
network::send_data(lobby_.construct_server_message(motd_), sock, send_gzipped_);
}
// Send other players in the lobby the update that the player has joined
lobby_.send_data(games_and_users_list_diff(),sock);
lobby_.send_data(games_and_users_list_diff(), sock);
LOG_SERVER << network::ip_address(sock) << "\t" << username
<< "\thas logged on. (socket: " << sock << ")\n";
@ -625,7 +643,7 @@ void server::process_query(const network::connection sock, const config& query)
} else {
response << "Error: unrecognized query";
}
network::send_data(lobby_.construct_server_message(response.str()),sock);
network::send_data(lobby_.construct_server_message(response.str()), sock, send_gzipped_);
}
std::string server::process_command(const std::string& query) {
@ -788,7 +806,7 @@ void server::process_whisper(const network::connection sock,
}
config cwhisper;
cwhisper.add_child("whisper",whisper);
network::send_data(cwhisper,i->first);
network::send_data(cwhisper,i->first, send_gzipped_);
sent = true;
break;
}
@ -799,7 +817,7 @@ void server::process_whisper(const network::connection sock,
msg["message"] = "Invalid number of arguments";
msg["sender"] = "server";
data.add_child("message", msg);
network::send_data(data,sock);
network::send_data(data, sock, send_gzipped_);
sent = true;
}
@ -813,7 +831,7 @@ void server::process_whisper(const network::connection sock,
}
msg["sender"] = "server";
data.add_child("message", msg);
network::send_data(data, sock);
network::send_data(data, sock, send_gzipped_);
}
}
@ -851,10 +869,10 @@ void server::process_data_lobby(const network::connection sock, const config& da
} catch(bad_lexical_cast&) {
WRN_SERVER << network::ip_address(sock) << "\t" << pl->second.name()
<< "\tattempted to join invalid game:\t" << id << "\n";
network::send_data(config("leave_game"), sock);
network::send_data(config("leave_game"), sock, send_gzipped_);
network::send_data(lobby_.construct_server_message(
"Attempt to join invalid game."), sock);
network::send_data(games_and_users_list_, sock);
"Attempt to join invalid game."), sock, send_gzipped_);
network::send_data(games_and_users_list_, sock, send_gzipped_);
return;
}
const std::vector<game>::iterator g =
@ -862,28 +880,28 @@ void server::process_data_lobby(const network::connection sock, const config& da
if (g == games_.end()) {
WRN_SERVER << network::ip_address(sock) << "\t" << pl->second.name()
<< "\tattempted to join unknown game:\t" << id << "\n";
network::send_data(config("leave_game"), sock);
network::send_data(config("leave_game"), sock, send_gzipped_);
network::send_data(lobby_.construct_server_message(
"Attempt to join unknown game."), sock);
network::send_data(games_and_users_list_, sock);
"Attempt to join unknown game."), sock, send_gzipped_);
network::send_data(games_and_users_list_, sock, send_gzipped_);
return;
} else if (g->player_is_banned(sock)) {
DBG_SERVER << network::ip_address(sock) << "\tReject banned player: "
<< pl->second.name() << "\tfrom game:\t\"" << g->name()
<< "\" (" << id << ").\n";
network::send_data(config("leave_game"), sock);
network::send_data(config("leave_game"), sock, send_gzipped_);
network::send_data(lobby_.construct_server_message(
"You are banned from this game."), sock);
network::send_data(games_and_users_list_, sock);
"You are banned from this game."), sock, send_gzipped_);
network::send_data(games_and_users_list_, sock, send_gzipped_);
return;
} else if (observer && !g->allow_observers()){
WRN_SERVER << network::ip_address(sock) << "\t" << pl->second.name()
<< "\tattempted to observe game:\t\"" << g->name() << "\" ("
<< id << ") which doesn't allow observers.\n";
network::send_data(config("leave_game"), sock);
network::send_data(config("leave_game"), sock, send_gzipped_);
network::send_data(lobby_.construct_server_message(
"Attempt to observe a game that doesn't allow observers."), sock);
network::send_data(games_and_users_list_, sock);
"Attempt to observe a game that doesn't allow observers."), sock, send_gzipped_);
network::send_data(games_and_users_list_, sock, send_gzipped_);
return;
}
LOG_SERVER << network::ip_address(sock) << "\t" << pl->second.name()
@ -905,7 +923,7 @@ void server::process_data_lobby(const network::connection sock, const config& da
} else if (pl->second.is_message_flooding()) {
network::send_data(lobby_.construct_server_message(
"Warning: you are sending too many messages too fast. "
"Your message has not been relayed."),pl->first);
"Your message has not been relayed."), pl->first, send_gzipped_);
return;
}
@ -921,14 +939,14 @@ void server::process_data_lobby(const network::connection sock, const config& da
<< pl->second.name() << "> " << msg << "\n";
}
lobby_.send_data(mdata,sock);
lobby_.send_data(mdata, sock);
}
// Player requests update of lobby content,
// for example when cancelling the create game dialog
const config* const refresh = data.child("refresh_lobby");
if (refresh != NULL) {
network::send_data(games_and_users_list_, sock);
network::send_data(games_and_users_list_, sock, send_gzipped_);
}
}
@ -980,7 +998,7 @@ void server::process_data_game(const network::connection sock, const config& dat
<< pl->second.name() << "\tfailed to get a side in game:\t\""
<< g->name() << "\" (" << g->id() << ").\n";
}
network::send_data(response,sock);
network::send_data(response, sock, send_gzipped_);
return;
// If this is data describing the level for a game.
} else if (data.child("side") != NULL) {
@ -1088,7 +1106,7 @@ void server::process_data_game(const network::connection sock, const config& dat
} else if (data.child("load_next_scenario") != NULL) {
config cfg_scenario;
cfg_scenario.add_child("next_scenario", g->level());
network::send_data(cfg_scenario, sock);
network::send_data(cfg_scenario, sock, send_gzipped_);
//Since every client decides himself when to get the data of the next
//scenario, we must not push this to other players.
//push_immediately = false;
@ -1100,7 +1118,7 @@ void server::process_data_game(const network::connection sock, const config& dat
// Send notification of the game starting immediately.
// g->start_game() will send data that assumes
// the [start_game] message has been sent
g->send_data(data,sock);
g->send_data(data, sock);
LOG_SERVER << network::ip_address(sock) << "\t" << pl->second.name()
<< "\tstarted game:\t\"" << g->name() << "\" (" << g->id() << ").\n";
@ -1131,10 +1149,10 @@ void server::process_data_game(const network::connection sock, const config& dat
<< (obs ? ") as an observer.\n" : ").\n");
}
// Send the player who has quit the game list
network::send_data(games_and_users_list_,sock);
network::send_data(games_and_users_list_, sock, send_gzipped_);
// Send all other players in the lobby the update to the lobby
lobby_.send_data(games_and_users_list_diff(),sock);
lobby_.send_data(games_and_users_list_diff(), sock);
return;
// If this is data describing side changes (so far only by the host).
} else if (data.child("scenario_diff")) {
@ -1176,7 +1194,7 @@ void server::process_data_game(const network::connection sock, const config& dat
bool ban = (data.child("ban") != NULL);
if (!g->is_owner(sock)) {
network::send_data(g->construct_server_message("You cannot "
+ *(ban ? "ban" : "kick") + *": not the game host."), sock);
+ *(ban ? "ban" : "kick") + *": not the game host."), sock, send_gzipped_);
return;
}
const network::connection user = (ban ? g->ban_user(*data.child("ban"))
@ -1185,7 +1203,7 @@ void server::process_data_game(const network::connection sock, const config& dat
lobby_.add_player(user, true);
g->describe_slots();
// Send the removed user the lobby game list.
network::send_data(games_and_users_list_, user);
network::send_data(games_and_users_list_, user, send_gzipped_);
// Send all other players in the lobby the update to the lobby.
lobby_.send_data(games_and_users_list_diff(), sock);
}
@ -1229,7 +1247,7 @@ void server::process_data_game(const network::connection sock, const config& dat
{
network::send_data(g->construct_server_message(
"You have been muted, others can't see your message!"),
pl->first);
pl->first, send_gzipped_);
return;
}
truncate_message((*speak)["message"]);
@ -1273,7 +1291,7 @@ void server::process_data_game(const network::connection sock, const config& dat
// except for the original data sender
// FIXME: Relaying arbitrary data that possibly didn't get handled at all
// seems like a bad idea.
g->send_data(data,sock);
g->send_data(data, sock);
if (g->started()) {
g->record_data(data);