Beispiel #1
0
	void entry::copy(entry const& e)
	{
		switch (e.type())
		{
		case int_t:
			new (&data) integer_type(e.integer());
			break;
		case string_t:
			new (&data) string_type(e.string());
			break;
		case list_t:
			new (&data) list_type(e.list());
			break;
		case dictionary_t:
			new (&data) dictionary_type(e.dict());
			break;
		case undefined_t:
			TORRENT_ASSERT(e.type() == undefined_t);
			break;
		case preformatted_t:
			new (&data) preformatted_type(e.preformatted());
			break;
		}
		m_type = e.type();
#if TORRENT_USE_ASSERTS
		m_type_queried = true;
#endif
	}
Beispiel #2
0
		int bencode_recursive(OutIt& out, const entry& e)
		{
			int ret = 0;
			switch(e.type())
			{
			case entry::int_t:
				write_char(out, 'i');
				ret += write_integer(out, e.integer());
				write_char(out, 'e');
				ret += 2;
				break;
			case entry::string_t:
				ret += write_integer(out, e.string().length());
				write_char(out, ':');
				ret += write_string(e.string(), out);
				ret += 1;
				break;
			case entry::list_t:
				write_char(out, 'l');
				for (entry::list_type::const_iterator i = e.list().begin(); i != e.list().end(); ++i)
					ret += bencode_recursive(out, *i);
				write_char(out, 'e');
				ret += 2;
				break;
			case entry::dictionary_t:
				write_char(out, 'd');
				for (entry::dictionary_type::const_iterator i = e.dict().begin();
					i != e.dict().end(); ++i)
				{
					// write key
					ret += write_integer(out, i->first.length());
					write_char(out, ':');
					ret += write_string(i->first, out);
					// write value
					ret += bencode_recursive(out, i->second);
					ret += 1;
				}
				write_char(out, 'e');
				ret += 2;
				break;
			default:
				// trying to encode a structure with uninitialized values!
				TORRENT_ASSERT_VAL(false, e.type());
				// do nothing
				break;
			}
			return ret;
		}
	void dht_tracker::start(entry const& bootstrap)
	{
		std::vector<udp::endpoint> initial_nodes;

		if (bootstrap.type() == entry::dictionary_t)
		{
			try
			{
			if (entry const* nodes = bootstrap.find_key("nodes"))
				read_endpoint_list<udp::endpoint>(nodes, initial_nodes);
			} catch (std::exception&) {}
		}

		error_code ec;
		m_timer.expires_from_now(seconds(1), ec);
		m_timer.async_wait(bind(&dht_tracker::tick, self(), _1));

		m_connection_timer.expires_from_now(seconds(10), ec);
		m_connection_timer.async_wait(
			bind(&dht_tracker::connection_timeout, self(), _1));

		m_refresh_timer.expires_from_now(seconds(5), ec);
		m_refresh_timer.async_wait(bind(&dht_tracker::refresh_timeout, self(), _1));

		m_dht.bootstrap(initial_nodes, boost::bind(&dht_tracker::on_bootstrap, self()));
	}
Beispiel #4
0
	torrent_handle session_handle::add_torrent(
		char const* tracker_url
		, sha1_hash const& info_hash
		, char const* name
		, std::string const& save_path
		, entry const& resume_data
		, storage_mode_t storage_mode
		, bool paused
		, storage_constructor_type sc
		, void* userdata)
	{
		TORRENT_ASSERT_PRECOND(!save_path.empty());

		add_torrent_params p(sc);
		p.trackers.push_back(tracker_url);
		p.info_hash = info_hash;
		p.save_path = save_path;
		p.storage_mode = storage_mode;

		if (paused) p.flags |= add_torrent_params::flag_paused;
		else p.flags &= ~add_torrent_params::flag_paused;

		p.userdata = userdata;
		p.name = name;
		if (resume_data.type() != entry::undefined_t)
		{
			bencode(std::back_inserter(p.resume_data), resume_data);
		}
		return add_torrent(p);
	}
void wx_entry_print(entry e, int depth)
{
	wxString padding(wxT(""));
	switch(e.type())
	{
		case entry::int_t:
			wxLogMessage(wxT("print:")+padding.Pad(depth, '\t')+wxString::Format(_T("int: %u"), e.integer()));
			break;

		case entry::string_t:
			wxLogMessage(wxT("print:")+padding.Pad(depth, '\t')+wxString::Format(wxT("str-len: %u "), e.string().length())+wxT("str: ")+wxString(e.string().c_str(), wxConvUTF8));
			break;

		case entry::list_t:
			for (entry::list_type::const_iterator i = e.list().begin(); i != e.list().end(); ++i)
			{
				wx_entry_print(*i, depth+1);
			}
			break;

		case entry::dictionary_t:
			for (entry::dictionary_type::const_iterator i = e.dict().begin(); i != e.dict().end(); ++i)
			{
				wx_entry_print(i->first, depth+1);// write key
				wx_entry_print(i->second, depth+1);// write value
			}
			break;

		default:
			break;
	}
}
Beispiel #6
0
		int bencode_recursive(OutIt& out, const entry& e)
		{
			int ret = 0;
			switch(e.type())
			{
			case entry::int_t:
				write_char(out, 'i');
				ret += write_integer(out, e.integer());
				write_char(out, 'e');
				ret += 2;
				break;
			case entry::string_t:
				ret += write_integer(out, e.string().length());
				write_char(out, ':');
				ret += write_string(e.string(), out);
				ret += 1;
				break;
			case entry::list_t:
				write_char(out, 'l');
				for (entry::list_type::const_iterator i = e.list().begin(); i != e.list().end(); ++i)
					ret += bencode_recursive(out, *i);
				write_char(out, 'e');
				ret += 2;
				break;
			case entry::dictionary_t:
				write_char(out, 'd');
				for (entry::dictionary_type::const_iterator i = e.dict().begin();
					i != e.dict().end(); ++i)
				{
					// write key
					ret += write_integer(out, i->first.length());
					write_char(out, ':');
					ret += write_string(i->first, out);
					// write value
					ret += bencode_recursive(out, i->second);
					ret += 1;
				}
				write_char(out, 'e');
				ret += 2;
				break;
			case entry::preformatted_t:
				std::copy(e.preformatted().begin(), e.preformatted().end(), out);
				ret += int(e.preformatted().size());
				break;
			case entry::undefined_t:

				// empty string
				write_char(out, '0');
				write_char(out, ':');

				ret += 2;
				break;
			}
			return ret;
		}
void dht_tracker::start(entry const& bootstrap)
{
    std::vector<udp::endpoint> initial_nodes;

    if (bootstrap.type() == entry::dictionary_t)
    {
        TORRENT_TRY {
            if (entry const* nodes = bootstrap.find_key("nodes"))
                read_endpoint_list<udp::endpoint>(nodes, initial_nodes);
        } TORRENT_CATCH(std::exception&) {}
    }
Beispiel #8
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);
		TORRENT_SYNC_CALL1(load_state, &e);
	}
Beispiel #9
0
	void save_struct(entry& e, void const* s, bencode_map_entry const* m, int num, void const* def)
	{
		if (e.type() != entry::dictionary_t) e = entry(entry::dictionary_t);
		for (int i = 0; i < num; ++i)
		{
			char const* key = m[i].name;
			void const* src = ((char*)s) + m[i].offset;
			if (def)
			{
				// if we have a default value for this field
				// and it is the default, don't save it
				void const* default_value = ((char*)def) + m[i].offset;
				switch (m[i].type)
				{
					case std_string:
						if (*((std::string*)src) == *((std::string*)default_value)) continue;
						break;
					case character:
						if (*((char*)src) == *((char*)default_value)) continue;
						break;
					case integer:
						if (*((int*)src) == *((int*)default_value)) continue;
						break;
					case size_integer:
						if (*((size_type*)src) == *((size_type*)default_value)) continue;
						break;
					case time_integer:
						if (*((time_t*)src) == *((time_t*)default_value)) continue;
						break;
					case floating_point:
						if (*((float*)src) == *((float*)default_value)) continue;
						break;
					case boolean:
						if (*((bool*)src) == *((bool*)default_value)) continue;
						break;
					default: TORRENT_ASSERT(false);
				}
			}
			entry& val = e[key];
			TORRENT_ASSERT_VAL(val.type() == entry::undefined_t, val.type());
			switch (m[i].type)
			{
				case std_string: val = *((std::string*)src); break;
				case character: val = *((char*)src); break;
				case integer: val = *((int*)src); break;
				case size_integer: val = *((size_type*)src); break;
				case time_integer: val = *((time_t*)src); break;
				case floating_point: val = size_type(*((float*)src) * 1000.f); break;
				case boolean: val = *((bool*)src); break;
				default: TORRENT_ASSERT(false);
			}
		}
	}
Beispiel #10
0
void dht_tracker::start(entry const& bootstrap
                        , find_data::nodes_callback const& f)
{
    TORRENT_ASSERT(m_ses.is_network_thread());
    std::vector<udp::endpoint> initial_nodes;

    if (bootstrap.type() == entry::dictionary_t)
    {
        TORRENT_TRY {
            if (entry const* nodes = bootstrap.find_key("nodes"))
                read_endpoint_list<udp::endpoint>(nodes, initial_nodes);
        } TORRENT_CATCH(std::exception&) {}
    }
Beispiel #11
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);
	}
Beispiel #12
0
void entry::copy(entry const& e)
{
    switch (e.type())
    {
    case int_t:
        new(data) integer_type(e.integer());
        break;
    case string_t:
        new(data) string_type(e.string());
        break;
    case list_t:
        new(data) list_type(e.list());
        break;
    case dictionary_t:
        new (data) dictionary_type(e.dict());
        break;
    default:
        TORRENT_ASSERT(e.type() == undefined_t);
    }
    m_type = e.type();
#ifdef TORRENT_DEBUG
    m_type_queried = true;
#endif
}
 static object convert0(entry const& e)
 {
     switch (e.type())
     {
     case entry::int_t:
         return object(e.integer());
     case entry::string_t:
         return object(e.string());
     case entry::list_t:
         return convert(e.list());
     case entry::dictionary_t:
         return convert(e.dict());
     default:
         return object();
     }
 }
	bool http_tracker_connection::extract_peer_info(const entry& info, peer_entry& ret)
	{
		// extract peer id (if any)
		if (info.type() != entry::dictionary_t)
		{
			fail(-1, "invalid response from tracker (invalid peer entry)");
			return false;
		}
		entry const* i = info.find_key("peer id");
		if (i != 0)
		{
			if (i->type() != entry::string_t || i->string().length() != 20)
			{
				fail(-1, "invalid response from tracker (invalid peer id)");
				return false;
			}
			std::copy(i->string().begin(), i->string().end(), ret.pid.begin());
		}
		else
		{
			// if there's no peer_id, just initialize it to a bunch of zeroes
			std::fill_n(ret.pid.begin(), 20, 0);
		}

		// extract ip
		i = info.find_key("ip");
		if (i == 0 || i->type() != entry::string_t)
		{
			fail(-1, "invalid response from tracker");
			return false;
		}
		ret.ip = i->string();

		// extract port
		i = info.find_key("port");
		if (i == 0 || i->type() != entry::int_t)
		{
			fail(-1, "invalid response from tracker");
			return false;
		}
		ret.port = (unsigned short)i->integer();

		return true;
	}
Beispiel #15
0
	void session_handle::load_state(entry const& ses_state
		, std::uint32_t const flags)
	{
		if (ses_state.type() == entry::undefined_t) return;
		std::vector<char> buf;
		bencode(std::back_inserter(buf), ses_state);
		bdecode_node e;
		error_code ec;
#if TORRENT_USE_ASSERTS || !defined BOOST_NO_EXCEPTIONS
		int ret =
#endif
		bdecode(&buf[0], &buf[0] + buf.size(), e, ec);

		TORRENT_ASSERT(ret == 0);
#ifndef BOOST_NO_EXCEPTIONS
		if (ret != 0) throw system_error(ec);
#endif
		sync_call(&session_impl::load_state, &e, flags);
	}
	// if the torrent already exists, this will throw duplicate_torrent
	torrent_handle session::add_torrent(
		torrent_info const& ti
		, std::string const& save_path
		, entry const& resume_data
		, storage_mode_t storage_mode
		, bool paused
		, storage_constructor_type sc)
	{
		boost::intrusive_ptr<torrent_info> tip(new torrent_info(ti));
		add_torrent_params p(sc);
		p.ti = tip;
		p.save_path = save_path;
		if (resume_data.type() != entry::undefined_t)
		{
			bencode(std::back_inserter(p.resume_data), resume_data);
		}
		p.storage_mode = storage_mode;
		p.paused = paused;
		return add_torrent(p);
	}
Beispiel #17
0
	// if the torrent already exists, this will throw duplicate_torrent
	torrent_handle session_handle::add_torrent(
		torrent_info const& ti
		, std::string const& save_path
		, entry const& resume_data
		, storage_mode_t storage_mode
		, bool paused
		, storage_constructor_type sc)
	{
		add_torrent_params p(sc);
		p.ti = std::make_shared<torrent_info>(ti);
		p.save_path = save_path;
		if (resume_data.type() != entry::undefined_t)
		{
			bencode(std::back_inserter(p.resume_data), resume_data);
		}
		p.storage_mode = storage_mode;
		if (paused) p.flags |= add_torrent_params::flag_paused;
		else p.flags &= ~add_torrent_params::flag_paused;
		return add_torrent(p);
	}
Beispiel #18
0
	bool entry::operator==(entry const& e) const
	{
		if (type() != e.type()) return false;

		switch (m_type)
		{
		case int_t:
			return integer() == e.integer();
		case string_t:
			return string() == e.string();
		case list_t:
			return list() == e.list();
		case dictionary_t:
			return dict() == e.dict();
		case preformatted_t:
			return preformatted() == e.preformatted();
		default:
			TORRENT_ASSERT(m_type == undefined_t);
			return true;
		}
	}
Beispiel #19
0
	void dht_tracker::start(entry const& bootstrap
		, find_data::nodes_callback const& f)
	{
		std::vector<udp::endpoint> initial_nodes;
#if TORRENT_USE_IPV6
		std::vector<udp::endpoint> initial_nodes6;
#endif

		if (bootstrap.type() == entry::dictionary_t)
		{
			TORRENT_TRY {
				if (entry const* nodes = bootstrap.find_key("nodes"))
					read_endpoint_list<udp::endpoint>(nodes, initial_nodes);
			} TORRENT_CATCH(std::exception&) {}
#if TORRENT_USE_IPV6
			TORRENT_TRY{
				if (entry const* nodes = bootstrap.find_key("nodes6"))
					read_endpoint_list<udp::endpoint>(nodes, initial_nodes6);
			} TORRENT_CATCH(std::exception&) {}
#endif
		}
Beispiel #20
0
		void bencode_recursive(OutIt& out, const entry& e)
		{
			switch(e.type())
			{
			case entry::int_t:
				write_char(out, 'i');
				write_integer(out, e.integer());
				write_char(out, 'e');
				break;
			case entry::string_t:
				write_integer(out, e.string().length());
				write_char(out, ':');
				write_string(out, e.string());
				break;
			case entry::list_t:
				write_char(out, 'l');
				for (entry::list_type::const_iterator i = e.list().begin(); i != e.list().end(); ++i)
					bencode_recursive(out, *i);
				write_char(out, 'e');
				break;
			case entry::dictionary_t:
				write_char(out, 'd');
				for (entry::dictionary_type::const_iterator i = e.dict().begin();
					i != e.dict().end(); ++i)
				{
					// write key
					write_integer(out, i->first.length());
					write_char(out, ':');
					write_string(out, i->first);
					// write value
					bencode_recursive(out, i->second);
				}
				write_char(out, 'e');
				break;
			default:
				// do nothing
				break;
			}
		}
Beispiel #21
0
	torrent_handle session::add_torrent(
		boost::intrusive_ptr<torrent_info> ti
		, std::string const& save_path
		, entry const& resume_data
		, storage_mode_t storage_mode
		, bool paused
		, storage_constructor_type sc
		, void* userdata)
	{
		add_torrent_params p(sc);
		p.ti = ti;
		p.save_path = save_path;
		std::vector<char> buf;
		if (resume_data.type() != entry::undefined_t)
		{
			bencode(std::back_inserter(buf), resume_data);
			p.resume_data = &buf;
		}
		p.storage_mode = storage_mode;
		p.paused = paused;
		p.userdata = userdata;
		return add_torrent(p);
	}
Beispiel #22
0
Value entryToJson(const entry &e)
{
    Array lst;
    Object o;
    switch( e.type() ) {
        case entry::int_t:
            return e.integer();
        case entry::string_t:
            return e.string();
        case entry::list_t:
            for (entry::list_type::const_iterator i = e.list().begin(); i != e.list().end(); ++i) {
                lst.push_back( entryToJson(*i) );
            }
            return lst;
        case entry::dictionary_t:
            for (entry::dictionary_type::const_iterator i = e.dict().begin(); i != e.dict().end(); ++i) {
                o.push_back(Pair(i->first, entryToJson(i->second)));
            }
            return o;
        default:
            return string("<uninitialized>");
    }
}
Beispiel #23
0
	bool default_storage::write_resume_data(entry& rd) const
	{
		TORRENT_ASSERT(rd.type() == entry::dictionary_t);
		return false;
	}
	// class that puts the networking and the kademlia node in a single
	// unit and connecting them together.
	dht_tracker::dht_tracker(asio::io_service& ios, dht_settings const& settings
		, asio::ip::address listen_interface, entry const& bootstrap)
		: m_strand(ios)
		, m_socket(ios, udp::endpoint(listen_interface, settings.service_port))
		, m_dht(bind(&dht_tracker::send_packet, this, _1), settings
			, read_id(bootstrap))
		, m_buffer(0)
		, m_last_new_key(time_now() - minutes(key_refresh))
		, m_timer(ios)
		, m_connection_timer(ios)
		, m_refresh_timer(ios)
		, m_settings(settings)
		, m_refresh_bucket(160)
		, m_abort(false)
		, m_host_resolver(ios)
		, m_refs(0)
	{
		using boost::bind;

		m_in_buf[0].resize(1000);
		m_in_buf[1].resize(1000);
#ifdef TORRENT_DHT_VERBOSE_LOGGING
		m_counter = 0;
		std::fill_n(m_replies_bytes_sent, 5, 0);
		std::fill_n(m_queries_bytes_received, 5, 0);
		std::fill_n(m_replies_sent, 5, 0);
		std::fill_n(m_queries_received, 5, 0);
		m_announces = 0;
		m_failed_announces = 0;
		m_total_message_input = 0;
		m_ut_message_input = 0;
		m_lt_message_input = 0;
		m_mp_message_input = 0;
		m_gr_message_input = 0;
		m_mo_message_input = 0;
		m_total_in_bytes = 0;
		m_total_out_bytes = 0;
		m_queries_out_bytes = 0;
		
		// turns on and off individual components' logging

//		rpc_log().enable(false);
//		node_log().enable(false);
//		traversal_log().enable(false);
//		dht_tracker_log.enable(false);

#endif
		std::vector<udp::endpoint> initial_nodes;

		if (bootstrap.type() == entry::dictionary_t)
		{
			try
			{
			if (entry const* nodes = bootstrap.find_key("nodes"))
				read_endpoint_list<udp::endpoint>(nodes, initial_nodes);
			} catch (std::exception&) {}
		}

		m_socket.async_receive_from(asio::buffer(&m_in_buf[m_buffer][0]
			, m_in_buf[m_buffer].size()), m_remote_endpoint[m_buffer]
			, m_strand.wrap(bind(&dht_tracker::on_receive, self(), _1, _2)));
		m_timer.expires_from_now(seconds(1));
		m_timer.async_wait(m_strand.wrap(bind(&dht_tracker::tick, self(), _1)));

		m_connection_timer.expires_from_now(seconds(10));
		m_connection_timer.async_wait(m_strand.wrap(
			bind(&dht_tracker::connection_timeout, self(), _1)));

		m_refresh_timer.expires_from_now(seconds(5));
		m_refresh_timer.async_wait(m_strand.wrap(bind(&dht_tracker::refresh_timeout, self(), _1)));

		m_dht.bootstrap(initial_nodes, bind(&dht_tracker::on_bootstrap, self()));
	}