void do_handshake(tcp::socket& s, sha1_hash const& ih, char* buffer)
{
	char handshake[] = "\x13" "BitTorrent protocol\0\0\0\0\0\x10\0\x04"
		"                    " // space for info-hash
		"aaaaaaaaaaaaaaaaaaaa"; // peer-id
	log("==> handshake");
	error_code ec;
	std::memcpy(handshake + 28, ih.begin(), 20);
	boost::asio::write(s, boost::asio::buffer(handshake, sizeof(handshake) - 1)
		, boost::asio::transfer_all(), ec);
	if (ec)
	{
		TEST_ERROR(ec.message());
		return;
	}

	// read handshake
	boost::asio::read(s, boost::asio::buffer(buffer, 68)
		, boost::asio::transfer_all(), ec);
	if (ec)
	{
		TEST_ERROR(ec.message());
		return;
	}
	log("<== handshake");

	TEST_CHECK(buffer[0] == 19);
	TEST_CHECK(std::memcmp(buffer + 1, "BitTorrent protocol", 19) == 0);

	char* extensions = buffer + 20;
	// check for fast extension support
	TEST_CHECK(extensions[7] & 0x4);

	// check for extension protocol support
	bool const lt_extension_protocol = (extensions[5] & 0x10) != 0;
#ifndef TORRENT_DISABLE_EXTENSIONS
	TEST_CHECK(lt_extension_protocol == true);
#else
	TEST_CHECK(lt_extension_protocol == false);
#endif

	// check for DHT support
	bool const dht_support = (extensions[7] & 0x1) != 0;
#ifndef TORRENT_DISABLE_DHT
	TEST_CHECK(dht_support == true);
#else
	TEST_CHECK(dht_support == false);
#endif

	TEST_CHECK(std::memcmp(buffer + 28, ih.begin(), 20) == 0);
}
void do_handshake(stream_socket& s, sha1_hash const& ih, char* buffer)
{
	char handshake[] = "\x13" "BitTorrent protocol\0\0\0\0\0\0\0\x04"
		"                    " // space for info-hash
		"aaaaaaaaaaaaaaaaaaaa" // peer-id
		"\0\0\0\x01\x0e"; // have_all
	std::cout << "send handshake" << std::endl;
	error_code ec;
	std::memcpy(handshake + 28, ih.begin(), 20);
	libtorrent::asio::write(s, libtorrent::asio::buffer(handshake, sizeof(handshake) - 1), libtorrent::asio::transfer_all(), ec);
	if (ec)
	{
		std::cout << ec.message() << std::endl;
		exit(1);
	}

	// read handshake
	libtorrent::asio::read(s, libtorrent::asio::buffer(buffer, 68), libtorrent::asio::transfer_all(), ec);
	if (ec)
	{
		std::cout << ec.message() << std::endl;
		exit(1);
	}
	std::cout << "received handshake" << std::endl;

	TEST_CHECK(buffer[0] == 19);
	TEST_CHECK(std::memcmp(buffer + 1, "BitTorrent protocol", 19) == 0);

	char* extensions = buffer + 20;
	// check for fast extension support
	TEST_CHECK(extensions[7] & 0x4);
	
#ifndef TORRENT_DISABLE_EXTENSIONS
	// check for extension protocol support
	TEST_CHECK(extensions[5] & 0x10);
#endif
	
#ifndef TORRENT_DISABLE_DHT
	// check for DHT support
	TEST_CHECK(extensions[7] & 0x1);
#endif
	
	TEST_CHECK(std::memcmp(buffer + 28, ih.begin(), 20) == 0);
}
Beispiel #3
0
		hasher& update(std::string const& data) { update(data.c_str(), data.size()); return *this; }
		hasher& update(const char* data, int len)
		{
			TORRENT_ASSERT(data != 0);
			TORRENT_ASSERT(len > 0);
#ifdef TORRENT_USE_GCRYPT
			gcry_md_write(m_context, data, len);
#else
			SHA1_Update(&m_context, reinterpret_cast<unsigned char const*>(data), len);
#endif
			return *this;
		}

		sha1_hash final()
		{
			sha1_hash digest;
#ifdef TORRENT_USE_GCRYPT
			gcry_md_final(m_context);
			digest.assign((const char*)gcry_md_read(m_context, 0));
#else
			SHA1_Final(digest.begin(), &m_context);
#endif
			return digest;
		}

		void reset()
		{
#ifdef TORRENT_USE_GCRYPT
			gcry_md_reset(m_context);
#else
			SHA1_Init(&m_context);
Beispiel #4
0
bytes sha1_hash_bytes(const sha1_hash& bn) {
    return bytes(bn.to_string());
}
Beispiel #5
0
		gcry_md_write(m_context, data.data(), data.size());
#elif TORRENT_USE_COMMONCRYPTO
		CC_SHA1_Update(&m_context, reinterpret_cast<unsigned char const*>(data.data()), CC_LONG(data.size()));
#elif TORRENT_USE_CRYPTOAPI
		m_context.update(data);
#elif defined TORRENT_USE_LIBCRYPTO
		SHA1_Update(&m_context, reinterpret_cast<unsigned char const*>(data.data()), data.size());
#else
		SHA1_update(&m_context, reinterpret_cast<unsigned char const*>(data.data()), data.size());
#endif
		return *this;
	}

	sha1_hash hasher::final()
	{
		sha1_hash digest;
#ifdef TORRENT_USE_LIBGCRYPT
		gcry_md_final(m_context);
		digest.assign((char const*)gcry_md_read(m_context, 0));
#elif TORRENT_USE_COMMONCRYPTO
		CC_SHA1_Final(reinterpret_cast<unsigned char*>(digest.data()), &m_context);
#elif TORRENT_USE_CRYPTOAPI
		m_context.get_hash(digest.data(), digest.size());
#elif defined TORRENT_USE_LIBCRYPTO
		SHA1_Final(reinterpret_cast<unsigned char*>(digest.data()), &m_context);
#else
		SHA1_final(reinterpret_cast<unsigned char*>(digest.data()), &m_context);
#endif
		return digest;
	}
tracker_response parse_tracker_response(char const* data, int size, error_code& ec
                                        , int flags, sha1_hash scrape_ih)
{
    tracker_response resp;

    bdecode_node e;
    int res = bdecode(data, data + size, e, ec);

    if (ec) return resp;

    if (res != 0 || e.type() != bdecode_node::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;

    bdecode_node tracker_id = e.dict_find_string("tracker id");
    if (tracker_id)
        resp.trackerid = tracker_id.string_value();

    // parse the response
    bdecode_node 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;
    }

    bdecode_node warning = e.dict_find_string("warning message");
    if (warning)
        resp.warning_message = warning.string_value();

    if (0 != (flags & tracker_request::scrape_request))
    {
        bdecode_node files = e.dict_find_dict("files");
        if (!files)
        {
            ec.assign(errors::invalid_files_entry, get_libtorrent_category());
            return resp;
        }

        bdecode_node scrape_data = files.dict_find_dict(
                                       scrape_ih.to_string());

        if (!scrape_data)
        {
            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));

    bdecode_node peers_ent = e.dict_find("peers");
    if (peers_ent && peers_ent.type() == bdecode_node::string_t)
    {
        char const* peers = peers_ent.string_ptr();
        int len = peers_ent.string_length();
#if TORRENT_USE_I2P
        if (0 != (flags & tracker_request::i2p))
        {
            error_code parse_error;
            for (int i = 0; i < len; i += 32)
            {
                if (len - i < 32) break;
                peer_entry p;
                p.hostname = base32encode(std::string(peers + i, 32), string::i2p);
                p.hostname += ".b32.i2p";
                p.port = 6881;
                resp.peers.push_back(p);
            }
        }
        else
#endif
        {
            resp.peers4.reserve(len / 6);
            for (int i = 0; i < len; i += 6)
            {
                if (len - i < 6) break;

                ipv4_peer_entry p;
                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() == bdecode_node::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.clear();
    }

#if TORRENT_USE_IPV6
    bdecode_node 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.clear();
    }
#else
    bdecode_node ipv6_peers;
#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;
    		}
    */
    bdecode_node 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;
}
Beispiel #7
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;
	}
Beispiel #8
0
 bool is_valid() const
 {
     return !t_hash.is_all_zeros()
         && !peer_id.is_all_zeros();
 }