Exemplo n.º 1
0
void sendAnnounce(std::string action, const std::vector<std::string> & clients_names, double uptime, u32 game_time, float lag, std::string gameid, std::vector<ModSpec> mods) {
	Json::Value server;
	if (action.size())
		server["action"]	= action;
	server["port"]		= g_settings->get("port");
	server["address"]	= g_settings->get("server_address");
	if (action != "delete") {
		server["name"]		= g_settings->get("server_name");
		server["description"]	= g_settings->get("server_description");
		server["version"]	= minetest_version_simple;
		server["url"]		= g_settings->get("server_url");
		server["creative"]	= g_settings->get("creative_mode");
		server["damage"]	= g_settings->get("enable_damage");
		server["password"]	= g_settings->getBool("disallow_empty_password");
		server["pvp"]		= g_settings->getBool("enable_pvp");
		server["clients"]	= (int)clients_names.size();
		server["clients_max"]	= g_settings->get("max_users");
		server["clients_list"]	= Json::Value(Json::arrayValue);
		for(u32 i = 0; i < clients_names.size(); ++i) {
			server["clients_list"].append(clients_names[i]);
		}
		if (uptime >= 1)	server["uptime"]	= (int)uptime;
		if (gameid != "")	server["gameid"]	= gameid;
		if (game_time >= 1)	server["game_time"]	= game_time;
	}

	if(server["action"] == "start") {
		server["dedicated"]	= g_settings->get("server_dedicated");
		server["privs"]		= g_settings->get("default_privs");
		server["rollback"]	= g_settings->getBool("enable_rollback_recording");
		server["liquid_finite"]	= g_settings->getBool("liquid_finite");
		server["mapgen"]	= g_settings->get("mg_name");
		server["can_see_far_names"]	= g_settings->getBool("unlimited_player_transfer_distance");
		server["mods"]		= Json::Value(Json::arrayValue);
		for(std::vector<ModSpec>::iterator m = mods.begin(); m != mods.end(); m++) {
			server["mods"].append(m->name);
		}
		actionstream << "announcing to " << g_settings->get("serverlist_url") << std::endl;
	} else {
		if (lag)
			server["lag"]	= lag;
	}

	Json::FastWriter writer;
	HTTPFetchRequest fetchrequest;
	fetchrequest.url = g_settings->get("serverlist_url") + std::string("/announce");
	std::string query = std::string("json=") + urlencode(writer.write(server));
	if (query.size() < 1000)
		fetchrequest.url += "?" + query;
	else
		fetchrequest.post_fields = query;
	httpfetch_async(fetchrequest);
}
Exemplo n.º 2
0
void sendAnnounce(const std::string &action,
		const std::vector<std::string> &clients_names,
		const double uptime,
		const u32 game_time,
		const float lag,
		const std::string &gameid,
		const std::string &mg_name,
		const std::vector<ModSpec> &mods)
{
#if USE_CURL
	Json::Value server;
	server["action"] = action;
	server["port"]    = g_settings->getU16("port");
	if (g_settings->exists("server_address")) {
		server["address"] = g_settings->get("server_address");
	}
	if (action != "delete") {
		server["name"]         = g_settings->get("server_name");
		server["description"]  = g_settings->get("server_description");
		server["version"]      = minetest_version_simple;
		server["url"]          = g_settings->get("server_url");
		server["creative"]     = g_settings->getBool("creative_mode");
		server["damage"]       = g_settings->getBool("enable_damage");
		server["password"]     = g_settings->getBool("disallow_empty_password");
		server["pvp"]          = g_settings->getBool("enable_pvp");
		if (uptime >= 1)
			server["uptime"]   = (int) uptime;
		if (game_time >= 1)
			server["game_time"]= game_time;
		server["clients"]      = (int) clients_names.size();
		server["clients_max"]  = g_settings->getU16("max_users");
		server["clients_list"] = Json::Value(Json::arrayValue);
		for (std::vector<std::string>::const_iterator it = clients_names.begin();
				it != clients_names.end();
				++it) {
			server["clients_list"].append(*it);
		}
		if (gameid != "") server["gameid"] = gameid;
	}

	if (action == "start") {
		server["dedicated"]         = g_settings->getBool("server_dedicated");
		server["rollback"]          = g_settings->getBool("enable_rollback_recording");
		server["mapgen"]            = mg_name;
		server["privs"]             = g_settings->get("default_privs");
		server["can_see_far_names"] = g_settings->getS16("player_transfer_distance") <= 0;
		server["liquid_real"]       = g_settings->getBool("liquid_real");
		server["mods"]              = Json::Value(Json::arrayValue);
		for (std::vector<ModSpec>::const_iterator it = mods.begin();
				it != mods.end();
				++it) {
			server["mods"].append(it->name);
		}
		actionstream << "Announcing to " << g_settings->get("serverlist_url") << std::endl;
	} else {
		if (lag)
			server["lag"] = lag;
	}

	Json::FastWriter writer;
	HTTPFetchRequest fetch_request;
	fetch_request.timeout = fetch_request.connect_timeout = 59000;
	fetch_request.url = g_settings->get("serverlist_url") + std::string("/announce");

	std::string query = std::string("json=") + urlencode(writer.write(server));
	if (query.size() < 1000)
		fetch_request.url += "?" + query;
	else
		fetch_request.post_data = query;

/*
	fetch_request.post_fields["json"] = writer.write(server);
	fetch_request.multipart = true;
*/

	httpfetch_async(fetch_request);
#endif
}
Exemplo n.º 3
0
void ClientMediaDownloader::startRemoteMediaTransfers()
{
	bool changing_name_bound = true;

	for (std::map<std::string, FileStatus*>::iterator
			files_iter = m_files.upper_bound(m_name_bound);
			files_iter != m_files.end(); ++files_iter) {

		// Abort if active fetch limit is exceeded
		if (m_httpfetch_active >= m_httpfetch_active_limit)
			break;

		const std::string &name = files_iter->first;
		FileStatus *filestatus = files_iter->second;

		if (!filestatus->received && filestatus->current_remote < 0) {
			// File has not been received yet and is not currently
			// being transferred. Choose a server for it.
			s32 remote_id = selectRemoteServer(filestatus);
			if (remote_id >= 0) {
				// Found a server, so start fetching
				RemoteServerStatus *remote =
					m_remotes[remote_id];

				std::string url = remote->baseurl +
					(remote->request_by_filename ? name :
					hex_encode(filestatus->sha1));
				verbosestream << "Client: "
					<< "Requesting remote media file "
					<< "\"" << name << "\" "
					<< "\"" << url << "\"" << std::endl;

				HTTPFetchRequest fetchrequest;
				fetchrequest.url = url;
				fetchrequest.caller = m_httpfetch_caller;
				fetchrequest.request_id = m_httpfetch_next_id;
				fetchrequest.timeout = 0; // no data timeout!
				fetchrequest.connect_timeout =
					m_httpfetch_timeout;
				httpfetch_async(fetchrequest);

				m_remote_file_transfers.insert(std::make_pair(
							m_httpfetch_next_id,
							name));

				filestatus->current_remote = remote_id;
				remote->active_count++;
				m_httpfetch_active++;
				m_httpfetch_next_id++;
			}
		}

		if (filestatus->received ||
				(filestatus->current_remote < 0 &&
				 !m_outstanding_hash_sets)) {
			// If we arrive here, we conclusively know that we
			// won't fetch this file from a remote server in the
			// future. So update the name bound if possible.
			if (changing_name_bound)
				m_name_bound = name;
		}
		else
			changing_name_bound = false;
	}

}
Exemplo n.º 4
0
void ClientMediaDownloader::initialStep(Client *client)
{
	// Check media cache
	m_uncached_count = m_files.size();
	for (std::map<std::string, FileStatus*>::iterator
			it = m_files.begin();
			it != m_files.end(); ++it) {
		std::string name = it->first;
		FileStatus *filestatus = it->second;
		const std::string &sha1 = filestatus->sha1;

		std::ostringstream tmp_os(std::ios_base::binary);
		bool found_in_cache = m_media_cache.load(hex_encode(sha1), tmp_os);

		// If found in cache, try to load it from there
		if (found_in_cache) {
			bool success = checkAndLoad(name, sha1,
					tmp_os.str(), true, client);
			if (success) {
				filestatus->received = true;
				m_uncached_count--;
			}
		}
	}

	assert(m_uncached_received_count == 0);

	// Create the media cache dir if we are likely to write to it
	if (m_uncached_count != 0) {
		bool did = fs::CreateAllDirs(getMediaCacheDir());
		if (!did) {
			errorstream << "Client: "
				<< "Could not create media cache directory: "
				<< getMediaCacheDir()
				<< std::endl;
		}
	}

	// If we found all files in the cache, report this fact to the server.
	// If the server reported no remote servers, immediately start
	// conventional transfers. Note: if cURL support is not compiled in,
	// m_remotes is always empty, so "!USE_CURL" is redundant but may
	// reduce the size of the compiled code
	if (!USE_CURL || m_uncached_count == 0 || m_remotes.empty()) {
		startConventionalTransfers(client);
	}
	else {
		// Otherwise start off by requesting each server's sha1 set

		// This is the first time we use httpfetch, so alloc a caller ID
		m_httpfetch_caller = httpfetch_caller_alloc();
		m_httpfetch_timeout = g_settings->getS32("curl_timeout");

		// Set the active fetch limit to curl_parallel_limit or 84,
		// whichever is greater. This gives us some leeway so that
		// inefficiencies in communicating with the httpfetch thread
		// don't slow down fetches too much. (We still want some limit
		// so that when the first remote server returns its hash set,
		// not all files are requested from that server immediately.)
		// One such inefficiency is that ClientMediaDownloader::step()
		// is only called a couple times per second, while httpfetch
		// might return responses much faster than that.
		// Note that httpfetch strictly enforces curl_parallel_limit
		// but at no inter-thread communication cost. This however
		// doesn't help with the aforementioned inefficiencies.
		// The signifance of 84 is that it is 2*6*9 in base 13.
		m_httpfetch_active_limit = g_settings->getS32("curl_parallel_limit");
		m_httpfetch_active_limit = MYMAX(m_httpfetch_active_limit, 84);

		// Write a list of hashes that we need. This will be POSTed
		// to the server using Content-Type: application/octet-stream
		std::string required_hash_set = serializeRequiredHashSet();

		// minor fixme: this loop ignores m_httpfetch_active_limit

		// another minor fixme, unlikely to matter in normal usage:
		// these index.mth fetches do (however) count against
		// m_httpfetch_active_limit when starting actual media file
		// requests, so if there are lots of remote servers that are
		// not responding, those will stall new media file transfers.

		for (u32 i = 0; i < m_remotes.size(); ++i) {
			assert(m_httpfetch_next_id == i);

			RemoteServerStatus *remote = m_remotes[i];
			actionstream << "Client: Contacting remote server \""
				<< remote->baseurl << "\"" << std::endl;

			HTTPFetchRequest fetchrequest;
			fetchrequest.url =
				remote->baseurl + MTHASHSET_FILE_NAME;
			fetchrequest.caller = m_httpfetch_caller;
			fetchrequest.request_id = m_httpfetch_next_id; // == i
			fetchrequest.timeout = m_httpfetch_timeout;
			fetchrequest.connect_timeout = m_httpfetch_timeout;
			fetchrequest.post_data = required_hash_set;
			fetchrequest.extra_headers.push_back(
				"Content-Type: application/octet-stream");
			httpfetch_async(fetchrequest);

			m_httpfetch_active++;
			m_httpfetch_next_id++;
			m_outstanding_hash_sets++;
		}
	}
}
Exemplo n.º 5
0
void sendAnnounce(const std::string &action,
		const u16 port,
		const std::vector<std::string> &clients_names,
		const double uptime,
		const u32 game_time,
		const float lag,
		const std::string &gameid,
		const std::string &mg_name,
		const std::vector<ModSpec> &mods)
{
	Json::Value server;
	server["action"] = action;
	server["port"] = port;
	if (g_settings->exists("server_address")) {
		server["address"] = g_settings->get("server_address");
	}
	if (action != "delete") {
		bool strict_checking = g_settings->getBool("strict_protocol_version_checking");
		server["name"]         = g_settings->get("server_name");
		server["description"]  = g_settings->get("server_description");
		server["version"]      = g_version_string;
		server["proto_min"]    = strict_checking ? LATEST_PROTOCOL_VERSION : SERVER_PROTOCOL_VERSION_MIN;
		server["proto_max"]    = strict_checking ? LATEST_PROTOCOL_VERSION : SERVER_PROTOCOL_VERSION_MAX;
		server["url"]          = g_settings->get("server_url");
		server["creative"]     = g_settings->getBool("creative_mode");
		server["damage"]       = g_settings->getBool("enable_damage");
		server["password"]     = g_settings->getBool("disallow_empty_password");
		server["pvp"]          = g_settings->getBool("enable_pvp");
		server["uptime"]       = (int) uptime;
		server["game_time"]    = game_time;
		server["clients"]      = (int) clients_names.size();
		server["clients_max"]  = g_settings->getU16("max_users");
		server["clients_list"] = Json::Value(Json::arrayValue);
		for (std::vector<std::string>::const_iterator it = clients_names.begin();
				it != clients_names.end();
				++it) {
			server["clients_list"].append(*it);
		}
		if (gameid != "") server["gameid"] = gameid;
	}

	if (action == "start") {
		server["dedicated"]         = g_settings->getBool("server_dedicated");
		server["rollback"]          = g_settings->getBool("enable_rollback_recording");
		server["mapgen"]            = mg_name;
		server["privs"]             = g_settings->get("default_privs");
		server["can_see_far_names"] = g_settings->getS16("player_transfer_distance") <= 0;
		server["mods"]              = Json::Value(Json::arrayValue);
		for (std::vector<ModSpec>::const_iterator it = mods.begin();
				it != mods.end();
				++it) {
			server["mods"].append(it->name);
		}
		actionstream << "Announcing to " << g_settings->get("serverlist_url") << std::endl;
	} else {
		if (lag)
			server["lag"] = lag;
	}

	Json::FastWriter writer;
	HTTPFetchRequest fetch_request;
	fetch_request.url = g_settings->get("serverlist_url") + std::string("/announce");
	fetch_request.post_fields["json"] = writer.write(server);
	fetch_request.multipart = true;
	httpfetch_async(fetch_request);
}