Added network bandwidth usage statistics collection code for server
This commit is contained in:
parent
4aa84be8ec
commit
cd49b14af2
6 changed files with 352 additions and 70 deletions
221
src/network.cpp
221
src/network.cpp
|
@ -25,6 +25,8 @@
|
|||
#include "network_worker.hpp"
|
||||
#include "thread.hpp"
|
||||
|
||||
#include "filesystem.hpp"
|
||||
|
||||
#include "SDL_net.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
@ -32,6 +34,7 @@
|
|||
#include <cerrno>
|
||||
#include <queue>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <ctime>
|
||||
|
@ -625,11 +628,19 @@ void queue_disconnect(network::connection sock)
|
|||
disconnection_queue.push_back(sock);
|
||||
}
|
||||
|
||||
connection receive_data(config& cfg, connection connection_num, unsigned int timeout)
|
||||
connection receive_data(config& cfg, connection connection_num, unsigned int timeout
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
, bandwidth_in_ptr* bandwidth_in
|
||||
#endif
|
||||
)
|
||||
{
|
||||
unsigned int start_ticks = SDL_GetTicks();
|
||||
while(true) {
|
||||
const connection res = receive_data(cfg,connection_num);
|
||||
const connection res = receive_data(cfg,connection_num
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
,(bool*)0 , bandwidth_in
|
||||
#endif
|
||||
);
|
||||
if(res != 0) {
|
||||
return res;
|
||||
}
|
||||
|
@ -647,7 +658,11 @@ connection receive_data(config& cfg, connection connection_num, unsigned int tim
|
|||
return 0;
|
||||
}
|
||||
|
||||
connection receive_data(config& cfg, connection connection_num, bool* gzipped)
|
||||
connection receive_data(config& cfg, connection connection_num, bool* gzipped
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
, bandwidth_in_ptr* bandwidth_in
|
||||
#endif
|
||||
)
|
||||
{
|
||||
if(!socket_set) {
|
||||
return 0;
|
||||
|
@ -702,7 +717,18 @@ connection receive_data(config& cfg, connection connection_num, bool* gzipped)
|
|||
|
||||
TCPsocket sock = connection_num == 0 ? 0 : get_socket(connection_num);
|
||||
TCPsocket s = sock;
|
||||
sock = network_worker_pool::get_received_data(sock,cfg, gzipped);
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
bandwidth_in_ptr temp;
|
||||
if (!bandwidth_in)
|
||||
{
|
||||
bandwidth_in = &temp;
|
||||
}
|
||||
#endif
|
||||
sock = network_worker_pool::get_received_data(sock,cfg, gzipped
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
, *bandwidth_in
|
||||
#endif
|
||||
);
|
||||
if (sock == NULL) {
|
||||
if (!is_server() && last_ping != 0 && ping_timeout != 0)
|
||||
{
|
||||
|
@ -746,7 +772,11 @@ connection receive_data(config& cfg, connection connection_num, bool* gzipped)
|
|||
return result;
|
||||
}
|
||||
|
||||
connection receive_data(std::vector<char>& buf)
|
||||
connection receive_data(std::vector<char>& buf
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
, bandwidth_in_ptr* bandwidth_in
|
||||
#endif
|
||||
)
|
||||
{
|
||||
if(!socket_set) {
|
||||
return 0;
|
||||
|
@ -804,6 +834,18 @@ connection receive_data(std::vector<char>& buf)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
{
|
||||
bandwidth_in_ptr temp;
|
||||
if (!bandwidth_in)
|
||||
{
|
||||
bandwidth_in = &temp;
|
||||
}
|
||||
const int headers = 5;
|
||||
bandwidth_in->reset(new network::bandwidth_in(buf.size() + headers));
|
||||
}
|
||||
#endif
|
||||
|
||||
SDLNet_TCP_AddSocket(socket_set,sock);
|
||||
|
||||
connection result = 0;
|
||||
|
@ -818,8 +860,137 @@ connection receive_data(std::vector<char>& buf)
|
|||
waiting_sockets.insert(result);
|
||||
return result;
|
||||
}
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
struct bandwidth_stats {
|
||||
int out_packets;
|
||||
int out_bytes;
|
||||
int in_packets;
|
||||
int in_bytes;
|
||||
int day;
|
||||
const static size_t type_width = 16;
|
||||
const static size_t packet_width = 7;
|
||||
const static size_t bytes_width = 10;
|
||||
bandwidth_stats& operator+=(const bandwidth_stats& a)
|
||||
{
|
||||
out_packets += a.out_packets;
|
||||
out_bytes += a.out_bytes;
|
||||
in_packets += a.in_packets;
|
||||
in_bytes += a.in_bytes;
|
||||
|
||||
void send_file(const std::string& filename, connection connection_num)
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
typedef std::map<const std::string, bandwidth_stats> bandwidth_map;
|
||||
typedef std::vector<bandwidth_map> hour_stats_vector;
|
||||
hour_stats_vector hour_stats(24);
|
||||
|
||||
|
||||
|
||||
static bandwidth_map::iterator add_bandwidth_entry(const std::string packet_type)
|
||||
{
|
||||
time_t now = time(0);
|
||||
struct tm * timeinfo = localtime(&now);
|
||||
int hour = timeinfo->tm_hour;
|
||||
int day = timeinfo->tm_mday;
|
||||
assert(hour < 24 && hour >= 0);
|
||||
std::pair<bandwidth_map::iterator,bool> insertion = hour_stats[hour].insert(std::make_pair(packet_type, bandwidth_stats()));
|
||||
if (!insertion.second && day != inserted->second.day)
|
||||
{
|
||||
// clear previuos day stats
|
||||
hour[hour].clear();
|
||||
//insert again to cleared map
|
||||
insertion = hour_stats[hour].insert(std::make_pair(packet_type, bandwidth_stats()));
|
||||
}
|
||||
bandwidth_map::iterator inserted = insertion.first;
|
||||
inserted->second.day = day;
|
||||
return inserted;
|
||||
}
|
||||
|
||||
typedef boost::shared_ptr<bandwidth_stats> bandwidth_stats_ptr;
|
||||
|
||||
|
||||
struct bandwidth_stats_output {
|
||||
bandwidth_stats_output(std::stringstream& ss) : ss_(ss), totals_(new bandwidth_stats())
|
||||
{}
|
||||
void operator()(const bandwidth_map::value_type& stats)
|
||||
{
|
||||
// name
|
||||
ss_ << " " << std::setw(bandwidth_stats::type_width) << stats.first << "| "
|
||||
<< std::setw(bandwidth_stats::packet_width)<< stats.second.out_packets << "| "
|
||||
<< std::setw(bandwidth_stats::bytes_width) << stats.second.out_bytes/1024 << "| "
|
||||
<< std::setw(bandwidth_stats::packet_width)<< stats.second.in_packets << "| "
|
||||
<< std::setw(bandwidth_stats::bytes_width) << stats.second.in_bytes/1024 << "\n";
|
||||
*totals_ += stats.second;
|
||||
}
|
||||
void output_totals()
|
||||
{
|
||||
(*this)(std::make_pair(std::string("total"), *totals_));
|
||||
}
|
||||
private:
|
||||
std::stringstream& ss_;
|
||||
bandwidth_stats_ptr totals_;
|
||||
};
|
||||
|
||||
std::string get_bandwidth_stats_all()
|
||||
{
|
||||
std::string result;
|
||||
for (int hour = 0; hour < 24; ++hour)
|
||||
{
|
||||
result += get_bandwidth_stats(hour);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string get_bandwidth_stats()
|
||||
{
|
||||
time_t now = time(0);
|
||||
struct tm * timeinfo = localtime(&now);
|
||||
int hour = timeinfo->tm_hour - 1;
|
||||
if (hour < 0)
|
||||
hour = 23;
|
||||
return get_bandwidth_stats(hour);
|
||||
}
|
||||
|
||||
std::string get_bandwidth_stats(int hour)
|
||||
{
|
||||
assert(hour < 24 && hour >= 0);
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "Hour stat starting from " << hour << "\n " << std::left << std::setw(bandwidth_stats::type_width) << "Type of packet" << "| "
|
||||
<< std::setw(bandwidth_stats::packet_width)<< "out #" << "| "
|
||||
<< std::setw(bandwidth_stats::bytes_width) << "out kb" << "| "
|
||||
<< std::setw(bandwidth_stats::packet_width)<< "in #" << "| "
|
||||
<< std::setw(bandwidth_stats::bytes_width) << "in kb" << "\n";
|
||||
|
||||
bandwidth_stats_output outputer(ss);
|
||||
std::for_each(hour_stats[hour].begin(), hour_stats[hour].end(), outputer);
|
||||
|
||||
outputer.output_totals();
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void add_bandwidth_out(const std::string packet_type, size_t len)
|
||||
{
|
||||
bandwidth_map::iterator itor = add_bandwidth_entry(packet_type);
|
||||
itor->second.out_bytes += len;
|
||||
++(itor->second.out_packets);
|
||||
}
|
||||
|
||||
void add_bandwidth_in(const std::string packet_type, size_t len)
|
||||
{
|
||||
bandwidth_map::iterator itor = add_bandwidth_entry(packet_type);
|
||||
itor->second.in_bytes += len;
|
||||
++(itor->second.in_packets);
|
||||
}
|
||||
|
||||
bandwidth_in::~bandwidth_in()
|
||||
{
|
||||
add_bandwidth_in(type_, len_);
|
||||
}
|
||||
|
||||
#endif
|
||||
void send_file(const std::string& filename, connection connection_num, const std::string packet_type
|
||||
)
|
||||
{
|
||||
assert(connection_num > 0);
|
||||
if(bad_sockets.count(connection_num) || bad_sockets.count(0)) {
|
||||
|
@ -833,6 +1004,10 @@ void send_file(const std::string& filename, connection connection_num)
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
const int packet_headers = 5;
|
||||
add_bandwidth_out(packet_type, file_size(filename) + packet_headers);
|
||||
#endif
|
||||
network_worker_pool::queue_file(info->second.sock, filename);
|
||||
|
||||
}
|
||||
|
@ -840,7 +1015,8 @@ void send_file(const std::string& filename, 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)
|
||||
void send_data(const config& cfg, connection connection_num, const bool gzipped, const std::string packet_type
|
||||
)
|
||||
{
|
||||
DBG_NW << "in send_data()...\n";
|
||||
|
||||
|
@ -858,7 +1034,11 @@ void send_data(const config& cfg, connection connection_num, const bool gzipped)
|
|||
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, gzipped);
|
||||
send_data(cfg,*i, gzipped
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
, packet_type
|
||||
#endif
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -871,10 +1051,15 @@ void send_data(const config& cfg, connection connection_num, const bool gzipped)
|
|||
}
|
||||
|
||||
LOG_NW << "SENDING to: " << connection_num << ": " << cfg;
|
||||
network_worker_pool::queue_data(info->second.sock, cfg, gzipped);
|
||||
network_worker_pool::queue_data(info->second.sock, cfg, gzipped
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
, packet_type
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
void send_raw_data(const char* buf, int len, connection connection_num)
|
||||
void send_raw_data(const char* buf, int len, connection connection_num, const std::string packet_type
|
||||
)
|
||||
{
|
||||
if(len == 0) {
|
||||
return;
|
||||
|
@ -887,7 +1072,8 @@ void send_raw_data(const char* buf, int len, connection connection_num)
|
|||
if(!connection_num) {
|
||||
for(sockets_list::const_iterator i = sockets.begin();
|
||||
i != sockets.end(); ++i) {
|
||||
send_raw_data(buf, len, connection_num);
|
||||
send_raw_data(buf, len, connection_num, packet_type
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -898,6 +1084,10 @@ void send_raw_data(const char* buf, int len, connection connection_num)
|
|||
<< "\tnot found in connection_map. Not sending...\n";
|
||||
return;
|
||||
}
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
const int packet_headers = 5;
|
||||
add_bandwidth_out(packet_type, len + packet_headers);
|
||||
#endif
|
||||
|
||||
network_worker_pool::queue_raw_data(info->second.sock, buf, len);
|
||||
}
|
||||
|
@ -908,14 +1098,19 @@ void process_send_queue(connection, size_t)
|
|||
}
|
||||
|
||||
//! @todo Note the gzipped parameter should be removed later.
|
||||
void send_data_all_except(const config& cfg, connection connection_num, const bool gzipped)
|
||||
void send_data_all_except(const config& cfg, connection connection_num, const bool gzipped, const std::string packet_type
|
||||
)
|
||||
{
|
||||
for(sockets_list::const_iterator i = sockets.begin(); i != sockets.end(); ++i) {
|
||||
if(*i == connection_num) {
|
||||
continue;
|
||||
}
|
||||
|
||||
send_data(cfg,*i, gzipped);
|
||||
send_data(cfg,*i, gzipped
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
, packet_type
|
||||
#endif
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,10 @@
|
|||
|
||||
#ifndef NETWORK_HPP_INCLUDED
|
||||
#define NETWORK_HPP_INCLUDED
|
||||
/**
|
||||
* Enable bandwidth stats
|
||||
**/
|
||||
//#define BANDWIDTH_MONITOR
|
||||
|
||||
class config;
|
||||
|
||||
|
@ -25,6 +29,8 @@ class config;
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace threading
|
||||
{
|
||||
class waiter;
|
||||
|
@ -121,6 +127,35 @@ bool disconnect(connection connection_num=0, bool force=false);
|
|||
//! on the given connection (and presumably then the handling of the error
|
||||
//! will include closing the connection).
|
||||
void queue_disconnect(connection connection_num);
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
|
||||
std::string get_bandwidth_stats();
|
||||
std::string get_bandwidth_stats_all();
|
||||
std::string get_bandwidth_stats(int hour);
|
||||
|
||||
void add_bandwidth_out(const std::string packet_type, size_t len);
|
||||
void add_bandwidth_in(const std::string packet_type, size_t len);
|
||||
struct bandwidth_in {
|
||||
bandwidth_in(int len) : len_(len), type_("unknown") {}
|
||||
~bandwidth_in();
|
||||
// {
|
||||
// network::add_bandwidth_in(type_, len_);
|
||||
// }
|
||||
|
||||
void set_type(const std::string& type)
|
||||
{
|
||||
type_ = type;
|
||||
}
|
||||
|
||||
private:
|
||||
int len_;
|
||||
std::string type_;
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<bandwidth_in> bandwidth_in_ptr;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//! Function to receive data from either a certain connection,
|
||||
//! or all connections if connection_num is 0.
|
||||
|
@ -129,18 +164,30 @@ void queue_disconnect(connection connection_num);
|
|||
//! Returns the connection that data was received from,
|
||||
//! or 0 if timeout occurred.
|
||||
//! Throws error if an error occurred.
|
||||
connection receive_data(config& cfg, connection connection_num=0, bool* gzipped = 0);
|
||||
connection receive_data(config& cfg, connection connection_num, unsigned int timeout);
|
||||
connection receive_data(std::vector<char>& buf);
|
||||
connection receive_data(config& cfg, connection connection_num=0, bool* gzipped = 0
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
, bandwidth_in_ptr* b = 0
|
||||
#endif
|
||||
);
|
||||
connection receive_data(config& cfg, connection connection_num, unsigned int timeout
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
, bandwidth_in_ptr* b = 0
|
||||
#endif
|
||||
);
|
||||
connection receive_data(std::vector<char>& buf
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
, bandwidth_in_ptr* = 0
|
||||
#endif
|
||||
);
|
||||
|
||||
void send_file(const std::string&, connection);
|
||||
void send_file(const std::string&, connection, const std::string packet_type = "unknown");
|
||||
|
||||
//! 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*/, const bool gzipped);
|
||||
void send_data(const config& cfg, connection connection_num /*= 0*/, const bool gzipped, const std::string packet_type = "unknown");
|
||||
|
||||
void send_raw_data(const char* buf, int len, connection connection_num);
|
||||
void send_raw_data(const char* buf, int len, connection connection_num, const std::string packet_type = "unknown");
|
||||
|
||||
//! Function to send any data that is in a connection's send_queue,
|
||||
//! up to a maximum of 'max_size' bytes --
|
||||
|
@ -148,7 +195,8 @@ void send_raw_data(const char* buf, int len, connection connection_num);
|
|||
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, const bool gzipped);
|
||||
void send_data_all_except(const config& cfg, connection connection_num, const bool gzipped, const std::string packet_type = "unknown"
|
||||
);
|
||||
|
||||
//! Function to get the remote ip address of a socket.
|
||||
std::string ip_address(connection connection_num);
|
||||
|
|
|
@ -806,7 +806,11 @@ void receive_data(TCPsocket sock)
|
|||
}
|
||||
}
|
||||
|
||||
TCPsocket get_received_data(TCPsocket sock, config& cfg, bool* gzipped)
|
||||
TCPsocket get_received_data(TCPsocket sock, config& cfg, bool* gzipped
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
,network::bandwidth_in_ptr& bandwidth_in
|
||||
#endif
|
||||
)
|
||||
{
|
||||
assert(!raw_data_only);
|
||||
const threading::lock lock_received(*received_mutex);
|
||||
|
@ -837,6 +841,9 @@ TCPsocket get_received_data(TCPsocket sock, config& cfg, bool* gzipped)
|
|||
if (gzipped)
|
||||
*gzipped = buf->gzipped;
|
||||
received_data_queue.erase(itor);
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
bandwidth_in.reset(new network::bandwidth_in((*itor)->raw_buffer.size()));
|
||||
#endif
|
||||
delete buf;
|
||||
return res;
|
||||
}
|
||||
|
@ -890,13 +897,20 @@ void queue_raw_data(TCPsocket sock, const char* buf, int len)
|
|||
queue_buffer(sock, queued_buf);
|
||||
}
|
||||
|
||||
void queue_data(TCPsocket sock,const config& buf, const bool gzipped)
|
||||
void queue_data(TCPsocket sock,const config& buf, const bool gzipped
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
, const std::string& packet_type
|
||||
#endif
|
||||
)
|
||||
{
|
||||
DBG_NW << "queuing data...\n";
|
||||
|
||||
buffer* queued_buf = new buffer(sock);
|
||||
output_to_buffer(sock, buf, queued_buf->stream, gzipped);
|
||||
queued_buf->gzipped = gzipped;
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
network::add_bandwidth_out(packet_type, queued_buf->stream.str().size());
|
||||
#endif
|
||||
queue_buffer(sock, queued_buf);
|
||||
}
|
||||
|
||||
|
|
|
@ -51,13 +51,21 @@ void set_raw_data_only();
|
|||
//! Function to asynchronously received data to the given socket.
|
||||
void receive_data(TCPsocket sock);
|
||||
|
||||
TCPsocket get_received_data(TCPsocket sock, config& cfg, bool* gzipped = 0);
|
||||
TCPsocket get_received_data(TCPsocket sock, config& cfg, bool* gzipped
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
, network::bandwidth_in_ptr&
|
||||
#endif
|
||||
);
|
||||
TCPsocket get_received_data(std::vector<char>& buf);
|
||||
|
||||
void queue_file(TCPsocket sock, const std::string&);
|
||||
|
||||
void queue_raw_data(TCPsocket sock, const char* buf, int len);
|
||||
void queue_data(TCPsocket sock, const config& buf, const bool gzipped);
|
||||
void queue_data(TCPsocket sock, const config& buf, const bool gzipped
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
, const std::string& packet_type
|
||||
#endif
|
||||
);
|
||||
bool is_locked(const TCPsocket sock);
|
||||
bool close_socket(TCPsocket sock, bool force=false);
|
||||
TCPsocket detect_error();
|
||||
|
|
|
@ -214,7 +214,7 @@ bool game::take_side(const player_map::const_iterator user)
|
|||
// Tell the host which side the new player should take.
|
||||
|
||||
simple_wml::string_span data = cfg.output_compressed();
|
||||
network::send_raw_data(data.begin(), data.size(), owner_);
|
||||
network::send_raw_data(data.begin(), data.size(), owner_, "game");
|
||||
DBG_GAME << "take_side: took side " << side_num << " because the name matched\n";
|
||||
DBG_GAME << debug_player_info();
|
||||
return true;
|
||||
|
@ -236,7 +236,7 @@ bool game::take_side(const player_map::const_iterator user)
|
|||
cfg.root().set_attr_dup("side", (**side)["side"]);
|
||||
// Tell the host which side the new player should take.
|
||||
simple_wml::string_span data = cfg.output_compressed();
|
||||
network::send_raw_data(data.begin(), data.size(), owner_);
|
||||
network::send_raw_data(data.begin(), data.size(), owner_, "game");
|
||||
DBG_GAME << "take_side: took the first free network side which was " << side_num << "\n";
|
||||
DBG_GAME << debug_player_info();
|
||||
return true;
|
||||
|
@ -469,7 +469,7 @@ void game::transfer_ai_sides() {
|
|||
drop.root().set_attr("side_drop", side_drop.c_str());
|
||||
drop.root().set_attr("controller", "ai");
|
||||
const simple_wml::string_span data = drop.output_compressed();
|
||||
network::send_raw_data(data.begin(), data.size(), owner_);
|
||||
network::send_raw_data(data.begin(), data.size(), owner_, "game");
|
||||
sides_[side] = owner_;
|
||||
}
|
||||
if (ai_transfer) {
|
||||
|
@ -488,7 +488,7 @@ void game::notify_new_host(){
|
|||
cfg_host_transfer.set_attr("name", owner_name.c_str());
|
||||
cfg_host_transfer.set_attr("value", "1");
|
||||
const simple_wml::string_span data = cfg.output_compressed();
|
||||
network::send_raw_data(data.begin(), data.size(), owner_);
|
||||
network::send_raw_data(data.begin(), data.size(), owner_,"game");
|
||||
send_and_record_server_message((owner_name
|
||||
+ " has been chosen as the new host.").c_str());
|
||||
}
|
||||
|
@ -612,7 +612,7 @@ network::connection game::kick_member(const simple_wml::node& kick,
|
|||
// Tell the user to leave the game.
|
||||
static simple_wml::document leave_game("[leave_game]\n[/leave_game]\n", simple_wml::INIT_COMPRESSED);
|
||||
static const simple_wml::string_span leave_game_data = leave_game.output_compressed();
|
||||
network::send_raw_data(leave_game_data.begin(), leave_game_data.size(), user->first);
|
||||
network::send_raw_data(leave_game_data.begin(), leave_game_data.size(), user->first,"game");
|
||||
remove_player(user->first);
|
||||
return user->first;
|
||||
}
|
||||
|
@ -653,7 +653,7 @@ network::connection game::ban_user(const simple_wml::node& ban,
|
|||
//tell the user to leave the game.
|
||||
static simple_wml::document leave_game("[leave_game]\n[/leave_game]\n", simple_wml::INIT_COMPRESSED);
|
||||
static const simple_wml::string_span leave_game_data = leave_game.output_compressed();
|
||||
network::send_raw_data(leave_game_data.begin(), leave_game_data.size(), user->first);
|
||||
network::send_raw_data(leave_game_data.begin(), leave_game_data.size(), user->first,"game");
|
||||
remove_player(user->first);
|
||||
return user->first;
|
||||
}
|
||||
|
@ -900,12 +900,12 @@ void game::add_player(const network::connection player, bool observer) {
|
|||
// Send the user the game data.
|
||||
//std::cerr << "SENDING LEVEL {{{" << level_.output() << "}}}\n";
|
||||
simple_wml::string_span level_data = level_.output_compressed();
|
||||
network::send_raw_data(level_data.begin(), level_data.size(), player);
|
||||
network::send_raw_data(level_data.begin(), level_data.size(), player,"game");
|
||||
if(started_) {
|
||||
//tell this player that the game has started
|
||||
static simple_wml::document start_game_doc("[start_game]\n[/start_game]\n", simple_wml::INIT_COMPRESSED);
|
||||
static const simple_wml::string_span start_game = start_game_doc.output_compressed();
|
||||
network::send_raw_data(start_game.begin(), start_game.size(), player);
|
||||
network::send_raw_data(start_game.begin(), start_game.size(), player,"game");
|
||||
// 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.
|
||||
|
@ -1043,7 +1043,7 @@ void game::load_next_scenario(const player_map::const_iterator user) const {
|
|||
simple_wml::document cfg_scenario;
|
||||
level_.root().copy_into(cfg_scenario.root().add_child("next_scenario"));
|
||||
simple_wml::string_span data = cfg_scenario.output_compressed();
|
||||
network::send_raw_data(data.begin(), data.size(), user->first);
|
||||
network::send_raw_data(data.begin(), data.size(), user->first, "game");
|
||||
// Send the player the history of the game to-date.
|
||||
send_history(user->first);
|
||||
// Send observer join of all the observers in the game to the user.
|
||||
|
@ -1056,7 +1056,7 @@ void game::send_data(simple_wml::document& data, const network::connection exclu
|
|||
const user_vector& users = all_game_users();
|
||||
for(user_vector::const_iterator i = users.begin(); i != users.end(); ++i) {
|
||||
if (*i != exclude) {
|
||||
network::send_raw_data(s.begin(), s.size(), *i);
|
||||
network::send_raw_data(s.begin(), s.size(), *i, "user_diff");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1064,7 +1064,7 @@ void game::send_data(simple_wml::document& data, const network::connection exclu
|
|||
void game::send_to_one(simple_wml::document& data, const network::connection sock) const
|
||||
{
|
||||
simple_wml::string_span s = data.output_compressed();
|
||||
network::send_raw_data(s.begin(), s.size(), sock);
|
||||
network::send_raw_data(s.begin(), s.size(), sock,"game");
|
||||
}
|
||||
|
||||
void game::send_data_team(simple_wml::document& data,
|
||||
|
@ -1074,7 +1074,7 @@ void game::send_data_team(simple_wml::document& data,
|
|||
simple_wml::string_span s = data.output_compressed();
|
||||
for(user_vector::const_iterator i = players_.begin(); i != players_.end(); ++i) {
|
||||
if(*i != exclude && is_on_team(team,*i)) {
|
||||
network::send_raw_data(s.begin(), s.size(), *i);
|
||||
network::send_raw_data(s.begin(), s.size(), *i, "game");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1083,7 +1083,7 @@ void game::send_data_observers(simple_wml::document& data, const network::connec
|
|||
simple_wml::string_span s = data.output_compressed();
|
||||
for(user_vector::const_iterator i = observers_.begin(); i != observers_.end(); ++i) {
|
||||
if (*i != exclude) {
|
||||
network::send_raw_data(s.begin(), s.size(), *i);
|
||||
network::send_raw_data(s.begin(), s.size(), *i,"game");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1127,7 +1127,7 @@ void game::send_observerjoins(const network::connection sock) const {
|
|||
} else {
|
||||
// Send to the (new) user.
|
||||
const simple_wml::string_span& data = cfg.output_compressed();
|
||||
network::send_raw_data(data.begin(), data.size(), sock);
|
||||
network::send_raw_data(data.begin(), data.size(), sock,"game");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1163,7 +1163,7 @@ void game::send_history(const network::connection sock) const
|
|||
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);
|
||||
network::send_raw_data(data.begin(), data.size(), sock,"game_history");
|
||||
history_.clear();
|
||||
history_.push_back(doc);
|
||||
}
|
||||
|
|
|
@ -113,10 +113,10 @@ namespace {
|
|||
// we take profiling info on every n requests
|
||||
int request_sample_frequency = 1;
|
||||
|
||||
void send_doc(simple_wml::document& doc, network::connection connection)
|
||||
void send_doc(simple_wml::document& doc, network::connection connection, std::string type = "unknown")
|
||||
{
|
||||
simple_wml::string_span s = doc.output_compressed();
|
||||
network::send_raw_data(s.begin(), s.size(), connection);
|
||||
network::send_raw_data(s.begin(), s.size(), connection, type);
|
||||
}
|
||||
|
||||
void make_add_diff(const simple_wml::node& src, const char* gamelist,
|
||||
|
@ -322,7 +322,7 @@ void server::send_error(network::connection sock, const char* msg) const
|
|||
simple_wml::document doc;
|
||||
doc.root().add_child("error").set_attr("message", msg);
|
||||
simple_wml::string_span output = doc.output_compressed();
|
||||
network::send_raw_data(output.begin(), output.size(), sock);
|
||||
network::send_raw_data(output.begin(), output.size(), sock, "error");
|
||||
}
|
||||
|
||||
void server::send_error_dup(network::connection sock, const std::string& msg) const
|
||||
|
@ -330,7 +330,7 @@ void server::send_error_dup(network::connection sock, const std::string& msg) co
|
|||
simple_wml::document doc;
|
||||
doc.root().add_child("error").set_attr_dup("message", msg.c_str());
|
||||
simple_wml::string_span output = doc.output_compressed();
|
||||
network::send_raw_data(output.begin(), output.size(), sock);
|
||||
network::send_raw_data(output.begin(), output.size(), sock, "error");
|
||||
}
|
||||
|
||||
config server::read_config() const {
|
||||
|
@ -489,7 +489,7 @@ void server::run() {
|
|||
for (player_map::const_iterator i = players_.begin();
|
||||
i != players_.end(); ++i)
|
||||
{
|
||||
network::send_data(ping, i->first, true);
|
||||
network::send_data(ping, i->first, true, "ping");
|
||||
}
|
||||
last_ping_ = now;
|
||||
}
|
||||
|
@ -510,7 +510,7 @@ void server::run() {
|
|||
} else {
|
||||
DBG_SERVER << ip << "\tnew connection accepted. (socket: "
|
||||
<< sock << ")\n";
|
||||
send_doc(version_query_response_, sock);
|
||||
send_doc(version_query_response_, sock,"command");
|
||||
not_logged_in_.add_player(sock, true);
|
||||
}
|
||||
}
|
||||
|
@ -518,7 +518,14 @@ void server::run() {
|
|||
static int sample_counter = 0;
|
||||
|
||||
std::vector<char> buf;
|
||||
while ((sock = network::receive_data(buf)) != network::null_connection) {
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
network::bandwidth_in_ptr bandwidth_type;
|
||||
#endif
|
||||
while ((sock = network::receive_data(buf
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
, &bandwidth_type
|
||||
#endif
|
||||
)) != network::null_connection) {
|
||||
metrics_.service_request();
|
||||
|
||||
if(buf.empty()) {
|
||||
|
@ -553,6 +560,9 @@ void server::run() {
|
|||
|
||||
process_data(sock, data);
|
||||
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
bandwidth_type->set_type("command");
|
||||
#endif
|
||||
if(sample) {
|
||||
const clock_t after_processing = get_cpu_time(sample);
|
||||
metrics_.record_sample(data.root().first_child(),
|
||||
|
@ -693,7 +703,7 @@ void server::process_login(const network::connection sock,
|
|||
LOG_SERVER << network::ip_address(sock)
|
||||
<< "\tplayer joined using accepted version " << version_str
|
||||
<< ":\ttelling them to log in.\n";
|
||||
send_doc(login_response_, sock);
|
||||
send_doc(login_response_, sock, "command");
|
||||
return;
|
||||
}
|
||||
std::map<std::string,config>::const_iterator config_it;
|
||||
|
@ -711,7 +721,7 @@ void server::process_login(const network::connection sock,
|
|||
<< ":" << config_it->second["port"] << "\n";
|
||||
config response;
|
||||
response.add_child("redirect",config_it->second);
|
||||
network::send_data(response, sock, true);
|
||||
network::send_data(response, sock, true, "redirect");
|
||||
return;
|
||||
}
|
||||
// Check if it's a version we should start a proxy for.
|
||||
|
@ -743,7 +753,7 @@ void server::process_login(const network::connection sock,
|
|||
ERR_SERVER << "ERROR: This server doesn't accept any versions at all.\n";
|
||||
response["version"] = "null";
|
||||
}
|
||||
network::send_data(response, sock, true);
|
||||
network::send_data(response, sock, true, "error");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -786,7 +796,7 @@ void server::process_login(const network::connection sock,
|
|||
}
|
||||
}
|
||||
|
||||
send_doc(join_lobby_response_, sock);
|
||||
send_doc(join_lobby_response_, sock, "join_lobby");
|
||||
|
||||
simple_wml::node& player_cfg = games_and_users_list_.root().add_child("user");
|
||||
const player new_player(username, player_cfg, default_max_messages_,
|
||||
|
@ -797,7 +807,7 @@ void server::process_login(const network::connection sock,
|
|||
lobby_.add_player(sock, true);
|
||||
|
||||
// Send the new player the entire list of games and players
|
||||
send_doc(games_and_users_list_, sock);
|
||||
send_doc(games_and_users_list_, sock, "lobby_list");
|
||||
|
||||
if (motd_ != "") {
|
||||
lobby_.send_server_message(motd_.c_str(), sock);
|
||||
|
@ -839,7 +849,7 @@ void server::process_query(const network::connection sock,
|
|||
} else if (command == "status") {
|
||||
response << process_command(command.to_string() + " " + pl->second.name());
|
||||
} else if (command == "status " + pl->second.name() || command == "metrics"
|
||||
|| command == "motd" || command == "wml" || command == "netstats") {
|
||||
|| command == "motd" || command == "wml" || command == "netstats" || command == "netstats all") {
|
||||
response << process_command(command.to_string());
|
||||
} else if (command == admin_passwd_) {
|
||||
LOG_SERVER << "New Admin recognized:" << "\tIP: "
|
||||
|
@ -922,6 +932,12 @@ std::string server::process_command(const std::string& query) {
|
|||
out << "Network stats:\nPending send buffers: "
|
||||
<< stats.npending_sends << "\nBytes in buffers: "
|
||||
<< stats.nbytes_pending_sends << "\n";
|
||||
#ifdef BANDWIDTH_MONITOR
|
||||
if (parameters == "all")
|
||||
out << network::get_bandwidth_stats_all();
|
||||
else
|
||||
out << network::get_bandwidth_stats(); // stats from previuos hour
|
||||
#endif
|
||||
} else if (command == "msg" || command == "lobbymsg") {
|
||||
if (parameters == "") {
|
||||
return "You must type a message.";
|
||||
|
@ -1079,7 +1095,7 @@ void server::process_whisper(const network::connection sock,
|
|||
"message=\"Invalid number of arguments\"\n"
|
||||
"sender=\"server\"\n"
|
||||
"[/message]\n", simple_wml::INIT_COMPRESSED);
|
||||
send_doc(data, sock);
|
||||
send_doc(data, sock, "error");
|
||||
return;
|
||||
}
|
||||
const player_map::const_iterator pl = players_.find(sock);
|
||||
|
@ -1109,7 +1125,7 @@ void server::process_whisper(const network::connection sock,
|
|||
|
||||
simple_wml::document cwhisper;
|
||||
whisper.copy_into(cwhisper.root().add_child("whisper"));
|
||||
send_doc(cwhisper, i->first);
|
||||
send_doc(cwhisper, i->first, "command");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1123,7 +1139,7 @@ void server::process_whisper(const network::connection sock,
|
|||
}
|
||||
|
||||
msg.set_attr("sender", "server");
|
||||
send_doc(data, sock);
|
||||
send_doc(data, sock, "error");
|
||||
}
|
||||
|
||||
void server::process_data_lobby(const network::connection sock,
|
||||
|
@ -1140,9 +1156,9 @@ void server::process_data_lobby(const network::connection sock,
|
|||
if (data.root().child("create_game")) {
|
||||
if (graceful_restart) {
|
||||
static simple_wml::document leave_game_doc("[leave_game]\n[/leave_game]\n", simple_wml::INIT_COMPRESSED);
|
||||
send_doc(leave_game_doc, sock);
|
||||
send_doc(leave_game_doc, sock,"command");
|
||||
lobby_.send_server_message("This server is shutting down. You aren't allowed to make new games. Please reconnect to the new server.", sock);
|
||||
send_doc(games_and_users_list_, sock);
|
||||
send_doc(games_and_users_list_, sock, "lobby_list");
|
||||
return;
|
||||
}
|
||||
const std::string game_name = (*data.root().child("create_game"))["name"].to_string();
|
||||
|
@ -1180,41 +1196,41 @@ void server::process_data_lobby(const network::connection sock,
|
|||
if (g == games_.end()) {
|
||||
WRN_SERVER << network::ip_address(sock) << "\t" << pl->second.name()
|
||||
<< "\tattempted to join unknown game:\t" << game_id << ".\n";
|
||||
send_doc(leave_game_doc, sock);
|
||||
send_doc(leave_game_doc, sock, "command");
|
||||
lobby_.send_server_message("Attempt to join unknown game.", sock);
|
||||
send_doc(games_and_users_list_, sock);
|
||||
send_doc(games_and_users_list_, sock, "lobby_list");
|
||||
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()
|
||||
<< "\" (" << game_id << ").\n";
|
||||
send_doc(leave_game_doc, sock);
|
||||
send_doc(leave_game_doc, sock, "command");
|
||||
lobby_.send_server_message("You are banned from this game.", sock);
|
||||
send_doc(games_and_users_list_, sock);
|
||||
send_doc(games_and_users_list_, sock, "lobby_list");
|
||||
return;
|
||||
} else if(!observer && !(*g)->password_matches(password)) {
|
||||
WRN_SERVER << network::ip_address(sock) << "\t" << pl->second.name()
|
||||
<< "\tattempted to join game:\t\"" << (*g)->name() << "\" ("
|
||||
<< game_id << ") with bad password\n";
|
||||
send_doc(leave_game_doc, sock);
|
||||
send_doc(leave_game_doc, sock, "command");
|
||||
lobby_.send_server_message("Incorrect password.", sock);
|
||||
send_doc(games_and_users_list_, sock);
|
||||
send_doc(games_and_users_list_, sock, "lobby_list");
|
||||
return;
|
||||
} else if (observer && !(*g)->allow_observers()) {
|
||||
WRN_SERVER << network::ip_address(sock) << "\t" << pl->second.name()
|
||||
<< "\tattempted to observe game:\t\"" << (*g)->name() << "\" ("
|
||||
<< game_id << ") which doesn't allow observers.\n";
|
||||
send_doc(leave_game_doc, sock);
|
||||
send_doc(leave_game_doc, sock, "command");
|
||||
lobby_.send_server_message("Attempt to observe a game that doesn't allow observers.", sock);
|
||||
send_doc(games_and_users_list_, sock);
|
||||
send_doc(games_and_users_list_, sock, "lobby_list");
|
||||
return;
|
||||
} else if (!(*g)->level_init()) {
|
||||
WRN_SERVER << network::ip_address(sock) << "\t" << pl->second.name()
|
||||
<< "\tattempted to join uninitialized game:\t\"" << (*g)->name()
|
||||
<< "\" (" << game_id << ").\n";
|
||||
send_doc(leave_game_doc, sock);
|
||||
send_doc(leave_game_doc, sock, "command");
|
||||
lobby_.send_server_message("Attempt to observe a game that doesn't allow observers.", sock);
|
||||
send_doc(games_and_users_list_, sock);
|
||||
send_doc(games_and_users_list_, sock, "lobby_list");
|
||||
return;
|
||||
}
|
||||
LOG_SERVER << network::ip_address(sock) << "\t" << pl->second.name()
|
||||
|
@ -1244,7 +1260,7 @@ void server::process_data_lobby(const network::connection sock,
|
|||
// Player requests update of lobby content,
|
||||
// for example when cancelling the create game dialog
|
||||
if (data.child("refresh_lobby")) {
|
||||
send_doc(games_and_users_list_, sock);
|
||||
send_doc(games_and_users_list_, sock, "lobby_list");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1502,7 +1518,7 @@ void server::process_data_game(const network::connection sock,
|
|||
}
|
||||
|
||||
// Send the player who has quit the gamelist.
|
||||
send_doc(games_and_users_list_, sock);
|
||||
send_doc(games_and_users_list_, sock, "lobby_list");
|
||||
}
|
||||
return;
|
||||
// If this is data describing side changes by the host.
|
||||
|
@ -1555,7 +1571,7 @@ void server::process_data_game(const network::connection sock,
|
|||
update_game_in_lobby(g, user);
|
||||
}
|
||||
// Send the removed user the lobby game list.
|
||||
send_doc(games_and_users_list_, user);
|
||||
send_doc(games_and_users_list_, user, "lobby_list");
|
||||
// FIXME: should also send a user diff to the lobby
|
||||
// to mark this player as available for others
|
||||
}
|
||||
|
@ -1677,6 +1693,7 @@ int main(int argc, char** argv) {
|
|||
std::string config_file;
|
||||
|
||||
#ifndef FIFODIR
|
||||
# warning "No FIFODIR set"
|
||||
# define FIFODIR "/var/run/wesnothd"
|
||||
#endif
|
||||
std::string fifo_path = std::string(FIFODIR) + "/socket";
|
||||
|
|
Loading…
Add table
Reference in a new issue