예제 #1
0
	add_torrent_params read_resume_data(char const* buffer, int size, error_code& ec)
	{
		bdecode_node rd;
		bdecode(buffer, buffer + size, rd, ec);
		if (ec) return add_torrent_params();

		return read_resume_data(rd, ec);
	}
예제 #2
0
	bdecode_node dht_direct_response_alert::response() const
	{
		if (m_response_size == 0) return bdecode_node();
		char const* start = m_alloc.ptr(m_response_idx);
		char const* end = start + m_response_size;
		error_code ec;
		bdecode_node ret;
		bdecode(start, end, ret, ec);
		TORRENT_ASSERT(!ec);
		return ret;
	}
예제 #3
0
		// This function looks up keys from the info-dictionary of the loaded
		// torrent file. It can be used to access extension values put in the
		// .torrent file. If the specified key cannot be found, it returns NULL.
		bdecode_node info(char const* key) const
		{
			if (m_info_dict.type() == bdecode_node::none_t)
			{
				error_code ec;
				bdecode(m_info_section.get(), m_info_section.get()
					+ m_info_section_size, m_info_dict, ec);
				if (ec) return bdecode_node();
			}
			return m_info_dict.dict_find(key);
		}
	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();
	}
예제 #5
0
	std::string dht_pkt_alert::message() const
	{
		bdecode_node print;
		error_code ec;

		// ignore errors here. This is best-effort. It may be a broken encoding
		// but at least we'll print the valid parts
		bdecode(pkt_buf(), pkt_buf() + pkt_size(), print, ec, NULL, 100, 100);

		std::string msg = print_entry(print, true);

		char const* prefix[2] = { "<==", "==>"};
		char buf[1024];
		snprintf(buf, sizeof(buf), "%s [%s] %s", prefix[dir]
			, print_endpoint(node).c_str(), msg.c_str());

		return buf;
	}
예제 #6
0
int dump_torrent::printInfo(int argc, char* argv[])
{
    fileList.clear();
	if (argc < 2 || argc > 4)
	{
		fputs("usage: dump_torrent torrent-file [total-items-limit] [recursion-limit]\n", stderr);
		return 1;
	}

	int item_limit = 1000000;
	int depth_limit = 1000;

    std::vector<char> buf;
    error_code ec;
    int ret = dump_torrent::load_file(argv[0], buf, ec, 40 * 1000000);
	if (ret == -1)
	{
		fprintf(stderr, "file too big, aborting\n");
		return 1;
	}

	if (ret != 0)
	{
		fprintf(stderr, "failed to load file: %s\n", ec.message().c_str());
		return 1;
	}
    bdecode_node e;
	int pos = -1;
	printf("decoding. recursion limit: %d total item count limit: %d\n"
		, depth_limit, item_limit);
    ret = bdecode(&buf[0], &buf[0] + buf.size(), e, ec, &pos
		, depth_limit, item_limit);

	printf("\n\n----- raw info -----\n\n%s\n", print_entry(e).c_str());

	if (ret != 0)
    {
		fprintf(stderr, "failed to decode: '%s' at character: %d\n", ec.message().c_str(), pos);
		return 1;
	}

    torrent_info t(e, ec);
	if (ec)
	{
		fprintf(stderr, "%s\n", ec.message().c_str());
		return 1;
	}
	e.clear();
	std::vector<char>().swap(buf);

	// print info about torrent
	printf("\n\n----- torrent file info -----\n\n"
		"nodes:\n");

	typedef std::vector<std::pair<std::string, int> > node_vec;
	node_vec const& nodes = t.nodes();
	for (node_vec::const_iterator i = nodes.begin(), end(nodes.end());
		i != end; ++i)
	{
		printf("%s: %d\n", i->first.c_str(), i->second);
	}
    puts("trackers:\n");
    for (std::vector<announce_entry>::const_iterator i = t.trackers().begin();
		i != t.trackers().end(); ++i)
	{
		printf("%2d: %s\n", i->tier, i->url.c_str());
	}

	char ih[41];
	to_hex((char const*)&t.info_hash()[0], 20, ih);
	printf("number of pieces: %d\n"
		"piece length: %d\n"
		"info hash: %s\n"
		"comment: %s\n"
		"created by: %s\n"
		"magnet link: %s\n"
		"name: %s\n"
		"number of files: %d\n"
        "files:\n"
		, t.num_pieces()
		, t.piece_length()
		, ih
		, t.comment().c_str()
		, t.creator().c_str()
		, make_magnet_uri(t).c_str()
		, t.name().c_str()
        , t.num_files());

    emit setNumOfPieces(t.num_pieces());
    emit setPiecesLength(t.piece_length());
    emit setInfoHash(ih);
    emit setComment(t.comment().c_str());
    emit setCreatedBy(t.creator().c_str());
    emit setMagnetLink(make_magnet_uri(t).c_str());
    emit setName(t.name().c_str());
    emit setNumOfFiles(t.num_files());

    fileList.begin();
	file_storage const& st = t.files();
	for (int i = 0; i < st.num_files(); ++i)
	{
		int first = st.map_file(i, 0, 0).piece;
		int last = st.map_file(i, (std::max)(boost::int64_t(st.file_size(i))-1, boost::int64_t(0)), 0).piece;
		int flags = st.file_flags(i);
        printf(" %8" PRIx64 " %11" PRId64 " %c%c%c%c [ %5d, %5d ] %7u %s %s %s     %s\n"
			, st.file_offset(i)
			, st.file_size(i)
			, ((flags & file_storage::flag_pad_file)?'p':'-')
			, ((flags & file_storage::flag_executable)?'x':'-')
            , ((flags & file_storage::flag_hidden)?'h':'-')
			, ((flags & file_storage::flag_symlink)?'l':'-')
			, first, last
            , boost::uint32_t(st.mtime(i))
			, st.hash(i) != sha1_hash(0) ? to_hex(st.hash(i).to_string()).c_str() : ""
			, st.file_path(i).c_str()
			, (flags & file_storage::flag_symlink) ? "-> " : ""
			, (flags & file_storage::flag_symlink) ? st.symlink(i).c_str() : "");

       fileName[i] = st.file_path(i).c_str();

       fileList.append(QString(st.file_path(i).c_str()));
    }

    emit setFilesList(fileList);


    for(int i = 0; i < 4;i++){
        printf("\n%s\n", fileName[i]);
    }
    return 0;
}
void TorrentDownloadManager::Run(){

	this->isRunning=true;

	syslog(LOG_NOTICE,"TorrentDownloadManager starting up");

	// Set verboseness of libtorrent
	int alertlvl = alert::all_categories & ~alert::debug_notification;

	alertlvl &= ~alert::progress_notification;

	this->s.set_alert_mask(alertlvl);

	// Get default config
	FtdConfig& cfg=FtdConfig::Instance();

	// Set config
	session_settings settings;
	settings.user_agent=USER_AGENT;
	if(cfg.GetStringOrDefault("general","proxyip","")!=""){
#ifdef SARGE
		settings.proxy_ip=cfg.GetStringOrDefault("general","proxyip","");
		settings.proxy_port=cfg.GetIntegerOrDefault("general","proxyport",0);
		settings.proxy_login=cfg.GetStringOrDefault("general","proxylogin","");
		settings.proxy_password=cfg.GetStringOrDefault("general","proxypassword","");
#endif
#ifdef ETCH
		//TODO: Implement proxy settings
#endif
	}

	if(cfg.GetBoolOrDefault("torrent","metadatasupport",true)){
		syslog(LOG_INFO,"Adding metadata support to session");
		this->s.add_extension(&libtorrent::create_metadata_plugin);
	}else{
		syslog(LOG_DEBUG,"Not adding metadatasupport");
	}

	if(cfg.GetBoolOrDefault("torrent","peerexchangesupport",true)){
		syslog(LOG_INFO,"Adding peer exchange support to session");
		this->s.add_extension(&libtorrent::create_ut_pex_plugin);
	}else{
		syslog(LOG_DEBUG,"Not adding peer exchange support");
	}


	if(cfg.GetBoolOrDefault("torrent","dhtsupport",false)){
		settings.use_dht_as_fallback = false;
		dht_settings dht_s;
		dht_s.service_port=cfg.GetIntegerOrDefault("torrent","listenportstart",10000);
		this->s.set_dht_settings(dht_s);

		entry e;

		string stpath=cfg.GetStringOrDefault("general","statedir","/etc/ftd")+"/dhtstate";
		if(Stat::FileExists(stpath)){
			try{
				filebuf fb;
				fb.open(stpath.c_str(),ios::in);
				iostream infile(&fb);
				infile.unsetf(std::ios_base::skipws);
				e = bdecode(std::istream_iterator<char>(infile),std::istream_iterator<char>());
			}catch(invalid_encoding& ie){
				syslog(LOG_ERR,"DHT state file not valid");
			}

		}
		syslog(LOG_INFO,"Starting dht support");
		this->s.start_dht(e);
		this->s.add_dht_router(std::make_pair(std::string("router.bittorrent.com"),6881));
		this->s.add_dht_router(std::make_pair(std::string("router.utorrent.com"),6881));
		this->s.add_dht_router(std::make_pair(std::string("router.bitcomet.com"),6881));
	}else{
		syslog(LOG_DEBUG,"Not starting dht support");
	}

	this->s.set_max_uploads(cfg.GetIntegerOrDefault("torrent","maxuploads",8));
	this->s.set_max_half_open_connections(cfg.GetIntegerOrDefault("torrent","maxhalfopenconnections",-1));


	int startport=cfg.GetIntegerOrDefault("torrent","listenportstart",10000);
	int endport=cfg.GetIntegerOrDefault("torrent","listenportend",14000);

	this->s.set_settings(settings);

	if(!this->s.listen_on(make_pair(startport,endport))){
		syslog(LOG_CRIT,"Could not open a listening port.");
		throw std::runtime_error("Could not open a listening port.");
	}

	int downloadthrottle=cfg.GetIntegerOrDefault("torrent","maxdownload",0);
	int uploadthrottle=cfg.GetIntegerOrDefault("torrent","maxupload",0);

	this->SetDownloadThrottle(downloadthrottle);
	this->SetUploadThrottle(uploadthrottle);

	DirWatcher::Instance().Start();

	while(this->isRunning){
		this->HandleAlerts();
		this->UpdateDownloaders();
		sleep(1);
	}

}
예제 #8
0
bool dht_tracker::incoming_packet(udp::endpoint const& ep
                                  , span<char const> const buf)
{
    int const buf_size = int(buf.size());
    if (buf_size <= 20
            || buf.front() != 'd'
            || buf.back() != 'e') return false;

    m_counters.inc_stats_counter(counters::dht_bytes_in, buf_size);
    // account for IP and UDP overhead
    m_counters.inc_stats_counter(counters::recv_ip_overhead_bytes
                                 , ep.address().is_v6() ? 48 : 28);
    m_counters.inc_stats_counter(counters::dht_messages_in);

    if (m_settings.ignore_dark_internet && ep.address().is_v4())
    {
        address_v4::bytes_type b = ep.address().to_v4().to_bytes();

        // these are class A networks not available to the public
        // if we receive messages from here, that seems suspicious
        static std::uint8_t const class_a[] = { 3, 6, 7, 9, 11, 19, 21, 22, 25
                                                , 26, 28, 29, 30, 33, 34, 48, 51, 56
                                              };

        if (std::find(std::begin(class_a), std::end(class_a), b[0]) != std::end(class_a))
        {
            m_counters.inc_stats_counter(counters::dht_messages_in_dropped);
            return true;
        }
    }

    if (!m_blocker.incoming(ep.address(), clock_type::now(), m_log))
    {
        m_counters.inc_stats_counter(counters::dht_messages_in_dropped);
        return true;
    }

    TORRENT_ASSERT(buf_size > 0);

    int pos;
    error_code err;
    int ret = bdecode(buf.data(), buf.data() + buf_size, m_msg, err, &pos, 10, 500);
    if (ret != 0)
    {
        m_counters.inc_stats_counter(counters::dht_messages_in_dropped);
#ifndef TORRENT_DISABLE_LOGGING
        m_log->log_packet(dht_logger::incoming_message, buf, ep);
#endif
        return false;
    }

    if (m_msg.type() != bdecode_node::dict_t)
    {
        m_counters.inc_stats_counter(counters::dht_messages_in_dropped);
#ifndef TORRENT_DISABLE_LOGGING
        m_log->log_packet(dht_logger::incoming_message, buf, ep);
#endif
        // it's not a good idea to send a response to an invalid messages
        return false;
    }

#ifndef TORRENT_DISABLE_LOGGING
    m_log->log_packet(dht_logger::incoming_message, buf, ep);
#endif

    libtorrent::dht::msg m(m_msg, ep);
    m_dht.incoming(m);
#if TORRENT_USE_IPV6
    m_dht6.incoming(m);
#endif
    return true;
}
예제 #9
0
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;
}