Ejemplo n.º 1
0
int lazy_bdecode(char const* start, char const* end
                 , lazy_entry& ret, int depth_limit, int item_limit)
{
    error_code ec;
    int pos;
    return lazy_bdecode(start, end, ret, ec, &pos, depth_limit, item_limit);
}
Ejemplo n.º 2
0
void save_settings::load_impl(std::string filename, error_code& ec)
{
	std::vector<char> buf;
	if (load_file(filename, buf, ec) < 0)
		return;

	lazy_entry sett;
	if (lazy_bdecode(&buf[0], &buf[0] + buf.size(), sett, ec) != 0)
		return;

	m_ses.load_state(sett);

	// load the custom int and string keys
	if (sett.type() != lazy_entry::dict_t) return;
	int num_items = sett.dict_size();
	for (int i = 0; i < num_items; ++i)
	{
		lazy_entry const* item;
		std::string key;
		boost::tie(key, item) = sett.dict_at(i);
		if (item->type() == lazy_entry::string_t)
		{
			m_strings[key] = item->string_value();
		}
		else if (item->type() == lazy_entry::int_t)
		{
			m_ints[key] = item->int_value();
		}
	}
}
	void http_tracker_connection::on_response(error_code const& ec
		, http_parser const& parser, char const* data, int size)
	{
		// keep this alive
		boost::intrusive_ptr<http_tracker_connection> me(this);

		if (ec && ec != asio::error::eof)
		{
			fail(-1, ec.message().c_str());
			return;
		}
		
		if (!parser.header_finished())
		{
			fail(-1, "premature end of file");
			return;
		}

		if (parser.status_code() != 200)
		{
			fail(parser.status_code(), parser.message().c_str());
			return;
		}
	
		if (ec && ec != asio::error::eof)
		{
			fail(parser.status_code(), ec.message().c_str());
			return;
		}
		
		received_bytes(size + parser.body_start());

		// handle tracker response
		lazy_entry e;
		int res = lazy_bdecode(data, data + size, e);

		if (res == 0 && e.type() == lazy_entry::dict_t)
		{
			parse(parser.status_code(), e);
		}
		else
		{
			std::string error_str("invalid encoding of tracker response: \"");
			for (char const* i = data, *end(data + size); i != end; ++i)
			{
				if (*i >= ' ' && *i <= '~') error_str += *i;
				else
				{
					char val[30];
					snprintf(val, sizeof(val), "0x%02x ", *i);
					error_str += val;
				}
			}
			error_str += "\"";
			fail(parser.status_code(), error_str.c_str());
		}
		close();
	}
Ejemplo n.º 4
0
	void session::load_state(entry const& ses_state)
	{
		std::vector<char> buf;
		bencode(std::back_inserter(buf), ses_state);
		lazy_entry e;
		error_code ec;
		int ret = lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec);
		TORRENT_ASSERT(ret == 0);
		TORRENT_SYNC_CALL1(load_state, &e);
	}
Ejemplo n.º 5
0
	void http_tracker_connection::on_response(error_code const& ec
		, http_parser const& parser, char const* data, int size)
	{
		// keep this alive
		boost::intrusive_ptr<http_tracker_connection> me(this);

		if (ec && ec != asio::error::eof)
		{
			fail(ec);
			return;
		}
		
		if (!parser.header_finished())
		{
			fail(asio::error::eof);
			return;
		}

		if (parser.status_code() != 200)
		{
			fail(error_code(parser.status_code(), get_http_category())
				, parser.status_code(), parser.message().c_str());
			return;
		}
	
		if (ec && ec != asio::error::eof)
		{
			fail(ec, parser.status_code());
			return;
		}
		
		received_bytes(size + parser.body_start());

		// Howdy Patch to work around extra lines in tracker responses.
		while (data && (*data == 0x0d || *data == 0x0a))
                {
			data++;
			size--;
		}

		// handle tracker response
		lazy_entry e;
		error_code ecode;
		int res = lazy_bdecode(data, data + size, e, ecode);

		if (res == 0 && e.type() == lazy_entry::dict_t)
		{
			parse(parser.status_code(), e);
		}
		else
		{
			fail(ecode, parser.status_code());
		}
		close();
	}
Ejemplo n.º 6
0
	void session::load_state(entry const& ses_state)
	{
		if (ses_state.type() == entry::undefined_t) return;
		std::vector<char> buf;
		bencode(std::back_inserter(buf), ses_state);
		lazy_entry e;
		error_code ec;
		int ret = lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec);
		TORRENT_ASSERT(ret == 0);
#ifndef BOOST_NO_EXCEPTIONS
		if (ret != 0) throw libtorrent_exception(ec);
#endif
		TORRENT_SYNC_CALL1(load_state, &e);
	}
Ejemplo n.º 7
0
	void session::load_state(entry const& ses_state)
	{
		if (ses_state.type() == entry::undefined_t) return;
		std::vector<char> buf;
		bencode(std::back_inserter(buf), ses_state);
		lazy_entry e;
		error_code ec;
#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
		int ret =
#endif
		lazy_bdecode(&buf[0], &buf[0] + buf.size(), e, ec);

		TORRENT_ASSERT(ret == 0);
		TORRENT_SYNC_CALL1(load_state, &e);
	}
Ejemplo n.º 8
0
	uTorrentParser::uTorrentParser(entry const& torrent_file)
		: torrent_info(m_info_hash)
	{
		std::vector<char> tmp;
		std::back_insert_iterator<std::vector<char> > out(tmp);
		bencode(out, torrent_file);

		lazy_entry e;
		if (tmp.size() == 0 || lazy_bdecode(&tmp[0], &tmp[0] + tmp.size(), e) != 0)
		{
#ifndef BOOST_NO_EXCEPTIONS
			throw invalid_torrent_file(errors::invalid_bencoding);
#endif
			return;
		}
		error_code ec;
#ifndef BOOST_NO_EXCEPTIONS
		if (!parse_torrent_file(e, ec))
			throw invalid_torrent_file(ec);
#else
		parse_torrent_file(e, ec);
#endif
	}
Ejemplo n.º 9
0
	tracker_response parse_tracker_response(char const* data, int size, error_code& ec
		, bool scrape_request, sha1_hash scrape_ih)
	{
		tracker_response resp;

		lazy_entry e;
		int res = lazy_bdecode(data, data + size, e, ec);

		if (ec) return resp;

		if (res != 0 || e.type() != lazy_entry::dict_t)
		{
			ec.assign(errors::invalid_tracker_response, get_libtorrent_category());
			return resp;
		}

		int interval = int(e.dict_find_int_value("interval", 0));
		// if no interval is specified, default to 30 minutes
		if (interval == 0) interval = 1800;
		int min_interval = int(e.dict_find_int_value("min interval", 30));

		resp.interval = interval;
		resp.min_interval = min_interval;

		lazy_entry const* tracker_id = e.dict_find_string("tracker id");
		if (tracker_id)
			resp.trackerid = tracker_id->string_value();

		// parse the response
		lazy_entry const* failure = e.dict_find_string("failure reason");
		if (failure)
		{
			resp.failure_reason = failure->string_value();
			ec.assign(errors::tracker_failure, get_libtorrent_category());
			return resp;
		}

		lazy_entry const* warning = e.dict_find_string("warning message");
		if (warning)
			resp.warning_message = warning->string_value();

		if (scrape_request)
		{
			lazy_entry const* files = e.dict_find_dict("files");
			if (files == 0)
			{
				ec.assign(errors::invalid_files_entry, get_libtorrent_category());
				return resp;
			}

			lazy_entry const* scrape_data = files->dict_find_dict(
				scrape_ih.to_string());

			if (scrape_data == 0)
			{
				ec.assign(errors::invalid_hash_entry, get_libtorrent_category());
				return resp;
			}

			resp.complete = int(scrape_data->dict_find_int_value("complete", -1));
			resp.incomplete = int(scrape_data->dict_find_int_value("incomplete", -1));
			resp.downloaded = int(scrape_data->dict_find_int_value("downloaded", -1));
			resp.downloaders = int(scrape_data->dict_find_int_value("downloaders", -1));

			return resp;
		}

		// look for optional scrape info
		resp.complete = int(e.dict_find_int_value("complete", -1));
		resp.incomplete = int(e.dict_find_int_value("incomplete", -1));
		resp.downloaded = int(e.dict_find_int_value("downloaded", -1));

		lazy_entry const* peers_ent = e.dict_find("peers");
		if (peers_ent && peers_ent->type() == lazy_entry::string_t)
		{
			char const* peers = peers_ent->string_ptr();
			int len = peers_ent->string_length();
			resp.peers4.reserve(len / 6);
			for (int i = 0; i < len; i += 6)
			{
				if (len - i < 6) break;

				ipv4_peer_entry p;
				error_code ec;
				p.ip = detail::read_v4_address(peers).to_v4().to_bytes();
				p.port = detail::read_uint16(peers);
				resp.peers4.push_back(p);
			}
		}
		else if (peers_ent && peers_ent->type() == lazy_entry::list_t)
		{
			int len = peers_ent->list_size();
			resp.peers.reserve(len);
			error_code parse_error;
			for (int i = 0; i < len; ++i)
			{
				peer_entry p;
				if (!extract_peer_info(*peers_ent->list_at(i), p, parse_error))
					continue;
				resp.peers.push_back(p);
			}

			// only report an error if all peer entries are invalid
			if (resp.peers.empty() && parse_error)
			{
				ec = parse_error;
				return resp;
			}
		}
		else
		{
			peers_ent = 0;
		}

#if TORRENT_USE_IPV6
		lazy_entry const* ipv6_peers = e.dict_find_string("peers6");
		if (ipv6_peers)
		{
			char const* peers = ipv6_peers->string_ptr();
			int len = ipv6_peers->string_length();
			resp.peers6.reserve(len / 18);
			for (int i = 0; i < len; i += 18)
			{
				if (len - i < 18) break;

				ipv6_peer_entry p;
				p.ip = detail::read_v6_address(peers).to_v6().to_bytes();
				p.port = detail::read_uint16(peers);
				resp.peers6.push_back(p);
			}
		}
		else
		{
			ipv6_peers = 0;
		}
#else
		lazy_entry const* ipv6_peers = 0;
#endif
/*
		// if we didn't receive any peers. We don't care if we're stopping anyway
		if (peers_ent == 0 && ipv6_peers == 0
			&& tracker_req().event != tracker_request::stopped)
		{
			ec.assign(errors::invalid_peers_entry, get_libtorrent_category());
			return resp;
		}
*/
		lazy_entry const* ip_ent = e.dict_find_string("external ip");
		if (ip_ent)
		{
			char const* p = ip_ent->string_ptr();
			if (ip_ent->string_length() == int(address_v4::bytes_type().size()))
				resp.external_ip = detail::read_v4_address(p);
#if TORRENT_USE_IPV6
			else if (ip_ent->string_length() == int(address_v6::bytes_type().size()))
				resp.external_ip = detail::read_v6_address(p);
#endif
		}
		
		return resp;
	}