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); }
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; }
// 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(); }
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; }
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); } }
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; }
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; }