Created attachment 55314 [details] webseed view Version: unspecified (using KDE 4.4.4) OS: Linux I have currently some downloads running that use webseeds as well as torrents: The webseed claims that it has already loaded some 500 MB, while the main torrent window claims it has only loaded some 100 MB, which is approximately in line with the file status (see screenshots). where hat the rest of the downloads gone. Reproducible: Sometimes Steps to Reproduce: May this depend on the webseed? OS: Linux (i686) release 2.6.34.7-0.5-desktop Compiler: gcc
Created attachment 55315 [details] File status
Version ?
(In reply to comment #2) > Version ? ktorrent? 3.3.4
Created attachment 55318 [details] 1.6 GB loaded on a 1.1 GB file, and still only 9% complete ...think it does not make sense to continue with webseeds
Send me the torrent
Two things: - There is a bug in the latest development code which results in the hash check always failing in this situation, this bug is not present in the version you are running, so this is not what you are seeing - The webseed and the torrent do not match, after 99 MB they diverge, none of the data beyond 99 MB matches. The fact that you get stuck at 9 % is thus very logical. So you need to stop using the webseed for this torrent, and I need to make it clear in the GUI that this is happening, instead of retrying continuously to download a chunk which is never gonna match.
commit 6f64659c7b05cc0033b4827b37aa87a4e9f4d1da branch master Author: Joris <joris.guisson@gmail.com> Date: Wed Dec 29 12:17:26 2010 +0100 Disable webseeds if they send data which does not match BUG: 261449 diff --git a/ChangeLog b/ChangeLog index 7192502..78664c3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -26,6 +26,7 @@ Changes in 1.1: - Fix crash in PeerConnector cleanup (258878) - Queue data checks so that they run one after the other (215711) - Revamp UTP code with smart pointers +- Disable webseeds if they send data which does not match (261449) Changes in 1.0.5: - Update PeerID client identifications diff --git a/src/download/downloader.cpp b/src/download/downloader.cpp index 78c89ac..8b55069 100644 --- a/src/download/downloader.cpp +++ b/src/download/downloader.cpp @@ -21,6 +21,7 @@ #include <QFile> #include <QTextStream> +#include <KLocale> #include <util/file.h> #include <util/log.h> #include <diskio/chunkmanager.h> @@ -758,6 +759,7 @@ namespace bt void Downloader::onChunkReady(Chunk* c) { + WebSeed* ws = webseeds_chunks.find(c->getIndex()); webseeds_chunks.erase(c->getIndex()); PieceData::Ptr piece = c->getPiece(0,c->getSize(),true); if (piece && c->checkHash(tor.getHash(c->getIndex()))) @@ -805,6 +807,7 @@ namespace bt cman.resetChunk(c->getIndex()); chunk_selector->reinsert(c->getIndex()); + ws->disable(i18n("Disabled because webseed does not match torrent")); } } diff --git a/src/download/webseed.cpp b/src/download/webseed.cpp index 9a18291..b569ff1 100644 --- a/src/download/webseed.cpp +++ b/src/download/webseed.cpp @@ -103,6 +103,13 @@ namespace bt reset(); } + void WebSeed::disable(const QString& reason) + { + setEnabled(false); + status = reason; + Out(SYS_CON|LOG_IMPORTANT) << "Auto disabled webseed " << url.prettyUrl() << endl; + } + bool WebSeed::busy() const { @@ -218,7 +225,6 @@ namespace bt if (path.endsWith('/') && !isUserCreated()) path += tor.getNameSuggestion(); - //Out(SYS_GEN|LOG_DEBUG) << "WebSeed: continuing current chunk " << cur_chunk << " " << bytes_of_cur_chunk << endl; first_chunk = cur_chunk; if (tor.isMultiFile()) { @@ -292,82 +298,88 @@ namespace bt Uint32 WebSeed::update() { - if (!conn || !busy()) - return 0; - - if (!conn->ok()) - { - readData(); - Out(SYS_CON|LOG_DEBUG) << "WebSeed: connection not OK" << endl; - // shit happened delete connection - status = conn->getStatusString(); - if (conn->responseCode() == 404) - { - // if not found then retire this webseed for now - retryLater(); - } - delete conn; - conn = 0; - chunkStopped(); - first_chunk = last_chunk = cur_chunk = tor.getNumChunks() + 1; - num_failures++; - if (num_failures == 3) - retryLater(); - return 0; - } - else if (conn->closed()) + try { - // Make sure we handle all data - readData(); + if (!conn || !busy()) + return 0; - Out(SYS_CON|LOG_DEBUG) << "WebSeed: connection closed" << endl; - delete conn; - conn = 0; - - status = i18n("Connection closed"); - chunkStopped(); - if (last_chunk < tor.getNumChunks()) + if (!conn->ok()) { - // lets try this again if we have not yet got the full range - download(cur_chunk,last_chunk); + readData(); + + Out(SYS_CON|LOG_DEBUG) << "WebSeed: connection not OK" << endl; + // shit happened delete connection status = conn->getStatusString(); - } - } - else if (conn->isRedirected()) - { - // Make sure we handle all data - readData(); - redirected(conn->redirectedUrl()); - } - else - { - readData(); - if (range_queue.count() > 0 && conn->ready()) - { - if (conn->closed()) + if (conn->responseCode() == 404) { - // after a redirect it is possible that the connection is closed - // so we need to reconnect to the old url - conn->deleteLater(); - conn = new HttpConnection(); - conn->setGroupIDs(up_gid,down_gid); - connectToServer(); + // if not found then retire this webseed for now + retryLater(); } + delete conn; + conn = 0; + chunkStopped(); + first_chunk = last_chunk = cur_chunk = tor.getNumChunks() + 1; + num_failures++; + if (num_failures == 3) + retryLater(); + return 0; + } + else if (conn->closed()) + { + // Make sure we handle all data + readData(); - QString path = url.path(); - if (path.endsWith('/')) - path += tor.getNameSuggestion(); + Out(SYS_CON|LOG_DEBUG) << "WebSeed: connection closed" << endl; + delete conn; + conn = 0; - // ask for the next range - Range r = range_queue[0]; - range_queue.pop_front(); - const TorrentFile & tf = tor.getFile(r.file); - QString host = redirected_url.isValid() ? redirected_url.host() : url.host(); - conn->get(host,path + '/' + tf.getPath(),r.off,r.len); + status = i18n("Connection closed"); + chunkStopped(); + if (last_chunk < tor.getNumChunks()) + { + // lets try this again if we have not yet got the full range + download(cur_chunk,last_chunk); + status = conn->getStatusString(); + } + } + else if (conn->isRedirected()) + { + // Make sure we handle all data + readData(); + redirected(conn->redirectedUrl()); + } + else + { + readData(); + if (range_queue.count() > 0 && conn->ready()) + { + if (conn->closed()) + { + // after a redirect it is possible that the connection is closed + // so we need to reconnect to the old url + conn->deleteLater(); + conn = new HttpConnection(); + conn->setGroupIDs(up_gid,down_gid); + connectToServer(); + } + + QString path = url.path(); + if (path.endsWith('/')) + path += tor.getNameSuggestion(); + + // ask for the next range + Range r = range_queue[0]; + range_queue.pop_front(); + const TorrentFile & tf = tor.getFile(r.file); + QString host = redirected_url.isValid() ? redirected_url.host() : url.host(); + conn->get(host,path + '/' + tf.getPath(),r.off,r.len); + } + status = conn->getStatusString(); } - status = conn->getStatusString(); } - + catch (AutoDisabled &) + { + } Uint32 ret = downloaded; downloaded = 0; total_downloaded += ret; @@ -397,7 +409,6 @@ namespace bt void WebSeed::handleData(const QByteArray & tmp) { -// Out(SYS_GEN|LOG_DEBUG) << "Handling data: " << tmp.length() << " bytes" << endl; Uint32 off = 0; while (off < (Uint32)tmp.size() && cur_chunk <= last_chunk) { @@ -427,6 +438,9 @@ namespace bt if (c->getStatus() != Chunk::ON_DISK) { chunkReady(c); + // It is possible that the webseed has been disabled due receiving a bad chunk + if (!isEnabled()) + throw AutoDisabled(); } chunkStopped(); diff --git a/src/download/webseed.h b/src/download/webseed.h index e0e9cc9..b4ae35a 100644 --- a/src/download/webseed.h +++ b/src/download/webseed.h @@ -119,6 +119,9 @@ namespace bt virtual void setEnabled(bool on); + /// Disable the webseed + void disable(const QString & reason); + /// Get the number of failed attempts Uint32 failedAttempts() const {return num_failures;} @@ -165,6 +168,8 @@ namespace bt Uint64 len; }; + class AutoDisabled {}; // Exception + void fillRangeList(Uint32 chunk); void handleData(const QByteArray & data); void chunkStarted(Uint32 chunk);