Download::Download(UserConnection& conn, QueueItem& qi, const string& path, bool supportsTrees) noexcept : Transfer(conn, path, qi.getTTH()), tempTarget(qi.getTempTarget()), file(0), treeValid(false) { conn.setDownload(this); QueueItem::SourceConstIter source = qi.getSource(getUser()); if(qi.isSet(QueueItem::FLAG_PARTIAL_LIST)) { setType(TYPE_PARTIAL_LIST); } else if(qi.isSet(QueueItem::FLAG_USER_LIST)) { setType(TYPE_FULL_LIST); } if(getType() == TYPE_FILE && qi.getSize() != -1) { if(HashManager::getInstance()->getTree(getTTH(), getTigerTree())) { setTreeValid(true); setSegment(qi.getNextSegment(getTigerTree().getBlockSize(), conn.getChunkSize(),conn.getSpeed(), source->getPartialSource())); } else if(supportsTrees && conn.isSet(UserConnection::FLAG_SUPPORTS_TTHL) && !qi.getSource(conn.getUser())->isSet(QueueItem::Source::FLAG_NO_TREE) && qi.getSize() > HashManager::MIN_BLOCK_SIZE) { // Get the tree unless the file is small (for small files, we'd probably only get the root anyway) setType(TYPE_TREE); getTigerTree().setFileSize(qi.getSize()); setSegment(Segment(0, -1)); } else { // Use the root as tree to get some sort of validation at least... getTigerTree() = TigerTree(qi.getSize(), qi.getSize(), getTTH()); setTreeValid(true); setSegment(qi.getNextSegment(getTigerTree().getBlockSize(), 0, 0, source->getPartialSource())); } if(getSegment().getOverlapped()) { setFlag(FLAG_OVERLAP); // set overlapped flag to original segment for(DownloadList::const_iterator i = qi.getDownloads().begin(); i != qi.getDownloads().end(); ++i) { if((*i)->getSegment().contains(getSegment())) { (*i)->setOverlapped(true); break; } } } } }
void DownloadQueue::getParams(DownloadQueue::VarMap ¶ms, const QueueItem *item){ QString nick = ""; QMap<QString, QString> source; int online = 0; if (!item) return; params["FNAME"] = _q(item->getTargetFileName()); params["PATH"] = _q(Util::getFilePath(item->getTarget())); params["TARGET"] = _q(item->getTarget()); params["USERS"] = QString(""); QStringList user_list; QueueItem::SourceConstIter it = item->getSources().begin(); for (; it != item->getSources().end(); ++it){ HintedUser usr = it->getUser(); const dcpp::CID &cid = usr.user->getCID(); if (usr.user->isOnline()) ++online; nick = WulforUtil::getInstance()->getNicks(cid, _q(usr.hint)); if (!nick.isEmpty()){ source[nick] = _q(cid.toBase32()); user_list.push_back(nick); } } if (!user_list.isEmpty()) params["USERS"] = user_list.join(", "); else params["USERS"] = tr("No users..."); Q_D(DownloadQueue); d->sources[_q(item->getTarget())] = source; if (item->isWaiting()) params["STATUS"] = tr("%1 of %2 user(s) online").arg(online).arg(item->getSources().size()); else params["STATUS"] = tr("Running..."); params["ESIZE"] = (qlonglong)item->getSize(); params["DOWN"] = (qlonglong)item->getDownloadedBytes(); params["PRIO"] = static_cast<int>(item->getPriority()); source.clear(); params["ERRORS"] = QString(""); it = item->getBadSources().begin(); for (; it != item->getBadSources().end(); ++it){ QString errors = params["ERRORS"].toString(); UserPtr usr = it->getUser(); nick = WulforUtil::getInstance()->getNicks(usr->getCID()); source[nick] = _q(usr->getCID().toBase32()); if (!it->isSet(QueueItem::Source::FLAG_REMOVED)){ if (!errors.isEmpty()) errors += ", "; errors += nick + " ("; if (it->isSet(QueueItem::Source::FLAG_FILE_NOT_AVAILABLE)) errors += tr("File not available"); else if (it->isSet(QueueItem::Source::FLAG_PASSIVE)) errors += tr("Passive user"); else if (it->isSet(QueueItem::Source::FLAG_CRC_FAILED)) errors += tr("Checksum mismatch"); else if (it->isSet(QueueItem::Source::FLAG_BAD_TREE)) errors += tr("Full tree does not match TTH root"); else if (it->isSet(QueueItem::Source::FLAG_SLOW_SOURCE)) errors += tr("Source too slow"); else if (it->isSet(QueueItem::Source::FLAG_NO_TTHF)) errors += tr("Remote client does not fully support TTH - cannot download"); params["ERRORS"] = errors + ")"; } } if (params["ERRORS"].toString().isEmpty()) params["ERRORS"] = tr("No errors"); d->badSources[_q(item->getTarget())] = source; params["ADDED"] = _q(Util::formatTime("%Y-%m-%d %H:%M", item->getAdded())); params["TTH"] = _q(item->getTTH().toBase32()); }
Download::Download(UserConnection& conn, QueueItem& qi) noexcept : Transfer(conn, qi.getTarget(), qi.getTTH()), tempTarget(qi.getTempTarget()) { conn.setDownload(this); QueueItem::SourceConstIter source = qi.getSource(getUser()); if(qi.isSet(QueueItem::FLAG_PARTIAL_LIST)) { setType(TYPE_PARTIAL_LIST); } else if(qi.isSet(QueueItem::FLAG_USER_LIST)) { setType(TYPE_FULL_LIST); } if(source->isSet(QueueItem::Source::FLAG_PARTIAL)) setFlag(FLAG_PARTIAL); if(qi.isSet(QueueItem::FLAG_CLIENT_VIEW)) setFlag(FLAG_VIEW); if(qi.isSet(QueueItem::FLAG_MATCH_QUEUE)) setFlag(FLAG_QUEUE); if(qi.isSet(QueueItem::FLAG_VIEW_NFO)) setFlag(FLAG_NFO); if(qi.isSet(QueueItem::FLAG_RECURSIVE_LIST)) setFlag(FLAG_RECURSIVE); if(qi.isSet(QueueItem::FLAG_TTHLIST_BUNDLE)) setFlag(FLAG_TTHLIST_BUNDLE); if (qi.getPriority() == QueueItemBase::HIGHEST) setFlag(FLAG_HIGHEST_PRIO); if (qi.getBundle()) { dcassert(!qi.isSet(QueueItem::FLAG_USER_LIST)); dcassert(!qi.isSet(QueueItem::FLAG_TEXT)); setBundle(qi.getBundle()); } if(getType() == TYPE_FILE && qi.getSize() != -1) { if(HashManager::getInstance()->getTree(getTTH(), getTigerTree())) { setTreeValid(true); setSegment(qi.getNextSegment(getTigerTree().getBlockSize(), conn.getChunkSize(), conn.getSpeed(), source->getPartialSource(), true)); qi.setBlockSize(getTigerTree().getBlockSize()); } else if(conn.isSet(UserConnection::FLAG_SUPPORTS_TTHL) && !source->isSet(QueueItem::Source::FLAG_NO_TREE) && qi.getSize() > HashManager::MIN_BLOCK_SIZE) { // Get the tree unless the file is small (for small files, we'd probably only get the root anyway) setType(TYPE_TREE); getTigerTree().setFileSize(qi.getSize()); setSegment(Segment(0, -1)); } else { // Use the root as tree to get some sort of validation at least... getTigerTree() = TigerTree(qi.getSize(), qi.getSize(), getTTH()); setTreeValid(true); setSegment(qi.getNextSegment(getTigerTree().getBlockSize(), 0, 0, source->getPartialSource(), true)); } if ((getStartPos() + getSegmentSize()) != qi.getSize() || (conn.getDownload() && conn.getDownload()->isSet(FLAG_CHUNKED))) { setFlag(FLAG_CHUNKED); } if(getSegment().getOverlapped()) { setFlag(FLAG_OVERLAP); // set overlapped flag to original segment for(auto d: qi.getDownloads()) { if(d->getSegment().contains(getSegment())) { d->setOverlapped(true); break; } } } } }