void UploadManager::addFailedUpload(const UserConnection& source, string filename) { { Lock l(cs); if (!count_if(waitingUsers.begin(), waitingUsers.end(), CompareFirst<User::Ptr, uint32_t>(source.getUser()))) waitingUsers.push_back(WaitingUser(source.getUser(), GET_TICK())); waitingFiles[source.getUser()].insert(filename); //files for which user's asked } fire(UploadManagerListener::WaitingAddFile(), source.getUser(), filename); }
void Transfer::getParams(const UserConnection& aSource, StringMap& params) { params["userNI"] = aSource.getUser()->getNick(); params["userI4"] = aSource.getRemoteIp(); params["hub"] = aSource.getUser()->getClientName(); params["hubURL"] = aSource.getUser()->getClientUrl(); params["fileSI"] = Util::toString(getSize()); params["fileSIshort"] = Util::formatBytes(getSize()); params["fileSIchunk"] = Util::toString(getTotal()); params["fileSIchunkshort"] = Util::formatBytes(getTotal()); params["fileSIactual"] = Util::toString(getActual()); params["fileSIactualshort"] = Util::formatBytes(getActual()); params["speed"] = Util::formatBytes(getAverageSpeed()) + "/s"; params["time"] = Util::formatSeconds((GET_TICK() - getStart()) / 1000); params["fileTR"] = getTTH().toBase32(); }
Download::Download(UserConnection& conn, QueueItem& qi, const string& path, bool supportsTrees) throw() : Transfer(conn, path, qi.getTTH()), tempTarget(qi.getTempTarget()), file(0), treeValid(false) { conn.setDownload(this); if(qi.isSet(QueueItem::FLAG_PARTIAL_LIST)) { setType(TYPE_PARTIAL_LIST); } else if(qi.isSet(QueueItem::FLAG_USER_LIST)) { setType(TYPE_FULL_LIST); } if(qi.getSize() != -1) { if(HashManager::getInstance()->getTree(getTTH(), getTigerTree())) { setTreeValid(true); setSegment(qi.getNextSegment(getTigerTree().getBlockSize(), conn.getChunkSize())); } else if(supportsTrees && !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)); } } }
void ConnectionManager::disconnect(const User::Ptr& aUser, int isDownload) { Lock l(cs); for(UserConnection::Iter i = userConnections.begin(); i != userConnections.end(); ++i) { UserConnection* uc = *i; if(uc->getUser() == aUser && uc->isSet(isDownload ? UserConnection::FLAG_DOWNLOAD : UserConnection::FLAG_UPLOAD)) { uc->disconnect(true); break; } } }
void DownloadManager::checkIdle(const UserPtr& user) { Lock l(cs); for(UserConnectionList::iterator i = idlers.begin(); i != idlers.end(); ++i) { UserConnection* uc = *i; if(uc->getUser() == user) { uc->updated(); return; } } }
void Transfer::getParams(const UserConnection& aSource, StringMap& params) { params["userCID"] = aSource.getUser()->getCID().toBase32(); params["userNI"] = Util::toString(ClientManager::getInstance()->getNicks(aSource.getUser()->getCID(), aSource.getHubUrl())); params["userI4"] = aSource.getRemoteIp(); StringList hubNames = ClientManager::getInstance()->getHubNames(aSource.getUser()->getCID(), aSource.getHubUrl()); if(hubNames.empty()) hubNames.push_back(_("Offline")); params["hub"] = Util::toString(hubNames); StringList hubs = ClientManager::getInstance()->getHubs(aSource.getUser()->getCID(), aSource.getHubUrl()); if(hubs.empty()) hubs.push_back(_("Offline")); params["hubURL"] = Util::toString(hubs); params["fileSI"] = Util::toString(getSize()); params["fileSIshort"] = Util::formatBytes(getSize()); params["fileSIactual"] = Util::toString(getActual()); params["fileSIactualshort"] = Util::formatBytes(getActual()); params["speed"] = str(F_("%1%/s") % Util::formatBytes(getAverageSpeed())); params["time"] = Util::formatSeconds((GET_TICK() - getStart()) / 1000); params["fileTR"] = getTTH().toBase32(); }
void Transfer::getParams(const UserConnection& aSource, StringMap& params) const { params["userCID"] = aSource.getUser()->getCID().toBase32(); params["userNI"] = Util::toString(ClientManager::getInstance()->getNicks(aSource.getUser()->getCID(), aSource.getHubUrl())); params["userI4"] = aSource.getRemoteIp(); StringList hubNames = ClientManager::getInstance()->getHubNames(aSource.getUser()->getCID(), aSource.getHubUrl()); if(hubNames.empty()) hubNames.push_back(STRING(OFFLINE)); params["hub"] = Util::toString(hubNames); StringList hubs = ClientManager::getInstance()->getHubs(aSource.getUser()->getCID(), aSource.getHubUrl()); if(hubs.empty()) hubs.push_back(STRING(OFFLINE)); params["hubURL"] = Util::toString(hubs); params["fileSI"] = Util::toString(getSize()); params["fileSIshort"] = Util::formatBytes(getSize()); params["fileSIchunk"] = Util::toString(getPos()); params["fileSIchunkshort"] = Util::formatBytes(getPos()); params["fileSIactual"] = Util::toString(getActual()); params["fileSIactualshort"] = Util::formatBytes(getActual()); params["speed"] = Util::formatBytes(static_cast<int64_t>(getAverageSpeed())) + "/s"; params["time"] = Text::fromT(Util::formatSeconds((GET_TICK() - getStart()) / 1000)); params["fileTR"] = getTTH().toBase32(); }
bool UploadManager::prepareFile(UserConnection& aSource, const string& aType, const string& aFile, int64_t aStartPos, int64_t aBytes, bool listRecursive) { if(aFile.empty() || aStartPos < 0 || aBytes < -1 || aBytes == 0) { aSource.fileNotAvail("Invalid request"); return false; } InputStream* is = 0; int64_t start = 0; int64_t bytesLeft = 0; int64_t size = 0; bool userlist = (aFile == Transfer::USER_LIST_NAME_BZ || aFile == Transfer::USER_LIST_NAME); bool free = userlist; bool leaves = false; bool partList = false; string sourceFile; try { if(aType == Transfer::TYPE_FILE) { sourceFile = ShareManager::getInstance()->toReal(aFile); if(aFile == Transfer::USER_LIST_NAME) { // Unpack before sending... string bz2 = File(sourceFile, File::READ, File::OPEN).read(); string xml; CryptoManager::getInstance()->decodeBZ2(reinterpret_cast<const uint8_t*>(bz2.data()), bz2.size(), xml); // Clear to save some memory... string().swap(bz2); is = new MemoryInputStream(xml); start = 0; bytesLeft = size = xml.size(); } else { File* f = new File(sourceFile, File::READ, File::OPEN); start = aStartPos; size = f->getSize(); bytesLeft = (aBytes == -1) ? size : aBytes; if(size < (start + bytesLeft)) { aSource.fileNotAvail(); delete f; return false; } free = free || (size <= (int64_t)(SETTING(FREE_SLOTS_SIZE) * 1024) ); f->setPos(start); is = f; if((start + bytesLeft) < size) { is = new LimitedInputStream<true>(is, aBytes); } } } else if(aType == Transfer::TYPE_TTHL) { sourceFile = ShareManager::getInstance()->toReal(aFile); MemoryInputStream* mis = ShareManager::getInstance()->getTree(aFile); if(!mis) { aSource.fileNotAvail(); return false; } start = 0; bytesLeft = size = mis->getSize(); is = mis; leaves = true; free = true; } else { aSource.fileNotAvail("Unknown file type"); return false; } } catch(const ShareException& e) { aSource.fileNotAvail(e.getError()); return false; } catch(const Exception& e) { LogManager::getInstance()->message(STRING(UNABLE_TO_SEND_FILE) + sourceFile + ": " + e.getError()); aSource.fileNotAvail(); return false; } Lock l(cs); bool extraSlot = false; if(!aSource.isSet(UserConnection::FLAG_HASSLOT)) { bool hasReserved = (reservedSlots.find(aSource.getUser()) != reservedSlots.end()); bool isFavorite = aSource.getUser()->getFavoriteGrantSlot(); if(!(hasReserved || isFavorite || getFreeSlots() > 0 || getAutoSlot())) { bool supportsFree = aSource.isSet(UserConnection::FLAG_SUPPORTS_MINISLOTS); bool allowedFree = aSource.isSet(UserConnection::FLAG_HASEXTRASLOT) || aSource.isSet(UserConnection::FLAG_OP) || getFreeExtraSlots() > 0; if(free && supportsFree && allowedFree) { extraSlot = true; } else { delete is; aSource.maxedOut(); // Check for tth root identifier string tFile = aFile; if (tFile.compare(0, 4, "TTH/") == 0) tFile = ShareManager::getInstance()->toVirtual(TTHValue(aFile.substr(4))); addFailedUpload(aSource, tFile + " (" + Util::toString((aStartPos*1000/(size+10))/10.0)+"% of " + Util::formatBytes(size) + " done)"); aSource.disconnect(); return false; } } else { clearUserFiles(aSource.getUser()); // this user is using a full slot, nix them. } setLastGrant(GET_TICK()); } Upload* u = new Upload(aSource); u->setStream(is); if(aBytes == -1) u->setSize(size); else u->setSize(start + bytesLeft); u->setStartPos(start); u->setSourceFile(sourceFile); if(userlist) u->setFlag(Upload::FLAG_USER_LIST); if(leaves) u->setFlag(Upload::FLAG_TTH_LEAVES); if(partList) u->setFlag(Upload::FLAG_PARTIAL_LIST); uploads.push_back(u); if(!aSource.isSet(UserConnection::FLAG_HASSLOT)) { if(extraSlot) { if(!aSource.isSet(UserConnection::FLAG_HASEXTRASLOT)) { aSource.setFlag(UserConnection::FLAG_HASEXTRASLOT); extra++; } } else { if(aSource.isSet(UserConnection::FLAG_HASEXTRASLOT)) { aSource.unsetFlag(UserConnection::FLAG_HASEXTRASLOT); extra--; } aSource.setFlag(UserConnection::FLAG_HASSLOT); running++; } reservedSlots.erase(aSource.getUser()); } return true; }
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; } } } } }