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 &params, 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());

}
Exemple #3
0
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;
				}
			}
		}
	}
}