void handle_alert(libtorrent::session& ses, libtorrent::alert* a) { using namespace libtorrent; if (torrent_finished_alert* p = dynamic_cast<torrent_finished_alert*>(a)) { p->handle.set_max_connections(30); // write resume data for the finished torrent torrent_handle h = p->handle; h.save_resume_data(); } else if (save_resume_data_alert* p = dynamic_cast<save_resume_data_alert*>(a)) { torrent_handle h = p->handle; TORRENT_ASSERT(p->resume_data); if (p->resume_data) { boost::filesystem::ofstream out(h.save_path() / (h.name() + ".fastresume") , std::ios_base::binary); out.unsetf(std::ios_base::skipws); bencode(std::ostream_iterator<char>(out), *p->resume_data); if (h.is_paused() && !h.is_auto_managed()) ses.remove_torrent(h); } } }
void load_dht_state(lt::session& s) { FILE* f = fopen(".dht", "rb"); if (f == NULL) return; fseek(f, 0, SEEK_END); int size = ftell(f); fseek(f, 0, SEEK_SET); if (size > 0) { std::vector<char> state; state.resize(size); fread(&state[0], 1, state.size(), f); bdecode_node e; error_code ec; bdecode(&state[0], &state[0] + state.size(), e, ec); if (ec) fprintf(stderr, "failed to parse .dht file: (%d) %s\n" , ec.value(), ec.message().c_str()); else { printf("load dht state from .dht\n"); s.load_state(e); } } fclose(f); }
bool on_alert(libtorrent::alert const* alert , int session_idx , std::vector<libtorrent::torrent_handle> const& handles , libtorrent::session& ses) override { if (alert_cast<metadata_received_alert>(alert)) { m_metadata_alerts += 1; } // make sure this function can be called on // torrents without metadata if ((m_flags & disconnect) == 0) { handles[session_idx].status(); } if ((m_flags & disconnect) && session_idx == 1 && alert_cast<metadata_received_alert>(alert)) { ses.remove_torrent(handles[session_idx]); return true; } return false; }
void filter_ips(lt::session& ses) { using namespace libtorrent; ip_filter filter; filter.add_rule(asio::ip::address_v4::from_string("50.0.0.1") , asio::ip::address_v4::from_string("50.0.0.2"), ip_filter::blocked); ses.set_ip_filter(filter); }
//----------------------------------------------------------------------------- JNIEXPORT jboolean JNICALL Java_com_softwarrior_libtorrent_LibTorrent_ResumeSession (JNIEnv *, jobject) { jboolean result = JNI_FALSE; try { if(gSessionState){ gSession.resume(); bool paused = gSession.is_paused(); if(!paused) result = JNI_TRUE; } } catch(...){ LOG_ERR("Exception: failed to resume session"); gSessionState=false; } if(!gSessionState) LOG_ERR("LibTorrent.ResumeSession SessionState==false"); gSessionState==true ? result=JNI_TRUE : result=JNI_FALSE; return result; }
void enable_enc(lt::session& ses) { using namespace libtorrent; settings_pack p; p.set_bool(settings_pack::prefer_rc4, true); p.set_int(settings_pack::in_enc_policy, settings_pack::pe_forced); p.set_int(settings_pack::out_enc_policy, settings_pack::pe_forced); p.set_int(settings_pack::allowed_enc_level, settings_pack::pe_both); ses.apply_settings(p); }
void enable_utp(lt::session& ses) { using namespace libtorrent; settings_pack p; p.set_bool(settings_pack::enable_outgoing_tcp, false); p.set_bool(settings_pack::enable_incoming_tcp, false); p.set_bool(settings_pack::enable_outgoing_utp, true); p.set_bool(settings_pack::enable_incoming_utp, true); ses.apply_settings(p); }
//----------------------------------------------------------------------------- JNIEXPORT jboolean JNICALL Java_com_softwarrior_libtorrent_LibTorrent_SetSession (JNIEnv *env, jobject obj, jint ListenPort, jint UploadLimit, jint DownloadLimit) { jboolean result = JNI_FALSE; try{ gSession.set_alert_mask(libtorrent::alert::all_categories & ~(libtorrent::alert::dht_notification + libtorrent::alert::progress_notification + libtorrent::alert::debug_notification + libtorrent::alert::stats_notification)); int listenPort = 54321; if(ListenPort > 0) listenPort = ListenPort; gSession.listen_on(std::make_pair(listenPort, listenPort+10)); int uploadLimit = UploadLimit; if(uploadLimit > 0){ gSession.set_upload_rate_limit(uploadLimit * 1000); } else{ gSession.set_upload_rate_limit(0); } int downloadLimit = DownloadLimit; if(downloadLimit > 0){ gSession.set_download_rate_limit(downloadLimit * 1000); } else{ gSession.set_download_rate_limit(0); } libtorrent::session_settings sets = gSession.settings(); sets.announce_to_all_trackers = true; sets.announce_to_all_tiers = true; sets.prefer_udp_trackers = false; sets.max_peerlist_size = 0; gSession.set_settings(sets); LOG_INFO("ListenPort: %d\n", listenPort); LOG_INFO("DownloadLimit: %d\n", downloadLimit); LOG_INFO("UploadLimit: %d\n", uploadLimit); gSessionState=true; }catch(...){ LOG_ERR("Exception: failed to set session"); gSessionState=false; } if(!gSessionState) LOG_ERR("LibTorrent.SetSession SessionState==false"); gSessionState==true ? result=JNI_TRUE : result=JNI_FALSE; return result; }
//----------------------------------------------------------------------------- JNIEXPORT jboolean JNICALL Java_com_softwarrior_libtorrent_LibTorrent_SetSessionOptions (JNIEnv *env, jobject obj, jboolean LSD, jboolean UPNP, jboolean NATPMP) { jboolean result = JNI_FALSE; try{ if(gSessionState){ if(LSD == JNI_TRUE) gSession.start_lsd(); else gSession.stop_lsd(); if(UPNP == JNI_TRUE) gSession.start_upnp(); else gSession.stop_upnp(); if(NATPMP == JNI_TRUE) gSession.start_natpmp(); else gSession.stop_natpmp(); LOG_INFO("LSD: %d\n", LSD); LOG_INFO("UPNP: %d\n", UPNP); LOG_INFO("NATPMP: %d\n", NATPMP); } }catch(...){ LOG_ERR("Exception: failed to set session options"); gSessionState=false; } if(!gSessionState) LOG_ERR("LibTorrent.SetSessionOptions SessionState==false"); gSessionState==true ? result=JNI_TRUE : result=JNI_FALSE; return result; }
void bootstrap_session(std::vector<dht_network*> networks, lt::session& ses) { lt::dht_settings sett; sett.ignore_dark_internet = false; ses.set_dht_settings(sett); lt::entry state; for (auto dht : networks) { // bootstrap off of 8 of the nodes auto router_nodes = dht->router_nodes(); char const* nodes_key; if (router_nodes.front().address().is_v6()) nodes_key = "nodes6"; else nodes_key = "nodes"; lt::entry::list_type& nodes = state["dht state"][nodes_key].list(); for (auto const& n : router_nodes) { std::string node; std::back_insert_iterator<std::string> out(node); lt::detail::write_endpoint(n, out); nodes.push_back(lt::entry(node)); } } std::vector<char> buf; lt::bencode(std::back_inserter(buf), state); lt::bdecode_node e; lt::error_code ec; lt::bdecode(&buf[0], &buf[0] + buf.size(), e, ec); ses.load_state(e); lt::settings_pack pack; pack.set_bool(lt::settings_pack::enable_dht, true); ses.apply_settings(pack); }
//----------------------------------------------------------------------------- JNIEXPORT jboolean JNICALL Java_com_softwarrior_libtorrent_LibTorrent_AbortSession (JNIEnv *, jobject) { jboolean result = JNI_FALSE; try { if(gSessionState) gSession.abort(); } catch(...){ LOG_ERR("Exception: failed to abort session"); gSessionState=false; } if(!gSessionState) LOG_ERR("LibTorrent.AbortSession SessionState==false"); gSessionState==true ? result=JNI_TRUE : result=JNI_FALSE; return result; }
int save_dht_state(lt::session& s) { entry e; s.save_state(e, session::save_dht_state); std::vector<char> state; bencode(std::back_inserter(state), e); FILE* f = fopen(".dht", "wb+"); if (f == NULL) { fprintf(stderr, "failed to open file .dht for writing"); return 1; } fwrite(&state[0], 1, state.size(), f); fclose(f); return 0; }
// monitored_dir is true if this torrent is added because // it was found in the directory that is monitored. If it // is, it should be remembered so that it can be removed // if it's no longer in that directory. void add_torrent(libtorrent::session& ses , handles_t& handles , std::string const& torrent , float preferred_ratio , bool compact_mode , path const& save_path , bool monitored_dir , int torrent_upload_limit , int torrent_download_limit) { using namespace libtorrent; boost::intrusive_ptr<torrent_info> t(new torrent_info(torrent.c_str())); std::cout << t->name() << "\n"; add_torrent_params p; lazy_entry resume_data; std::string filename = (save_path / (t->name() + ".fastresume")).string(); std::vector<char> buf; if (load_file(filename.c_str(), buf) == 0) p.resume_data = &buf; p.ti = t; p.save_path = save_path; p.storage_mode = compact_mode ? storage_mode_compact : storage_mode_sparse; p.paused = true; p.duplicate_is_error = false; p.auto_managed = true; torrent_handle h = ses.add_torrent(p); handles.insert(std::make_pair( monitored_dir?std::string(torrent):std::string(), h)); h.set_max_connections(50); h.set_max_uploads(-1); h.set_ratio(preferred_ratio); h.set_upload_limit(torrent_upload_limit); h.set_download_limit(torrent_download_limit); #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES h.resolve_countries(true); #endif }
void set_proxy(lt::session& ses, int proxy_type, int flags = 0, bool proxy_peer_connections = true) { // apply the proxy settings to session 0 using namespace libtorrent; settings_pack p; p.set_int(settings_pack::proxy_type, proxy_type); if (proxy_type == settings_pack::socks4) p.set_int(settings_pack::proxy_port, 4444); else p.set_int(settings_pack::proxy_port, 5555); if (flags & ipv6) p.set_str(settings_pack::proxy_hostname, "2001::2"); else p.set_str(settings_pack::proxy_hostname, "50.50.50.50"); p.set_bool(settings_pack::proxy_hostnames, true); p.set_bool(settings_pack::proxy_peer_connections, proxy_peer_connections); p.set_bool(settings_pack::proxy_tracker_connections, true); ses.apply_settings(p); }
//----------------------------------------------------------------------------- JNIEXPORT jboolean JNICALL Java_com_softwarrior_libtorrent_LibTorrent_SetProxy (JNIEnv *env, jobject obj, jint Type, jstring HostName, jint Port, jstring UserName, jstring Password) { jboolean result = JNI_FALSE; try{ if(gSessionState){ int type = Type; // if(type > 0){ std::string hostName; JniToStdString(env, &hostName, HostName); int port = Port; std::string userName; JniToStdString(env, &userName, UserName); std::string password; JniToStdString(env, &password, Password); gProxy.type = libtorrent::proxy_settings::proxy_type(type); gProxy.hostname = hostName; gProxy.port = port; gProxy.username = userName; gProxy.password = password; gSession.set_proxy(gProxy); LOG_INFO("ProxyType: %d\n", type); // LOG_INFO("HostName: %s\n", hostName.c_str()); // LOG_INFO("ProxyPort: %d\n", port); // LOG_INFO("UserName: %s\n", userName.c_str()); // LOG_INFO("Password: %s\n", password.c_str()); // } } }catch(...){ LOG_ERR("Exception: failed to set proxy"); gSessionState=false; } if(!gSessionState) LOG_ERR("LibTorrent.SetProxy SessionState==false"); gSessionState==true ? result=JNI_TRUE : result=JNI_FALSE; return result; }
//----------------------------------------------------------------------------- JNIEXPORT jboolean JNICALL Java_com_softwarrior_libtorrent_LibTorrent_RemoveTorrent (JNIEnv *env, jobject obj, jstring ContentFile) { jboolean result = JNI_FALSE; try { if(gSessionState){ libtorrent::torrent_handle* pTorrent = GetTorrentHandle(env,ContentFile); if(pTorrent){ LOG_INFO("Remove torrent name %s", pTorrent->name().c_str()); pTorrent->auto_managed(false); pTorrent->pause(); // the alert handler for save_resume_data_alert // will save it to disk /*pTorrent->save_resume_data(); // loop through the alert queue to see if anything has happened. std::auto_ptr<libtorrent::alert> a; a = gSession.pop_alert(); while (a.get()){ //LOG_INFO("RemoveTorrent Alert: %s", a->message().c_str()); HandleAlert(a.get()); a = gSession.pop_alert(); }*/ gSession.remove_torrent(*pTorrent); LOG_INFO("remove_torrent"); gTorrents.erase(TorrentFileInfo(env,ContentFile)); result = JNI_TRUE; } } } catch(...){ LOG_ERR("Exception: failed to remove torrent"); try { gTorrents.erase(TorrentFileInfo(env,ContentFile)); }catch(...){} } return result; }
//----------------------------------------------------------------------------- JNIEXPORT jstring JNICALL Java_com_softwarrior_libtorrent_LibTorrent_GetSessionStatusText (JNIEnv *env, jobject obj) { jstring result = NULL; try { if(gSessionState){ std::string out; char str[500]; memset(str,0,500); libtorrent::session_status s_s = gSession.status(); snprintf(str, sizeof(str), "%25s%20d\n" "%22s%20s/%s\n" "%25s%20s/%s\n" "%18s%20s/%s\n" "%15s%20s/%s\n" "%19s%20s/%s\n" ,"conns:" , s_s.num_peers , "down/rate:" , add_suffix(s_s.total_download).c_str(), add_suffix(s_s.download_rate, "/s").c_str() , "up/rate:" , add_suffix(s_s.total_upload).c_str(), add_suffix(s_s.upload_rate, "/s").c_str() , "ip rate down/up:" , add_suffix(s_s.ip_overhead_download_rate, "/s").c_str(), add_suffix(s_s.ip_overhead_upload_rate, "/s").c_str() , "dht rate down/up:" , add_suffix(s_s.dht_download_rate, "/s").c_str(), add_suffix(s_s.dht_upload_rate, "/s").c_str() , "tr rate down/up:" , add_suffix(s_s.tracker_download_rate, "/s").c_str(), add_suffix(s_s.tracker_upload_rate, "/s").c_str()); out += str; result = env->NewStringUTF(out.c_str()); } } catch(...){ LOG_ERR("Exception: failed to get session status"); } return result; }
torrent_handle test_resume_flags(libtorrent::session& ses, int flags , char const* file_priorities = "1111", char const* resume_file_prio = "") { boost::shared_ptr<torrent_info> ti = generate_torrent(); add_torrent_params p; p.ti = ti; p.flags = flags; #ifdef TORRENT_WINDOWS p.save_path = "c:\\add_torrent_params save_path"; #else p.save_path = "/add_torrent_params save_path"; #endif p.trackers.push_back("http://add_torrent_params_tracker.com/announce"); p.url_seeds.push_back("http://add_torrent_params_url_seed.com"); std::vector<char> rd = generate_resume_data(ti.get(), resume_file_prio); p.resume_data.swap(rd); p.max_uploads = 1; p.max_connections = 2; p.upload_limit = 3; p.download_limit = 4; std::vector<boost::uint8_t> priorities_vector; for (int i = 0; file_priorities[i]; ++i) priorities_vector.push_back(file_priorities[i] - '0'); p.file_priorities = priorities_vector; torrent_handle h = ses.add_torrent(p); torrent_status s = h.status(); TEST_EQUAL(s.info_hash, ti->info_hash()); return h; }
int main(int argc, char* argv[]) { if (argc == 1) { printhelp(argv[0]); } int tmp; char torrentfile[255]; int usrpid = 0; int mypid; char pidfilename[255]; char ip[16]; int delay = 10; strcpy(ip, "0.0.0.0"); strcpy(pidfilename, argv[0]); strcat(pidfilename, ".pid"); while((tmp=getopt(argc,argv,"ht:p:f:b:d:"))!=-1) { switch(tmp) { case 'h': printhelp(argv[0]); break; case 't': strcpy(torrentfile, optarg); break; case 'p': usrpid = atoi(optarg); break; case 'f': strcpy(pidfilename, optarg); break; case 'b': strcpy(ip, optarg); break; case 'd': delay = atoi(optarg); break; default: printhelp(argv[0]); break; } } if (usrpid == 0) { printhelp(argv[0]); } mypid = ::getpid(); std::signal(SIGINT, exit_signalHandler); std::signal(SIGTERM, exit_signalHandler); using namespace libtorrent; // set peer_id to nodename char hostname[HOST_NAME_MAX]; gethostname(hostname, HOST_NAME_MAX); char buff[21]; snprintf(buff, sizeof(buff), "%20s", hostname); peer_id my_peer_id = sha1_hash(buff); s.set_peer_id(my_peer_id); error_code ec; // set up torrent session s.listen_on(std::make_pair(6881, 6889), ec, ip); if (ec) { fprintf(stderr, "failed to open listen socket: %s\n", ec.message().c_str()); return 1; } // create torrent object add_torrent_params p; p.save_path = "./"; p.ti = new torrent_info(torrentfile, ec); if (ec) { fprintf(stderr, "%s\n", ec.message().c_str()); return 1; } // start downloading torrent torrent_handle torrent = s.add_torrent(p, ec); if (ec) { fprintf(stderr, "%s\n", ec.message().c_str()); return 1; } // create pidfile std::ofstream pidfile; pidfile.open(pidfilename); pidfile << mypid; pidfile << "\n"; pidfile.close(); std::vector<torrent_status> vts; s.get_torrent_status(&vts, &yes, 0); torrent_status& st = vts[0]; boost::int64_t remains = st.total_wanted - st.total_wanted_done; fprintf(stdout, "Remains: %i\n", remains); //fprintf(stdout, "Torrent: %i\n", torrent); while( remains > 0 && run ) { usleep(delay*1000000); std::vector<torrent_status> vts; s.get_torrent_status(&vts, &yes, 0); torrent_status& st = vts[0]; remains = st.total_wanted - st.total_wanted_done; fprintf(stdout, "Remains: %i\n", remains); torrent.force_reannounce(); } // send SIGUSR1 to process fprintf(stdout, "Done with torrent. Sending SIGUSR1 to PID %i\n", usrpid); kill(usrpid, SIGUSR1); while (run) { usleep(delay*1000000); torrent.force_reannounce(); } s.abort(); remove(pidfilename); fprintf(stdout, "Exit.\n"); return 0; }
bool is_seed(lt::session& ses) { lt::torrent_handle h = ses.get_torrents()[0]; return h.status().is_seeding; }
//----------------------------------------------------------------------------- JNIEXPORT jboolean JNICALL Java_com_softwarrior_libtorrent_LibTorrent_AddTorrent (JNIEnv *env, jobject obj, jstring SavePath, jstring TorrentFile, jint StorageMode) { jboolean result = JNI_FALSE; try{ if(gSessionState){ TorrentFileInfo torrentFileInfo(env, SavePath, TorrentFile); std::map<TorrentFileInfo, libtorrent::torrent_handle>::iterator iter = gTorrents.find(torrentFileInfo); if(iter != gTorrents.end()) { LOG_INFO("Torrent file already presents: %s", torrentFileInfo.TorrentFileName.c_str()); } else{ LOG_INFO("SavePath: %s", torrentFileInfo.SavePath.c_str()); LOG_INFO("TorrentFile: %s", torrentFileInfo.TorrentFileName.c_str()); boost::intrusive_ptr<libtorrent::torrent_info> t; libtorrent::error_code ec; t = new libtorrent::torrent_info(torrentFileInfo.TorrentFileName.c_str(), ec); if (ec){ std::string errorMessage = ec.message(); LOG_ERR("%s: %s\n", torrentFileInfo.TorrentFileName.c_str(), errorMessage.c_str()); } else{ LOG_INFO("%s\n", t->name().c_str()); LOG_INFO("StorageMode: %d\n", StorageMode); libtorrent::add_torrent_params torrentParams; libtorrent::lazy_entry resume_data; boost::filesystem::path save_path = torrentFileInfo.SavePath; std::string filename = torrentFileInfo.SavePath + "/" + t->name() + ".resume"; std::vector<char> buf; boost::system::error_code errorCode; if (libtorrent::load_file(filename.c_str(), buf, errorCode) == 0) torrentParams.resume_data = &buf; torrentParams.ti = t; torrentParams.save_path = torrentFileInfo.SavePath; torrentParams.duplicate_is_error = false; torrentParams.auto_managed = true; libtorrent::storage_mode_t storageMode = libtorrent::storage_mode_sparse; switch(StorageMode){ case 0: storageMode = libtorrent::storage_mode_allocate; break; case 1: storageMode = libtorrent::storage_mode_sparse; break; case 2: storageMode = libtorrent::storage_mode_compact; break; } torrentParams.storage_mode = storageMode; libtorrent::torrent_handle th = gSession.add_torrent(torrentParams,ec); th.move_storage(save_path.string()); if(ec) { std::string errorMessage = ec.message(); LOG_ERR("failed to add torrent: %s\n", errorMessage.c_str()); } else{ if(th.is_paused()){ th.resume(); } if(!th.is_auto_managed()){ th.auto_managed(true); } gTorrents[torrentFileInfo] = th; result=JNI_TRUE; } } } } }catch(...){ LOG_ERR("Exception: failed to add torrent"); try { TorrentFileInfo torrentFileInfo(env, SavePath, TorrentFile); gTorrents.erase(torrentFileInfo); }catch(...){} } return result; }
// proxy: 0=none, 1=socks4, 2=socks5, 3=socks5_pw 4=http 5=http_pw void test_transfer(lt::session& ses, boost::shared_ptr<torrent_info> torrent_file , int proxy, int port, char const* protocol, bool url_seed , bool chunked_encoding, bool test_ban, bool keepalive, bool proxy_peers) { using namespace libtorrent; TORRENT_ASSERT(torrent_file->web_seeds().size() > 0); std::string save_path = "tmp2_web_seed"; save_path += proxy_name[proxy]; error_code ec; remove_all(save_path, ec); static char const* test_name[] = {"no", "SOCKS4", "SOCKS5", "SOCKS5 password", "HTTP", "HTTP password"}; fprintf(stderr, "\n\n ==== TESTING === proxy: %s ==== protocol: %s " "==== seed: %s === transfer-encoding: %s === corruption: %s " "==== keepalive: %s\n\n\n" , test_name[proxy], protocol, url_seed ? "URL seed" : "HTTP seed" , chunked_encoding ? "chunked": "none", test_ban ? "yes" : "no" , keepalive ? "yes" : "no"); int proxy_port = 0; if (proxy) { proxy_port = start_proxy(proxy); if (proxy_port < 0) { fprintf(stderr, "failed to start proxy"); return; } settings_pack pack; pack.set_str(settings_pack::proxy_hostname, "127.0.0.1"); pack.set_str(settings_pack::proxy_username, "testuser"); pack.set_str(settings_pack::proxy_password, "testpass"); pack.set_int(settings_pack::proxy_type, (settings_pack::proxy_type_t)proxy); pack.set_int(settings_pack::proxy_port, proxy_port); pack.set_bool(settings_pack::proxy_peer_connections, proxy_peers); ses.apply_settings(pack); } else { settings_pack pack; pack.set_str(settings_pack::proxy_hostname, ""); pack.set_str(settings_pack::proxy_username, ""); pack.set_str(settings_pack::proxy_password, ""); pack.set_int(settings_pack::proxy_type, settings_pack::none); pack.set_int(settings_pack::proxy_port, 0); pack.set_bool(settings_pack::proxy_peer_connections, proxy_peers); ses.apply_settings(pack); } add_torrent_params p; p.flags &= ~add_torrent_params::flag_paused; p.flags &= ~add_torrent_params::flag_auto_managed; p.ti = torrent_file; p.save_path = save_path; #ifndef TORRENT_NO_DEPRECATE p.storage_mode = storage_mode_compact; #endif torrent_handle th = ses.add_torrent(p, ec); printf("adding torrent, save_path = \"%s\" cwd = \"%s\" torrent = \"%s\"\n" , save_path.c_str(), current_working_directory().c_str() , torrent_file->name().c_str()); std::vector<announce_entry> empty; th.replace_trackers(empty); const boost::int64_t total_size = torrent_file->total_size(); file_storage const& fs = torrent_file->files(); int pad_file_size = 0; for (int i = 0; i < fs.num_files(); ++i) { if (fs.file_flags(i) & file_storage::flag_pad_file) pad_file_size += fs.file_size(i); } peer_disconnects = 0; std::map<std::string, boost::int64_t> cnt = get_counters(ses); for (int i = 0; i < 40; ++i) { torrent_status s = th.status(); cnt = get_counters(ses); print_ses_rate(i / 10.f, &s, NULL); print_alerts(ses, " >> ses", test_ban, false, false, &on_alert); if (test_ban && th.url_seeds().empty() && th.http_seeds().empty()) { fprintf(stderr, "testing ban: URL seed removed\n"); // when we don't have any web seeds left, we know we successfully banned it break; } if (s.is_seeding) { fprintf(stderr, "SEEDING\n"); fprintf(stderr, "session.payload: %d session.redundant: %d\n" , int(cnt["net.recv_payload_bytes"]), int(cnt["net.recv_redundant_bytes"])); fprintf(stderr, "torrent.payload: %d torrent.redundant: %d\n" , int(s.total_payload_download), int(s.total_redundant_bytes)); TEST_EQUAL(s.total_payload_download - s.total_redundant_bytes, total_size - pad_file_size); // we need to sleep here a bit to let the session sync with the torrent stats // commented out because it takes such a long time // TEST_EQUAL(ses.status().total_payload_download - ses.status().total_redundant_bytes // , total_size - pad_file_size); break; } // if the web seed connection is disconnected, we're going to fail // the test. make sure to do so quickly if (keepalive && peer_disconnects >= 1) break; test_sleep(100); } // for test_ban tests, make sure we removed // the url seed (i.e. banned it) TEST_CHECK(!test_ban || (th.url_seeds().empty() && th.http_seeds().empty())); cnt = get_counters(ses); // if the web seed senr corrupt data and we banned it, we probably didn't // end up using all the cache anyway if (!test_ban) { torrent_status st = th.status(); TEST_EQUAL(st.is_seeding, true); if (st.is_seeding) { for (int i = 0; i < 50; ++i) { cnt = get_counters(ses); if (cnt["disk.read_cache_blocks"] == (torrent_file->total_size() + 0x3fff) / 0x4000 && cnt["disk.disk_blocks_in_use"] == (torrent_file->total_size() + 0x3fff) / 0x4000) break; fprintf(stderr, "cache_size: %d/%d\n", int(cnt["disk.read_cache_blocks"]) , int(cnt["disk.disk_blocks_in_use"])); test_sleep(100); } TEST_EQUAL(cnt["disk.disk_blocks_in_use"] , (torrent_file->total_size() + 0x3fff) / 0x4000); } } std::cerr << "total_size: " << total_size << " read cache size: " << cnt["disk.disk_blocks_in_use"] << " total used buffer: " << cnt["disk.disk_blocks_in_use"] << " session total download: " << cnt["net.recv_payload_bytes"] << " torrent total download: " << th.status().total_payload_download << " redundant: " << th.status().total_redundant_bytes << std::endl; // if test_ban is true, we're not supposed to have completed the download // otherwise, we are supposed to have TEST_CHECK(th.status().is_seeding == !test_ban); if (proxy) stop_proxy(proxy_port); th.flush_cache(); // synchronize to make sure the files have been created on disk wait_for_alert(ses, cache_flushed_alert::alert_type, "ses"); print_alerts(ses, " >> ses", true, true, false, &on_alert, true); if (!test_ban) { std::string first_file_path = combine_path(save_path, torrent_file->files().file_path(0)); fprintf(stderr, "checking file: %s\n", first_file_path.c_str()); TEST_CHECK(exists(first_file_path)); } ses.remove_torrent(th); remove_all(save_path, ec); }