コード例 #1
0
// TODO: 3 use span here instead of zero-terminated string
std::tuple<int, int, bool> feed_bytes(http_parser& parser, char const* str)
{
	std::tuple<int, int, bool> ret(0, 0, false);
	std::tuple<int, int, bool> prev(0, 0, false);
	for (int chunks = 1; chunks < 70; ++chunks)
	{
		ret = std::make_tuple(0, 0, false);
		parser.reset();
		span<char const> recv_buf(str, 0);
		for (;;)
		{
			int chunk_size = (std::min)(chunks, int(strlen(recv_buf.end())));
			if (chunk_size == 0) break;
			recv_buf = span<char const>(recv_buf.data(), recv_buf.size() + chunk_size);
			int payload, protocol;
			bool error = false;
			std::tie(payload, protocol) = parser.incoming(recv_buf, error);
			std::get<0>(ret) += payload;
			std::get<1>(ret) += protocol;
			std::get<2>(ret) |= error;
//			std::cerr << payload << ", " << protocol << ", " << chunk_size << std::endl;
			TORRENT_ASSERT(payload + protocol == chunk_size || std::get<2>(ret));
		}
		TEST_CHECK(prev == std::make_tuple(0, 0, false) || ret == prev || std::get<2>(ret));
		if (!std::get<2>(ret))
		{
			TEST_EQUAL(std::get<0>(ret) + std::get<1>(ret), int(strlen(str)));
		}

		prev = ret;
	}
	return ret;
}
コード例 #2
0
tuple<int, int, bool> feed_bytes(http_parser& parser, char const* str)
{
	tuple<int, int, bool> ret(0, 0, false);
	tuple<int, int, bool> prev(0, 0, false);
	for (int chunks = 1; chunks < 70; ++chunks)
	{
		ret = make_tuple(0, 0, false);
		parser.reset();
		buffer::const_interval recv_buf(str, str);
		for (; *str;)
		{
			int chunk_size = (std::min)(chunks, int(strlen(recv_buf.end)));
			if (chunk_size == 0) break;
			recv_buf.end += chunk_size;
			int payload, protocol;
			bool error = false;
			tie(payload, protocol) = parser.incoming(recv_buf, error);
			ret.get<0>() += payload;
			ret.get<1>() += protocol;
			ret.get<2>() += error;
//			std::cerr << payload << ", " << protocol << ", " << chunk_size << std::endl;
			TORRENT_ASSERT(payload + protocol == chunk_size);
		}
		TEST_CHECK(prev == make_tuple(0, 0, false) || ret == prev);
		prev = ret;
	}
	return ret;
}
コード例 #3
0
void print_http_header(http_parser const& p)
{
    std::cerr << " < " << p.status_code() << " " << p.message() << std::endl;

    for (std::map<std::string, std::string>::const_iterator i
            = p.headers().begin(), end(p.headers().end()); i != end; ++i)
    {
        std::cerr << " < " << i->first << ": " << i->second << std::endl;
    }
}
コード例 #4
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();
	}
コード例 #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(-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();
	}
コード例 #6
0
void http_handler(error_code const& ec, http_parser const& parser
                  , char const* data, int size, http_connection& c)
{
    ++handler_called;
    data_size = size;
    g_error_code = ec;

    if (parser.header_finished())
    {
        http_status = parser.status_code();
        if (http_status == 200)
        {
            TEST_CHECK(memcmp(data, data_buffer, size) == 0);
        }
    }
    print_http_header(parser);
}
コード例 #7
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(-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;
		}
		
		// handle tracker response
		entry e;
		e = bdecode(data, data + size);

		if (e.type() == entry::dictionary_t)
		{
			parse(parser.status_code(), e);
		}
		else
		{
			std::string error_str("invalid bencoding of tracker response: \"");
			for (char const* i = data, *end(data + size); i != end; ++i)
			{
				if (*i >= ' ' && *i <= '~') error_str += *i;
				else error_str += "0x" + boost::lexical_cast<std::string>((unsigned int)*i) + " ";
			}
			error_str += "\"";
			fail(parser.status_code(), error_str.c_str());
		}
		close();
	}
コード例 #8
0
ファイル: rss.cpp プロジェクト: deluge-clone/libtorrent
void feed::on_feed(error_code const& ec
	, http_parser const& parser, char const* data, int size)
{
	// enabling this assert makes the unit test a lot more difficult
//	TORRENT_ASSERT(m_updating);
	m_updating = false;

	if (ec && ec != asio::error::eof)
	{
		++m_failures;
		m_error = ec;
		if (m_ses.m_alerts.should_post<rss_alert>())
		{
			m_ses.m_alerts.post_alert(rss_alert(my_handle(), m_settings.url
				, rss_alert::state_error, m_error));
		}
		return;
	}

	if (parser.status_code() != 200)
	{
		++m_failures;
		m_error = error_code(parser.status_code(), get_http_category());
		if (m_ses.m_alerts.should_post<rss_alert>())
		{
			m_ses.m_alerts.post_alert(rss_alert(my_handle(), m_settings.url
				, rss_alert::state_error, m_error));
		}
		return;
	}

	m_failures = 0;

	char* buf = const_cast<char*>(data);

	feed_state s(*this);
	xml_parse(buf, buf + size, boost::bind(&parse_feed, boost::ref(s), _1, _2, _3));

	time_t now = time(NULL);

	// keep history of the typical feed size times 5
	int max_history = (std::max)(s.num_items * 5, 100);

	// this is not very efficient, but that's probably OK for now
	while (int(m_added.size()) > max_history)
	{
		// loop over all elements and find the one with the lowest timestamp
		// i.e. it was added the longest ago, then remove it
		std::map<std::string, time_t>::iterator i = std::min_element(
			m_added.begin(), m_added.end()
			, boost::bind(&std::pair<const std::string, time_t>::second, _1)
			< boost::bind(&std::pair<const std::string, time_t>::second, _2));
		m_added.erase(i);
	}

	m_last_update = now;

	// report that we successfully updated the feed
	if (m_ses.m_alerts.should_post<rss_alert>())
	{
		m_ses.m_alerts.post_alert(rss_alert(my_handle(), m_settings.url
			, rss_alert::state_updated, error_code()));
	}

	// update m_ses.m_next_rss_update timestamps
	// now that we have updated our timestamp
	m_ses.update_rss_feeds();
}
コード例 #9
0
ファイル: rss.cpp プロジェクト: 771805315/avplayer
void feed::on_feed(error_code const& ec
	, http_parser const& parser, char const* data, int size)
{
	// enabling this assert makes the unit test a lot more difficult
//	TORRENT_ASSERT(m_updating);
	m_updating = false;

	if (ec && ec != asio::error::eof)
	{
		++m_failures;
		m_error = ec;
		if (m_ses.m_alerts.should_post<rss_alert>())
		{
			m_ses.m_alerts.post_alert(rss_alert(my_handle(), m_settings.url
				, rss_alert::state_error, m_error));
		}
		return;
	}

	if (parser.status_code() != 200)
	{
		++m_failures;
		m_error = error_code(parser.status_code(), get_http_category());
		if (m_ses.m_alerts.should_post<rss_alert>())
		{
			m_ses.m_alerts.post_alert(rss_alert(my_handle(), m_settings.url
				, rss_alert::state_error, m_error));
		}
		return;
	}

	m_failures = 0;

	char* buf = const_cast<char*>(data);

	feed_state s(*this);
	xml_parse(buf, buf + size, boost::bind(&parse_feed, boost::ref(s), _1, _2, _3));

	time_t now = time(NULL);

	if (m_settings.auto_download || m_settings.auto_map_handles)
	{
		for (std::vector<feed_item>::iterator i = m_items.begin()
			, end(m_items.end()); i != end; ++i)
		{
			i->handle = torrent_handle(m_ses.find_torrent(i->uuid.empty() ? i->url : i->uuid));

			// if we're already downloading this torrent, or if we
			// don't have auto-download enabled, just move along to
			// the next one
			if (i->handle.is_valid() || !m_settings.auto_download) continue;

			// has this already been added?
			if (m_added.find(i->url) != m_added.end()) continue;

			// this means we should add this torrent to the session
			add_torrent_params p = m_settings.add_args;
			p.url = i->url;
			p.uuid = i->uuid;
			p.source_feed_url = m_settings.url;
			p.ti.reset();
			p.info_hash.clear();
			p.name = i->title.c_str();

			error_code e;
			torrent_handle h = m_ses.add_torrent(p, e);
			m_ses.m_alerts.post_alert(add_torrent_alert(h, p, e));
			m_added.insert(make_pair(i->url, now));
		}
	}

	m_last_update = now;

	// keep history of the typical feed size times 5
	int max_history = (std::max)(s.num_items * 5, 100);

	// this is not very efficient, but that's probably OK for now
	while (int(m_added.size()) > max_history)
	{
		// loop over all elements and find the one with the lowest timestamp
		// i.e. it was added the longest ago, then remove it
		std::map<std::string, time_t>::iterator i = std::min_element(
			m_added.begin(), m_added.end()
			, boost::bind(&std::pair<const std::string, time_t>::second, _1)
			< boost::bind(&std::pair<const std::string, time_t>::second, _2));
		m_added.erase(i);
	}

	// report that we successfully updated the feed
	if (m_ses.m_alerts.should_post<rss_alert>())
	{
		m_ses.m_alerts.post_alert(rss_alert(my_handle(), m_settings.url
			, rss_alert::state_updated, error_code()));
	}

	// update m_ses.m_next_rss_update timestamps
	// now that we have updated our timestamp
	m_ses.update_rss_feeds();
}
コード例 #10
0
void http_tracker_connection::on_response(error_code const& ec
        , http_parser const& parser, char const* data, int size)
{
    // keep this alive
    boost::shared_ptr<http_tracker_connection> me(shared_from_this());

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

    if (!parser.header_finished())
    {
        fail(boost::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 != boost::asio::error::eof)
    {
        fail(ec, parser.status_code());
        return;
    }

    received_bytes(size + parser.body_start());

    // handle tracker response
    error_code ecode;

    boost::shared_ptr<request_callback> cb = requester();
    if (!cb)
    {
        close();
        return;
    }

    tracker_response resp = parse_tracker_response(data, size, ecode
                            , tracker_req().kind, tracker_req().info_hash);

    if (!resp.warning_message.empty())
        cb->tracker_warning(tracker_req(), resp.warning_message);

    if (ecode)
    {
        fail(ecode, parser.status_code(), resp.failure_reason.c_str()
             , resp.interval, resp.min_interval);
        close();
        return;
    }

    // do slightly different things for scrape requests
    if (0 != (tracker_req().kind & tracker_request::scrape_request))
    {
        cb->tracker_scrape_response(tracker_req(), resp.complete
                                    , resp.incomplete, resp.downloaded, resp.downloaders);
    }
    else
    {
        std::list<address> ip_list;
        if (m_tracker_connection)
        {
            error_code ignore;
            std::vector<tcp::endpoint> const& epts = m_tracker_connection->endpoints();
            for (std::vector<tcp::endpoint>::const_iterator i = epts.begin()
                    , end(epts.end()); i != end; ++i)
            {
                ip_list.push_back(i->address());
            }
        }

        cb->tracker_response(tracker_req(), m_tracker_ip, ip_list, resp);
    }
    close();
}